Snaffler 快速上手:它如何在 Windows 域里快速揪出敏感文件
【免费下载链接】Snafflera tool for pentesters to help find delicious candy, by @l0ss and @Sh3r4 ( Twitter: @/mikeloss and @/sh3r4_hax )项目地址: https://gitcode.com/gh_mirrors/sn/Snaffler
Snaffler 是一款 C# 编写的网络共享扫描与敏感文件搜寻工具,面向渗透测试和蓝队红队场景:拿到一台域内机器的立足点之后,它替你在上千台主机、数百万个文件里把密码文件、私钥、数据库凭据这些"candy"(作者的叫法)挑出来。本文不讲它是什么,讲它怎么不浪费时间——三级流水线的分工逻辑和规则引擎的成本取舍,读完你能直接跑起来,也能改规则。
域扫描的真正难题:资源花在哪里
先算笔账。一个中型域有几百到几千台计算机,每台若干可读共享,每个共享下成百上千个文件。全量逐个读内容,核显都不够烧。Snaffler 的整个架构围绕一个决策展开:每一步只把最可能出活的东西放进下一步。
执行入口在SnaffCon.cs:共享发现、目录遍历、文件扫描三个阶段各自挂在独立调度器上,互不阻塞。共享枚举完一台主机,产出的目录任务立刻进队列开跑;某个目录里翻出的文件,同样直接喂给文件扫描线程。三个队列各有限高上限,下游消化不动时上游自然被反压,内存占用因此可以控住。
第一道闸门:共享枚举之后先筛再扫
入口组件 ShareFinder 用 Windows NetAPI 的NetShareEnum按主机拉共享清单,源码在 SnaffCore/ShareFind/ShareFinder.cs。拿到清单后有三层过滤:
- 硬编码跳过
IPC$和PRINT$。这类共享要么是纯连接通道要么是打印机队列,不含文件数据,扫了只会徒增 SMB 流量; - 分类器规则逐个过共享名,命中的丢弃规则直接踢出局,默认共享规则在 Snaffler/SnaffRules/DefaultRules/ShareRules/,另有一条保留规则专门留
$结尾的默认共享(C$、ADMIN$ 这类)和 SCCM 的 ContentLib 共享——后者往往是整域文件内容的金矿; - 可写性探测:打不开的就标红不深入,能读的才派目录遍历任务。
两个特判值得单独说。SYSVOL 和 NETLOGON 是域控之间互相复制的同一份内容,Snaffler 只扫碰到的第一份副本,再遇到同名共享直接跳过。DFS(Distributed File System,分布式文件系统命名空间)场景更极端:同一份内容可以挂在几十台主机的不同共享后面。开 DFS 发现后,Snaffler 先从 AD 里把命名空间路径拉出来,之后凡是能在 DFS 里命中的\\主机\共享直连路径就替换成 DFS UNC——每个命名空间只扫一次,重复的直连副本全部作废。
目录怎么翻:递归、排除与特判
目录遍历的核心就是一个递归函数,SnaffCore/TreeWalk/TreeWalker.cs 里不到十行:
string[] files = Directory.GetFiles(currentDir); foreach (string file in files) FileTaskScheduler.New(() => FileScanner.ScanFile(file)); string[] subDirs = Directory.GetDirectories(currentDir); foreach (string dirStr in subDirs) { // 先过 DirClassifiers,命中 Discard 的目录直接不派任务 TreeTaskScheduler.New(() => WalkTree(dirStr)); }每个文件立刻扔给文件扫描线程池,每个子目录也各自派一个新遍历任务——递归深度由调度器并行度决定,不是单线程一层层往下钻。
系统目录靠 Snaffler/SnaffRules/DefaultRules/PathRules/ 下的目录规则排除,典型的一条按路径"包含"匹配,把\\windows\\system32、\\winsxs、\\AppData\\Local\\Microsoft这些纯噪声目录整体剪掉:
RuleName = "DiscardWinSystemDirs" MatchAction = "Discard" MatchLocation = "FilePath" WordListType = "Contains" WordList = ["\\winsxs", "\\syswow64", "\\system32", ...]命中即剪枝,子树一个字节都不读。另有两处硬编码特判:SCCM ContentLib 共享里的文件是哈希命名的.INI指针文件,WalkSccmTree会读指针、换算出真实文件路径再送扫描;共享根不可读、路径超长这类异常全部吞掉记 trace,不让单个坏点拖死整棵树的遍历。
文件凭什么被判为敏感:分类器链与四种动作
这是 Snaffler 的灵魂,也是"敏感文件搜寻"四个字落到实处的一层。每个文件按顺序过一遍文件分类器链,每条规则判定两个东西:拿什么比(MatchLocation:扩展名 / 文件名 / 完整路径 / 文件大小)和比中之后干什么(MatchAction)。
四种动作各有分工:
| 动作 | 行为 | 典型场景 |
|---|---|---|
| Discard | 文件出局,不再看后续规则 | 大体积假阳性目录、已知无关扩展名 |
| Snaffle | 命中即输出结果 | id_rsa、.kdbx、NTDS.DIT |
| Relay | 转交指定的下游规则再判一次 | 先认扩展名,再搜内容 |
| CheckForKeys | 解析证书,确认是否带私钥 | .pfx、.der、.pem |
匹配方式共五种:Exact、Contains、EndsWith、StartsWith、Regex,全部写在 TOML 规则文件里,字段就是上面表里那些。比如一条 SSH 私钥规则,全部家当如下:
RuleName = "KeepSSHKeysByFileExtension" MatchAction = "Snaffle" MatchLocation = "FileExtension" WordListType = "Exact" WordList = ["\\.ppk"]注意 Relay 的接力方式:一条规则命中后返回 false,链继续往下走;只有 Discard 命中(返回 true)才会短路整条链。Snaffle 命中后还会先过一轮 PostMatch 校验——比如文件名命中了"password"但内容里其实没有凭据的模式,可以在最后一关剔除,降低误报。
证书特判:CheckForKeys 在干什么
普通文本文件靠正则就够,证书文件得真解析。x509Match会加载 X.509 对象再判断:能不带密码直接解析,说明私钥就躺在里面,直接标HasPrivateKey+NoPasswordRequired;需要密码时先试空密码和文件名,破了标PasswordCracked,破不了标HasPassword并提示去附近目录翻.txt。一枚免密码且带私钥的证书,红队眼里就是半张域管通行证。
规则链的成本学
链的排列不是随意的。扩展名、文件名比较是纳秒级操作,正则扫全文是毫秒级且吃内存。所以默认规则集把"廉价"判别放在链前段——先按扩展名、文件名把绝大多数文件过滤掉;只有 Relay 转交进来的幸存者才会被打开读内容,且内容搜索只针对配置上限(默认约 1MB)以内的文件。缺了这层设计,对几百万文件全量跑正则,扫描时间会涨一个数量级。
三个调度器:并行的秘密
Snaffler 用 ShareTaskScheduler、TreeTaskScheduler、FileTaskScheduler 三个独立调度器对应三级流水线,各自配线程数和队列上限,参考配置在 example-config.toml。
线程配比有明确逻辑:文件扫描线程(示例里 50)远多于共享发现(30)和目录遍历(20)。因为任务量级完全不同——一个共享任务产出几十个目录任务,一个目录任务又能产出上千个文件任务,文件队列清不快,整条流水线会在反压里堵死。
动态再平衡是它不太起眼但实用的设计:主循环每分钟检查一次各队列水位。共享发现全部完成时,它的并发额度直接划给文件调度器;文件队列快见底就向目录调度器要并发,堆满了就还回去。跑大域时日志里会周期性看到 "rebalancing workload",那就是它在干活。
规则怎么写:TOML 与默认规则集
规则全部是 TOML,一条[[ClassifierRules]]就是一张表:
| 字段 | 取值示例 | 作用 |
|---|---|---|
| EnumerationScope | FileEnumeration / DirectoryEnumeration | 这条规则管哪一层 |
| MatchLocation | FileExtension / FileName / FilePath | 拿哪个属性比 |
| WordListType | Exact / Contains / EndsWith / StartsWith / Regex | 怎么比 |
| MatchAction | Discard / Snaffle / Relay / CheckForKeys | 比中了怎么办 |
| Triage | Black / Red / Green | 输出的严重度分级 |
默认规则按用途分层放在 Snaffler/SnaffRules/DefaultRules/:FileRules 按语言和业务场景分组(代码里的数据库连接串、PowerShell 凭据、各类配置文件),PathRules 管目录剪枝,ShareRules 管共享层,PostMatchRules 管命中后的终审。想换自己的规则集,指定一个目录即可,Snaffler 用整个目录替换默认集而不是叠加——所以自定义目录里得自己保证覆盖面。
上手前必调的三个参数
参数不用全记,先调这三个:
- 目标范围:
-f开 DFS 发现(域内跑基本必开,省掉大量重复副本扫描);-i切本地扫描模式,不对外发起共享枚举; - 规模阀门:
-l限制参与内容搜索的文件大小上限,域里大量 GB 级备份文件读不起也没必要读;-b设兴趣级别,只看你当下心脏能承受的结果量; - 规则与输出:
-p指到自定义规则集目录;-j调匹配上下文字节数,看够判读即可;-m打开后 Snaffler 会把命中文件按原相对路径复制一份到本地,证据留存一步到位。
最后两句话的 OPSEC 提醒:默认的全域扫描会产生大量 SMB 流量,SIEM 基本都会告警,实战时缩小目标集、控制节奏;本地扫描模式(-i)不走网络共享枚举,流量特征最弱,优先用。
【免费下载链接】Snafflera tool for pentesters to help find delicious candy, by @l0ss and @Sh3r4 ( Twitter: @/mikeloss and @/sh3r4_hax )项目地址: https://gitcode.com/gh_mirrors/sn/Snaffler
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考