https://github.com/fox-it/aclpwn.py
Aclpwn.py 是一种与 BloodHound 交互以识别和利用基于 ACL 的特权升级路径的工具。它需要一个起点和终点,并将使用 Neo4j 寻路算法找到最有效的基于 ACL 的权限升级路径。
程序的入口在aclpwn目录下的__init__.py
文件中的main()
函数。
程序开始使用Python标准库中的argparse模块,解析命令行参数。
创建ArgumentParser对象,并设置相关的参数说明和默认值。使用parse_args()方法解析命令行参数,并将结果存储在args变量中。将args变量转换为字典形式,并将其存储在argsdict变量中,以便后续使用。
parser \= argparse.ArgumentParser(description\='Exploit ACL escalation paths via BloodHound')
parser.\_optionals.title \= "Main options"
parser.\_positionals.title \= "Required options"
#Main parameters
maingroup \= parser.add\_argument\_group("aclpwn options")
maingroup.add\_argument("-f","--from", type\=str, metavar\='SOURCE', help\="Source object to start the path (usually a user). Example: user@domain.local")
······略
validtypes \= \['User', 'Group', 'Domain', 'Computer'\]
args \= parser.parse\_args()
\# Since we deal with some reserved keywords, we use a dictionary too
argsdict \= vars(args)
添加不同的命令行选项:
接着,55-91行对参数进行检查和处理:
dry_run
参数未指定,则检查 --domain 和 --server 是否指定了有效值,以及是否已提供源用户的密码。接着初始化数据库连接
database.init\_driver(args.database, args.database\_user, args.database\_password)
接着进行路径查找,如果Dijkstra参数设定了,则使用Dijkstra算法路径查找。其中根据输入参数的不同,分别采用 REST API 或 Cypher 查询来进行 Dijkstra 算法路径查找。在使用 REST API 查询时,首先需要获取节点的 ID,然后使用 dijkstra_find() 函数来进行查找。查询结果将经过校验,去除不支持的操作后输出可行的路径供选择。
如果使用的是除了dijkstra和dijkstra-cypher之外的算法,会调用get_path函数,从源对象到目标对象获取路径信息。
通过循环处理所有找到的路径,测试每个路径上是否存在不受支持的操作,并打印出路径成本。
找到最便捷的路径,并存储它的数据以供后续使用。如果没有找到路径,将打印错误消息。如果找到了多条路径,则允许用户选择使用哪条路径。如果只找到了一条路径,则直接使用该路径。
最后使用了 exploitpath 变量中的路径,使用 exploitation.walk_path 函数进行路径的遍历,并尝试利用此路径进行攻击,获取了攻击后的操作队列和状态信息。
exploitdata \= exploitation.walk\_path(exploitpath, args, None, args.dry\_run)
task\_queue, state \= exploitdata
然后根据是否使用了 --dry-run 参数进行实际的操作或者只是模拟操作,并在运行操作过程中记录操作的执行情况,最后如果操作成功,就输出一条消息表明操作已经完成,并且保存操作的恢复数据。
exploitation.run\_tasks(task\_queue, args.dry\_run)
state.save\_restore\_data()
utils库主要用于提供通用的实用函数,帮助其他部分更轻松地处理数据。
getnodemap(nodes):
将节点列表转换为一个以id为键、以节点对象为值的映射字典。 print_path(record):
打印查询Neo4j数据库时返回的path对象,格式为“(start_node_name)-[relationship_type]->(end_node_name)”。 build_path(record):
将查询Neo4j数据库时返回的path对象构建成一个元组列表,元组中第一个元素为relationship对象,第二个元素为end node对象。 build_rest_path(nodes, rels):
将REST API返回的节点列表和关系列表构建成一个元组列表,元组中第一个元素为relationship对象,第二个元素为end node对象。 print_rest_path(nodes, rels):
打印REST API返回的节点列表和关系列表,格式为“(start_node_name)-[relationship_type]->(end_node_name)”。 get_modify_length(record):
返回一个查询Neo4j数据库时返回的path对象中,具有“isacl”属性的节点数量。 append_domain(name, otype, domain):
将指定类型的名称添加到指定的域名后面,如果该名称已经包含域名,则返回该名称。 prompt_path(pathlen):
用于提示用户选择一个路径。 domain2ldap(domain):
将域名转换为LDAP格式。 ldap2domain(ldap):
将LDAP格式的域名转换为正常格式的域名。 get_sam_name(fullname):
从BloodHound格式的名称中获取SAM名称(用户、组、计算机)。 get_domain(fullname):
从BloodHound格式的名称中获取域名(用户、组、计算机)。
这个库比较基础,不进行深入分析。
这个库主要用来连接Neo4j数据库的,实现了初始化连接、关闭连接、预处理数据等操作。其中还有一个detect_db_config()函数用于检测Bloodhound配置文件,因此可以在不同的操作系统下连接到不同的数据库。
这个库同样比较基础,不进行深入分析。
这个库用来查找Neo4j图数据库中两个节点之间的最短路径。它提供了两个函数:dijkstra_find()和dijkstra_find_cypher(),它们使用不同的方法来查找路径。其中,dijkstra_find()使用REST API,
而dijkstra_find_cypher()使用Cypher查询语言。
它还提供了一些其他的查询方法,例如get_path(),可以查询所有的最短路径或所有简单路径。
resolve_dijkstra_path()函数用于解析Dijkstra算法的结果。
Dijkstra算法: Dijkstra算法来寻找最短路径,该算法基于贪心策略和动态规划思想。它使用了成本映射(即costmap),其中关系类型的成本用于确定路径的总成本。Dijkstra算法使用BFS(广度优先搜索)来查找最短路径,首先将起始节点添加到队列中,然后将其弹出并检查其所有出边。如果边指向未访问的节点,则将其添加到队列中,并更新到该节点的距离。此过程将一直持续,直到队列为空或找到目标节点。
resolve_rest_path()函数用于解析REST API返回的路径。
这个模块是对域的ACL进行安全行测试的核心部分。
100-349行是实现LDAP(轻量目录访问协议)连接并操作Active Directory(AD)的Python代码。LDAP是一种轻量级的目录访问协议,用于在分布式环境中查找和验证用户信息。Active Directory是一种用于管理计算机网络上的用户、计算机、组织等对象的目录服务。
这些操作通常用于在Windows Active Directory环境中进行提权。其中涉及了对安全描述符(Security Descriptor)的修改,以及对LDAP目录树中对象(如用户、组)的添加、修改和查询。通过这些操作,攻击者可以获取到更高的权限,例如域管理员权限,甚至是企业管理员权限,从而控制整个AD域。
主要包括如下函数:
351-382行这段代码定义了一个函数test_path,其作用是检查传入的路径是否包含了不支持的操作。该函数遍历了路径中的每一个关系,如果发现关系类型不被支持,则输出错误信息并返回False,否则返回True。
具体来说,对于关系类型为MemberOf的关系,函数直接跳过。对于关系类型为AddMember的关系,如果其终点是Group类型的节点,则也直接跳过,否则输出错误信息并返回False。对于关系类型为DCSync和GetChangesAll的关系,函数同样直接跳过。对于关系类型为WriteDacl、GenericAll、GenericWrite和Owns的关系,如果其终点是Group类型或Domain类型的节点,则也直接跳过,否则输出错误信息并返回False。对于关系类型为WriteOwner的关系,如果其终点是Group类型或Domain类型的节点,则也直接跳过,否则输出错误信息并返回False。对于所有其他类型的关系,函数同样输出错误信息并返回False。
这个函数的作用是执行操作路径中定义的操作。操作路径指定了在哪些节点执行哪些操作。该函数根据节点上的标签和操作类型,将每个操作分配给相应的函数,并将操作作为任务添加到任务队列中,最后在状态中记录对目录对象所做的更改。如果dry_run设置为True,则不执行任何更改操作。
这个程序是一个用于自动化执行某些恶意操作的Python脚本。它通过在Windows Active Directory中执行一系列特权升级操作来获取域管理员权限。它的工作原理是使用BloodHound生成的关系路径(即在域内访问某些对象需要执行的一系列操作)来自动化执行特权升级操作。
9 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!