打不动了,开摸,很多地方(其实是基本上)都是cv的,原文是英文的,阅读不方便,记下来方便自己看看。。
基本介绍
id
ID 不得包含空格。这样做是为了让输出解析更容易。
id: git-config
信息
关于模板的下一个重要信息是信息块。信息块提供 名称 、 作者 、 严重性 、 描述 、参考和 标签 。它还包含表示模板严重性的严重性字段,信息块还支持动态字段,因此可以定义N个key: value
块以提供有关模板的更多有用信息。reference是另一个流行的标签,用于定义模板的外部参考链接。
另一个总是添加到info
块中的有用标签是 tags 。这允许您将一些自定义标签设置为模板,具体取决于目的等cve
。rce
这允许核心使用您的输入标签识别模板并仅运行它们。
info:
name: Git Config File Detection Template
author: Ice3man
severity: medium
description: Searches for the pattern /.git/config on passed URLs.
reference: https://www.acunetix.com/vulnerabilities/web/git-repository-found/
tags: git,config
实际请求和相应的匹配器被放置在信息块下方,它们执行向目标服务器发出请求并查找模板请求是否成功的任务。
基本请求
请求
Nuclei 为与 HTTP 协议相关的各种功能提供了广泛的支持。支持基于原始和模型的 HTTP 请求,以及非 RFC 客户端请求选项也支持。还可以指定有效负载,并且可以根据有效负载值以及本页面稍后显示的更多功能来转换原始请求。
HTTP 请求以一个request
块开始,该块指定模板请求的开始。
requests:
请求方法
根据poc需要,来决定请求方法GET 、 POST 、 PUT 、DELETE等。
yamethod: GET
重定向
默认情况下不支持重定向。如果有需要,可以添加redirects: true
在请求详细信息中启用。然后使用max-redirects
字段,后面的数字是允许重定向的次数,默认情况下最多遵循 10 个重定向。
requests:
- method: GET
path:
- "{{BaseURL}}/login.php"
redirects: true
max-redirects: 3
路径
请求的下一部分是请求的路径。动态变量可以放置在路径中以在运行时修改其行为。变量以开头{{
和}}
结尾并且区分大小写。
{{BaseURL}} - 这将在请求的运行时替换为目标文件中指定的输入 URL。
{{RootURL}} - 这将在运行时将请求中的根 URL 替换为目标文件中指定的根 URL。
{{Hostname}} - 主机名变量被替换为主机名,包括运行时目标的端口。
{{Host}} - 这将在运行时替换目标文件中指定的输入主机的请求。
{{Port}} - 这将在请求中的运行时替换为目标文件中指定的输入端口。
{{Path}} - 这将在请求中的运行时替换为目标文件中指定的输入路径。
{{File}} - 这将在请求中的运行时替换为目标文件中指定的输入文件名。
{{Scheme}} - 这将在运行时按目标文件中指定的协议替换模板中的请求。
Variable | Value |
---|---|
{{BaseURL}} | https://example.com:443/foo/bar.php |
{{RootURL}} | https://example.com:443 |
{{Hostname}} | example.com:443 |
{{Host}} | example.com |
{{Port}} | 443 |
{{Path}} | /foo |
{{File}} | bar.php |
{{Scheme}} | https |
path: "{{BaseURL}}/.git/config"
# This path will be replaced on execution with BaseURL
# If BaseURL is set to https://abc.com then the
# path will get replaced to the following: https://abc.com/.git/config
请求头
指定请求头。
# headers contain the headers for the request
headers:
# Custom user-agent header
User-Agent: Some-Random-User-Agent
# Custom request origin
Origin: https://google.com
body
请求时需要发送的内容。
# Body is a string sent along with the request
body: "{\"some random JSON\"}"
# Body is a string sent along with the request
body: "admin=test"
Session
在发起多个请求时,需要保持会话,可以添加cookie-reuse: true
来保持多个请求时会话得到保持,这在有身份验证时很有用。
# cookie-reuse accepts boolean input and false as default
cookie-reuse: true
请求条件
请求条件允许检查多个请求之间的条件,以编写复杂的检查和涉及多个 HTTP 请求的漏洞利用以完成漏洞利用链。
使用 DSL 匹配器,可以通过添加req-condition: true
和 作为后缀的数字来使用相应的属性,status_code_1
例如。status_code_3
body_2
req-condition: true
matchers:
- type: dsl
dsl:
- "status_code_1 == 404 && status_code_2 == 200 && contains((body_2), 'secret_string')"
最终HTTP请求
id: git-config
info:
name: Git Config File
author: Ice3man
severity: medium
description: Searches for the pattern /.git/config on passed URLs.
requests:
- method: GET
path:
- "{{BaseURL}}/.git/config"
matchers:
- type: word
words:
- "[core]"
原始 HTTP 请求
另一种创建请求的方法是使用原始请求,它具有更大的灵活性和对 DSL 辅助函数的支持,例如以下请求(现在建议将Host
标头保留为示例中的变量{{Hostname}}
)、所有匹配器、提取器功能可以以与上述相同的方式与 RAW 请求一起使用。
requests:
- raw:
- |
POST /path2/ HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
a=test&b=pd
可以根据需要修改请求。Nuclei 请求是完全可配置的,这意味着可以配置和定义关于将发送到目标服务器的请求每个属性。
RAW 请求格式还支持各种辅助函数,让我们可以使用输入进行运行时操作,能省不少事儿。
raw:
- |
GET /manager/html HTTP/1.1
Host: {{Hostname}}
Authorization: Basic {{base64('username:password')}} # Helper function to encode input at run time.
HTTP 模糊测试
Nuclei 引擎支持 fuzzing 模块,允许以多种格式运行各种类型的Payload,可以使用简单的关键字定义占位符(或者使用{{helper_function(variable)}}
在需要突变函数的情况下使用括号),并执行 batteringram 、pitchfork和clusterbomb攻击。这些攻击的词表需要在请求定义期间在 Payload 字段下定义,名称与关键字匹配,Nuclei 支持基于文件和模板中的词表引用,最后所有 DSL 功能都完全可用和支持,并且可以使用操纵最终值。
Payloads是使用变量名称定义的,并且可以§ §
或{{ }}
在之间中引用。
使用本地字典时:
# HTTP Intruder fuzzing using local wordlist.
payloads:
paths: params.txt
header: local.txt
使用列表时:
# HTTP Intruder fuzzing using in template wordlist.
payloads:
password:
- admin
- guest
- password
注意: 选择攻击类型时要注意,因为不正确的输入可能会导致异常。
例如,如果在使用clusterbomb
orpitchfork
作为攻击类型并且在有效负载部分中仅定义了一个变量,则模板将无法编译,因为clusterbomb
或pitchfork
期望在模板中使用多个变量。
攻击模式
Nuclei 引擎支持多种攻击类型,包括batteringram
默认类型,通常用于 fuzz 单个参数,clusterbomb
以及pitchfork
用于 fuzz 多个参数,其工作方式与经典 burp intruder 相同。
Type | batteringram | pitchfork | clusterbomb |
---|---|---|---|
Support |
batteringram
batteringram在所有位置放置相同的Payload。它只使用一个Payload。它遍历Payload标记位并用Payload集合遍历替换所有位置。
pitchfork
pitchfork每个位置使用一个有效载荷集。它将第一个Payload放在第一个位置,第二个Payload放在第二个位置,依此类推。
然后它同时遍历所有Payload标记位。第一个请求使用每个Payload集合中的第一个Payload,第二个请求使用每个Payload集合中的第二个Payload,依此类推。
clusterbomb
clusterbomb攻击尝试所有不同的Payload组合。它仍然将第一个Payload放在第一个位置,将第二个有效载荷放在第二个位置。但是当它遍历有Payload集合时,它会尝试所有组合。
然后它同时遍历所有Payload集合。第一个请求使用每个Payload集合中的第一个Payload,第二个请求使用每个Payload集合中的第二个Payload,依此类推。
这种攻击类型对于蛮力攻击很有用。在第一个有效负载集中加载常用用户名列表,在第二个有效负载集中加载常用密码列表。然后,集束炸弹攻击将尝试所有组合。
clusterbomb
使用攻击进行模糊测试的示例。
requests:
- raw:
- |
POST /?file={{path}} HTTP/1.1
User-Agent: {{header}}
Host: {{Hostname}}
payloads:
path: helpers/wordlists/prams.txt
header: helpers/wordlists/header.txt
attack: clusterbomb # Defining HTTP fuzz attack type
不安全的 HTTP 请求
Nuclei 支持rawhttp以实现完整的请求控制和自定义,允许针对 HTTP 请求走私、host头注入、带有畸形字符的 CRLF 等问题 的任何类型的畸形请求 。
rawhttp库默认是禁用的,可以通过包含unsafe: true
在请求块中来启用。
requests:
- raw:
- |+
POST / HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
Content-Length: 150
Transfer-Encoding: chunked
0
GET /post?postId=5 HTTP/1.1
User-Agent: a"/><script>alert(1)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5
x=1
- |+
GET /post?postId=5 HTTP/1.1
Host: {{Hostname}}
unsafe: true # Enables rawhttp client
matchers:
- type: dsl
dsl:
- 'contains(body, "<script>alert(1)</script>")'
高级模糊测试
nuclei允许对 Web 服务器进行高级模糊测试。可以使用多个选项来调整 HTTP fuzzing 工作流程。
流水线
添加了 HTTP Pipelining 支持,允许在同一连接上发送多个 HTTP 请求。
在运行基于 HTTP 流水线的模板之前,请确保运行的目标支持 HTTP 流水线连接,否则核心引擎会回退到标准 HTTP 请求引擎。
如果你想确认给定的域或子域列表支持 HTTP Pipelining,httpx有一个标志-pipeline
可以这样做。
配置显示nuclei的流水线属性的示例。
unsafe: true
pipeline: true
pipeline-concurrent-connections: 40
pipeline-requests-per-connection: 25000
一个演示nucile流水线功能的示例模板
id: pipeline-testing
info:
name: pipeline testing
author: pdteam
severity: info
requests:
- raw:
- |+
GET /{{path}} HTTP/1.1
Host: {{Hostname}}
Referer: {{BaseURL}}
attack: batteringram
payloads:
path: path_wordlist.txt
unsafe: true
pipeline: true
pipeline-concurrent-connections: 40
pipeline-requests-per-connection: 25000
matchers:
- type: status
part: header
status:
- 200
连接池
虽然早期版本的 nuclei 没有进行连接池,但用户现在可以配置模板以使用或不使用 HTTP 连接池。这允许根据需要进行更快的扫描。
要在模板中启用连接池,threads
可以使用要在有效负载部分中使用的相应线程数来定义属性。
Connection: Close
标头不能在 HTTP 连接池模板中使用,否则引擎将失败并回退到带有池的标准 HTTP 请求。
id: fuzzing-example
info:
name: Connection pooling example
author: pdteam
severity: info
requests:
- raw:
- |
GET /protected HTTP/1.1
Host: {{Hostname}}
Authorization: Basic {{base64('admin:§password§')}}
attack: batteringram
payloads:
password: password.txt
threads: 40
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
words:
- "Unique string"
part: body
走私
HTTP Smuggling 漏洞的最基本示例是 CL.TE Smuggling。下面提供了一个用于检测 CE.TL http走私 漏洞的示例模板,该模板使用unsafe: true
基于 raw http 的请求的属性。
id: CL.TE-http-smuggling
info:
name: HTTP request smuggling, basic CL.TE vulnerability
author: pdteam
severity: info
lab: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
requests:
- raw:
- |+
POST / HTTP/1.1
Host: {{Hostname}}
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
0
G
- |+
POST / HTTP/1.1
Host: {{Hostname}}
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Transfer-Encoding: chunked
0
G
unsafe: true
matchers:
- type: word
words:
- 'Unrecognized method GPOST'
条件竞争
竞争条件是另一类不易通过传统工具自动化的错误。Burp Suite 为 Turbo Intruder 引入了一种 Gate 机制,其中所有请求的所有字节都被发送,期望同时发送最后一个字节,仅针对同步发送事件的所有请求一起发送。
我们在 nuclei 引擎中实现了Gate机制,并允许它们通过模板运行,这使得对该特定 bug 类的测试变得简单且可移植。
要在模板中启用竞争条件检查,race
可以将属性设置为true
并race_count
定义要启动的同时请求的数量。
下面是一个示例模板,其中使用逻辑相同的请求 10 次。
id: race-condition-testing
info:
name: Race condition testing
author: pdteam
severity: info
requests:
- raw:
- |
POST /coupons HTTP/1.1
Host: {{Hostname}}
promo_code=20OFF
race: true
race_count: 10
matchers:
- type: status
part: header
status:
- 200
nuclei -t race.yaml -target https://api.target.com
多请求竞争条件测试
对于需要发送多个请求以利用竞争条件的场景,我们可以使用线程。
下面是一个示例模板,其中将使用同时发送多个 (5) 请求。
threads: 5
race: true
threads
是使用模板发出的用于执行竞争条件测试的请求总数。
id: multi-request-race
info:
name: Race condition testing with multiple requests
author: pd-team
severity: info
requests:
- raw:
- |
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
id=1
- |
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
id=2
- |
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
id=3
- |
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
id=4
- |
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
id=5
threads: 5
race: true
请求注释
请求内联注释允许执行每个请求属性/行为覆盖。它们与 python/java 类注释非常相似,并且必须在 RFC 行之前放在请求中。目前,仅支持以下覆盖:
@Host:
它覆盖了请求的真实目标(通常是作为输入提供的主机/IP)。它支持带有 ip/domain、port 和 scheme 的语法,例如:domain.tld
domain.tld:port
http://domain.tld:port
@tls-sni:
它会覆盖 TLS 请求的 SNI 名称(通常是作为输入提供的主机名)。它支持任何文字,特殊值request.host
使用Host
标头的值。
- |
@Host: https://projectdiscovery.io:443
POST / HTTP/1.1
Pragma: no-cache
Host: {{Hostname}}
Cache-Control: no-cache, no-transform
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
这特别有用,例如,在具有多个请求的模板的情况下,需要对特定主机执行第一个请求之后的一个请求(例如检查 API 有效性):
requests:
- raw:
# this request will be sent to {{Hostname}} to get the token
- |
GET /getkey HTTP/1.1
Host: {{Hostname}}
# This request will be sent instead to https://api.target.com:443 to verify the token validity
- |
@Host: https://api.target.com:443
GET /api/key={{token} HTTP/1.1
Host: api.target.com:443
extractors:
- type: regex
name: token
part: body
regex:
# random extractor of strings between prefix and suffix
- 'prefix(.*)suffix'
matchers:
- type: word
part: body
words:
- valid token