Skip to content

Commit

Permalink
Merge remote-tracking branch 'simondotsh/add_synclapspassword' into 4.2
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/components/Modals/HelpModal.jsx
#	src/components/SearchContainer/EdgeFilter/EdgeFilter.jsx
#	src/index.js
  • Loading branch information
rvazarkar committed Aug 1, 2022
2 parents ee0831d + febdbf1 commit 68bfaf5
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 3 deletions.
36 changes: 36 additions & 0 deletions docs/data-analysis/edges.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,42 @@ http://www.harmj0y.net/blog/redteaming/the-trustpocalypse/

|
SyncLAPSPassword
^^^^^^^^^^^^^^^^^^^^

A principal with this signifies the capability of retrieving, through a directory
synchronization, the value of confidential and RODC filtered attributes, such as
LAPS' *ms-Mcs-AdmPwd*.

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

To abuse these privileges, use DirSync:

::

Sync-LAPS -LDAPFilter '(samaccountname=TargetComputer$)'
For other optional parameters, view the DirSync documentation.

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

Executing the attack will generate a 4662 (An operation was performed on an object)
event at the domain controller if an appropriate SACL is in place on the target object.

References
----------

* https://github.com/simondotsh/DirSync
* https://simondotsh.com/infosec/2022/07/11/dirsync.html

|
----

|
AZAddMembers
^^^^^^^^^^^^

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

