news 2026/8/27 16:21:37

Snaffler 快速上手:它如何在 Windows 域里快速揪出敏感文件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Snaffler 快速上手:它如何在 Windows 域里快速揪出敏感文件

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]]就是一张表:

字段取值示例作用
EnumerationScopeFileEnumeration / DirectoryEnumeration这条规则管哪一层
MatchLocationFileExtension / FileName / FilePath拿哪个属性比
WordListTypeExact / Contains / EndsWith / StartsWith / Regex怎么比
MatchActionDiscard / Snaffle / Relay / CheckForKeys比中了怎么办
TriageBlack / 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!