
Python-инструмент для простого сопоставления прав доступа к сетевым ресурсам с OpenGraphs BloodHound
Инструмент для отображения прав доступа к сетевым ресурсам в BloodHound OpenGraph.
Читайте сопутствующую статью в блоге: https://specterops.io/blog/2025/10/30/sharehound-an-opengraph-collector-for-network-shares/
В этом репозитории содержатся две реализации ShareHound. Они преследуют одну и ту же цель — генерацию BloodHound OpenGraph JSON из разрешений SMB-ресурсов, — но отличаются языком, средой выполнения и набором функций. Выбирайте ту, которая подходит под ваш рабочий процесс.
| Реализация | Путь | Автор | Для чего подходит |
|---|---|---|---|
| Python | Python/ | Remi Gascou (@podalirius_) @ SpecterOps | Эталонная реализация; легко расширяется и скриптуется |
| Go | Go/ | Javier Azofra @ Siemens Healthineers | Крупномасштабное сканирование (60 000+ хостов), контрольные точки, статические бинарники |
В каждом подкаталоге есть собственный README с полной информацией по установке, использованию и настройке:
--effective-access-only для значительного уменьшения размера графа в крупных средахПосле импорта OpenGraph в BloodHound эти запросы покрывают наиболее частые потребности. Больше примеров — в README каждой реализации.
MATCH (p)-[r]->(s:NetworkShareSMB)
WHERE (p)-[:CanDelete]->(s)
AND (p)-[:CanDsControlAccess]->(s)
AND (p)-[:CanDsCreateChild]->(s)
AND (p)-[:CanDsDeleteChild]->(s)
AND (p)-[:CanDsDeleteTree]->(s)
AND (p)-[:CanDsListContents]->(s)
AND (p)-[:CanDsListObject]->(s)
AND (p)-[:CanDsReadProperty]->(s)
AND (p)-[:CanDsWriteExtendedProperties]->(s)
AND (p)-[:CanDsWriteProperty]->(s)
AND (p)-[:CanReadControl]->(s)
AND (p)-[:CanWriteDacl]->(s)
AND (p)-[:CanWriteOwner]->(s)
RETURN p,r,s
MATCH x=(p)-[r:CanWriteDacl|CanWriteOwner|CanDsWriteProperty|CanDsWriteExtendedProperties]->(s:NetworkShareSMB)
RETURN x
MATCH p=(h:NetworkShareHost)-[:HasNetworkShare]->(s:NetworkShareSMB)-[:Contains*0..]->(f:File)
WHERE toLower(f.name) = toLower("flag.txt")
RETURN p
MATCH p=(h:NetworkShareHost)-[:HasNetworkShare]->(s:NetworkShareSMB)-[:Contains*0..]->(f:File)
WHERE toLower(f.extension) = toLower(".vmdk")
RETURN p
Рёбра CanEffectiveRead / CanEffectiveWrite / CanEffectiveExecute формируются
реализацией на Go, когда один и тот же SID имеет соответствующие права как на уровне ресурса, так и на уровне
NTFS — то есть реальный доступ, предоставляемый по SMB.
MATCH p=(principal)-[:CanEffectiveRead]->(f:File)
RETURN p
Принимаются pull request'ы для обеих реализаций. Откройте issue, если хотите сначала обсудить новую функцию.