打不动了,开摸,很多地方(其实是基本上)都是cv的,原文是英文的,阅读不方便,记下来方便自己看看。。

基本介绍

id

ID 不得包含空格。这样做是为了让输出解析更容易。

id: git-config

信息

关于模板的下一个重要信息是信息块。信息块提供 名称作者严重性描述参考标签 。它还包含表示模板严重性的严重性字段,信息块还支持动态字段,因此可以定义N个key: value块以提供有关模板的更多有用信息。reference是另一个流行的标签,用于定义模板的外部参考链接。

另一个总是添加到info块中的有用标签是 tags 。这允许您将一些自定义标签设置为模板,具体取决于目的等cverce这允许核心使用您的输入标签识别模板并仅运行它们。

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需要,来决定请求方法GETPOSTPUTDELETE等。

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)}}在需要突变函数的情况下使用括号),并执行 batteringrampitchforkclusterbomb攻击。这些攻击的词表需要在请求定义期间在 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

注意: 选择攻击类型时要注意,因为不正确的输入可能会导致异常。

例如,如果在使用clusterbomborpitchfork作为攻击类型并且在有效负载部分中仅定义了一个变量,则模板将无法编译,因为clusterbombpitchfork期望在模板中使用多个变量。

攻击模式

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可以将属性设置为truerace_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