mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-08 10:10:18 -10:00
Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3be6ccf28a | ||
|
|
55a4be4b6d | ||
|
|
49811d24a1 | ||
|
|
cb1bbff0f0 | ||
|
|
ebdabef420 | ||
|
|
0442aa79da | ||
|
|
7a9facfc26 | ||
|
|
abc63f1f8d | ||
|
|
f5f5f5fc21 | ||
|
|
efb27cfd49 | ||
|
|
5f952fc87a | ||
|
|
505ebc752f | ||
|
|
44f398c08d | ||
|
|
d7c8c8af80 | ||
|
|
7e4b4a8c55 | ||
|
|
92213e1335 | ||
|
|
159a8a53cf | ||
|
|
98948d0266 | ||
|
|
2c832f5590 | ||
|
|
53f56e179d | ||
|
|
cc5c5509dc | ||
|
|
aab2cadb64 | ||
|
|
4ef058758c | ||
|
|
d68af67e6e | ||
|
|
888a732fbc | ||
|
|
3f0de96726 | ||
|
|
1cd42c46c7 | ||
|
|
82680980a5 | ||
|
|
690089e1ce | ||
|
|
f0624820d3 | ||
|
|
7ba5d51b00 | ||
|
|
8b9acb2927 | ||
|
|
23825c77b2 |
No files matched your search
@@ -1,6 +1,7 @@
|
||||
addReviewers: true
|
||||
reviewers:
|
||||
- dogancanbakir
|
||||
- dwisiswant0
|
||||
|
||||
numberOfReviewers: 1
|
||||
skipKeywords:
|
||||
|
||||
+6
-1
@@ -42,4 +42,9 @@ pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
|
||||
vendor
|
||||
|
||||
# Headless `screenshot` action
|
||||
*.png
|
||||
*.png
|
||||
|
||||
# Profiling & tracing
|
||||
*.prof
|
||||
*.pprof
|
||||
*.trace
|
||||
@@ -457,26 +457,49 @@ func (template *Template) compileProtocolRequests(options protocols.ExecuterOpti
|
||||
That's it, you've added a new protocol to Nuclei. The next good step would be to write integration tests which are described in `integration-tests` and `cmd/integration-tests` directories.
|
||||
|
||||
|
||||
## Profiling Instructions
|
||||
## Profiling and Tracing
|
||||
|
||||
To enable dumping of Memory profiling data, `-profile-mem` flag can be used along with path to a file. This writes a pprof formatted file which can be used for investigate resource usage with `pprof` tool.
|
||||
To analyze Nuclei's performance and resource usage, you can generate memory profiles and trace files using the `-profile-mem` flag:
|
||||
|
||||
```console
|
||||
$ nuclei -t nuclei-templates/ -u https://example.com -profile-mem mem.pprof
|
||||
```bash
|
||||
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
|
||||
```
|
||||
|
||||
To view profile data in pprof, first install pprof. Then run the below command -
|
||||
This command creates two files:
|
||||
|
||||
```console
|
||||
$ go tool pprof mem.pprof
|
||||
* `nuclei.prof`: Memory (heap) profile
|
||||
* `nuclei.trace`: Execution trace
|
||||
|
||||
### Analyzing the Memory Profile
|
||||
|
||||
1. View the profile in the terminal:
|
||||
|
||||
```bash
|
||||
go tool pprof nuclei.prof
|
||||
```
|
||||
|
||||
To open a web UI on a port to visualize debug data, the below command can be used.
|
||||
2. Display top memory consumers:
|
||||
|
||||
```console
|
||||
$ go tool pprof -http=:8081 mem.pprof
|
||||
```bash
|
||||
go tool pprof -top nuclei.prof | grep "$(go list -m)" | head -10
|
||||
```
|
||||
|
||||
3. Visualize the profile in a web browser:
|
||||
|
||||
```bash
|
||||
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.prof
|
||||
```
|
||||
|
||||
### Analyzing the Trace File
|
||||
|
||||
To examine the execution trace:
|
||||
|
||||
```bash
|
||||
go tool trace nuclei.trace
|
||||
```
|
||||
|
||||
These tools help identify performance bottlenecks and memory leaks, allowing for targeted optimizations of Nuclei's codebase.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- [pkg/reporting](./pkg/reporting) - Reporting modules for nuclei.
|
||||
|
||||
@@ -54,6 +54,12 @@ Nuclei is a modern, high-performance vulnerability scanner that leverages simple
|
||||
- [Contributors ❤️](#contributors-️)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
||||
| :exclamation: **Disclaimer** |
|
||||
|---------------------------------|
|
||||
| **This project is in active development**. Expect breaking changes with releases. Review the release changelog before updating. |
|
||||
| This project is primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
|
||||
## Get Started
|
||||
|
||||
@@ -66,11 +72,6 @@ Install Nuclei on your machine. Get started by following the installation guide
|
||||
- Access latest nuclei templates
|
||||
- Discover and store your targets
|
||||
|
||||
| :exclamation: **Disclaimer** |
|
||||
|:--------------------------------|
|
||||
| **This project is in active development**. Expect breaking changes with releases. Review the release changelog before updating. |
|
||||
| This project is primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
|
||||
### **2. Pro and Enterprise Editions**
|
||||
|
||||
For security teams and enterprises, we provide a cloud-hosted service built on top of Nuclei OSS, fine-tuned to help you continuously run vulnerability scans at scale with your team and existing workflows:
|
||||
@@ -84,8 +85,6 @@ For security teams and enterprises, we provide a cloud-hosted service built on t
|
||||
- We're constantly [adding new features](https://feedback.projectdiscovery.io/changelog)!
|
||||
- **Ideal for:** Pentesters, security teams, and enterprises
|
||||
|
||||
[Sign up to Pro](https://projectdiscovery.io/pricing?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme) or [Talk to our team](https://projectdiscovery.io/request-demo?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme) if you have large organization and complex requirements.
|
||||
|
||||
## Documentation
|
||||
|
||||
Browse the full Nuclei [documentation here](https://docs.projectdiscovery.io/tools/nuclei/running). If you’re new to Nuclei, check out our [foundational Youtube series.](https://www.youtube.com/playlist?list=PLZRbR9aMzTTpItEdeNSulo8bYsvil80Rl)
|
||||
@@ -112,231 +111,235 @@ Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
Usage:
|
||||
./nuclei [flags]
|
||||
./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)
|
||||
-eh, -exclude-hosts string[] hosts to exclude to scan from the input list (ip, cidr, hostname)
|
||||
-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)
|
||||
-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)
|
||||
-eh, -exclude-hosts string[] hosts to exclude to scan from the input list (ip, cidr, hostname)
|
||||
-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)
|
||||
|
||||
TARGET-FORMAT:
|
||||
-im, -input-mode string mode of input file (list, burp, jsonl, yaml, openapi, swagger) (default "list")
|
||||
-ro, -required-only use only required fields in input format when generating requests
|
||||
-sfv, -skip-format-validation skip format validation (like missing vars) when parsing input file
|
||||
-im, -input-mode string mode of input file (list, burp, jsonl, yaml, openapi, swagger) (default "list")
|
||||
-ro, -required-only use only required fields in input format when generating requests
|
||||
-sfv, -skip-format-validation skip format validation (like missing vars) when parsing input file
|
||||
|
||||
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)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-tgl list all available tags
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
-dut, -disable-unsigned-templates disable running unsigned templates or templates with mismatched signature
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-tgl list all available tags
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
-dut, -disable-unsigned-templates disable running unsigned templates or templates with mismatched signature
|
||||
|
||||
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, allow-wildcard)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] path to template file or directory to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] path to template file or 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, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
-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, allow-wildcard)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] path to template file or directory to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] path to template file or 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, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-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)
|
||||
-j, -jsonl write output in JSONL(ines) format
|
||||
-irr, -include-rr -omit-raw include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-or, -omit-raw omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)
|
||||
-ot, -omit-template omit encoded template in the JSON, JSONL output
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
-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
|
||||
-je, -json-export string file to export results in JSON format
|
||||
-jle, -jsonl-export string file to export results in JSONL(ine) format
|
||||
-rd, -redact string[] redact given list of keys from query parameter, request header and body
|
||||
-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)
|
||||
-j, -jsonl write output in JSONL(ines) format
|
||||
-irr, -include-rr -omit-raw include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-or, -omit-raw omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)
|
||||
-ot, -omit-template omit encoded template in the JSON, JSONL output
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
-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
|
||||
-je, -json-export string file to export results in JSON format
|
||||
-jle, -jsonl-export string file to export results in JSONL(ine) format
|
||||
-rd, -redact string[] redact given list of keys from query parameter, request header and body
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string path to the nuclei configuration file
|
||||
-tp, -profile string template profile config file to run
|
||||
-tpl, -profile-list list community template profiles
|
||||
-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 [Deprecated] autofallback to ztls is enabled by default
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-dka, -dialer-keep-alive value keep-alive duration for network requests.
|
||||
-lfa, -allow-local-file-access allows file (payload) access anywhere on the system
|
||||
-lna, -restrict-local-network-access blocks connections to the local / private network
|
||||
-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
|
||||
-rsr, -response-size-read int max response size to read in bytes
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
-reset reset removes all nuclei configuration and data files (including nuclei-templates)
|
||||
-tlsi, -tls-impersonate enable experimental client hello (ja3) tls randomization
|
||||
-hae, -http-api-endpoint string experimental http api endpoint
|
||||
-config string path to the nuclei configuration file
|
||||
-tp, -profile string template profile config file to run
|
||||
-tpl, -profile-list list community template profiles
|
||||
-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 [Deprecated] autofallback to ztls is enabled by default
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-dka, -dialer-keep-alive value keep-alive duration for network requests.
|
||||
-lfa, -allow-local-file-access allows file (payload) access anywhere on the system
|
||||
-lna, -restrict-local-network-access blocks connections to the local / private network
|
||||
-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
|
||||
-rsr, -response-size-read int max response size to read in bytes
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
-reset reset removes all nuclei configuration and data files (including nuclei-templates)
|
||||
-tlsi, -tls-impersonate enable experimental client hello (ja3) tls randomization
|
||||
-hae, -http-api-endpoint string experimental http api endpoint
|
||||
|
||||
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
|
||||
-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
|
||||
|
||||
FUZZING:
|
||||
-ft, -fuzzing-type string overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string overrides fuzzing mode set in template (multiple, single)
|
||||
-fuzz enable loading fuzzing templates (Deprecated: use -dast instead)
|
||||
-dast enable / run dast (fuzz) nuclei templates
|
||||
-dfp, -display-fuzz-points display fuzz points in the output for debugging
|
||||
-fuzz-param-frequency int frequency of uninteresting parameters for fuzzing before skipping (default 10)
|
||||
-fa, -fuzz-aggression string fuzzing aggression level controls payload count for fuzz (low, medium, high) (default "low")
|
||||
-ft, -fuzzing-type string overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string overrides fuzzing mode set in template (multiple, single)
|
||||
-fuzz enable loading fuzzing templates (Deprecated: use -dast instead)
|
||||
-dast enable / run dast (fuzz) nuclei templates
|
||||
-dfp, -display-fuzz-points display fuzz points in the output for debugging
|
||||
-fuzz-param-frequency int frequency of uninteresting parameters for fuzzing before skipping (default 10)
|
||||
-fa, -fuzz-aggression string fuzzing aggression level controls payload count for fuzz (low, medium, high) (default "low")
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow,google) (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)
|
||||
-ur, -uncover-ratelimit int override ratelimit of engines with unknown ratelimit (default 60 req/min) (default 60)
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow,google) (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)
|
||||
-ur, -uncover-ratelimit int override ratelimit of engines with unknown ratelimit (default 60 req/min) (default 60)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rld, -rate-limit-duration value maximum number of requests to send per second (default 1s)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute (DEPRECATED)
|
||||
-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)
|
||||
-jsc, -js-concurrency int maximum number of javascript runtimes to be executed in parallel (default 120)
|
||||
-pc, -payload-concurrency int max payload concurrency for each template (default 25)
|
||||
-prc, -probe-concurrency int http probe concurrency with httpx (default 50)
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rld, -rate-limit-duration value maximum number of requests to send per second (default 1s)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute (DEPRECATED)
|
||||
-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)
|
||||
-jsc, -js-concurrency int maximum number of javascript runtimes to be executed in parallel (default 120)
|
||||
-pc, -payload-concurrency int max payload concurrency for each template (default 25)
|
||||
-prc, -probe-concurrency int http probe concurrency with httpx (default 50)
|
||||
|
||||
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)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-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 (default "/tmp")
|
||||
-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 auto)
|
||||
-irt, -input-read-timeout value timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
-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)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-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 (default "/tmp")
|
||||
-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 auto)
|
||||
-irt, -input-read-timeout value 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
|
||||
-ho, -headless-options string[] start headless chrome with additional options
|
||||
-sc, -system-chrome use local installed Chrome browser instead of nuclei installed
|
||||
-lha, -list-headless-action list available headless actions
|
||||
-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
|
||||
-ho, -headless-options string[] start headless chrome with additional options
|
||||
-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
|
||||
-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 generate memory (heap) profile & trace files
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-vdl, -var-dump-limit int limit the number of characters displayed in var dump (default 255)
|
||||
-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:
|
||||
-up, -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
|
||||
-up, -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 display statistics in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json display statistics in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth configure projectdiscovery cloud (pdcp) api key (default true)
|
||||
-tid, -team-id string upload scan results to given team id (optional) (default "none")
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard
|
||||
-sid, -scan-id string upload scan results to existing scan id (optional)
|
||||
-sname, -scan-name string scan name to set (optional)
|
||||
-auth configure projectdiscovery cloud (pdcp) api key (default true)
|
||||
-tid, -team-id string upload scan results to given team id (optional) (default "none")
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard [DEPRECATED use -dashboard]
|
||||
-sid, -scan-id string upload scan results to existing scan id (optional)
|
||||
-sname, -scan-name string scan name to set (optional)
|
||||
-pd, -dashboard upload / view nuclei results in projectdiscovery cloud (pdcp) UI dashboard
|
||||
-pdu, -dashboard-upload string upload / view nuclei results file (jsonl) in projectdiscovery cloud (pdcp) UI dashboard
|
||||
|
||||
AUTHENTICATION:
|
||||
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
|
||||
-ps, -prefetch-secrets prefetch secrets from the secrets file
|
||||
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
|
||||
-ps, -prefetch-secrets prefetch secrets from the secrets file
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Run nuclei on single host:
|
||||
$ nuclei -target example.com
|
||||
$ nuclei -target example.com
|
||||
|
||||
Run nuclei with specific template directories:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Run nuclei against a list of hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Run nuclei with a JSON output:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
Run nuclei with sorted Markdown outputs (with environment variables):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
Additional documentation is available at: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
Additional documentation is available at: [https://docs.nuclei.sh/getting-started/running](https://docs.nuclei.sh/getting-started/running?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme)
|
||||
@@ -380,7 +383,7 @@ nuclei -u https://example.com -t /path/to/your-template.yaml
|
||||
You can run the scans on your machine and upload the results to the cloud platform for further analysis and remediation.
|
||||
|
||||
```sh
|
||||
nuclei -target https://example.com -cloud-upload
|
||||
nuclei -target https://example.com -dashboard
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
@@ -457,100 +460,6 @@ Thanks to all the amazing [community contributors for sending PRs](https://githu
|
||||
<a href="https://github.com/geeknik"><img src="https://avatars.githubusercontent.com/u/466878?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/TerminalFi"><img src="https://avatars.githubusercontent.com/u/32599364?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KaulSe"><img src="https://avatars.githubusercontent.com/u/45340011?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sullo"><img src="https://avatars.githubusercontent.com/u/1474884?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/wdahlenburg"><img src="https://avatars.githubusercontent.com/u/4451504?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ghost"><img src="https://avatars.githubusercontent.com/u/10137?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Nishan8583"><img src="https://avatars.githubusercontent.com/u/20457968?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jdk2588"><img src="https://avatars.githubusercontent.com/u/985054?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/nothinux"><img src="https://avatars.githubusercontent.com/u/17433202?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/CodFrm"><img src="https://avatars.githubusercontent.com/u/22783163?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/CasperGN"><img src="https://avatars.githubusercontent.com/u/5549643?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ankh2054"><img src="https://avatars.githubusercontent.com/u/6784287?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/revblock"><img src="https://avatars.githubusercontent.com/u/72813848?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/cn-kali-team"><img src="https://avatars.githubusercontent.com/u/30642514?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/EndPositive"><img src="https://avatars.githubusercontent.com/u/25148195?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jimen0"><img src="https://avatars.githubusercontent.com/u/6826244?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xstevens"><img src="https://avatars.githubusercontent.com/u/69216?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mjkim610"><img src="https://avatars.githubusercontent.com/u/17107206?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/organiccrap"><img src="https://avatars.githubusercontent.com/u/376317?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lu4nx"><img src="https://avatars.githubusercontent.com/u/3006875?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/souvikhazra1"><img src="https://avatars.githubusercontent.com/u/13842393?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tovask"><img src="https://avatars.githubusercontent.com/u/22732484?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Marmelatze"><img src="https://avatars.githubusercontent.com/u/199681?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/doug-threatmate"><img src="https://avatars.githubusercontent.com/u/127235272?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/yabeow"><img src="https://avatars.githubusercontent.com/u/21117771?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/olearycrew"><img src="https://avatars.githubusercontent.com/u/6044920?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/gano3s"><img src="https://avatars.githubusercontent.com/u/2551605?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/alizmhdi"><img src="https://avatars.githubusercontent.com/u/79321261?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hackerpain"><img src="https://avatars.githubusercontent.com/u/61242234?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lc"><img src="https://avatars.githubusercontent.com/u/19563282?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/savushkin-yauheni"><img src="https://avatars.githubusercontent.com/u/5173352?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/74616e696d"><img src="https://avatars.githubusercontent.com/u/97121933?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/edoardottt"><img src="https://avatars.githubusercontent.com/u/35783570?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zt2"><img src="https://avatars.githubusercontent.com/u/7644862?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/moonD4rk"><img src="https://avatars.githubusercontent.com/u/24284231?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/wk8"><img src="https://avatars.githubusercontent.com/u/2536231?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mikerott"><img src="https://avatars.githubusercontent.com/u/857712?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/toufik-airane"><img src="https://avatars.githubusercontent.com/u/5610269?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hktalent"><img src="https://avatars.githubusercontent.com/u/18223385?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jturner"><img src="https://avatars.githubusercontent.com/u/1825202?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/gaby"><img src="https://avatars.githubusercontent.com/u/835733?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vavkamil"><img src="https://avatars.githubusercontent.com/u/47953210?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/leonjza"><img src="https://avatars.githubusercontent.com/u/1148127?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mionskowski-form3"><img src="https://avatars.githubusercontent.com/u/91873652?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/chenrui333"><img src="https://avatars.githubusercontent.com/u/1580956?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iamargus95"><img src="https://avatars.githubusercontent.com/u/77744293?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/shashikarsiddharth"><img src="https://avatars.githubusercontent.com/u/60960197?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/trypa11"><img src="https://avatars.githubusercontent.com/u/67585616?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Zeokat"><img src="https://avatars.githubusercontent.com/u/1313154?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/alban-stourbe-wmx"><img src="https://avatars.githubusercontent.com/u/159776828?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/anykno"><img src="https://avatars.githubusercontent.com/u/2528207?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ronaudinho"><img src="https://avatars.githubusercontent.com/u/10264710?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/boy-hack"><img src="https://avatars.githubusercontent.com/u/18695984?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iuliu8899"><img src="https://avatars.githubusercontent.com/u/31680027?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/debasishbsws"><img src="https://avatars.githubusercontent.com/u/65381620?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/denysvitali-niantic"><img src="https://avatars.githubusercontent.com/u/157139422?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/fail-open"><img src="https://avatars.githubusercontent.com/u/72417455?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Xc1Ym"><img src="https://avatars.githubusercontent.com/u/29765332?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/XTeam-Wing"><img src="https://avatars.githubusercontent.com/u/25416365?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Weltolk"><img src="https://avatars.githubusercontent.com/u/40228052?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tonghuaroot"><img src="https://avatars.githubusercontent.com/u/23011166?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/praetorian-thendrickson"><img src="https://avatars.githubusercontent.com/u/69640071?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/S0obi"><img src="https://avatars.githubusercontent.com/u/4180104?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/skahn007gl"><img src="https://avatars.githubusercontent.com/u/144735608?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/shouichi"><img src="https://avatars.githubusercontent.com/u/99586?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/seb-elttam"><img src="https://avatars.githubusercontent.com/u/111818823?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/AdallomRoy"><img src="https://avatars.githubusercontent.com/u/4046118?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rotemreiss"><img src="https://avatars.githubusercontent.com/u/9288082?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/oscarintherocks"><img src="https://avatars.githubusercontent.com/u/1785821?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xxcdd"><img src="https://avatars.githubusercontent.com/u/42600601?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/chen2aaron"><img src="https://avatars.githubusercontent.com/u/9978183?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/voidz0r"><img src="https://avatars.githubusercontent.com/u/1032286?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vince-isec"><img src="https://avatars.githubusercontent.com/u/149686094?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/true13"><img src="https://avatars.githubusercontent.com/u/18207552?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/skhalsa-sigsci"><img src="https://avatars.githubusercontent.com/u/68570441?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ShuBo6"><img src="https://avatars.githubusercontent.com/u/41125338?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/seeyarh"><img src="https://avatars.githubusercontent.com/u/16869800?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/securibee"><img src="https://avatars.githubusercontent.com/u/51520913?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sduc"><img src="https://avatars.githubusercontent.com/u/2879617?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/scottdharvey"><img src="https://avatars.githubusercontent.com/u/25498254?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rykkard"><img src="https://avatars.githubusercontent.com/u/51889048?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/monitor403"><img src="https://avatars.githubusercontent.com/u/45124775?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mlec1"><img src="https://avatars.githubusercontent.com/u/42201667?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/meme-lord"><img src="https://avatars.githubusercontent.com/u/17912559?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/LazyMaple"><img src="https://avatars.githubusercontent.com/u/12314941?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lvyaoting"><img src="https://avatars.githubusercontent.com/u/166296299?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/llussy"><img src="https://avatars.githubusercontent.com/u/18432966?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/linchizhen"><img src="https://avatars.githubusercontent.com/u/170242051?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kiokuless"><img src="https://avatars.githubusercontent.com/u/110003596?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Jarnpher553"><img src="https://avatars.githubusercontent.com/u/10233873?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/c-f"><img src="https://avatars.githubusercontent.com/u/35263248?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hanghuge"><img src="https://avatars.githubusercontent.com/u/166206050?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/testwill"><img src="https://avatars.githubusercontent.com/u/8717479?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/galoget"><img src="https://avatars.githubusercontent.com/u/8353133?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/fudancoder"><img src="https://avatars.githubusercontent.com/u/171416994?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/revolunet"><img src="https://avatars.githubusercontent.com/u/124937?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jsoref"><img src="https://avatars.githubusercontent.com/u/2119212?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MachadoOtto"><img src="https://avatars.githubusercontent.com/u/93268441?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jonathanwalker"><img src="https://avatars.githubusercontent.com/u/14978093?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/nHurD"><img src="https://avatars.githubusercontent.com/u/233374?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
|
||||
+51
-3
@@ -1651,6 +1651,19 @@ FuzzPreConditionOperator is the operator between multiple PreConditions for fuzz
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>global-matchers</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
GlobalMatchers marks matchers as static and applies globally to all result events from other templates
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3210,6 +3223,19 @@ read-all: false
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>stop-at-first-match</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3764,11 +3790,33 @@ Appears in:
|
||||
Part Definitions:
|
||||
|
||||
|
||||
- <code>type</code> - Type is the type of request made
|
||||
- <code>response</code> - JSON SSL protocol handshake details
|
||||
- <code>not_after</code> - Timestamp after which the remote cert expires
|
||||
- <code>template-id</code> - ID of the template executed
|
||||
- <code>template-info</code> - Info Block of the template executed
|
||||
- <code>template-path</code> - Path of the template executed
|
||||
- <code>host</code> - Host is the input to the template
|
||||
- <code>port</code> - Port is the port of the host
|
||||
- <code>matched</code> - Matched is the input which was matched upon
|
||||
- <code>type</code> - Type is the type of request made
|
||||
- <code>timestamp</code> - Timestamp is the time when the request was made
|
||||
- <code>response</code> - JSON SSL protocol handshake details
|
||||
- <code>cipher</code> - Cipher is the encryption algorithm used
|
||||
- <code>domains</code> - Domains are the list of domain names in the certificate
|
||||
- <code>fingerprint_hash</code> - Fingerprint hash is the unique identifier of the certificate
|
||||
- <code>ip</code> - IP is the IP address of the server
|
||||
- <code>issuer_cn</code> - Issuer CN is the common name of the certificate issuer
|
||||
- <code>issuer_dn</code> - Issuer DN is the distinguished name of the certificate issuer
|
||||
- <code>issuer_org</code> - Issuer organization is the organization of the certificate issuer
|
||||
- <code>not_after</code> - Timestamp after which the remote cert expires
|
||||
- <code>not_before</code> - Timestamp before which the certificate is not valid
|
||||
- <code>probe_status</code> - Probe status indicates if the probe was successful
|
||||
- <code>serial</code> - Serial is the serial number of the certificate
|
||||
- <code>sni</code> - SNI is the server name indication used in the handshake
|
||||
- <code>subject_an</code> - Subject AN is the list of subject alternative names
|
||||
- <code>subject_cn</code> - Subject CN is the common name of the certificate subject
|
||||
- <code>subject_dn</code> - Subject DN is the distinguished name of the certificate subject
|
||||
- <code>subject_org</code> - Subject organization is the organization of the certificate subject
|
||||
- <code>tls_connection</code> - TLS connection is the type of TLS connection used
|
||||
- <code>tls_version</code> - TLS version is the version of the TLS protocol used
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
@@ -162,3 +162,14 @@
|
||||
# duplicate-issue-check: false
|
||||
# # open-state-id is the ID of the open state in Linear
|
||||
# open-state-id: ""
|
||||
#mongodb:
|
||||
# # the connection string to the MongoDB database
|
||||
# # (e.g., mongodb://root:example@localhost:27017/nuclei?ssl=false&authSource=admin)
|
||||
# connection-string: ""
|
||||
# # the name of the collection to store the issues
|
||||
# collection-name: ""
|
||||
# # excludes the Request and Response from the results (helps with filesize)
|
||||
# omit-raw: false
|
||||
# # determines the number of results to be kept in memory before writing it to the database or 0 to
|
||||
# # persist all in memory and write all results at the end (default)
|
||||
# batch-size: 0
|
||||
+31
-10
@@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -103,21 +104,40 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Profiling related code
|
||||
// Profiling & tracing related code
|
||||
if memProfile != "" {
|
||||
f, err := os.Create(memProfile)
|
||||
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".prof"
|
||||
memProfileFile, err := os.Create(memProfile)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q file: %v", memProfile, err)
|
||||
}
|
||||
old := runtime.MemProfileRate
|
||||
|
||||
traceFilepath := strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".trace"
|
||||
traceFile, err := os.Create(traceFilepath)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create trace %q file: %v", traceFilepath, err)
|
||||
}
|
||||
|
||||
oldMemProfileRate := runtime.MemProfileRate
|
||||
runtime.MemProfileRate = 4096
|
||||
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
|
||||
|
||||
// Start tracing
|
||||
if err := trace.Start(traceFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = pprof.Lookup("heap").WriteTo(f, 0)
|
||||
f.Close()
|
||||
runtime.MemProfileRate = old
|
||||
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
|
||||
// Start CPU profiling
|
||||
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
|
||||
}
|
||||
memProfileFile.Close()
|
||||
traceFile.Close()
|
||||
trace.Stop()
|
||||
runtime.MemProfileRate = oldMemProfileRate
|
||||
|
||||
gologger.Info().Msgf("Memory profile saved at %q", memProfile)
|
||||
gologger.Info().Msgf("Traced at %q", traceFilepath)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -402,9 +422,10 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CallbackVar(printVersion, "version", "show nuclei version"),
|
||||
flagSet.BoolVarP(&options.HangMonitor, "hang-monitor", "hm", false, "enable nuclei hang monitoring"),
|
||||
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "generate memory (heap) profile & trace files"),
|
||||
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
||||
flagSet.BoolVarP(&options.ShowVarDump, "show-var-dump", "svd", false, "show variables dump for debugging"),
|
||||
flagSet.IntVarP(&options.VarDumpLimit, "var-dump-limit", "vdl", 255, "limit the number of characters displayed in var dump"),
|
||||
flagSet.BoolVarP(&options.EnablePprof, "enable-pprof", "ep", false, "enable pprof debugging server"),
|
||||
flagSet.CallbackVarP(printTemplateVersion, "templates-version", "tv", "shows the version of the installed nuclei-templates"),
|
||||
flagSet.BoolVarP(&options.HealthCheck, "health-check", "hc", false, "run diagnostic check up"),
|
||||
|
||||
+4
-4
@@ -21,9 +21,9 @@ WORKFLOW="Build Test"
|
||||
GREP_ERROR_PATTERN='Test "http/interactsh.yaml" failed'
|
||||
|
||||
#Set fonts for Help.
|
||||
NORM=`tput sgr0`
|
||||
BOLD=`tput bold`
|
||||
REV=`tput smso`
|
||||
NORM=$(tput sgr0)
|
||||
BOLD=$(tput bold)
|
||||
REV=$(tput smso)
|
||||
|
||||
HELP()
|
||||
{
|
||||
@@ -73,7 +73,7 @@ function print_bold() {
|
||||
function retry_failed_jobs() {
|
||||
print_bold "Checking failed workflows for branch $BRANCH before $BEFORE"
|
||||
|
||||
date=`date +%Y-%m-%d'T'%H:%M'Z' -d "$BEFORE"`
|
||||
date=$(date +%Y-%m-%d'T'%H:%M'Z' -d "$BEFORE")
|
||||
|
||||
workflowIds=$(gh run list --limit "$LIMIT" --json headBranch,status,name,conclusion,databaseId,updatedAt | jq -c '.[] |
|
||||
select ( .headBranch==$branch ) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/projectdiscovery/nuclei/v3
|
||||
|
||||
go 1.21
|
||||
go 1.21.0
|
||||
|
||||
require (
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
|
||||
@@ -21,11 +21,11 @@ require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/projectdiscovery/clistats v0.1.1
|
||||
github.com/projectdiscovery/fastdialer v0.2.9
|
||||
github.com/projectdiscovery/hmap v0.0.59
|
||||
github.com/projectdiscovery/hmap v0.0.62
|
||||
github.com/projectdiscovery/interactsh v1.2.0
|
||||
github.com/projectdiscovery/rawhttp v0.1.67
|
||||
github.com/projectdiscovery/retryabledns v1.0.77
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78
|
||||
github.com/projectdiscovery/rawhttp v0.1.70
|
||||
github.com/projectdiscovery/retryabledns v1.0.80
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@@ -81,30 +81,32 @@ require (
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/ory/dockertest/v3 v3.10.0
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9
|
||||
github.com/projectdiscovery/dsl v0.2.1
|
||||
github.com/projectdiscovery/dsl v0.3.0
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
||||
github.com/projectdiscovery/goflags v0.1.64
|
||||
github.com/projectdiscovery/gologger v1.1.24
|
||||
github.com/projectdiscovery/gologger v1.1.28
|
||||
github.com/projectdiscovery/gostruct v0.0.2
|
||||
github.com/projectdiscovery/gozero v0.0.2
|
||||
github.com/projectdiscovery/httpx v1.6.8
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32
|
||||
github.com/projectdiscovery/httpx v1.6.9
|
||||
github.com/projectdiscovery/mapcidr v1.1.34
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/ratelimit v0.0.56
|
||||
github.com/projectdiscovery/ratelimit v0.0.60
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.7
|
||||
github.com/projectdiscovery/uncover v1.0.9
|
||||
github.com/projectdiscovery/useragent v0.0.71
|
||||
github.com/projectdiscovery/utils v0.2.11
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18
|
||||
github.com/projectdiscovery/utils v0.2.15
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22
|
||||
github.com/redis/go-redis/v9 v9.1.0
|
||||
github.com/seh-msft/burpxml v1.0.1
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9
|
||||
github.com/yassinebenaid/godump v0.10.0
|
||||
github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706
|
||||
go.mongodb.org/mongo-driver v1.17.0
|
||||
golang.org/x/term v0.24.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
moul.io/http2curl v1.0.0
|
||||
@@ -195,6 +197,7 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
@@ -207,7 +210,7 @@ require (
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/projectdiscovery/asnmap v1.1.1 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.1.0 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.6 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.7 // indirect
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
|
||||
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect
|
||||
github.com/refraction-networking/utls v1.6.7 // indirect
|
||||
@@ -228,9 +231,13 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/ysmood/fetchup v0.2.3 // indirect
|
||||
github.com/ysmood/got v0.34.1 // indirect
|
||||
github.com/yuin/goldmark v1.7.4 // indirect
|
||||
|
||||
@@ -755,6 +755,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
@@ -843,28 +845,30 @@ github.com/projectdiscovery/cdncheck v1.1.0 h1:qDITidmJsejzpk3rMkauCh6sjI2GH9hW/
|
||||
github.com/projectdiscovery/cdncheck v1.1.0/go.mod h1:sZ8U4MjHSsyaTVjBbYWHT1cwUVvUYwDX1W+WvWRicIc=
|
||||
github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE=
|
||||
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
|
||||
github.com/projectdiscovery/dsl v0.2.1 h1:TK3KD4jsg4YbvY7WJqnz1QyH4AOvAwezeBFOX97Evgk=
|
||||
github.com/projectdiscovery/dsl v0.2.1/go.mod h1:IRQXsmi5/g1dDZ79//A9t2vrRtxm4frRSd5t8CZVSbI=
|
||||
github.com/projectdiscovery/dsl v0.3.0 h1:NzU6WcJ8GFQ676IVefrxC5nk/bvb7FCuhmp8tbNC9dQ=
|
||||
github.com/projectdiscovery/dsl v0.3.0/go.mod h1:GMVxLtQuQUc/RmSn3jQxGCI4yit3iyf2AoZxUoXbsb0=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9 h1:vDCqxVMCyUu3oVEizEK1K8K+CCcLkVDW3X2HfiWaVFA=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9/go.mod h1:mYv5QaNBDDSHlZO9DI0niRMw+G5hUzwIhs8QixSElUI=
|
||||
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.6 h1:ROqzuXN8JPqkGdBueb3ah691nS2g2p7r3/3x2E33GbI=
|
||||
github.com/projectdiscovery/freeport v0.0.6/go.mod h1:T2kIy+WrbyxBIhI8V3Y9aeNGnuhnM8tEUSK/cm9GjAg=
|
||||
github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk=
|
||||
github.com/projectdiscovery/freeport v0.0.7/go.mod h1:cOhWKvNBe9xM6dFJ3RrrLvJ5vXx2NQ36SecuwjenV2k=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG906Drtbpz4DwU5mhGIeOhRcktDH4cGQitGUMAsg=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY=
|
||||
github.com/projectdiscovery/goflags v0.1.64 h1:FDfwdt9N97Hi8OuhbkDlKtVttpc/CRMIWQVa08VsHsI=
|
||||
github.com/projectdiscovery/goflags v0.1.64/go.mod h1:3FyHIVQtnycNOc1LE3O1jj/XR5XuMdF9QfHd0ujhnX4=
|
||||
github.com/projectdiscovery/gologger v1.1.24 h1:TmA4k9sA6ZvfyRnprZKQ0Uq34g//u5R9yTDPL9IzTOQ=
|
||||
github.com/projectdiscovery/gologger v1.1.24/go.mod h1:JA0JMJ+ply+J2wD062TN4h85thm6/28jAlrntwccKVU=
|
||||
github.com/projectdiscovery/gologger v1.1.28 h1:3OYYnoEaHAYkPm2c2KgUifBDPy93JCQq1hl5ICtpJT8=
|
||||
github.com/projectdiscovery/gologger v1.1.28/go.mod h1:rB7xNi4tcx/HqpQu4QgpFIopIg8SNF/VBc6cTeQLqWQ=
|
||||
github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
|
||||
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
|
||||
github.com/projectdiscovery/gozero v0.0.2 h1:8fJeaCjxL9tpm33uG/RsCQs6HGM/NE6eA3cjkilRQ+E=
|
||||
github.com/projectdiscovery/gozero v0.0.2/go.mod h1:d8bZvDWW07LWNYWrwjZ4OO1I0cpkfqaysyDfSs9ibK8=
|
||||
github.com/projectdiscovery/hmap v0.0.59 h1:xWCr/GY2QJanFzwKydh/EkGdOKM4iAcN9hQvvCMgO6A=
|
||||
github.com/projectdiscovery/hmap v0.0.59/go.mod h1:uHhhnPmvq9qXvCjBSQXCBAlmA1r8JGufP775IkBSbgs=
|
||||
github.com/projectdiscovery/httpx v1.6.8 h1:k0Y5g3ue/7QbDP0+LykIxp/VhPDLfau3UEUyuxtP7qE=
|
||||
github.com/projectdiscovery/httpx v1.6.8/go.mod h1:7BIsDxyRwkBjthqFmEajXrA5f3yb4tlVfLmpNdf0ZXA=
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32 h1:PubQkk+F/BiW4+wqBhWiMwPEKYxi/LdYXjxUtHd/tpM=
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32/go.mod h1:d8bZvDWW07LWNYWrwjZ4OO1I0cpkfqaysyDfSs9ibK8=
|
||||
github.com/projectdiscovery/hmap v0.0.62 h1:Pb3omgGQkRHB2EBDhgXniUXVC8Jz2CBzpSMKZYRUKFs=
|
||||
github.com/projectdiscovery/hmap v0.0.62/go.mod h1:pNheW3ukrLOcRUDFWrq8OAZiizhosDonIKRVg/4PGnM=
|
||||
github.com/projectdiscovery/httpx v1.6.9 h1:ihyFclesLjvQpiJpRIlAYeebapyIbOI/arDAvvy1ES8=
|
||||
github.com/projectdiscovery/httpx v1.6.9/go.mod h1:zQtX5CtcDYXzIRWne1ztCVtqG0sXCnx84tFwfMHoB8Q=
|
||||
github.com/projectdiscovery/interactsh v1.2.0 h1:Al6jHiR+Usl9egYJDLJaWNHOcH8Rugk8gWMasc8Cmw8=
|
||||
github.com/projectdiscovery/interactsh v1.2.0/go.mod h1:Wxt0fnzxsfrAZQQlpVrf3xMatP4OXZaZbjuDkIQKdYY=
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8=
|
||||
@@ -877,16 +881,16 @@ github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9 h1:IrlDoYZagNNO8y+7iZeHT8k5izE+nek7TdtvEBwCxqk=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9/go.mod h1:XFJ2Lnv8BE/ziQCFjBHMsH1w6VmkPiQtk+NlBpdMU7M=
|
||||
github.com/projectdiscovery/ratelimit v0.0.56 h1:WliU7NvfMb5hK/IJjOFlWIXU1G7+QRylMhSybaSCTI8=
|
||||
github.com/projectdiscovery/ratelimit v0.0.56/go.mod h1:GbnAo+MbB4R/4jiOI1mH4KAJfovmrPnq4NElcI99fvs=
|
||||
github.com/projectdiscovery/rawhttp v0.1.67 h1:HYzathMk3c8Y83hYjHM4GCBFbz/G+vABe0Lz6ajaowY=
|
||||
github.com/projectdiscovery/rawhttp v0.1.67/go.mod h1:5viJ6odzc9ZuEFppj/E7HdX+u99FoYlvXnhHyTNc7N0=
|
||||
github.com/projectdiscovery/ratelimit v0.0.60 h1:8nz8gVPPIH7by8ZZKY4LnsjwrlKPkQzJiTACILIdqvo=
|
||||
github.com/projectdiscovery/ratelimit v0.0.60/go.mod h1:ld9toJ1gj8E92pJz5/WFClEaoa6ke5xS62JIYMbctGk=
|
||||
github.com/projectdiscovery/rawhttp v0.1.70 h1:tzCns5KLL98qLYJwSSCdjT41ljX8G58lDrL20gL1YZ8=
|
||||
github.com/projectdiscovery/rawhttp v0.1.70/go.mod h1:fv/488Z6p5ifZ9hl/MWGYOoaDvpR7lV7IOMwIl8mATo=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.77 h1:rCFSiTPNI7h9PP1uUvrmcq/6XVZVdxpha2H1ioArKpk=
|
||||
github.com/projectdiscovery/retryabledns v1.0.77/go.mod h1:ce1JTjAOxLujqITtA5VLlbhLRVubx+GETYasivapai4=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78 h1:If7/XjCWk893YrnTMaW69TNMsfE1Er3i1SWOkWbEk4E=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78/go.mod h1:NqzTdnGihSRkF9c/aXo+3qTJXEeNwnOuza6GrlPo9qw=
|
||||
github.com/projectdiscovery/retryabledns v1.0.80 h1:P1oqWHZdF/IMtxXV4mrtENTNsghYojVlrNcv8dZAMu8=
|
||||
github.com/projectdiscovery/retryabledns v1.0.80/go.mod h1:BdCE4+Lph6hkNx+f+EjOnG+K8Z6shFWs9ZiTj6YcNvU=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82 h1:XS+ZEKO291KGZVhHMO+RhvNvVE+IK8VHeM5i6CQ4Ixc=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82/go.mod h1:JvlWId6aXT8en1ly22///wHoRQwSsMNAttdJ/YkhHHY=
|
||||
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=
|
||||
@@ -897,10 +901,10 @@ github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0Jpre
|
||||
github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U=
|
||||
github.com/projectdiscovery/useragent v0.0.71 h1:Q02L3LV15ztOQ6FfmVSqVmOd5QhvzI+yAgYOc/32Nvg=
|
||||
github.com/projectdiscovery/useragent v0.0.71/go.mod h1:DHPruFLCvCvkd2qqPwwQZrP9sziv0lxQJ0R1rE1fa8E=
|
||||
github.com/projectdiscovery/utils v0.2.11 h1:TO7fBG5QI256sn1YuTD87yn4+4OjGJ2wT1772uEnp4Q=
|
||||
github.com/projectdiscovery/utils v0.2.11/go.mod h1:W0E74DWkKxlcyKS5XwcAwiob7+smoszPPi1NgX3vZyk=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18 h1:fFgETis0HcsNE7wREaUPYP45JqIyHgGorJaVp1RH7g4=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18/go.mod h1:/hzgxkBFTMe2wDbA93nFfoMjULw7/vIZ9QPSAnCgUa8=
|
||||
github.com/projectdiscovery/utils v0.2.15 h1:FO3n7uhLazHtat3qBxWIq0JCfLoR/IvP5JXAOSKaQ5w=
|
||||
github.com/projectdiscovery/utils v0.2.15/go.mod h1:2NAFRu8j/82bkVqx2TcsZFdgtUOnHEUi7u6s3lv79Lo=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22 h1:7QnpeZy/txsvVcQNlL1n4xIu8IXgMxEsda3w6k6bShY=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22/go.mod h1:wnvmbC10pQTOoCKnCTmWKP20rpEtqrMJZvzuTuleeyw=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4/go.mod h1:8PIPRcUD55UbtQdcfFR1hpIGRWG0P7alClXNGt1TBik=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -1085,6 +1089,12 @@ github.com/xanzy/go-gitlab v0.107.0 h1:P2CT9Uy9yN9lJo3FLxpMZ4xj6uWcpnigXsjvqJ6nd
|
||||
github.com/xanzy/go-gitlab v0.107.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -1096,8 +1106,12 @@ github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yassinebenaid/godump v0.10.0 h1:FolBA+Ix5uwUiXYBBYOsf1VkT5+0f4gtFNTkYTiIR08=
|
||||
github.com/yassinebenaid/godump v0.10.0/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44=
|
||||
github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
|
||||
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
|
||||
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
|
||||
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
|
||||
@@ -1150,6 +1164,8 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k=
|
||||
go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
||||
@@ -68,6 +68,7 @@ func ParseOptions(options *types.Options) {
|
||||
|
||||
if options.ShowVarDump {
|
||||
vardump.EnableVarDump = true
|
||||
vardump.Limit = options.VarDumpLimit
|
||||
}
|
||||
if options.ShowActions {
|
||||
gologger.Info().Msgf("Showing available headless actions: ")
|
||||
|
||||
@@ -48,6 +48,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/automaticscan"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/globalmatchers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/hosterrorscache"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolinit"
|
||||
@@ -475,6 +476,7 @@ func (r *Runner) RunEnumeration() error {
|
||||
TemporaryDirectory: r.tmpDir,
|
||||
Parser: r.parser,
|
||||
FuzzParamsFrequency: fuzzFreqCache,
|
||||
GlobalMatchers: globalmatchers.New(),
|
||||
}
|
||||
|
||||
if config.DefaultConfig.IsDebugArgEnabled(config.DebugExportURLPattern) {
|
||||
|
||||
@@ -100,6 +100,7 @@ func (e *NucleiEngine) LoadAllTemplates() error {
|
||||
return errorutil.New("Could not create loader client: %s\n", err)
|
||||
}
|
||||
e.store.Load()
|
||||
e.templatesLoaded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package nuclei
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -171,6 +172,7 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Browser: e.browserInstance,
|
||||
Parser: e.parser,
|
||||
InputHelper: input.NewHelper(),
|
||||
}
|
||||
if len(e.opts.SecretsFile) > 0 {
|
||||
authTmplStore, err := runner.GetAuthTmplStore(*e.opts, e.catalog, e.executerOpts)
|
||||
|
||||
@@ -889,6 +889,11 @@
|
||||
],
|
||||
"title": "condition between the filters",
|
||||
"description": "Operator to use between multiple per-conditions"
|
||||
},
|
||||
"global-matchers": {
|
||||
"type": "boolean",
|
||||
"title": "global matchers",
|
||||
"description": "marks matchers as static and applies globally to all result events from other templates"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -1365,6 +1370,11 @@
|
||||
"title": "read all response stream",
|
||||
"description": "Read all response stream till the server stops sending"
|
||||
},
|
||||
"stop-at-first-match": {
|
||||
"type": "boolean",
|
||||
"title": "stop at first match",
|
||||
"description": "Stop the execution after a match is found"
|
||||
},
|
||||
"matchers": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/matchers.Matcher"
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
CLIConfigFileName = "config.yaml"
|
||||
ReportingConfigFilename = "reporting-config.yaml"
|
||||
// Version is the current version of nuclei
|
||||
Version = `v3.3.4`
|
||||
Version = `v3.3.5`
|
||||
// Directory Names of custom templates
|
||||
CustomS3TemplatesDirName = "s3"
|
||||
CustomGitHubTemplatesDirName = "github"
|
||||
|
||||
@@ -353,6 +353,20 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
|
||||
if isParsingError("Error occurred parsing template %s: %s\n", templatePath, err) {
|
||||
areTemplatesValid = false
|
||||
}
|
||||
} else if template == nil {
|
||||
// NOTE(dwisiswant0): possibly global matchers template.
|
||||
// This could definitely be handled better, for example by returning an
|
||||
// `ErrGlobalMatchersTemplate` during `templates.Parse` and checking it
|
||||
// with `errors.Is`.
|
||||
//
|
||||
// However, I’m not sure if every reference to it should be handled
|
||||
// that way. Returning a `templates.Template` pointer would mean it’s
|
||||
// an active template (sending requests), and adding a specific field
|
||||
// like `isGlobalMatchers` in `templates.Template` (then checking it
|
||||
// with a `*templates.Template.IsGlobalMatchersEnabled` method) would
|
||||
// just introduce more unknown issues - like during template
|
||||
// clustering, AFAIK.
|
||||
continue
|
||||
} else {
|
||||
if existingTemplatePath, found := templateIDPathMap[template.ID]; !found {
|
||||
templateIDPathMap[template.ID] = templatePath
|
||||
|
||||
@@ -6,12 +6,19 @@ import (
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
)
|
||||
|
||||
type MultiPartForm struct {
|
||||
boundary string
|
||||
boundary string
|
||||
filesMetadata map[string]FileMetadata
|
||||
}
|
||||
|
||||
type FileMetadata struct {
|
||||
ContentType string
|
||||
Filename string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -41,11 +48,40 @@ func (m *MultiPartForm) Encode(data KV) (string, error) {
|
||||
data.Iterate(func(key string, value any) bool {
|
||||
var fw io.Writer
|
||||
var err error
|
||||
|
||||
if filesArray, ok := value.([]interface{}); ok {
|
||||
fileMetadata, ok := m.filesMetadata[key]
|
||||
if !ok {
|
||||
Itererr = fmt.Errorf("file metadata not found for key %s", key)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, file := range filesArray {
|
||||
h := make(textproto.MIMEHeader)
|
||||
h.Set("Content-Disposition",
|
||||
fmt.Sprintf(`form-data; name=%q; filename=%q`,
|
||||
key, fileMetadata.Filename))
|
||||
h.Set("Content-Type", fileMetadata.ContentType)
|
||||
|
||||
if fw, err = w.CreatePart(h); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(file.(string))); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Add field
|
||||
if fw, err = w.CreateFormField(key); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(value.(string))); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
@@ -98,6 +134,7 @@ func (m *MultiPartForm) Decode(data string) (KV, error) {
|
||||
result.Set(key, values[0])
|
||||
}
|
||||
}
|
||||
m.filesMetadata = make(map[string]FileMetadata)
|
||||
for key, files := range form.File {
|
||||
fileContents := []interface{}{}
|
||||
for _, fileHeader := range files {
|
||||
@@ -112,6 +149,11 @@ func (m *MultiPartForm) Decode(data string) (KV, error) {
|
||||
return KV{}, err
|
||||
}
|
||||
fileContents = append(fileContents, buffer.String())
|
||||
|
||||
m.filesMetadata[key] = FileMetadata{
|
||||
ContentType: fileHeader.Header.Get("Content-Type"),
|
||||
Filename: fileHeader.Filename,
|
||||
}
|
||||
}
|
||||
result.Set(key, fileContents)
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object {
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// client.Authenticate('user', 'password');
|
||||
// ```
|
||||
func (c *Client) Authenticate(username, password string) {
|
||||
func (c *Client) Authenticate(username, password string) bool {
|
||||
c.nj.Require(c.conn != nil, "no existing connection")
|
||||
if c.BaseDN == "" {
|
||||
c.BaseDN = fmt.Sprintf("dc=%s", strings.Join(strings.Split(c.Realm, "."), ",dc="))
|
||||
@@ -163,19 +163,21 @@ func (c *Client) Authenticate(username, password string) {
|
||||
if err := c.conn.NTLMBind(c.Realm, username, password); err == nil {
|
||||
// if bind with NTLMBind(), there is nothing
|
||||
// else to do, you are authenticated
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
var err error
|
||||
switch password {
|
||||
case "":
|
||||
if err := c.conn.UnauthenticatedBind(username); err != nil {
|
||||
if err = c.conn.UnauthenticatedBind(username); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
default:
|
||||
if err := c.conn.Bind(username, password); err != nil {
|
||||
if err = c.conn.Bind(username, password); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// AuthenticateWithNTLMHash authenticates with the ldap server using the given username and NTLM hash
|
||||
@@ -185,14 +187,16 @@ func (c *Client) Authenticate(username, password string) {
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// client.AuthenticateWithNTLMHash('pdtm', 'hash');
|
||||
// ```
|
||||
func (c *Client) AuthenticateWithNTLMHash(username, hash string) {
|
||||
func (c *Client) AuthenticateWithNTLMHash(username, hash string) bool {
|
||||
c.nj.Require(c.conn != nil, "no existing connection")
|
||||
if c.BaseDN == "" {
|
||||
c.BaseDN = fmt.Sprintf("dc=%s", strings.Join(strings.Split(c.Realm, "."), ",dc="))
|
||||
}
|
||||
if err := c.conn.NTLMBindWithHash(c.Realm, username, hash); err != nil {
|
||||
var err error
|
||||
if err = c.conn.NTLMBindWithHash(c.Realm, username, hash); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Search accepts whatever filter and returns a list of maps having provided attributes
|
||||
@@ -279,9 +283,10 @@ func (c *Client) CollectMetadata() Metadata {
|
||||
}
|
||||
metadata.BaseDN = c.BaseDN
|
||||
|
||||
// Use scope as Base since Root DSE doesn't have subentries
|
||||
srMetadata := ldap.NewSearchRequest(
|
||||
"",
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.ScopeBaseObject,
|
||||
ldap.NeverDerefAliases,
|
||||
0, 0, false,
|
||||
"(objectClass=*)",
|
||||
|
||||
@@ -39,6 +39,11 @@ func (w *StandardWriter) formatScreen(output *ResultEvent) []byte {
|
||||
}
|
||||
}
|
||||
|
||||
if output.GlobalMatchers {
|
||||
builder.WriteString("] [")
|
||||
builder.WriteString(w.aurora.BrightMagenta("global").String())
|
||||
}
|
||||
|
||||
builder.WriteString("] [")
|
||||
builder.WriteString(w.aurora.BrightBlue(output.Type).String())
|
||||
builder.WriteString("] ")
|
||||
|
||||
@@ -184,6 +184,9 @@ type ResultEvent struct {
|
||||
MatcherStatus bool `json:"matcher-status"`
|
||||
// Lines is the line count for the specified match
|
||||
Lines []int `json:"matched-line,omitempty"`
|
||||
// GlobalMatchers identifies whether the matches was detected in the response
|
||||
// of another template's result event
|
||||
GlobalMatchers bool `json:"global-matchers,omitempty"`
|
||||
|
||||
// IssueTrackers is the metadata for issue trackers
|
||||
IssueTrackers map[string]IssueTrackerMetadata `json:"issue_trackers,omitempty"`
|
||||
|
||||
@@ -235,7 +235,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
gologger.Verbose().Msgf("[%s] Executed code on local machine %v", request.options.TemplateID, input.MetaInput.Input)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Code Protocol request variables: \n%s\n", vardump.DumpVariables(allvars))
|
||||
gologger.Debug().Msgf("Code Protocol request variables: %s\n", vardump.DumpVariables(allvars))
|
||||
}
|
||||
|
||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||
|
||||
@@ -39,3 +39,34 @@ func TestCodeProtocol(t *testing.T) {
|
||||
require.Nil(t, err, "could not run code request")
|
||||
require.NotEmpty(t, gotEvent, "could not get event items")
|
||||
}
|
||||
|
||||
func TestCodeProtocolForGO(t *testing.T) {
|
||||
options := testutils.DefaultOptions
|
||||
|
||||
testutils.Init(options)
|
||||
templateID := "testing-code"
|
||||
request := &Request{
|
||||
Engine: []string{"go"},
|
||||
Source: `package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("hello world")
|
||||
}`,
|
||||
}
|
||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||
ID: templateID,
|
||||
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "hello-world"},
|
||||
})
|
||||
err := request.Compile(executerOpts)
|
||||
require.Nil(t, err, "could not compile code request")
|
||||
|
||||
var gotEvent output.InternalEvent
|
||||
ctxArgs := contextargs.NewWithInput(context.Background(), "")
|
||||
err = request.ExecuteWithResults(ctxArgs, nil, nil, func(event *output.InternalWrappedEvent) {
|
||||
gotEvent = event.InternalEvent
|
||||
})
|
||||
require.Nil(t, err, "could not run code request")
|
||||
require.NotEmpty(t, gotEvent, "could not get event items")
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package globalmatchers
|
||||
|
||||
import (
|
||||
"maps"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
)
|
||||
|
||||
// Storage is a struct that holds the global matchers
|
||||
type Storage struct {
|
||||
requests []*Item
|
||||
}
|
||||
|
||||
// Callback is called when a global matcher is matched.
|
||||
// It receives internal event & result of the operator execution.
|
||||
type Callback func(event output.InternalEvent, result *operators.Result)
|
||||
|
||||
// Item is a struct that holds the global matchers
|
||||
// details for a template
|
||||
type Item struct {
|
||||
TemplateID string
|
||||
TemplatePath string
|
||||
TemplateInfo model.Info
|
||||
Operators []*operators.Operators
|
||||
}
|
||||
|
||||
// New creates a new storage for global matchers
|
||||
func New() *Storage {
|
||||
return &Storage{requests: make([]*Item, 0)}
|
||||
}
|
||||
|
||||
// hasStorage checks if the Storage is initialized
|
||||
func (s *Storage) hasStorage() bool {
|
||||
return s != nil
|
||||
}
|
||||
|
||||
// AddOperator adds a new operator to the global matchers
|
||||
func (s *Storage) AddOperator(item *Item) {
|
||||
if !s.hasStorage() {
|
||||
return
|
||||
}
|
||||
|
||||
s.requests = append(s.requests, item)
|
||||
}
|
||||
|
||||
// HasMatchers returns true if we have global matchers
|
||||
func (s *Storage) HasMatchers() bool {
|
||||
if !s.hasStorage() {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(s.requests) > 0
|
||||
}
|
||||
|
||||
// Match matches the global matchers against the response
|
||||
func (s *Storage) Match(
|
||||
event output.InternalEvent,
|
||||
matchFunc operators.MatchFunc,
|
||||
extractFunc operators.ExtractFunc,
|
||||
isDebug bool,
|
||||
callback Callback,
|
||||
) {
|
||||
for _, item := range s.requests {
|
||||
for _, operator := range item.Operators {
|
||||
newEvent := maps.Clone(event)
|
||||
newEvent.Set("origin-template-id", event["template-id"])
|
||||
newEvent.Set("origin-template-info", event["template-info"])
|
||||
newEvent.Set("origin-template-path", event["template-path"])
|
||||
newEvent.Set("template-id", item.TemplateID)
|
||||
newEvent.Set("template-info", item.TemplateInfo)
|
||||
newEvent.Set("template-path", item.TemplatePath)
|
||||
newEvent.Set("global-matchers", true)
|
||||
|
||||
result, matched := operator.Execute(newEvent, matchFunc, extractFunc, isDebug)
|
||||
if !matched {
|
||||
continue
|
||||
}
|
||||
|
||||
callback(newEvent, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func CreateEventWithAdditionalOptions(request protocols.Request, outputEvent out
|
||||
// Dump response variables if ran in debug mode
|
||||
if vardump.EnableVarDump {
|
||||
protoName := cases.Title(language.English).String(request.Type().String())
|
||||
gologger.Debug().Msgf("%v Protocol response variables: \n%s\n", protoName, vardump.DumpVariables(outputEvent))
|
||||
gologger.Debug().Msgf("%v Protocol response variables: %s\n", protoName, vardump.DumpVariables(outputEvent))
|
||||
}
|
||||
for _, compiledOperator := range request.GetCompiledOperators() {
|
||||
if compiledOperator != nil {
|
||||
|
||||
@@ -77,9 +77,8 @@ var muGlobalChange sync.Mutex
|
||||
|
||||
// Global setting
|
||||
func GlobalGuardBytesBufferAlloc() error {
|
||||
if muGlobalChange.TryLock() {
|
||||
if !muGlobalChange.TryLock() {
|
||||
return nil
|
||||
|
||||
}
|
||||
defer muGlobalChange.Unlock()
|
||||
|
||||
@@ -95,9 +94,8 @@ func GlobalGuardBytesBufferAlloc() error {
|
||||
|
||||
// Global setting
|
||||
func GlobalRestoreBytesBufferAlloc() {
|
||||
if muGlobalChange.TryLock() {
|
||||
if !muGlobalChange.TryLock() {
|
||||
return
|
||||
|
||||
}
|
||||
defer muGlobalChange.Unlock()
|
||||
|
||||
|
||||
@@ -1,53 +1,67 @@
|
||||
package vardump
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
"github.com/yassinebenaid/godump"
|
||||
)
|
||||
|
||||
// EnableVarDump enables var dump for debugging optionally
|
||||
var EnableVarDump bool
|
||||
// variables is a map of variables
|
||||
type variables = map[string]any
|
||||
|
||||
// DumpVariables writes the truncated dump of variables to a string
|
||||
// in a formatted key-value manner.
|
||||
//
|
||||
// The values are truncated to return 50 characters from start and end.
|
||||
func DumpVariables(data map[string]interface{}) string {
|
||||
var counter int
|
||||
// DumpVariables dumps the variables in a pretty format
|
||||
func DumpVariables(data variables) string {
|
||||
if !EnableVarDump {
|
||||
return ""
|
||||
}
|
||||
|
||||
buffer := &strings.Builder{}
|
||||
buffer.Grow(len(data) * 78) // grow buffer to an approximate size
|
||||
d := godump.Dumper{
|
||||
Indentation: " ",
|
||||
HidePrivateFields: false,
|
||||
ShowPrimitiveNamedTypes: true,
|
||||
}
|
||||
|
||||
builder := &strings.Builder{}
|
||||
// sort keys for deterministic output
|
||||
d.Theme = godump.Theme{
|
||||
String: godump.RGB{R: 138, G: 201, B: 38},
|
||||
Quotes: godump.RGB{R: 112, G: 214, B: 255},
|
||||
Bool: godump.RGB{R: 249, G: 87, B: 56},
|
||||
Number: godump.RGB{R: 10, G: 178, B: 242},
|
||||
Types: godump.RGB{R: 0, G: 150, B: 199},
|
||||
Address: godump.RGB{R: 205, G: 93, B: 0},
|
||||
PointerTag: godump.RGB{R: 110, G: 110, B: 110},
|
||||
Nil: godump.RGB{R: 219, G: 57, B: 26},
|
||||
Func: godump.RGB{R: 160, G: 90, B: 220},
|
||||
Fields: godump.RGB{R: 189, G: 176, B: 194},
|
||||
Chan: godump.RGB{R: 195, G: 154, B: 76},
|
||||
UnsafePointer: godump.RGB{R: 89, G: 193, B: 180},
|
||||
Braces: godump.RGB{R: 185, G: 86, B: 86},
|
||||
}
|
||||
|
||||
return d.Sprint(process(data, Limit))
|
||||
}
|
||||
|
||||
// process is a helper function that processes the variables
|
||||
// and returns a new map of variables
|
||||
func process(data variables, limit int) variables {
|
||||
keys := mapsutil.GetSortedKeys(data)
|
||||
vars := make(variables)
|
||||
|
||||
if limit == 0 {
|
||||
limit = 255
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
v := data[k]
|
||||
valueString := types.ToString(v)
|
||||
|
||||
counter++
|
||||
if len(valueString) > 50 {
|
||||
builder.Grow(56)
|
||||
builder.WriteString(valueString[0:25])
|
||||
builder.WriteString(" .... ")
|
||||
builder.WriteString(valueString[len(valueString)-25:])
|
||||
valueString = builder.String()
|
||||
builder.Reset()
|
||||
v := types.ToString(data[k])
|
||||
v = strings.ReplaceAll(strings.ReplaceAll(v, "\r", " "), "\n", " ")
|
||||
if len(v) > limit {
|
||||
v = v[:limit]
|
||||
v += " [...]"
|
||||
}
|
||||
valueString = strings.ReplaceAll(strings.ReplaceAll(valueString, "\r", " "), "\n", " ")
|
||||
|
||||
buffer.WriteString("\t")
|
||||
buffer.WriteString(strconv.Itoa(counter))
|
||||
buffer.WriteString(". ")
|
||||
buffer.WriteString(k)
|
||||
buffer.WriteString(" => ")
|
||||
buffer.WriteString(valueString)
|
||||
buffer.WriteString("\n")
|
||||
vars[k] = v
|
||||
}
|
||||
final := buffer.String()
|
||||
return final
|
||||
|
||||
return vars
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package vardump
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDumpVariables(t *testing.T) {
|
||||
// Enable var dump for testing
|
||||
EnableVarDump = true
|
||||
|
||||
// Test case
|
||||
testVars := variables{
|
||||
"string": "test",
|
||||
"int": 42,
|
||||
"bool": true,
|
||||
"slice": []string{"a", "b", "c"},
|
||||
}
|
||||
|
||||
result := DumpVariables(testVars)
|
||||
|
||||
// Assertions
|
||||
assert.NotEmpty(t, result)
|
||||
assert.Contains(t, result, "string")
|
||||
assert.Contains(t, result, "test")
|
||||
assert.Contains(t, result, "int")
|
||||
assert.Contains(t, result, "42")
|
||||
assert.Contains(t, result, "bool")
|
||||
assert.Contains(t, result, "true")
|
||||
assert.Contains(t, result, "slice")
|
||||
assert.Contains(t, result, "a")
|
||||
assert.Contains(t, result, "b")
|
||||
assert.Contains(t, result, "c")
|
||||
|
||||
// Test with EnableVarDump set to false
|
||||
EnableVarDump = false
|
||||
result = DumpVariables(testVars)
|
||||
assert.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestProcess(t *testing.T) {
|
||||
testVars := variables{
|
||||
"short": "short string",
|
||||
"long": strings.Repeat("a", 300),
|
||||
"number": 42,
|
||||
}
|
||||
|
||||
processed := process(testVars, 255)
|
||||
|
||||
assert.Equal(t, "short string", processed["short"])
|
||||
assert.Equal(t, strings.Repeat("a", 255)+" [...]", processed["long"])
|
||||
assert.Equal(t, "42", processed["number"])
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package vardump
|
||||
|
||||
var (
|
||||
// EnableVarDump enables var dump for debugging optionally
|
||||
EnableVarDump bool
|
||||
// Limit is the maximum characters to be dumped
|
||||
Limit int = 255
|
||||
)
|
||||
@@ -108,7 +108,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata,
|
||||
func (request *Request) execute(input *contextargs.Context, domain string, metadata, previous output.InternalEvent, vars map[string]interface{}, callback protocols.OutputEventCallback) error {
|
||||
var err error
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("DNS Protocol request variables: \n%s\n", vardump.DumpVariables(vars))
|
||||
gologger.Debug().Msgf("DNS Protocol request variables: %s\n", vardump.DumpVariables(vars))
|
||||
}
|
||||
|
||||
// Compile each request for the template based on the URL
|
||||
|
||||
@@ -334,7 +334,7 @@ func (p *Page) NavigateURL(action *Action, out ActionData, allvars map[string]in
|
||||
allvars = generators.MergeMaps(allvars, defaultReqVars)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Headless Protocol request variables: \n%s\n", vardump.DumpVariables(allvars))
|
||||
gologger.Debug().Msgf("Headless Protocol request variables: %s\n", vardump.DumpVariables(allvars))
|
||||
}
|
||||
|
||||
// Evaluate the target url with all variables
|
||||
|
||||
@@ -122,7 +122,7 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
defer instance.Close()
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Headless Protocol request variables: \n%s\n", vardump.DumpVariables(payloads))
|
||||
gologger.Debug().Msgf("Headless Protocol request variables: %s\n", vardump.DumpVariables(payloads))
|
||||
}
|
||||
|
||||
instance.SetInteractsh(request.options.Interactsh)
|
||||
|
||||
@@ -204,7 +204,7 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
|
||||
finalVars := generators.MergeMaps(allVars, payloads)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("HTTP Protocol request variables: \n%s\n", vardump.DumpVariables(finalVars))
|
||||
gologger.Debug().Msgf("HTTP Protocol request variables: %s\n", vardump.DumpVariables(finalVars))
|
||||
}
|
||||
|
||||
// Note: If possible any changes to current logic (i.e evaluate -> then parse URL)
|
||||
|
||||
@@ -223,6 +223,9 @@ type Request struct {
|
||||
// FuzzPreConditionOperator is the operator between multiple PreConditions for fuzzing Default is OR
|
||||
FuzzPreConditionOperator string `yaml:"pre-condition-operator,omitempty" json:"pre-condition-operator,omitempty" jsonschema:"title=condition between the filters,description=Operator to use between multiple per-conditions,enum=and,enum=or"`
|
||||
fuzzPreConditionOperator matchers.ConditionType `yaml:"-" json:"-"`
|
||||
// description: |
|
||||
// GlobalMatchers marks matchers as static and applies globally to all result events from other templates
|
||||
GlobalMatchers bool `yaml:"global-matchers,omitempty" json:"global-matchers,omitempty" jsonschema:"title=global matchers,description=marks matchers as static and applies globally to all result events from other templates"`
|
||||
}
|
||||
|
||||
func (e Request) JSONSchemaExtend(schema *jsonschema.Schema) {
|
||||
|
||||
@@ -166,6 +166,10 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
if types.ToString(wrapped.InternalEvent["path"]) != "" {
|
||||
fields.Path = types.ToString(wrapped.InternalEvent["path"])
|
||||
}
|
||||
var isGlobalMatchers bool
|
||||
if value, ok := wrapped.InternalEvent["global-matchers"]; ok {
|
||||
isGlobalMatchers = value.(bool)
|
||||
}
|
||||
data := &output.ResultEvent{
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
@@ -183,6 +187,7 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
Timestamp: time.Now(),
|
||||
MatcherStatus: true,
|
||||
IP: fields.Ip,
|
||||
GlobalMatchers: isGlobalMatchers,
|
||||
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||
Response: request.truncateResponse(wrapped.InternalEvent["response"]),
|
||||
CURLCommand: types.ToString(wrapped.InternalEvent["curl-command"]),
|
||||
|
||||
@@ -973,13 +973,22 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
|
||||
// prune signature internal values if any
|
||||
request.pruneSignatureInternalValues(generatedRequest.meta)
|
||||
|
||||
event := eventcreator.CreateEventWithAdditionalOptions(request, generators.MergeMaps(generatedRequest.dynamicValues, finalEvent), request.options.Options.Debug || request.options.Options.DebugResponse, func(internalWrappedEvent *output.InternalWrappedEvent) {
|
||||
interimEvent := generators.MergeMaps(generatedRequest.dynamicValues, finalEvent)
|
||||
isDebug := request.options.Options.Debug || request.options.Options.DebugResponse
|
||||
event := eventcreator.CreateEventWithAdditionalOptions(request, interimEvent, isDebug, func(internalWrappedEvent *output.InternalWrappedEvent) {
|
||||
internalWrappedEvent.OperatorsResult.PayloadValues = generatedRequest.meta
|
||||
})
|
||||
|
||||
if hasInteractMatchers {
|
||||
event.UsesInteractsh = true
|
||||
}
|
||||
|
||||
if request.options.GlobalMatchers.HasMatchers() {
|
||||
request.options.GlobalMatchers.Match(interimEvent, request.Match, request.Extract, isDebug, func(event output.InternalEvent, result *operators.Result) {
|
||||
callback(eventcreator.CreateEventWithOperatorResults(request, event, result))
|
||||
})
|
||||
}
|
||||
|
||||
// if requrlpattern is enabled, only then it is reflected in result event else it is empty string
|
||||
// consult @Ice3man543 before changing this logic (context: vuln_hash)
|
||||
if request.options.ExportReqURLPattern {
|
||||
|
||||
@@ -319,7 +319,7 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
|
||||
templateCtx.Merge(payloadValues)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Javascript Protocol request variables: \n%s\n", vardump.DumpVariables(payloadValues))
|
||||
gologger.Debug().Msgf("JavaScript Protocol request variables: %s\n", vardump.DumpVariables(payloadValues))
|
||||
}
|
||||
|
||||
if request.PreCondition != "" {
|
||||
|
||||
@@ -85,6 +85,10 @@ type Request struct {
|
||||
// SelfContained specifies if the request is self-contained.
|
||||
SelfContained bool `yaml:"-" json:"-"`
|
||||
|
||||
// description: |
|
||||
// StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
|
||||
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" json:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop the execution after a match is found"`
|
||||
|
||||
// description: |
|
||||
// ports is post processed list of ports to scan (obtained from Port)
|
||||
ports []string `yaml:"-" json:"-"`
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -99,6 +100,16 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, metadata
|
||||
gologger.Verbose().Msgf("[%v] got errors while checking open ports: %s\n", request.options.TemplateID, err)
|
||||
}
|
||||
|
||||
// stop at first match if requested
|
||||
atomicBool := &atomic.Bool{}
|
||||
shouldStopAtFirstMatch := request.StopAtFirstMatch || request.options.StopAtFirstMatch || request.options.Options.StopAtFirstMatch
|
||||
wrappedCallback := func(event *output.InternalWrappedEvent) {
|
||||
if event != nil && event.HasOperatorResult() {
|
||||
atomicBool.Store(true)
|
||||
}
|
||||
callback(event)
|
||||
}
|
||||
|
||||
for _, port := range ports {
|
||||
input := target.Clone()
|
||||
// use network port updates input with new port requested in template file
|
||||
@@ -107,9 +118,12 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, metadata
|
||||
if err := input.UseNetworkPort(port, request.ExcludePorts); err != nil {
|
||||
gologger.Debug().Msgf("Could not network port from constants: %s\n", err)
|
||||
}
|
||||
if err := request.executeOnTarget(input, visitedAddresses, metadata, previous, callback); err != nil {
|
||||
if err := request.executeOnTarget(input, visitedAddresses, metadata, previous, wrappedCallback); err != nil {
|
||||
return err
|
||||
}
|
||||
if shouldStopAtFirstMatch && atomicBool.Load() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -141,6 +155,16 @@ func (request *Request) executeOnTarget(input *contextargs.Context, visited maps
|
||||
variablesMap := request.options.Variables.Evaluate(variables)
|
||||
variables = generators.MergeMaps(variablesMap, variables, request.options.Constants)
|
||||
|
||||
// stop at first match if requested
|
||||
atomicBool := &atomic.Bool{}
|
||||
shouldStopAtFirstMatch := request.StopAtFirstMatch || request.options.StopAtFirstMatch || request.options.Options.StopAtFirstMatch
|
||||
wrappedCallback := func(event *output.InternalWrappedEvent) {
|
||||
if event != nil && event.HasOperatorResult() {
|
||||
atomicBool.Store(true)
|
||||
}
|
||||
callback(event)
|
||||
}
|
||||
|
||||
for _, kv := range request.addresses {
|
||||
select {
|
||||
case <-input.Context().Done():
|
||||
@@ -154,12 +178,13 @@ func (request *Request) executeOnTarget(input *contextargs.Context, visited maps
|
||||
continue
|
||||
}
|
||||
visited.Set(actualAddress, struct{}{})
|
||||
|
||||
if err = request.executeAddress(variables, actualAddress, address, input, kv.tls, previous, callback); err != nil {
|
||||
if err = request.executeAddress(variables, actualAddress, address, input, kv.tls, previous, wrappedCallback); err != nil {
|
||||
outputEvent := request.responseToDSLMap("", "", "", address, "")
|
||||
callback(&output.InternalWrappedEvent{InternalEvent: outputEvent})
|
||||
gologger.Warning().Msgf("[%v] Could not make network request for (%s) : %s\n", request.options.TemplateID, actualAddress, err)
|
||||
continue
|
||||
}
|
||||
if shouldStopAtFirstMatch && atomicBool.Load() {
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -283,36 +308,37 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
||||
interimValues := generators.MergeMaps(variables, payloads)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Network Protocol request variables: \n%s\n", vardump.DumpVariables(interimValues))
|
||||
gologger.Debug().Msgf("Network Protocol request variables: %s\n", vardump.DumpVariables(interimValues))
|
||||
}
|
||||
|
||||
inputEvents := make(map[string]interface{})
|
||||
|
||||
for _, input := range request.Inputs {
|
||||
data := []byte(input.Data)
|
||||
dataInBytes := []byte(input.Data)
|
||||
var err error
|
||||
|
||||
if request.options.Interactsh != nil {
|
||||
var transformedData string
|
||||
transformedData, interactshURLs = request.options.Interactsh.Replace(string(data), []string{})
|
||||
data = []byte(transformedData)
|
||||
}
|
||||
|
||||
finalData, err := expressions.EvaluateByte(data, interimValues)
|
||||
dataInBytes, err = expressions.EvaluateByte(dataInBytes, interimValues)
|
||||
if err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return errors.Wrap(err, "could not evaluate template expressions")
|
||||
}
|
||||
|
||||
reqBuilder.Write(finalData)
|
||||
data := string(dataInBytes)
|
||||
if request.options.Interactsh != nil {
|
||||
data, interactshURLs = request.options.Interactsh.Replace(data, []string{})
|
||||
dataInBytes = []byte(data)
|
||||
}
|
||||
|
||||
if err := expressions.ContainsUnresolvedVariables(string(finalData)); err != nil {
|
||||
reqBuilder.Write(dataInBytes)
|
||||
|
||||
if err := expressions.ContainsUnresolvedVariables(data); err != nil {
|
||||
gologger.Warning().Msgf("[%s] Could not make network request for %s: %v\n", request.options.TemplateID, actualAddress, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if input.Type.GetType() == hexType {
|
||||
finalData, err = hex.DecodeString(string(finalData))
|
||||
dataInBytes, err = hex.DecodeString(data)
|
||||
if err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
@@ -320,7 +346,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := conn.Write(finalData); err != nil {
|
||||
if _, err := conn.Write(dataInBytes); err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return errors.Wrap(err, "could not write request to server")
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/progress"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/projectfile"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/globalmatchers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/hosterrorscache"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/excludematchers"
|
||||
@@ -126,6 +127,8 @@ type ExecutorOptions struct {
|
||||
// ExportReqURLPattern exports the request URL pattern
|
||||
// in ResultEvent it contains the exact url pattern (ex: {{BaseURL}}/{{randstr}}/xyz) used in the request
|
||||
ExportReqURLPattern bool
|
||||
// GlobalMatchers is the storage for global matchers with http passive templates
|
||||
GlobalMatchers *globalmatchers.Storage
|
||||
}
|
||||
|
||||
// todo: centralizing components is not feasible with current clogged architecture
|
||||
|
||||
@@ -222,7 +222,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
payloadValues = generators.MergeMaps(variablesMap, payloadValues, request.options.Constants)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("SSL Protocol request variables: \n%s\n", vardump.DumpVariables(payloadValues))
|
||||
gologger.Debug().Msgf("SSL Protocol request variables: %s\n", vardump.DumpVariables(payloadValues))
|
||||
}
|
||||
|
||||
finalAddress, dataErr := expressions.EvaluateByte([]byte(request.Address), payloadValues)
|
||||
@@ -347,11 +347,33 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
// description. Multiple definitions are separated by commas.
|
||||
// Definitions not having a name (generated on runtime) are prefixed & suffixed by <>.
|
||||
var RequestPartDefinitions = map[string]string{
|
||||
"type": "Type is the type of request made",
|
||||
"response": "JSON SSL protocol handshake details",
|
||||
"not_after": "Timestamp after which the remote cert expires",
|
||||
"host": "Host is the input to the template",
|
||||
"matched": "Matched is the input which was matched upon",
|
||||
"template-id": "ID of the template executed",
|
||||
"template-info": "Info Block of the template executed",
|
||||
"template-path": "Path of the template executed",
|
||||
"host": "Host is the input to the template",
|
||||
"port": "Port is the port of the host",
|
||||
"matched": "Matched is the input which was matched upon",
|
||||
"type": "Type is the type of request made",
|
||||
"timestamp": "Timestamp is the time when the request was made",
|
||||
"response": "JSON SSL protocol handshake details",
|
||||
"cipher": "Cipher is the encryption algorithm used",
|
||||
"domains": "Domains are the list of domain names in the certificate",
|
||||
"fingerprint_hash": "Fingerprint hash is the unique identifier of the certificate",
|
||||
"ip": "IP is the IP address of the server",
|
||||
"issuer_cn": "Issuer CN is the common name of the certificate issuer",
|
||||
"issuer_dn": "Issuer DN is the distinguished name of the certificate issuer",
|
||||
"issuer_org": "Issuer organization is the organization of the certificate issuer",
|
||||
"not_after": "Timestamp after which the remote cert expires",
|
||||
"not_before": "Timestamp before which the certificate is not valid",
|
||||
"probe_status": "Probe status indicates if the probe was successful",
|
||||
"serial": "Serial is the serial number of the certificate",
|
||||
"sni": "SNI is the server name indication used in the handshake",
|
||||
"subject_an": "Subject AN is the list of subject alternative names",
|
||||
"subject_cn": "Subject CN is the common name of the certificate subject",
|
||||
"subject_dn": "Subject DN is the distinguished name of the certificate subject",
|
||||
"subject_org": "Subject organization is the organization of the certificate subject",
|
||||
"tls_connection": "TLS connection is the type of TLS connection used",
|
||||
"tls_version": "TLS version is the version of the TLS protocol used",
|
||||
}
|
||||
|
||||
// Match performs matching operation for a matcher on model and returns:
|
||||
|
||||
@@ -207,7 +207,7 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context,
|
||||
}
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Websocket Protocol request variables: \n%s\n", vardump.DumpVariables(payloadValues))
|
||||
gologger.Debug().Msgf("WebSocket Protocol request variables: %s\n", vardump.DumpVariables(payloadValues))
|
||||
}
|
||||
|
||||
finalAddress, dataErr := expressions.EvaluateByte([]byte(request.Address), payloadValues)
|
||||
|
||||
@@ -99,7 +99,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
variables := generators.MergeMaps(vars, defaultVars, optionVars, dynamicValues, request.options.Constants)
|
||||
|
||||
if vardump.EnableVarDump {
|
||||
gologger.Debug().Msgf("Whois Protocol request variables: \n%s\n", vardump.DumpVariables(variables))
|
||||
gologger.Debug().Msgf("Whois Protocol request variables: %s\n", vardump.DumpVariables(variables))
|
||||
}
|
||||
|
||||
// and replace placeholders
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package mongo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
mongooptions "go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Exporter struct {
|
||||
options *Options
|
||||
mutex *sync.Mutex
|
||||
rows []output.ResultEvent
|
||||
collection *mongo.Collection
|
||||
connection *mongo.Client
|
||||
}
|
||||
|
||||
// Options contains the configuration options for MongoDB exporter client
|
||||
type Options struct {
|
||||
// ConnectionString is the connection string to the MongoDB database
|
||||
ConnectionString string `yaml:"connection-string"`
|
||||
// CollectionName is the name of the MongoDB collection in which to store the results
|
||||
CollectionName string `yaml:"collection-name"`
|
||||
// OmitRaw excludes the Request and Response from the results (helps with filesize)
|
||||
OmitRaw bool `yaml:"omit-raw"`
|
||||
// BatchSize determines the number of results to be kept in memory before writing it to the database or 0 to
|
||||
// persist all in memory and write all results at the end (default)
|
||||
BatchSize int `yaml:"batch-size"`
|
||||
}
|
||||
|
||||
// New creates a new MongoDB exporter integration client based on options.
|
||||
func New(options *Options) (*Exporter, error) {
|
||||
exporter := &Exporter{
|
||||
mutex: &sync.Mutex{},
|
||||
options: options,
|
||||
rows: []output.ResultEvent{},
|
||||
}
|
||||
|
||||
// If the environment variable for the connection string is set, then use that instead. This allows for easier
|
||||
// management of sensitive items such as credentials
|
||||
envConnectionString := os.Getenv("MONGO_CONNECTION_STRING")
|
||||
if envConnectionString != "" {
|
||||
options.ConnectionString = envConnectionString
|
||||
gologger.Info().Msgf("Using connection string from environment variable MONGO_CONNECTION_STRING")
|
||||
}
|
||||
|
||||
// Create the connection to the database
|
||||
clientOptions := mongooptions.Client().ApplyURI(options.ConnectionString)
|
||||
|
||||
// Create a new client and connect to the MongoDB server
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error creating MongoDB client: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the connection is valid
|
||||
err = client.Ping(context.Background(), nil)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error connecting to MongoDB: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the database from the connection string to set the database and collection
|
||||
parsed, err := url.Parse(options.ConnectionString)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error parsing connection string: %s", options.ConnectionString)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
databaseName := strings.TrimPrefix(parsed.Path, "/")
|
||||
|
||||
if databaseName == "" {
|
||||
return nil, errors.New("error getting database name from connection string")
|
||||
}
|
||||
|
||||
exporter.connection = client
|
||||
exporter.collection = client.Database(databaseName).Collection(options.CollectionName)
|
||||
|
||||
return exporter, nil
|
||||
}
|
||||
|
||||
// Export writes a result document to the configured MongoDB collection
|
||||
// in the database configured by the connection string
|
||||
func (exporter *Exporter) Export(event *output.ResultEvent) error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
if exporter.options.OmitRaw {
|
||||
event.Request = ""
|
||||
event.Response = ""
|
||||
}
|
||||
|
||||
// Add the row to the queue to be processed
|
||||
exporter.rows = append(exporter.rows, *event)
|
||||
|
||||
// If the batch size is greater than 0 and the number of rows has reached the batch, flush it to the database
|
||||
if exporter.options.BatchSize > 0 && len(exporter.rows) >= exporter.options.BatchSize {
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteRows writes all rows from the rows list to the MongoDB collection and removes them from the list
|
||||
func (exporter *Exporter) WriteRows() error {
|
||||
// Loop through the rows and write them, removing them as they're entered
|
||||
for len(exporter.rows) > 0 {
|
||||
data := exporter.rows[0]
|
||||
|
||||
// Write the data to the database
|
||||
_, err := exporter.collection.InsertOne(context.TODO(), data)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Error inserting record into MongoDB collection: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove the item from the list
|
||||
exporter.rows = exporter.rows[1:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (exporter *Exporter) Close() error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
// Write all pending rows
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
|
||||
// Close the database connection
|
||||
err = exporter.connection.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error disconnecting from MongoDB: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonexporter"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonl"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/sarif"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/splunk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters"
|
||||
@@ -44,6 +45,8 @@ type Options struct {
|
||||
JSONExporter *jsonexporter.Options `yaml:"json"`
|
||||
// JSONLExporter contains configuration options for JSONL Exporter Module
|
||||
JSONLExporter *jsonl.Options `yaml:"jsonl"`
|
||||
// MongoDBExporter containers the configuration options for the MongoDB Exporter Module
|
||||
MongoDBExporter *mongo.Options `yaml:"mongodb"`
|
||||
|
||||
HttpClient *retryablehttp.Client `yaml:"-"`
|
||||
OmitRaw bool `yaml:"-"`
|
||||
|
||||
@@ -2,6 +2,7 @@ package reporting
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
|
||||
"os"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -166,6 +167,13 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
|
||||
}
|
||||
client.exporters = append(client.exporters, exporter)
|
||||
}
|
||||
if options.MongoDBExporter != nil {
|
||||
exporter, err := mongo.New(options.MongoDBExporter)
|
||||
if err != nil {
|
||||
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
|
||||
}
|
||||
client.exporters = append(client.exporters, exporter)
|
||||
}
|
||||
|
||||
if doNotDedupe {
|
||||
return client, nil
|
||||
@@ -212,6 +220,7 @@ func CreateConfigIfNotExists() error {
|
||||
SplunkExporter: &splunk.Options{},
|
||||
JSONExporter: &json_exporter.Options{},
|
||||
JSONLExporter: &jsonl.Options{},
|
||||
MongoDBExporter: &mongo.Options{},
|
||||
}
|
||||
reportingFile, err := os.Create(reportingConfig)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/globalmatchers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/offlinehttp"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec"
|
||||
@@ -81,6 +82,18 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Executo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if template.isGlobalMatchersEnabled() {
|
||||
item := &globalmatchers.Item{
|
||||
TemplateID: template.ID,
|
||||
TemplatePath: filePath,
|
||||
TemplateInfo: template.Info,
|
||||
}
|
||||
for _, request := range template.RequestsHTTP {
|
||||
item.Operators = append(item.Operators, request.CompiledOperators)
|
||||
}
|
||||
options.GlobalMatchers.AddOperator(item)
|
||||
return nil, nil
|
||||
}
|
||||
// Compile the workflow request
|
||||
if len(template.Workflows) > 0 {
|
||||
compiled := &template.Workflow
|
||||
@@ -96,6 +109,25 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Executo
|
||||
return template, nil
|
||||
}
|
||||
|
||||
// isGlobalMatchersEnabled checks if any of requests in the template
|
||||
// have global matchers enabled. It iterates through all requests and
|
||||
// returns true if at least one request has global matchers enabled;
|
||||
// otherwise, it returns false.
|
||||
//
|
||||
// Note: This method only checks the `RequestsHTTP`
|
||||
// field of the template, which is specific to http-protocol-based
|
||||
// templates.
|
||||
//
|
||||
// TODO: support all protocols.
|
||||
func (template *Template) isGlobalMatchersEnabled() bool {
|
||||
for _, request := range template.RequestsHTTP {
|
||||
if request.GlobalMatchers {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// parseSelfContainedRequests parses the self contained template requests.
|
||||
func (template *Template) parseSelfContainedRequests() {
|
||||
if template.Signature.Value.String() != "" {
|
||||
|
||||
@@ -459,7 +459,7 @@ func init() {
|
||||
Value: "HTTP response headers in name:value format",
|
||||
},
|
||||
}
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 36)
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 37)
|
||||
HTTPRequestDoc.Fields[0].Name = "path"
|
||||
HTTPRequestDoc.Fields[0].Type = "[]string"
|
||||
HTTPRequestDoc.Fields[0].Note = ""
|
||||
@@ -668,6 +668,11 @@ func init() {
|
||||
HTTPRequestDoc.Fields[35].Note = ""
|
||||
HTTPRequestDoc.Fields[35].Description = "FuzzPreConditionOperator is the operator between multiple PreConditions for fuzzing Default is OR"
|
||||
HTTPRequestDoc.Fields[35].Comments[encoder.LineComment] = "FuzzPreConditionOperator is the operator between multiple PreConditions for fuzzing Default is OR"
|
||||
HTTPRequestDoc.Fields[36].Name = "global-matchers"
|
||||
HTTPRequestDoc.Fields[36].Type = "bool"
|
||||
HTTPRequestDoc.Fields[36].Note = ""
|
||||
HTTPRequestDoc.Fields[36].Description = "GlobalMatchers marks matchers as static and applies globally to all result events from other templates"
|
||||
HTTPRequestDoc.Fields[36].Comments[encoder.LineComment] = "GlobalMatchers marks matchers as static and applies globally to all result events from other templates"
|
||||
|
||||
GENERATORSAttackTypeHolderDoc.Type = "generators.AttackTypeHolder"
|
||||
GENERATORSAttackTypeHolderDoc.Comments[encoder.LineComment] = " AttackTypeHolder is used to hold internal type of the protocol"
|
||||
@@ -1329,7 +1334,7 @@ func init() {
|
||||
Value: "Full Network protocol data",
|
||||
},
|
||||
}
|
||||
NETWORKRequestDoc.Fields = make([]encoder.Doc, 10)
|
||||
NETWORKRequestDoc.Fields = make([]encoder.Doc, 11)
|
||||
NETWORKRequestDoc.Fields[0].Name = "id"
|
||||
NETWORKRequestDoc.Fields[0].Type = "string"
|
||||
NETWORKRequestDoc.Fields[0].Note = ""
|
||||
@@ -1388,6 +1393,11 @@ func init() {
|
||||
NETWORKRequestDoc.Fields[9].Comments[encoder.LineComment] = "ReadAll determines if the data stream should be read till the end regardless of the size"
|
||||
|
||||
NETWORKRequestDoc.Fields[9].AddExample("", false)
|
||||
NETWORKRequestDoc.Fields[10].Name = "stop-at-first-match"
|
||||
NETWORKRequestDoc.Fields[10].Type = "bool"
|
||||
NETWORKRequestDoc.Fields[10].Note = ""
|
||||
NETWORKRequestDoc.Fields[10].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
NETWORKRequestDoc.Fields[10].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
|
||||
NETWORKInputDoc.Type = "network.Input"
|
||||
NETWORKInputDoc.Comments[encoder.LineComment] = ""
|
||||
@@ -1657,25 +1667,113 @@ func init() {
|
||||
}
|
||||
SSLRequestDoc.PartDefinitions = []encoder.KeyValue{
|
||||
{
|
||||
Key: "type",
|
||||
Value: "Type is the type of request made",
|
||||
Key: "template-id",
|
||||
Value: "ID of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "response",
|
||||
Value: "JSON SSL protocol handshake details",
|
||||
Key: "template-info",
|
||||
Value: "Info Block of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "not_after",
|
||||
Value: "Timestamp after which the remote cert expires",
|
||||
Key: "template-path",
|
||||
Value: "Path of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "host",
|
||||
Value: "Host is the input to the template",
|
||||
},
|
||||
{
|
||||
Key: "port",
|
||||
Value: "Port is the port of the host",
|
||||
},
|
||||
{
|
||||
Key: "matched",
|
||||
Value: "Matched is the input which was matched upon",
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Value: "Type is the type of request made",
|
||||
},
|
||||
{
|
||||
Key: "timestamp",
|
||||
Value: "Timestamp is the time when the request was made",
|
||||
},
|
||||
{
|
||||
Key: "response",
|
||||
Value: "JSON SSL protocol handshake details",
|
||||
},
|
||||
{
|
||||
Key: "cipher",
|
||||
Value: "Cipher is the encryption algorithm used",
|
||||
},
|
||||
{
|
||||
Key: "domains",
|
||||
Value: "Domains are the list of domain names in the certificate",
|
||||
},
|
||||
{
|
||||
Key: "fingerprint_hash",
|
||||
Value: "Fingerprint hash is the unique identifier of the certificate",
|
||||
},
|
||||
{
|
||||
Key: "ip",
|
||||
Value: "IP is the IP address of the server",
|
||||
},
|
||||
{
|
||||
Key: "issuer_cn",
|
||||
Value: "Issuer CN is the common name of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "issuer_dn",
|
||||
Value: "Issuer DN is the distinguished name of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "issuer_org",
|
||||
Value: "Issuer organization is the organization of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "not_after",
|
||||
Value: "Timestamp after which the remote cert expires",
|
||||
},
|
||||
{
|
||||
Key: "not_before",
|
||||
Value: "Timestamp before which the certificate is not valid",
|
||||
},
|
||||
{
|
||||
Key: "probe_status",
|
||||
Value: "Probe status indicates if the probe was successful",
|
||||
},
|
||||
{
|
||||
Key: "serial",
|
||||
Value: "Serial is the serial number of the certificate",
|
||||
},
|
||||
{
|
||||
Key: "sni",
|
||||
Value: "SNI is the server name indication used in the handshake",
|
||||
},
|
||||
{
|
||||
Key: "subject_an",
|
||||
Value: "Subject AN is the list of subject alternative names",
|
||||
},
|
||||
{
|
||||
Key: "subject_cn",
|
||||
Value: "Subject CN is the common name of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "subject_dn",
|
||||
Value: "Subject DN is the distinguished name of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "subject_org",
|
||||
Value: "Subject organization is the organization of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "tls_connection",
|
||||
Value: "TLS connection is the type of TLS connection used",
|
||||
},
|
||||
{
|
||||
Key: "tls_version",
|
||||
Value: "TLS version is the version of the TLS protocol used",
|
||||
},
|
||||
}
|
||||
SSLRequestDoc.Fields = make([]encoder.Doc, 9)
|
||||
SSLRequestDoc.Fields[0].Name = "id"
|
||||
|
||||
@@ -174,7 +174,15 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
if !event.HasOperatorResult() && event.InternalEvent != nil {
|
||||
lastMatcherEvent = event
|
||||
} else {
|
||||
if writer.WriteResult(event, e.options.Output, e.options.Progress, e.options.IssuesClient) {
|
||||
var isGlobalMatchers bool
|
||||
isGlobalMatchers, _ = event.InternalEvent["global-matchers"].(bool)
|
||||
// NOTE(dwisiswant0): Don't store `matched` on a `global-matchers` template.
|
||||
// This will end up generating 2 events from the same `scan.ScanContext` if
|
||||
// one of the templates has `global-matchers` enabled. This way,
|
||||
// non-`global-matchers` templates can enter the `writeFailureCallback`
|
||||
// func to log failure output.
|
||||
wr := writer.WriteResult(event, e.options.Output, e.options.Progress, e.options.IssuesClient)
|
||||
if wr && !isGlobalMatchers {
|
||||
matched.Store(true)
|
||||
} else {
|
||||
lastMatcherEvent = event
|
||||
|
||||
@@ -206,6 +206,8 @@ type Options struct {
|
||||
VerboseVerbose bool
|
||||
// ShowVarDump displays variable dump
|
||||
ShowVarDump bool
|
||||
// VarDumpLimit limits the number of characters displayed in var dump
|
||||
VarDumpLimit int
|
||||
// No-Color disables the colored output.
|
||||
NoColor bool
|
||||
// UpdateTemplates updates the templates installed at startup (also used by cloud to update datasources)
|
||||
|
||||
Reference in new issue
Block a user