export default class AppContainer extends Component {
Expand Down
10 changes: 10 additions & 0 deletions src/components/Menu/MenuContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,16 @@ const MenuContainer = () => {

await executePostProcessSteps(ADPostProcessSteps, session);

const createSyncLAPSPasswordStatement = "MATCH (n)-[:GetChangesInFilteredSet]->(m:Domain) WHERE (n)-[:GetChanges]->(m) AND NOT (n)-[:GetChangesAll]->(m) AND NOT n.objectid ENDS WITH '-S-1-5-9' MATCH (o:Computer {haslaps: true, domainsid: m.domainsid}) CREATE (n)-[:SyncLAPSPassword {isacl: true, isinherited: false}]->(o)"
await session.run(createSyncLAPSPasswordStatement, null).catch((err) => {
console.log(err);
});

const deleteGetChangesInFilteredSetStatement = "MATCH ()-[r:GetChangesInFilteredSet]->(:Domain) DELETE r"
await session.run(deleteGetChangesInFilteredSetStatement, null).catch((err) => {
console.log(err);
});

await session.close();
};

Expand Down
4 changes: 3 additions & 1 deletion src/components/Modals/AddEdgeModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ const AddEdgeModal = () => {
edgeValue === 'ReadLAPSPassword' ||
edgeValue === 'WriteSPN' ||
edgeValue === 'AddKeyCredentialLink' ||
edgeValue === 'AddSelf'
edgeValue === 'AddSelf' ||
edgeValue === 'SyncLAPSPassword'
) {
edgepart = `[r:${edgeValue} {isacl: true}]`;
} else if (edgeValue === 'SQLAdmin') {
Expand Down Expand Up @@ -311,6 +312,7 @@ const AddEdgeModal = () => {
</option>
<option value='SQLAdmin'>SQLAdmin</option>
<option value='HasSIDHistory'>HasSIDHistory</option>
<option value='SyncLAPSPassword'>SyncLAPSPassword</option>
</FormControl>
{errors.edgeErrors.length > 0 && (
<span className={styles.error}>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Modals/HelpModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import WriteSPN from "./HelpTexts/WriteSPN/WriteSPN";
import AddSelf from "./HelpTexts/AddSelf/AddSelf";
import AddKeyCredentialLink from "./HelpTexts/AddKeyCredentialLink/AddKeyCredentialLink";
import DCSync from "./HelpTexts/DCSync/DCSync";
import SyncLAPSPassword from "./HelpTexts/SyncLAPSPassword/SyncLAPSPassword";

const HelpModal = () => {
const [sourceName, setSourceName] = useState('');
Expand Down Expand Up @@ -148,7 +149,8 @@ const HelpModal = () => {
WriteSPN: WriteSPN,
AddSelf: AddSelf,
AddKeyCredentialLink: AddKeyCredentialLink,
DCSync: DCSync
DCSync: DCSync,
SyncLAPSPassword: SyncLAPSPassword
};

const Component = edge in components ? components[edge] : Default;
Expand Down
15 changes: 15 additions & 0 deletions src/components/Modals/HelpTexts/SyncLAPSPassword/Abuse.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const Abuse = (sourceName, sourceType, targetName, targetType) => {
let text = `To abuse this privilege with DirSync, first import DirSync into your agent session or into a PowerShell instance at the console. You must authenticate to the Domain Controller as ${
sourceType === 'User'
? `${sourceName} if you are not running a process as that user`
: `a member of ${sourceName} if you are not running a process as a member`
}. Then, execute the <code>Sync-LAPS</code> function:
<code>Sync-LAPS -LDAPFilter '(samaccountname=TargetComputer$)</code>
You can target a specific domain controller using the <code>-Server</code> parameter.
`;
return { __html: text };
};

export default Abuse;
13 changes: 13 additions & 0 deletions src/components/Modals/HelpTexts/SyncLAPSPassword/General.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { groupSpecialFormat} from '../Formatter';

const General = (sourceName, sourceType, targetName, targetType) => {
let text = `${groupSpecialFormat(
sourceType,
sourceName
)} the ability to synchronize the password set by Local Administrator Password Solution (LAPS) on the computer ${targetName}.
The local administrator password for a computer managed by LAPS is stored in the confidential and Read-Only Domain Controller (RODC) filtered LDAP attribute <code>ms-mcs-AdmPwd</code>.`;
return { __html: text };
};

export default General;
6 changes: 6 additions & 0 deletions src/components/Modals/HelpTexts/SyncLAPSPassword/Opsec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const Opsec = () => {
let text = `Executing the attack will generate a 4662 (An operation was performed on an object) event at the domain controller if an appropriate SACL is in place on the target object.`;
return { __html: text };
};

export default Opsec;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const References = () => {
let text = `<a href="https://github.com/simondotsh/DirSync">https://github.com/simondotsh/DirSync</a>
<a href="https://simondotsh.com/infosec/2022/07/11/dirsync.html">https://simondotsh.com/infosec/2022/07/11/dirsync.html</a>`;
return { __html: text };
};

export default References;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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 SyncLAPSPassword = ({
sourceName,
sourceType,
targetName,
targetType,
}) => {
return (
<Tabs defaultActiveKey={1} id='help-tab-container' justified>
<Tab
eventKey={1}
title='Info'
dangerouslySetInnerHTML={General(
sourceName,
sourceType,
targetName,
targetType
)}
/>
<Tab
eventKey={2}
title='Abuse Info'
dangerouslySetInnerHTML={Abuse(
sourceName,
sourceType,
targetName,
targetType
)}
/>
<Tab
eventKey={3}
title='Opsec Considerations'
dangerouslySetInnerHTML={Opsec()}
/>
<Tab
eventKey={4}
title='References'
dangerouslySetInnerHTML={References()}
/>
</Tabs>
);
};

SyncLAPSPassword.propTypes = {
sourceName: PropTypes.string,
sourceType: PropTypes.string,
targetName: PropTypes.string,
targetType: PropTypes.string,
};
export default SyncLAPSPassword;
2 changes: 2 additions & 0 deletions src/components/SearchContainer/EdgeFilter/EdgeFilter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const EdgeFilter = ({ open }) => {
'AddSelf',
'AddAllowedToAct',
'DCSync',
'SyncLAPSPassword'
]}
sectionName='ACL'
/>
Expand All @@ -79,6 +80,7 @@ const EdgeFilter = ({ open }) => {
<EdgeFilterCheck name='AddSelf' />
<EdgeFilterCheck name='AddAllowedToAct' />
<EdgeFilterCheck name='DCSync' />
<EdgeFilterCheck name='SyncLAPSPassword' />
<EdgeFilterSection
title='Containers'
sectionName='container'
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ global.appStore = {
AddSelf: 'tapered',
WriteSPN: 'tapered',
AddKeyCredentialLink: 'tapered',
SyncLAPSPassword: 'tapered',
},
},
lowResPalette: {
Expand Down Expand Up @@ -304,6 +305,7 @@ global.appStore = {
ReadGMSAPassword: 'line',
HasSIDHistory: 'line',
CanPSRemote: 'line',
SyncLAPSPassword: 'line'
},
},
highResStyle: {
Expand Down Expand Up @@ -401,6 +403,7 @@ if (typeof conf.get('edgeincluded') === 'undefined') {
ReadGMSAPassword: true,
HasSIDHistory: true,
CanPSRemote: true,
SyncLAPSPassword: true,
});
}

Expand Down

0 comments on commit 68bfaf5

Please sign in to comment.