mirror of
https://github.com/mgeeky/Penetration-Testing-Tools.git
synced 2024-12-22 17:15:06 +01:00
added markOwnedNodesInNeo4j.py
This commit is contained in:
parent
0daff1b3d8
commit
edb128d4e0
@ -259,6 +259,24 @@ PS E:\PowerSploit\Recon> Get-DomainOU | Get-DomainOUTree
|
||||
|
||||
- **`malleable_redirector`** - A [proxy2](https://github.com/mgeeky/proxy2) plugin for resilient, evasive C2 infrastructures covering your redirectors from AV/EDR/Sandbox/IR lurking eyes based on the CobaltStrike's Malleable C2 Profile specified. Combines advantages of classic evasion techniques such as Apache2 Mod_Rewrite/`.htaccess` and deep c2-profile-drive HTTP/HTTPS request inspection
|
||||
|
||||
- **`markOwnedNodesInNeo4j.py`** - This script takes an input file containing Node names to be marked in Neo4j database as owned = True. The strategy for working with neo4j and Bloodhound becomes fruitful during complex Active Directory Security Review assessments or Red Teams. Imagine you've kerberoasted a number of accounts, access set of workstations or even cracked userPassword hashes. Using this script you can quickly instruct Neo4j to mark that principals as owned, which will enrich your future use of BloodHound.
|
||||
|
||||
```
|
||||
$ ./markOwnedNodesInNeo4j.py kerberoasted.txt
|
||||
[.] Connected to neo4j instance.
|
||||
[.] Marking nodes (0..10) ...
|
||||
[+] Marked 10 nodes in 4.617 seconds. Finish ETA: in 16.622 seconds.
|
||||
[.] Marking nodes (10..20) ...
|
||||
[+] Marked 10 nodes in 4.663 seconds. Finish ETA: in 12.064 seconds.
|
||||
[.] Marking nodes (20..30) ...
|
||||
[+] Marked 10 nodes in 4.157 seconds. Finish ETA: in 7.167 seconds.
|
||||
[.] Marking nodes (30..40) ...
|
||||
[+] Marked 10 nodes in 4.365 seconds. Finish ETA: in 2.670 seconds.
|
||||
[.] Marking nodes (40..46) ...
|
||||
[+] Marked 6 nodes in 2.324 seconds. Finish ETA: in 0 seconds.
|
||||
[+] Nodes marked as owned successfully in 20.246 seconds.
|
||||
```
|
||||
|
||||
- **`msbuild-powershell-msgbox.xml`** - Example of Powershell execution via MSBuild inline task XML file. On a simple Message-Box script.
|
||||
([gist](https://gist.github.com/mgeeky/617c54a23f0c4e99e6f475e6af070810))
|
||||
|
||||
|
125
red-teaming/markOwnedNodesInNeo4j.py
Normal file
125
red-teaming/markOwnedNodesInNeo4j.py
Normal file
@ -0,0 +1,125 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# This script takes an input file containing Node names to be marked in Neo4j database as
|
||||
# owned = True. The strategy for working with neo4j and Bloodhound becomes fruitful during
|
||||
# complex Active Directory Security Review assessments or Red Teams. Imagine you've kerberoasted
|
||||
# a number of accounts, access set of workstations or even cracked userPassword hashes. Using this
|
||||
# script you can quickly instruct Neo4j to mark that principals as owned, which will enrich your
|
||||
# future use of BloodHound.
|
||||
#
|
||||
# Mariusz B. / mgeeky
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
try:
|
||||
from neo4j import GraphDatabase
|
||||
except ImportError:
|
||||
print('[!] "neo4j >= 1.7.0" required. Install it with: python3 -m pip install neo4j')
|
||||
|
||||
#
|
||||
# ===========================================
|
||||
#
|
||||
|
||||
# Specify neo4j connection details
|
||||
NEO4J_CONNECTION_DETAILS = \
|
||||
{
|
||||
'Host': '127.0.0.1', # neo4j listening address.
|
||||
'Port': 7687, # Bolt port
|
||||
'User': 'neo4j',
|
||||
'Pass': 'neo4j1'
|
||||
}
|
||||
|
||||
#
|
||||
# ===========================================
|
||||
#
|
||||
|
||||
#
|
||||
# Construct a MATCH ... SET owned=TRUE query of not more than this number of nodes.
|
||||
# This number impacts single query execution time. If it is more than 1000, neo4j may complain
|
||||
# about running out of heap memory space (java...).
|
||||
#
|
||||
numberOfNodesToAddPerStep = 500
|
||||
|
||||
def markNodes(tx, nodes):
|
||||
query = ''
|
||||
|
||||
for i in range(len(nodes)):
|
||||
n = nodes[i]
|
||||
query += 'MATCH (n {name: "' + n + '"}) SET n.owned = TRUE '
|
||||
if i < len(nodes) - 1: query += 'UNION '
|
||||
|
||||
tx.run(query)
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 2:
|
||||
print('''
|
||||
Takes a file containing node names on input and marks them as Owned in specified neo4j database.
|
||||
|
||||
Usage: ./markOwnedNodesInNeo4j.py <nodes-file>
|
||||
''')
|
||||
return False
|
||||
|
||||
nodesFile = argv[1]
|
||||
programStart = time.time()
|
||||
|
||||
if not os.path.isfile(nodesFile):
|
||||
print(f'[!] Input file containing nodes does not exist: "{nodesFile}"!')
|
||||
return False
|
||||
|
||||
nodes = []
|
||||
with open(nodesFile) as f: nodes = [x.strip() for x in f.readlines()]
|
||||
|
||||
try:
|
||||
driver = GraphDatabase.driver(
|
||||
f"bolt://{NEO4J_CONNECTION_DETAILS['Host']}:{NEO4J_CONNECTION_DETAILS['Port']}",
|
||||
auth = (NEO4J_CONNECTION_DETAILS['User'], NEO4J_CONNECTION_DETAILS['Pass']),
|
||||
encrypted = False,
|
||||
connection_timeout = 10,
|
||||
max_retry_time = 5,
|
||||
keep_alive = True
|
||||
)
|
||||
except Exception as e:
|
||||
print(f'[-] Could not connect to the neo4j database. Reason: {str(e)}')
|
||||
return False
|
||||
|
||||
print('[.] Connected to neo4j instance.')
|
||||
|
||||
if len(nodes) >= 200:
|
||||
print('[*] Warning: Working with a large number of nodes may be time-consuming in large databases.')
|
||||
print('\te.g. setting 1000 nodes as owned can take up to 10 minutes easily.')
|
||||
print()
|
||||
|
||||
finishEta = 0.0
|
||||
totalTime = 0.0
|
||||
runs = 0
|
||||
|
||||
try:
|
||||
with driver.session() as session:
|
||||
for a in range(0, len(nodes), numberOfNodesToAddPerStep):
|
||||
b = a + min(numberOfNodesToAddPerStep, len(nodes) - a)
|
||||
print(f'[.] Marking nodes ({a}..{b}) ...')
|
||||
start = time.time()
|
||||
session.write_transaction(markNodes, nodes[a:b])
|
||||
stop = time.time()
|
||||
|
||||
totalTime += (stop - start)
|
||||
runs += 1
|
||||
|
||||
finishEta = ((len(nodes) / numberOfNodesToAddPerStep) - runs) * (totalTime / float(runs))
|
||||
if finishEta < 0: finishEta = 0
|
||||
|
||||
print(f'[+] Marked {b-a} nodes in {stop - start:.3f} seconds. Finish ETA: in {finishEta:.3f} seconds.')
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('[.] User interruption.')
|
||||
driver.close()
|
||||
return False
|
||||
|
||||
driver.close()
|
||||
programStop = time.time()
|
||||
print(f'\n[+] Nodes marked as owned successfully in {programStop - programStart:.3f} seconds.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
Loading…
Reference in New Issue
Block a user