-
Notifications
You must be signed in to change notification settings - Fork 471
FAQ
Hi, i setup it using git clone then iam trying to run it but i do not know why or what should i do next. Any help about the next steps to run it ?
No
The info section of afrog's PoC format is borrowed from nuclei, while the rest is more heavily influenced by xray.
No
The PoC formats of afrog and xray are similar, especially in the rules section, which is almost interchangeable. However, the info section in afrog and the details section in xray are different and would benefit more from borrowing the format of nuclei.
If the command 'afrog.exe -update' is executed, the following error may occur:
Error Info
[FTL] could not install latest release: looking up path of "afrog.exe": exec: "afrog.exe": cannot run executable found relative to current directory
How to solve the above problems?
Need to add afrog.exe to the environment variable.
To add afrog.exe to the environment variable in Windows, you can follow these steps:
1. Right-click on "This PC" and select "Properties".
2. In the left pane, select "Advanced system settings".
3. Click on the "Environment Variables" button.
4. Under "System Variables", find "Path" and double-click to edit.
5. Click the "New" button and enter the path where the afrog.exe file is located.
6. Click the "OK" button to save the changes.
7. Close all open windows, reopen the command prompt, and type the "afrog" command to test if the addition was successful.
To add afrog to the environment variable in Linux/macOS, you can follow these steps:
1. Open the Terminal application.
2. Enter the command: sudo nano /etc/paths.
3. Add the following line to the end of the file: /path/to/afrog, where /path/to/afrog is the path to the afrog file.
4. Save the file and exit the editor.
5. Enter the command: source /etc/paths to update the configuration.
6. Enter the command afrog to test if the addition was successful.
7. Note that if you are using a different shell, such as bash or zsh, you may need to edit the corresponding configuration file (e.g., ~/.bashrc or ~/.zshrc) and add the appropriate path.
--req-limit-per-target 的核心价值是把“限速”从全局维度细化到单目标(host:port)维度。它解决的是 -rate-limit 解决不了的那类问题:同一时间把请求集中打到某一个目标/某一个反连平台/某一个代理出口时,引发封禁、拥塞、误判或影响正常上网。
优点(相对 -rate-limit 的补充能力)
-
控制对单个目标的压力:
-rate-limit只限制全局 QPS,但并不能阻止“25 个并发恰好都在打同一个 host”的情况;--req-limit-per-target能保证这个 host 每秒最多 N 个请求。 - 降低被 WAF/限流/封禁概率:很多防护是按“同 IP → 单站点”维度做限流/熔断的,而不是按你工具的全局 QPS。per-target 限速可以显著降低触发概率。
- 更稳定、更不影响日常网络:当扫描集中到某些站点时,per-target 限速能减少对代理/带宽/浏览器访问同站点的抢占,缓解“扫描时上网巨慢”的情况。
- 对反连/OOB 相关 PoC 更友好:反连平台经常是“单域名/单端口”集中请求,per-target 限速可以避免把平台打爆导致漏报/延迟。
为什么有了 -rate-limit 还需要 --req-limit-per-target
-
-rate-limit解决的是“全局总吞吐不要太高”,避免把你的机器/你的网络/你的代理出口打满。 -
--req-limit-per-target解决的是“不要对某一个目标打得太猛”,避免把目标站/某个 host/某个端口/某个 OOB 平台打挂或触发防护。 - 两者不是替代关系:一个是“总量阀门”,一个是“单点阀门”。在多目标扫描里,常见情况是:
- 全局 QPS 看似合理(比如 150/s)
- 但某一两个 host 因为响应快/命中规则多/并发集中,瞬间承受过高 rps → 触发限流/封禁/网络拥塞
这就是 per-target 限速存在的意义。
最佳应用场景(什么时候最值得开)
-
少目标高并发:例如只扫 1~20 个目标,但
-c很高;这时请求很容易集中到单个 host,per-target 限速非常关键。 - 目标容易限流/封禁:有明显 WAF、CDN 限速、登录口、管理后台、API 网关等,对“突刺流量”敏感的站点。
- 使用代理/网关/扫描时影响上网:afrog 扫描时候 “浏览器打开网页巨慢甚至打不开”,很多时候是某些目标或某些端口把代理连接池/带宽抢占了;per-target 限速能明显缓解。
- 反连/OOB PoC 或集中域名:反连平台、回连检测点、单域名集中请求的场景,开 per-target 限速能避免平台拥塞导致误差。
- 需要更高稳定性而不是最高速度:追求“更少漏报/更少误判/更少卡顿”的批量扫描。
建议:
-
扫很多分散目标:优先用
-rate-limit(简单、效果直观) -
扫少量目标/单点压力大/影响上网:优先用
--req-limit-per-target或--balanced/--polite(更对症) -
不想调参:用
--auto-req-limit(自动兜底)
- 更完整的新手教程(v3.3.9+):OOB 体系大升级:新版写法与证据教程(v3.3.9)
-
HTTP OOB:通常用
3秒(覆盖大多数回连链路,整体更快) -
DNS OOB:通常用
5秒(DNS 解析/缓存/链路抖动更常见) -
异步回连:如果回连可能由队列/定时任务触发,或目标出网慢,可逐步加到
8~15秒
推荐写法(把触发条件与等待命中组合):
expression: response.status == 200 && oobCheck("http", 3)brute 是规则级枚举能力,支持对一个或多个变量做枚举:
-
mode: clusterbomb会做笛卡尔积组合,请求量 = 各列表长度相乘 -
mode: pitchfork会按索引对齐组合,请求量 = min(各列表长度)
为避免组合爆炸带来的扫描变慢/目标限流/误封,建议开启运行时硬阈值:
afrog -t https://example.com --brute-max-requests 2000默认 --brute-max-requests 为 5000,设置为 0 表示不限制。
-
continue: false:一旦命中就停止枚举(更快、更省请求) -
continue: true:命中后继续枚举(用于需要统计/比对,或希望拿到最后一次命中)
commit 用于决定命中后保留哪一次尝试的变量与 request/response:
-
winner/first:保留首次命中(默认) -
last:保留最后一次命中(常与continue: true配合) -
none:不保留 brute payload 变量,但保留命中的 request/response(减少对后续规则的变量污染)
用于“指纹门控”:让高成本 PoC(弱口令/爆破/默认口令等)仅在目标命中指定指纹后执行。完整用法、strict/opportunistic 区别、以及“为什么没跑”的排障请参考:
用于控制“应用类 PoC(依赖 info.tags 的那些)”在指纹证据不足时的跳过策略,核心目标是在“漏扫风险”和“扫描效率”之间做可控取舍。
它和 info.requires/requires-mode 的关系:
-
info.requires/requires-mode:是 PoC 自己声明 的“指纹门控”,主要用于高成本 PoC(弱口令/爆破等)。 -
--fingerprint-filter-mode:是 引擎侧的过滤策略,主要用于“应用类漏洞 PoC”,基于info.tags与指纹命中标签的关系来决定是否跳过。
- 当本次扫描里出现过指纹命中(任意目标命中即可),引擎会把这些命中的标签视为“应用标签集合”。
- 对于一个 PoC,如果它的
info.tags和上述“应用标签集合”有交集,则认为它是“应用类 PoC”。 - 如果当前目标没有任何指纹标签(没有拿到证据),则该“应用类 PoC”会对这个目标被跳过。
适用场景:
- 追求效率、减少无效请求、减少对目标/代理/带宽的压力
- 指纹阶段比较可靠,或你更愿意相信“没有指纹证据就不跑应用 PoC”
- 仍然会在“有指纹证据但不匹配 PoC 标签”的情况下跳过(避免明显不相关的 PoC)。
- 但当“当前目标完全没有指纹证据”时,不再跳过应用类 PoC,而是继续执行,用更多请求换更低漏报概率。
适用场景:
- 你怀疑指纹阶段会漏(例如:响应不稳定、鉴权导致指纹拿不到、协议/端口多样导致指纹覆盖不足)
- 你更在意“少漏扫”,可以接受更多请求与更多无效尝试
# 默认 strict,不需要显式设置
afrog -T targets.txt
# 降低“无指纹证据导致应用 PoC 被跳过”的漏扫风险
afrog -T targets.txt --fingerprint-filter-mode opportunistic很多新手写 PoC 时,会遇到下面这种“看起来没问题,但就是匹配不到/提取出来是乱码”的情况:
- 页面标题、提示语是中文(或其它非 ASCII 字符)
- 目标站点响应体不是 UTF-8(常见:GBK/Big5/Shift-JIS/ISO-8859-1…)
- 你用
response.body(bytes)直接做正则提取/匹配
为了解决“文本编码不一致”的问题,afrog 增加了 response_text,并对正则函数做了更明确的“字节 vs 文本”分工。
-
response.body:响应体 bytes(字节数组)- 适合:
bcontains/ibcontains/bmatches/bsubmatch这类 b* 字节函数 - 特点:不做任何文本解码,速度快、语义稳定,但不保证中文可读
- 适合:
-
response_text:响应体 string(文本)- 适合:
contains/icontains/matches/rmatches/submatch这类 文本函数 - 特点:会按响应的
charset等信息尝试把 bytes 解码成文本,更适合中文页面与文本提取
- 适合:
一句话:默认优先用 response.body;只有在你需要“可读文本(尤其中文/非 UTF-8)”或需要使用 submatch/rmatches/contains 这类文本函数时,才使用 response_text。
-
bsubmatch(xxx):对 bytes 做正则提取,常用于响应头、固定英文/数字字段、或你明确要按 bytes 处理的内容 -
submatch(xxx):对 string 做正则提取,推荐用于正文文本、标题、提示语、中文等
迁移对照(最常见):
# 旧写法(容易乱码):对 response.body(bytes)提取
title: '"<title>(?P<t>.+)</title>".bsubmatch(response.body)'
# 新写法(推荐):对 response_text(string)提取
title: '"<title>(?P<t>.+)</title>".submatch(response_text)'-
bmatches(xxx):对 bytes 做正则匹配(True/False) -
rmatches(xxx):对 string 做正则匹配(True/False),推荐搭配response_text
迁移对照(最常见):
# 旧写法:对 response.body(bytes)匹配
expression: response.status == 200 && "目标特征".bmatches(response.body)
# 新写法(推荐):对 response_text(string)匹配
expression: response.status == 200 && "目标特征".rmatches(response_text)定义:response_text 就是把 response.body(原始 bytes)“尽量转成你能直接读的文本”。
- 如果响应里带了
charset(例如charset=gbk/charset=utf-8),就按它来解码 - 解码后的结果是一个普通字符串(你可以把它当成 UTF-8 文本来写
submatch/rmatches/contains) - 可以粗暴理解为:
response_text ≈ toUtf8(response.body)
为什么要新增它:
-
response.body是 bytes,直接做正则/提取时不会“自动变成人类可读文本” - 很多站点的页面编码不是 UTF-8(例如 GBK),直接对 bytes 做正则提取中文时很容易乱码或匹配失败
-
response_text让你在“确实需要可读文本(尤其中文/非 UTF-8)”时,有一个现成的解码结果可用;其余情况下仍建议优先用response.body(更快、字节语义更稳定)
什么时候优先用 response_text:
- 你要匹配/提取“人类可读文本”(尤其是中文/非 ASCII 文本),并希望提取结果是正常可读的字符串
- 你不确定目标响应体是否 UTF-8(例如老系统常见 GBK/Big5),并且你的正则会捕获/比较到这些文本内容
- 你在做
submatch/rmatches/contains/icontains这类“文本语义”的表达式判断
什么时候不建议用 response_text:
- 你要处理/匹配的是二进制内容或“按字节语义”才准确的内容(此时用
response.body+ b* 函数) - 目标返回的不是可解码文本(这时
response_text可能为空或包含替换字符,属于正常现象)
一个更简单的选法:
默认优先用 response.body(更快、字节语义更稳定、内容更原始);只有在你需要“可读文本”(尤其中文/非 UTF-8)或需要用 submatch/rmatches 这类文本函数时,才使用 response_text。
定义:rmatches(text) 是对 文本 string 做正则匹配,返回 True/False,推荐与 response_text 搭配使用。
对比关系:
-
bmatches(response.body):bytes 正则匹配(不解码,适合按字节判断) -
rmatches(response_text):text 正则匹配(已解码,适合中文与正文文本) -
matches(...):CEL 自带的正则匹配(语义不同、实现不同),afrog 新增rmatches是为了让“regexp2 语义的文本匹配”更直观、也避免和内置matches概念混用
最常见用法:
# 正文文本匹配(推荐)
expression: response.status == 200 && "致远.*协同办公".rmatches(response_text)
# 中文标题匹配(推荐)
expression: response_text.icontains("<title>致远协同办公")
# 如果你明确要按 bytes 匹配(例如只关心 ASCII/固定字节)
expression: response.status == 200 && "root:.*?:[0-9]*:[0-9]*:".bmatches(response.body)