Conversation
max.py
Outdated
| petmax = switch.add_parser("pet-max",help="Pet max, hes a good boy (pet me again, I say different things)") | ||
|
|
||
| # GETINFO function parameters | ||
| adcs = switch.add_parser("adcs",help="adcs") |
There was a problem hiding this comment.
This is instantiated but never used. Use it and stay in line with the current code structure. Use adcs as a new module and structure it the same as get-info rather than having them combined
max.py
Outdated
| getinfo_switch.add_argument("--owned-paths",dest="ownedpaths",default=False,action="store_true",help="Return all paths from owned objects to HVTs") | ||
| getinfo_switch.add_argument("--owned-admins", dest="ownedadmins",default=False,action="store_true",help="Return all computers owned users are admins to") | ||
|
|
||
| getinfo_switch.add_argument("--adcs", dest="adcs", default=False, action="store_true", help="Perform AD CS ESC attack detection queries") |
There was a problem hiding this comment.
Similar to the comment above, separate get-info and adcs modules. Made the adcs module more granular with specific flags to be able to select one specific attack path required
max.py
Outdated
| } | ||
|
|
||
|
|
||
| if args.adcs: |
There was a problem hiding this comment.
Put all these in a new function/module similar to get info. Provide the ability for the user to select just one query rather than requiring all of them to be run
There was a problem hiding this comment.
it can literally be as simple as --esc1 --esc2 --esc3
max.py
Outdated
| cols = [] | ||
| data_format = "row" | ||
|
|
||
| if args.adcs: |
There was a problem hiding this comment.
As I said above, provide the ability to make this more granular. Provide an --all flag if you want to be able to pull everything at once
max.py
Outdated
| data_format = "row" | ||
|
|
||
| if args.adcs: | ||
| for query_name, query_info in queries.items(): |
There was a problem hiding this comment.
In general the coding here is very inefficient. You add your ADCS queries to the full list, then just iterate through the full list and identify the ADCS related ones. Again, speaks to separating it out to a new module. The arg parser is a mutually exclusive (mutex) grouping so if you select ADCS then you can't get any other datapoints, so there's no reason to add to the full queries then parse them back out
max.py
Outdated
| }, | ||
| { | ||
| 'query' : "match p = (k:Group)<-[:MemberOf*1..]-(m) where k.highvalue = true WITH [ n in nodes(p) WHERE n:User] as ulist UNWIND (ulist) as u RETURN DISTINCT u.enabled,u.ntds_uname,u.password,u.nt_hash", | ||
| 'query' : "MATCH p=(u:User {cracked:true})-[r:MemberOf*1..]->(g:Group {highvalue:true}) RETURN DISTINCT u.enabled,u.ntds_uname,u.password,u.nt_hash", |
There was a problem hiding this comment.
I like these additions, but please separate them out into a new PR if desired. Too much going on in this PR
max.py
Outdated
| }, | ||
| "unsupos" : { | ||
| "query" : "MATCH (c:Computer) WHERE toLower(c.operatingsystem) =~ '.*(2000|2003|2008|xp|vista| 7 |me).*' RETURN c.name,c.operatingsystem", | ||
| "query" : "MATCH (c:Computer) WHERE c.operatingsystem =~ '.*(2000|2003|2008|xp|vista| 7 |me).*' RETURN c.name,c.operatingsystem", |
There was a problem hiding this comment.
this needs to be lowered, undo this
this works now :)