Skip to content

设计

前言

(本文中提到的目录fuzz, 目录爆破, url爆破为同一个意思)

spray的设计不需要像gogo那样需要考虑非常多的取舍问题. spray的目标只有一个, 解决在目录fuzz领域的一切问题.

以chainreactors一贯的风格, spray的参数设计一样的会非常复杂, 但实际上很多参数并非为人类准备, 而是为了成为更大框架的一部分. 大多数人使用spray只需要关注一些最基本的操作即可.

目录爆破并非只是批量发包判断状态码, 这个领域还包括了对隐藏目录的发现, 字典的自动化构造, 智能判断有效目录, 爬虫与指纹识别, 与WAF的对抗等等

设计

spray的出发点想要自动化的分辨有效目录与无效目录, 减少对数据进行手动二次分析处理.

开源世界

市面上有很多目录爆破工具或者类似的httpfuzz工具.

  • dirsearch python开发的有性能瓶颈, 有一定的智能判断逻辑, 但还不够智能
  • ffuf 目前http fuzz领域的佼佼者, 但缺少对目录爆破的优化, 数据绝大部分情况需要二次处理才可以使用. 与spray定位有区别.
  • feroxbuster 目录爆破领域的佼佼者, 与spray有着类似的定位. 无法批量爆破, 同样不够智能, 在字典处理上不够自由.
  • gobuster 更接近go版本的dirsearch. 性能上比dirsearch更好, 能做的事情与dirsearch差不多
  • kiterunner 原本我很看好的项目, 一个结合了目录爆破与apifuzz的工具, 但后续没更新, 有不少bug.
  • httpx 它的设计上是为了从http协议中提取信息, 也有人用它来进行目录爆破, 效果上来说并不好, 但它对数据的一些处理方式值得学习

spray有从上面的这几个工具中学到一些东西, 也深入的分析了这些工具的优缺点, 并进行重新设计. 但请注意spray并非是对上面这些工具的重新造轮子, spray解决了不少这些工具没有考虑过的问题. 会在后续一一介绍.

还有一些更古早, 已经停止维护的项目不再介绍. 也有一些在某个细微领域有突破的工具, 将会在后续介绍.

spray的总体设计

  • 智能化, 目录爆破中99.9%的尝试都是无效的, 不能让人把精力放在这些无效的数据处理上. 需要找到一个通用的解决方案智能去除无效设计
  • 适应性, 每个目标都有着自己的规则, 根据目标去获取信息, 构造字典是智能化的基石. 尽可能的做到根据每个目标构造不同的字典.
  • 自动化与分布式, spray面对的场景包括了大规模高并发的目录探测, 这样的场景并不太适合人工使用spray, 为此spray设计了一些方式来适配这样的场景.
  • 辅助性, spary并不能做到发现漏洞, 但它将尽可能的帮助人类去分析相关的信息.

spray基于目录爆破实现, 但目录爆破并不是spray的目标.

spray最终的目标是对单个站点深入的信息分析与提取, 去辅助红队人员进一步的渗透攻击.

与kindred的联动

todo

智能化

背景

绝大多数目录爆破工具过度简化了现实世界中可能遇到的场景, 导致只能在理想状况下实现过滤无效页面. 当面对复杂的真实场景, 他们的这种方式既会导致误报, 又会导致漏报. 而spray要做的是尽可能减少误报与漏报.

这里指的智能化, 实际上是添加复杂的规则, 代替人类进行绝大多数重复无效的劳动. 主要是将我们对目录爆破这个领域的经验转为代码.

spray的智能判断是我们认为的最佳解决方案, 但不一定是实际上的最佳解决方案. 有可能因为智能判断反而导致了一些漏判误判. 也为此提供了多种补救与缓解方案. 我们也在不断改进我们的逻辑并不断将新的经验沉淀到spray的代码中.

在feroxbuster与dirsearch中, 对有效目录的判断主要通过状态码与body length. 这样的简单判断在很多场景下是不起作用的. 需要通过手动配置麻烦的filter, 通过人工介入的二次判断. 这种解决方案在单个目标上能通过几次交互修改找到一个特定的配置解决过滤的问题, 操作起来较为麻烦.

如果我们想一次性对多个目标进行扫描, dirsearch与feroxbuster的手动filter逻辑将会失效, 不同网站之间完全不能使用同一个filter策略. 并且feroxbuster采用多进程的方式进行多目标并发, 几乎破坏了它原本非常优雅直观的输出界面. 总而言之, 开源的工具在filter上都不够智能.

而ffuf与httpx更是只用来获取原始数据, 几乎100%的需要人工介入的方式进行二次数据处理. 它们虽然也提供了各种的filter之类的功能, 但在实际使用场景上的定位更接近发包器.

spray采用的方式是, 获取两个baseline(index页面与随机页面)的方式, 动态的根据每个网站自身建立基准值的模型. 然后在后续处理中, 都会根据这两个基准值进行判断. 基本上解决了90%的场景.

当然现实世界中不会如此简单, 只需要两个baseline不可能解决所有的问题, 为了解决后面的10%的问题以及为了性能上的优化, spray并设计了一个三段式的过滤逻辑, 每个阶段中都有大量的判断逻辑进行尽可能的智能判断. 具体的逻辑可以文档中的细节看到.

当然三个三段式的逻辑加上baseline解决了99%的问题, 但为了最后的1%, 设计的spray真正最复杂功能.

这些功能包括

  1. 通过模糊hash, 对网页相似度进行对比
  2. 通过模糊状态码进行更进一步的动态baseline. 即模糊状态码列表中的结果会与相同状态的baseline进行对比
  3. 手动维护的智能过滤状态码列表, 一定程度调整三段式逻辑
  4. --match--filter的表达式语言进行手动的规则配置

通过这几个对三段式智能过滤的补充, 我们才确定spray有了应对100%场景的能力 (欢迎找一些奇葩网站给我出难题^ ^).

当使用到3和4这两个高级功能时, 实际上spray就遇到了和feroxbuster与dirsearch类似的困境, 需要一定程度的人工手动配置了. 当然也不是没有解决办法, 只不过解决方案在spray之外, 需要引入更加庞大的分析引擎去实现. 这也是spray作为工件的意义所在.

而通过baseline, 三段式过滤, 以及补充功能的1与2. 在非人工干预的情况下, spray能覆盖到99.9%的场景. spray已经做到了对同类工具的跨越式突破.

无效的200页面

这个相对比较好理解, 例如实际上的404页面返回200状态码. 例如泛解析的目录, 所有页面都返回了200状态码.

是在实战中比较多见的情况, 可能针对单一情况其他工具能进行手动配置的过滤, 但是如果一个站有好几种不同的200状态码, 过滤起来还是比较麻烦的.

在单一200页面的情况下, 就是200页面是动态的, spray也能完美的进行过滤. 但是对于多个泛解析目录同时存在, 且返回的页面都不同. spray也只能通过手动配置去解决. 相对比其他工具的手足无措已经有了很大进步.

有效的404页面

这个情况知道的人可能少一些. 其实也和工具有关, 使用市面上的所有目录爆破工具去fuzz. 遇到404状态码, 都会选择过滤, 使用者根本无法判断有没有可能存在有效的404页面. 在真实世界中, 这样的情况在现代化的网站中并不少见.

举个例子, 某个网站给/api配置了泛解析, 但除非访问到/api/getUser是返回200, 其他页面均为404.

这种情况, 这个/api的路由实际上是有效的, 可以构造字典进行fuzz, 或者寻找api文档进行深度测试.

大部分工具只有/api这个路由被配置为403或者200的时候才有可能发现. 但在真实世界中, api通常会被重写其所有的输出, 以保证统一格式为json之类的结构化数据. 状态码不再是http状态码, 而是json中的一个字段.

还有一种情况, 在反代的场景中. 随机目录的404页面是由反代服务器返回的. 但当命中的反代的配置, 流量打到某个业务上时, 如果业务的这个目录恰巧返回的时404, 那么这个404页面也是有效的, 而且通常是高价值的.

刚才也提到了, 之所以这种情况少见不是因为它真的少见, 而是所有工具都会忽略这种情况.

在spray中, 404页面将被认为是需要模糊对比的页面. 如果发现的404页面与random baseline中的页面完全不同, 这个时候就会将其作为有效结果输出.

403/500/503页面的细节

这三个状态码是很常见的用来处理一些未授权/错误页面的状态码. 它们不同于404页面的只可能由中间件与业务提供, 这三个状态码可能是中间件|业务|框架|CDN|WAF. 造成的原因也多种多样, 可能是触发了WAF告警, 可能是中间件的统一配置, 可能是业务的错误处理页面, 可能是Cookie权限不够, 可能是框架的一些配置.

很多时候会发现*.do或者/cgi-bin/或者*/etc/password/*这样的路由都会发现通配符的这个页面. 通配符不再是单一的目录之后的场景, 而是可能在任意位置出现.

面对这种情况, 其他工具能做的也只有手动配置. 如果同时出现了上述多种情况, 手动配置就无能为力了, 只能首尾不顾, 或者选择使用ffuf配上一个脚本手动处理数据.

而spray实际上能做的也不多, 如果这些特例恰巧对应的不同的状态码, spray是能通过基于状态码的动态baseline去智能过滤的. 但如果这个站的所有特例都是403状态码. spray也只能手动编写一个复杂的表达式去处理. 好在spray也不是无能为力.

隐患

对spray来说, 智能过滤是最具代表性的智能化. 实际上, spray在很多其他细节上也有类似的智能设计. 但这是存在隐患的, 过度的智能导致某些东西被隐含了, 除非是这个领域的专家, 否则可能用了几年都理解不了其中的细节.

性能

背景

这个领域的性能不能通过一味的提高并发解决. 甚至可以说, 只提高并发数, 反而会导致性能降低. 现代的这类工具通过keep-alive解决了一部分问题, 但做法未免有些粗糙, 并没有最大程度的释放性能. 而且性能也是由多方面决定, 需要在不同的场景下选择不同的方案, 最终达成极限但又安全的性能释放.

目录爆破领域的唯一性能指标就是有效并发数量. 也就是一定时间内能交互多少包.

但这个指标实际上受到client, http协议, 目标状态影响. 要将其优化到极限, 需要从多方面入手.

client

这里的client指的是发包的工具, 在python中, 通常是urllib或request两个库. 在go中, 大多数工具选择了net/http.

而spray则是同时使用了net/httpfasthttp, 原本计划使用全部的fasthttp, 但这个库在host爆破时存在一些问题, 所以代码上封装了一层, 去自动的选择client.

当然语言本身也会带来一定程度的影响, go的并发调度性能比python强上一个数量级.

选择fasthttp原因是, fasthttp通过各种手段优化其代码性能. 在低负载场景, 可能感受不到, 因为这时候主要的瓶颈是目标的接受能力, 但当开始多目标批量爆破时, 这个影响会越来越大. 最终在本地的理论极限测试下, fasthttp会比net/http有2-3倍的性能提升. 这种几乎翻倍的性能最终让我接受了一些fasthttp的坑点, 使用了fasthttp作为默认的client.

使用fasthttp坑点

它复用了几乎所有的bytes buf, 因此releaseResponse之后, 可能buf会被复用, 导致buf的数据被覆盖. 这个bug我花费了好几天时间才定位到. 最新版本已经不存在这个bug了

HTTP

在大多数场景下, http协议对性能的影响最关键的就是keep-alive, 这个功能需要http1.1之后才支持. 好在绝大多数服务现在都已经支持了. 这也是spray性能提升最大因素.

keep-alive在http1.0中是需要手动打开, 在http1.1中是自动打开, 在http2中则变成了多路复用, 性能有数量级上的提升.

对于代码来说, keep-alive的影响就非常大了. 在python中, 需要手动控制keep-alive的并发池去复用. 但好在go中不论是fasthttp还是net/http都内置自带了链接的复用. 如果手段去维护这个链接池不仅带代码水平有一定要求, 实际效果也会远差于官方提供的. 这也是dirsearch, dirmap性能有数量级的代差的原因.

并且spray通过1.5倍thread的并发池的冗余, 解决了部分链接失效的导致keep-alive中断的问题.

在未来, spray还将支持http2, http3的client, 去实现最大的性能的并发.

并发数

spray每个目标都将维护一个自身的链接池, 可以通过-t参数控制每个目标的并发数, 因为keep-alive的影响, 实际上只需要很少的thread, 既可实现非常高的QPS.

spray默认的thread是20, 在爆破nginx时, 能打到1500/s的速度. 这个速度大多数场景下已经够用了. 如果需要跳转thread 也请注意, 不要开得太高, 这并没有意义. 超过100个thread的配置, 绝大多数情况都不会生产实际作用, 这个时候的性能瓶颈时自己/目标的带宽或者服务本身的性能上限.

spray在爆破反向代理中间件(nginx, f5, Lighttpd)时, 能实现最大理论性能

如果目标是tomcat之类的中间件, 请求可能会直接打到业务上, 而业务的性能是远远远低于那些反代中间件的. 这个时候就有可能导致CC攻击造成DOS.

Danger

请根据实际的情况选择并发.

请根据实际的情况选择并发.

请根据实际的情况选择并发.

错误处理

上述这些措施下的带来的性能提升比开一个非常高的线程数的效果要好的多, 能在相同thread实现数百倍的提升, 客户端与服务器的负载也会低得多. 但错误总是让人意想不到.

目标很可能部署了WAF, 或者CDN厂商的各种限制 导致任务执行到一半就被拉黑, 或者被banIP. 这种情况下后续的扫描都是没有意义, 继续执行全部的扫描任务反而会导致无法判断哪些效任务扫描. 这个时候, 就需要及时的退出并保证保存有效数据.

这一点非常关键, 是后续分布式扫描实现的基础. 对于反代的目录爆破来说, 选择分布式不是为了更快的完成任务, 而是绕过目标的种种限制.

在spray中, 进行了多种方式的判断. 将会通过一定间隔的check包, 去判断random与index是否已经发生偏离. 如果是被banIP, 这种情况简单的多, 通过设置错误阈值就可以解决.

但真实场景中, 错误可能是偶发性的, 比如某个字典命中了WAF, 导致单个包出现了WAF, 但后续包并没有再次触发. 所以如果每个正常的结果都会将错误累计清空, 只有连续发生的大量基准值偏差或者请求错误, 才会退出程序. 并通过记录每个错误数据, 来找到错误最初发生的位置.

后续的任务只需要换个节点, 接着上次的任务扫描即可.

错误处理还包括了一些其他的特殊情况, 例如

  • body超过spray默认的限制(默认为100k), 导致部分功能无法正常生效, 通过添加参数--read-all解决
  • 目标使用了chunked, 导致fasthttp无法解码. 通过添加-c standard切换client解决.

字典构造

背景

绝大部分工具将字典生成与爆破的行为分开了, 造成了一定程度的割裂. 很多人会发现有工具没合适的字典, 或者想拿一个字典批量爆破一批目标却找不到合适的工具. 我也正是因为遇到了这样的困境才选择去实现一个新的工具. 因此spray从设计上就考虑到了这种割裂, 并尝试解决这种割裂.

spray与其他目录爆破最大的不同还在于spray将字典构造引入到了目录爆破的过程中.

在传统的解决方案之下, 工具和字典是分离的(或许有些工具提供了一些简单的替换, 例如替换host, 替换ext之类的功能, 但在实际流程上还是脱节的), 需要提前准备一个覆盖足够广的字典, 然后读取字典进行高并发的扫描.

字典生成器

但在spray中, 提供了类似hashcat中的基于掩码生成器基于规则生成器, 以及一些函数装饰器对字典进行修饰, 可以在没准备字典的情况下, 对某些场景进行爆破.

举个例子, 不少大型机构, 会使用一台nginx对内网的多个服务进行反代, 而这样的反代绝大多数情况都是通过一个较短的path. 例如plms这样的缩写. 使用spray的掩码生成器, 生成一个四位的随机目录字典, 或者可以带上目标的一些关键字进行更复杂的掩码字典生成结合规则字典生成.

递归

在现代化的网站中, 递归实际上效果并不好, spray并不鼓励使用递归.

在传统的目录爆破工具中, 通常包含一个递归配置, 将爆破到的所有目录都在进行一次全量的字典爆破.

但spray中提供了另一种选择, 可以通过类似--recu current.IsDir() && current.Status == 200配置自定义的递归规则, 进行相对高效的递归.

虽然spray提供了相对高效的递归方式, 但还是不建议使用递归.

轻量级的递归

在spray中, 更优雅的解决方案是基于规则的进一步字典生成.

提供了--append-rule, 可以根据有效目录进行额外的字典生成. 这个是在爆破到某些目录之后, 进行进一步的字典组合.

例如, 想要扫描有效文件的备份, 当扫到了index.php的时候, 自动根据指定的规则, 生成如index.php~这样的字典, 进行爆破.

信息提取

背景

应该说100%的同类工具都只考虑http本身带来的信息, 例如状态码, body长度. 从没有考虑http内包含的更多信息, 例如指纹, title, 敏感信息. 在目录爆破时, 是会获取这些数据的, 但会被直接抛弃. 而spray不仅会收集这些被其他工具抛弃的数据, 还会尽可能从中榨取所有有价值的数据.

spray的输出结果更像是httpx与ffuf那样, 不仅仅只有目录. 有不少目录爆破工具在输出结果时, 抛弃了所有中间输出, 导致对其二次处理还需要httpx这样的工具配合,再次获取信息. 会额外发送不少请求包.

spray的文件输出结果中, 包含了完整的请求摘要信息.

在目录爆破时, spray还将对title, 指纹进行识别, 并提供了--extract自定义正则从网页中提取数据. 也包含了一个简易的爬虫.

在没有启动附加功能时, spray会获取的信息有:

  • http基本信息, 状态码, content-type, body-length, redirect,请求耗时等
  • html的title
  • 被动的指纹识别
  • body与header的hash
  • spray提供的一些额外属性, 例如被过滤原因, 目录来源, 是否有效, 是否为模糊有效

爬虫

爬虫的逻辑类似jsfinder, 从网页中提取可能的url, 并进行递归的爬虫处理.

这个爬虫的表现远低于headless爬虫, 如果有更高级的需要, 还是建议使用katana , rad,crawlgo 这样的headless爬虫工具.

但相比于原版的jsfinder中的逻辑, spray进行了大量优化和调整, 以jsfinder README.md中的https://www.mi.com为例, 有数百倍的差距(还是在额外限制了scope的情况下). 并能实现对很多jsfinder无法正确识别的链接进行识别.

当这个爬虫与智能过滤结合到一起, 就自然而然的实现了对这些有效目录的验证.

经过一段时间的实践, 我发现爬虫配合上spray的信息收集能力, 能创造出很多惊喜. 为此. spray进行了一些微小的调整.

  • 通过爬虫进行的扫描将跳过precompare的智能过滤. 因为爬虫获取的目录本身就是相对高价值的目录, 就算是404页面也不一定是无效结果. 现在爬虫将拥有更高的优先级
  • spray当前只关注目录/文件, 因此爬虫爬到的参数与frag将会被自动删除.
  • 爬虫配合--extract进行信息提取能拿到很多有趣的数据
  • 爬虫配合递归加上备份文件与通用文件的扫描, 也能发现很多有趣的新结果
  • 爬虫让favicon hash荣获新生. 非默认的(/favicon.ico)的ico也能准确识别出指纹了.

就算是简易的爬虫. 实现起来也较为复杂, spray目前内置的爬虫也不是最优的配置. 几乎每个版本都要对爬虫功能进行大量微调. 这个spray中的爬虫还有很大的潜力.

爬虫未来提升的方向:

  • 当前爬虫被强制指定为当前host, 但我发现很多网站会在第三方cdn上托管自己的js, 而这些js中有可能包含敏感数据. 因此后续将会对scope做智能优化, 以及提供对应的参数.
  • 根据爬虫的结果去构造字典

指纹

目前, 除了httpx提供了wappalyzer的规则库, 其他工具都没有实现类似的功能.

而wappalyzer关注的主要是网站的组件, 例如使用了什么语言, 引入了什么组件. 它的关注点与渗透测试场景实际上并不一致. 在红队/渗透测试场景中, 更需要的是类似whatweb那样的指纹识别, 供应商识别.

而spray与gogo共享了指纹库, 实现了对数千条红队可能会关注的指纹的识别.

并且同样引入了主动指纹识别, 根据配置生成可能存在关键信息的目录进行爆破. 这里的逻辑与gogo中的主动指纹识别有细微的不同. spray会将需要主动探测的目录生成一个字典, 并进行全量的规则匹配. 而非gogo那样的精准匹配. 因此实际上spray在配置了相同的指纹的情况下, 会比gogo有些许提升(可能只能提升1%不到, 某些情况下能带来惊喜)

spray没有gogo那么多顾虑, 后续也可能会考虑将wappalyzer接入, 提供更丰富的信息.

也因此, 在配置了同样指纹的情况下, spray的效果会远好于gogo, 有好几个方面综合达成了这一点.

  • spray中内置了爬虫, 爬虫配合上被动指纹识别, 能识别到很多之前识别不到的指纹, 例如通过js跳转的页面, 在gogo中只能通过识别跳转的url中的特征, 而spray通过爬虫可以获取到跳转后的页面,

  • 也因为爬虫可以获取到所有的ico路径, spray添加了基于content-type的智能判断, 可以将ico hash发挥到极致. 很多非/favicon.ico的ico也能正常识别

  • spray不会像gogo一样将host解析为ip, 因此配合上host爆破, 或者面对cdn常见, 指纹识别也能正常发挥作用.

  • spray手动处理redirect. 在gogo中并没有将指纹识别作用到redirect的每一次跳转, 而spray因为手动处理了所有redirect请求, 因此一些非常特殊的网站也能正常识别. 这一点曾经在好几次项目中发现了非常隐蔽且关键的指纹. 并且能获取每次redirect的基本信息.

正因为爬虫与被动指纹识别的结合, spray实际上还有用更加强大的指纹识别能力. 就算网站修改了首页的样式, 在JS文件中的特征依旧不能改变.

gogo原本的指纹库是为了内网场景做了不少取舍, 而现在这些舍弃的东西都可以加回来. 后续将会给spray提供更加强大的指纹库.

不得不说, 当初为gogo设计的最小化匹配的指纹库并不完全适应spray, 存在一定的误报, 还需要后续优化指纹库.

其他附加信息收集手法

除了已经提到过的爬虫和主动指纹识别之外, spray目前还提供了多种方式进行收集. 当然手法不止spray提供的这些, 如果有spray还不支持的类似的功能, 欢迎提供issue.

这些功能都需要添加额外的参数或者-a打开. 因此称之为additional信息收集手法.

  • --bak , 备份文件的爆破, 逻辑类似fuzzuli中的基于host的字典生成+通用的常见备份文件目录. 考虑到url请求可能会将备份文件下载到内存中, 造成溢出. 默认的body上限为100k. 超过100k的文件将不会继续读取, 而是放弃这个握手, 重新建立连接(keep-alive如果不读完body, 将无法复用链接)

  • --bak-file , 对于单个文件的备份字典生成, 与之前提高的轻量级递归有些类似. 如果发现有效文件(非目录), 将会根据这个文件生成一个字典, 进行爆破.

  • --common, 通用文件爆破, 语言 | 框架 | IDE | 开源等等都会有留下一些通用文件. 有些时候没有发现指纹, 但可以通过这些通用文件发现一些信息

  • --recon, 自动提取敏感信息, 在有效目录中提取敏感信息,可在yaml中配置规则, 目前的规则参考HaE与nuclei中的exposure

通过spray本身的功能即可创造出很多有趣的预设. 后续可能会维护一个预设仓库, 用来面对各种场景实现多种多样的玩法.

协议升级

如果对一个https网站使用http去访问, 则大概率会获得400的状态码, 告诉你协议错误. 但很多网站配置了自动的协议升级, 通过location重定向到https的对应网站. 而在批量爆破时, 很难人工一个一个去判断是http还是https.

为此spray中添加http upgrade to https的优化. 并且在协议升级时, 会重新获取baseline, 并在命令行有提示.

在未来, spray还会针对http2/http3自动尝试协议升级.

WAF判断

部分waf的逻辑会在爆破到一定数量时进行封ip,或者跳转到waf页面处理.

如果是封ip比较好处理, 连续的报错积累到一定程度退出程序即可.

处理跳转类型的waf相对复杂一下. 我们通过每隔一定请求, 发送check包, 并与最初的基准值进行对比, 如果连续多个check包的与基准值发生偏离, 那就判断已经被waf了.

实际上, 指纹库中支持了对waf指纹的识别, 但因为部分waf存在全局指纹, 导致可能出现一些误判, 这一点将会在指纹库优化后, 重新上线基于指纹的waf判断. 现在只能在输出结果中看到WAF指纹, 不会对被WAF退出有实际影响.

这是单个任务与waf对抗的手段, 仅限于发现waf, 并不能绕过WAF. 绕过的手段会在批量与分布式中介绍.

数据二次处理

因为spray的输出格式接近httpx与ffuf, 同样支持对他的数据的进行二次处理, 可以像httpx与ffuf一样使用spray.

为此提供了--dump参数不论结果是否有效, 保存spray请求的每一个响应.

后续还会提供完整的响应包的原始(header, body)数据. 用作进一步的的数据分析. 甚至实现类似nuclei中offline scan一样的功能.

批量与分布式

(功能已实现, 文档待完成)

断点续传

(功能已实现, 文档待完成)

死线

(功能已实现, 文档待完成)

其他目录收集方式

spray想要解决的是需要主动发包的场景. 实际上其他方式.

被动的url收集

即不与目标进行交互实现的纯被动url收集. 常见的有数据源:

  • webarchive
  • 各家搜索引擎
  • 各家威胁情报平台
  • ...

后续可能会提供一个类似subfinder那样的工具实现. 似乎开源社区也已经提供了类似的工具.

通过headless爬虫进行的url收集

  • katana projectdiscovery提供的工具, 比较符合chainreactor的设计, 后续将会集成到kindred中
  • rad 长亭提供的闭源的headless爬虫
  • crawlgo 360提供的开源headless爬虫

headless爬虫其实不少, 为安全领域设计的爬虫又不多

基于api的url收集

这个领域属于api安全, 也有非常多的细节, spray暂时不打算涉及.常见的有:

  • swagger
  • wsdl
  • graphql
  • showdoc/yapi/apidoc等自动生成的文档工具
  • ....

我个人会使用apifox进行手动测试

其他手法

除了上面这几项, 这个领域继续深挖还有很多内容.

  • 请求走私与缓存投毒在这个领域的利用
  • 一些CDN,中间件的特殊header对结果的影响.
  • 各种403bypass手段
  • java的权限绕过手法怎么自动化
  • CDN/反向代理真的只有host与path两种方式去爆破么?
  • 类似HaE的信息收集能在目录爆破中起到什么作用?

某些领域spray也无能为力, 但其中一部分, 将在spray后续更新中实现.

spray面临的场景是和gogo一样复杂的. 这个领域不需要我去强调其重要性, 在最近几年的红蓝对抗中就能深刻感受到. 很多时候真的只是工具不行, 心有余而力不足. 面对很多网站只能一遍遍的去针对性的编写一个python脚本, 就像写exp一样. spray是为了解决这样的问题设计, 并打磨了小半年.

有谁会去在一个项目中爆破几千个nginx呢?

todo

这些其他方式有些与spray的设计冲突, 有些只是暂时没有好的解决办法. 有些是因为我的时间有限, 还位于todo之中..

  • 各种403bypass与java权限绕过将会以rule的形式实现.
  • HaE的一些规则与nuclei中的exposures将会一起以插件的形式加入spray
  • ffuf中的一些fuzz技术将会经过重新设计后加入spray, 定位也与ffuf原本的设计有些许不同
  • yakit中的fuzztag也值得参考, 与mask和rule结合能创造出不少新玩法. 或许能解决更多问题

(这里就不使用tasklist了, 每实现一部分就会在todo中删除, 转化为文档)