Compare 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 |
No files matched your search
@@ -1,30 +1,4 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://nuclei.projectdiscovery.io"><img src="static/nuclei-logo.png" width="200px" alt="Nuclei"></a>
|
||||
</h1>
|
||||
|
||||
<h4 align="center">Fast and customisable vulnerability scanner based on simple YAML based DSL.</h4>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases"><img src="https://img.shields.io/github/downloads/projectdiscovery/nuclei/total">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors"><img src="https://img.shields.io/github/contributors-anon/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/releases/"><img src="https://img.shields.io/github/release/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/issues"><img src="https://img.shields.io/github/issues-raw/projectdiscovery/nuclei">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/discussions"><img src="https://img.shields.io/github/discussions/projectdiscovery/nuclei">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
||||
<a href="https://twitter.com/pdnuclei"><img src="https://img.shields.io/twitter/follow/pdnuclei.svg?logo=twitter"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#how-it-works">How</a> •
|
||||
<a href="#install-nuclei">Install</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/">Documentation</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Join Discord</a>
|
||||
</p>
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||
@@ -34,78 +8,103 @@
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">日本語</a>
|
||||
</p>
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img src="https://img.shields.io/badge/go-1.21-%2300ADD8.svg?style=for-the-badge&logo=go&logoColor=white">
|
||||
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/overview?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme"><img src="https://img.shields.io/badge/Documentation-%23000000.svg?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0ibHVjaWRlIGx1Y2lkZS1ib29rLW9wZW4iPjxwYXRoIGQ9Ik0xMiA3djE0Ii8+PHBhdGggZD0iTTMgMThhMSAxIDAgMCAxLTEtMVY0YTEgMSAwIDAgMSAxLTFoNWE0IDQgMCAwIDEgNCA0IDQgNCAwIDAgMSA0LTRoNWExIDEgMCAwIDEgMSAxdjEzYTEgMSAwIDAgMS0xIDFoLTZhMyAzIDAgMCAwLTMgMyAzIDMgMCAwIDAtMy0zeiIvPjwvc3ZnPg==&logoColor=white"></a>
|
||||
|
||||
<a href="https://github.com/projectdiscovery/nuclei-templates"><img src="https://img.shields.io/badge/Templates Library-%23000000.svg?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXNoaWVsZCI+PHBhdGggZD0iTTIwIDEzYzAgNS0zLjUgNy41LTcuNjYgOC45NWExIDEgMCAwIDEtLjY3LS4wMUM3LjUgMjAuNSA0IDE4IDQgMTNWNmExIDEgMCAwIDEgMS0xYzIgMCA0LjUtMS4yIDYuMjQtMi43MmExLjE3IDEuMTcgMCAwIDEgMS41MiAwQzE0LjUxIDMuODEgMTcgNSAxOSA1YTEgMSAwIDAgMSAxIDF6Ii8+PC9zdmc+&logoColor=white"></a>
|
||||
|
||||
<a href="https://discord.gg/projectdiscovery?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme"><img src="https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white"></a>
|
||||
|
||||
---
|
||||
|
||||
Nuclei is used to send requests across targets based on a template, leading to zero false positives and providing fast scanning on a large number of hosts. Nuclei offers scanning for a variety of protocols, including TCP, DNS, HTTP, SSL, File, Whois, Websocket, Headless, Code etc. With powerful and flexible templating, Nuclei can be used to model all kinds of security checks.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
We have a [dedicated repository](https://github.com/projectdiscovery/nuclei-templates) that houses various type of vulnerability templates contributed by **more than 300** security researchers and engineers.
|
||||
Nuclei is a modern, high-performance vulnerability scanner that leverages simple YAML-based templates. It empowers you to design custom vulnerability detection scenarios that mimic real-world conditions, leading to zero false positives.
|
||||
|
||||
## How it works
|
||||
- Simple YAML format for creating and customizing vulnerability templates.
|
||||
- Contributed by thousands of security professionals to tackle trending vulnerabilities.
|
||||
- Reduce false positives by simulating real-world steps to verify a vulnerability.
|
||||
- Ultra-fast parallel scan processing and request clustering.
|
||||
- Integrate into CI/CD pipelines for vulnerability detection and regression testing.
|
||||
- Supports multiple protocols like TCP, DNS, HTTP, SSL, WHOIS JavaScript, Code and more.
|
||||
- Integrate with Jira, Splunk, GitHub, Elastic, GitLab.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
- [Get Started](#get-started)
|
||||
- [1. Nuclei CLI](#1-nuclei-cli)
|
||||
- [2. Pro and Enterprise Editions](#2-pro-and-enterprise-editions)
|
||||
- [Documentation](#documentation)
|
||||
- [Command Line Flags](#command-line-flags)
|
||||
- [Single target scan](#single-target-scan)
|
||||
- [Scanning multiple targets](#scanning-multiple-targets)
|
||||
- [Network scan](#network-scan)
|
||||
- [Scanning with your custom template](#scanning-with-your-custom-template)
|
||||
- [Connect Nuclei to ProjectDiscovery](#connect-nuclei-to-projectdiscovery)
|
||||
- [Nuclei Templates, Community and Rewards 💎](#nuclei-templates-community-and-rewards-)
|
||||
- [Our Mission](#our-mission)
|
||||
- [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 was 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. |
|
||||
| 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. |
|
||||
|
||||
# Install Nuclei
|
||||
## Get Started
|
||||
|
||||
Nuclei requires **go1.21** to install successfully. Run the following command to install the latest version -
|
||||
### **1. Nuclei CLI**
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
Install Nuclei on your machine. Get started by following the installation guide [here](https://docs.projectdiscovery.io/tools/nuclei/install?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme). Additionally, We provide [a free cloud tier](https://cloud.projectdiscovery.io/sign-up) and comes with a generous monthly free limits:
|
||||
|
||||
<details>
|
||||
<summary>Brew</summary>
|
||||
|
||||
```sh
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Docker</summary>
|
||||
|
||||
```sh
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
</details>
|
||||
- Store and visualize your vulnerability findings
|
||||
- Write and manage your nuclei templates
|
||||
- Access latest nuclei templates
|
||||
- Discover and store your targets
|
||||
|
||||
**More installation [methods can be found here](https://docs.projectdiscovery.io/tools/nuclei/install).**
|
||||
### **2. Pro and Enterprise Editions**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
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:
|
||||
|
||||
### Nuclei Templates
|
||||
- 50x faster scans
|
||||
- Large scale scanning with high accuracy
|
||||
- Integrations with cloud services (AWS, GCP, Azure, CloudFlare, Fastly, Terraform, Kubernetes)
|
||||
- Jira, Slack, Linear, APIs and Webhooks
|
||||
- Executive and compliance reporting
|
||||
- Plus: Real-time scanning, SAML SSO, SOC 2 compliant platform (with EU and US hosting options), shared team workspaces, and more
|
||||
- We're constantly [adding new features](https://feedback.projectdiscovery.io/changelog)!
|
||||
- **Ideal for:** Pentesters, security teams, and enterprises
|
||||
|
||||
Nuclei has built-in support for automatic template download/update as default since version [v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2). [**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates) project provides a community-contributed list of ready-to-use templates that is constantly updated.
|
||||
## Documentation
|
||||
|
||||
You may still use the `update-templates` flag to update the nuclei templates at any time; You can write your own checks for your individual workflow and needs following Nuclei's [templating guide](https://docs.projectdiscovery.io/templates/).
|
||||
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)
|
||||
|
||||
The YAML DSL reference syntax is available [here](SYNTAX-REFERENCE.md).
|
||||
<p align="center">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a href="https://www.youtube.com/watch?v=b5qMyQvL1ZA&list=PLZRbR9aMzTTpItEdeNSulo8bYsvil80Rl&utm_source=github&utm_medium=web&utm_campaign=nuclei_readme" target="_blank"><img src="/static/nuclei-getting-started.png" width="350px"></a> <a href="https://www.youtube.com/watch?v=nFXygQdtjyw&utm_source=github&utm_medium=web&utm_campaign=nuclei_readme" target="_blank"><img src="/static/nuclei-write-your-first-template.png" width="350px"></a>
|
||||
|
||||
### Usage
|
||||
</p>
|
||||
|
||||
### Command Line Flags
|
||||
|
||||
To display all the flags for the tool:
|
||||
|
||||
```sh
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
This will display help for the tool. Here are all the switches it supports.
|
||||
|
||||
<details>
|
||||
<summary>Expand full help flags</summary>
|
||||
|
||||
```console
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
@@ -279,23 +278,24 @@ HEADLESS:
|
||||
-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
|
||||
@@ -310,11 +310,13 @@ STATISTICS:
|
||||
-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
|
||||
@@ -323,59 +325,189 @@ AUTHENTICATION:
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
### Running Nuclei
|
||||
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)
|
||||
|
||||
See https://docs.projectdiscovery.io/tools/nuclei/running for details on running Nuclei
|
||||
</details>
|
||||
|
||||
### Using Nuclei From Go Code
|
||||
### Single target scan
|
||||
|
||||
Complete guide of using Nuclei as Library/SDK is available at [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme)
|
||||
To perform a quick scan on web-application:
|
||||
|
||||
```sh
|
||||
nuclei -target https://example.com
|
||||
```
|
||||
|
||||
### Scanning multiple targets
|
||||
|
||||
Nuclei can handle bulk scanning by providing a list of targets. You can use a file containing multiple URLs.
|
||||
|
||||
```sh
|
||||
nuclei -targets urls.txt
|
||||
```
|
||||
|
||||
### Network scan
|
||||
|
||||
This will scan the entire subnet for network-related issues, such as open ports or misconfigured services.
|
||||
|
||||
```sh
|
||||
nuclei -target 192.168.1.0/24
|
||||
```
|
||||
|
||||
### Scanning with your custom template
|
||||
|
||||
To write and use your own template, create a `.yaml` file with specific rules, then use it as follows.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t /path/to/your-template.yaml
|
||||
```
|
||||
|
||||
### Connect Nuclei to ProjectDiscovery
|
||||
|
||||
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 -dashboard
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This feature is absolutely free and does not require any subscription. For a detailed guide, refer to the [documentation](https://docs.projectdiscovery.io/cloud/scanning/nuclei-scan?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme).
|
||||
|
||||
## Nuclei Templates, Community and Rewards 💎
|
||||
[Nuclei templates](https://github.com/projectdiscovery/nuclei-templates) are based on the concepts of YAML based template files that define how the requests will be sent and processed. This allows easy extensibility capabilities to nuclei. The templates are written in YAML which specifies a simple human-readable format to quickly define the execution process.
|
||||
|
||||
Try it online with our free AI powered Nuclei Templates Editor by [clicking here.](https://cloud.projectdiscovery.io/templates)
|
||||
|
||||
Nuclei Templates offer a streamlined way to identify and communicate vulnerabilities, combining essential details like severity ratings and detection methods. This open-source, community-developed tool accelerates threat response and is widely recognized in the cybersecurity world. Nuclei templates are actively contributed by thousands of security researchers globally. We run two programs for our contributors: [Pioneers](https://projectdiscovery.io/pioneers) and [💎 bounties](https://github.com/projectdiscovery/nuclei-templates/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22%F0%9F%92%8E%20Bounty%22).
|
||||
|
||||
|
||||
### Resources
|
||||
<p align="left">
|
||||
<a href="/static/nuclei-templates-teamcity.png" target="_blank"><img src="/static/nuclei-templates-teamcity.png" width="1200px" alt="Nuclei template example for detecting TeamCity misconfiguration" /></a>
|
||||
</p>
|
||||
|
||||
You can access the main documentation for Nuclei at https://docs.projectdiscovery.io/tools/nuclei/, and learn more about Nuclei in the cloud with [ProjectDiscovery Cloud Platform](https://cloud.projectdiscovery.io)
|
||||
#### Examples
|
||||
|
||||
See https://docs.projectdiscovery.io/tools/nuclei/resources for more resources and videos about Nuclei!
|
||||
Visit [our documentation](https://docs.projectdiscovery.io/templates/introduction) for use cases and ideas.
|
||||
|
||||
### Credits
|
||||
| Use case | Nuclei template |
|
||||
| :----------------------------------- | :------------------------------------------------- |
|
||||
| Detect known CVEs | **[CVE-2021-44228 (Log4Shell)](https://cloud.projectdiscovery.io/public/CVE-2021-45046)** |
|
||||
| Identify Out-of-Band vulnerabilities | **[Blind SQL Injection via OOB](https://cloud.projectdiscovery.io/public/CVE-2024-22120)** |
|
||||
| SQL Injection detection | **[Generic SQL Injection](https://cloud.projectdiscovery.io/public/CVE-2022-34265)** |
|
||||
| Cross-Site Scripting (XSS) | **[Reflected XSS Detection](https://cloud.projectdiscovery.io/public/CVE-2023-4173)** |
|
||||
| Default or weak passwords | **[Default Credentials Check](https://cloud.projectdiscovery.io/public/airflow-default-login)** |
|
||||
| Secret files or data exposure | **[Sensitive File Disclosure](https://cloud.projectdiscovery.io/public/airflow-configuration-exposure)** |
|
||||
| Identify open redirects | **[Open Redirect Detection](https://cloud.projectdiscovery.io/public/open-redirect)** |
|
||||
| Detect subdomain takeovers | **[Subdomain Takeover Templates](https://cloud.projectdiscovery.io/public/azure-takeover-detection)** |
|
||||
| Security misconfigurations | **[Unprotected Jenkins Console](https://cloud.projectdiscovery.io/public/unauthenticated-jenkins)** |
|
||||
| Weak SSL/TLS configurations | **[SSL Certificate Expiry](https://cloud.projectdiscovery.io/public/expired-ssl)** |
|
||||
| Misconfigured cloud services | **[Open S3 Bucket Detection](https://cloud.projectdiscovery.io/public/s3-public-read-acp)** |
|
||||
| Remote code execution vulnerabilities| **[RCE Detection Templates](https://cloud.projectdiscovery.io/public/CVE-2024-29824)** |
|
||||
| Directory traversal attacks | **[Path Traversal Detection](https://cloud.projectdiscovery.io/public/oracle-fatwire-lfi)** |
|
||||
| File inclusion vulnerabilities | **[Local/Remote File Inclusion](https://cloud.projectdiscovery.io/public/CVE-2023-6977)** |
|
||||
|
||||
|
||||
## Our Mission
|
||||
|
||||
Traditional vulnerability scanners were built decades ago. They are closed-source, incredibly slow, and vendor-driven. Today's attackers are mass exploiting newly released CVEs across the internet within days, unlike the years it used to take. This shift requires a completely different approach to tackling trending exploits on the internet.
|
||||
|
||||
We built Nuclei to solve this challenge. We made the entire scanning engine framework open and customizable—allowing the global security community to collaborate and tackle the trending attack vectors and vulnerabilities on the internet. Nuclei is now used and contributed by Fortune 500 enterprises, government agencies, universities.
|
||||
|
||||
You can participate by contributing to our code, [templates library](https://github.com/projectdiscovery/nuclei-templates), or [joining our team.](https://projectdiscovery.io/)
|
||||
|
||||
## Contributors :heart:
|
||||
|
||||
Thanks to all the amazing [community contributors for sending PRs](https://github.com/projectdiscovery/nuclei/graphs/contributors) and keeping this project updated. :heart:
|
||||
|
||||
If you have an idea or some kind of improvement, you are welcome to contribute and participate in the Project, feel free to send your PR.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/projectdiscovery/nuclei/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=projectdiscovery/nuclei&max=500">
|
||||
</a>
|
||||
<p align="left">
|
||||
<a href="https://github.com/Ice3man543"><img src="https://avatars.githubusercontent.com/u/22318055?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ehsandeep"><img src="https://avatars.githubusercontent.com/u/8293321?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Mzack9999"><img src="https://avatars.githubusercontent.com/u/13421144?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/forgedhallpass"><img src="https://avatars.githubusercontent.com/u/13679401?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tarunKoyalwar"><img src="https://avatars.githubusercontent.com/u/45962551?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/manuelbua"><img src="https://avatars.githubusercontent.com/u/819314?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/actions-user"><img src="https://avatars.githubusercontent.com/u/65916846?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dogancanbakir"><img src="https://avatars.githubusercontent.com/u/65292895?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/parrasajad"><img src="https://avatars.githubusercontent.com/u/16835787?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vzamanillo"><img src="https://avatars.githubusercontent.com/u/10209695?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ShubhamRasal"><img src="https://avatars.githubusercontent.com/u/45902122?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/RamanaReddy0M"><img src="https://avatars.githubusercontent.com/u/90540245?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/LuitelSamikshya"><img src="https://avatars.githubusercontent.com/u/85764322?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kchason"><img src="https://avatars.githubusercontent.com/u/1111099?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/pmareke"><img src="https://avatars.githubusercontent.com/u/3502075?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dwisiswant0"><img src="https://avatars.githubusercontent.com/u/25837540?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xm1k3"><img src="https://avatars.githubusercontent.com/u/73166077?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/5amu"><img src="https://avatars.githubusercontent.com/u/39925709?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ehrishirajsharma"><img src="https://avatars.githubusercontent.com/u/35542790?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zerodivisi0n"><img src="https://avatars.githubusercontent.com/u/687694?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<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/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>
|
||||
<a href="https://github.com/jessekelly881"><img src="https://avatars.githubusercontent.com/u/22938931?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/JaneX8"><img src="https://avatars.githubusercontent.com/u/5116641?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/eltociear"><img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/atomiczsec"><img src="https://avatars.githubusercontent.com/u/75549184?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/M-Faheem-Khan"><img src="https://avatars.githubusercontent.com/u/17150767?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/denandz"><img src="https://avatars.githubusercontent.com/u/5291556?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tibbon"><img src="https://avatars.githubusercontent.com/u/82880?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/dany74q"><img src="https://avatars.githubusercontent.com/u/2129762?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/0x123456789"><img src="https://avatars.githubusercontent.com/u/36066426?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/danigoland"><img src="https://avatars.githubusercontent.com/u/15079567?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ChrisMandich"><img src="https://avatars.githubusercontent.com/u/14286797?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/austintraver"><img src="https://avatars.githubusercontent.com/u/25112463?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/socialsister"><img src="https://avatars.githubusercontent.com/u/155628741?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Anemys"><img src="https://avatars.githubusercontent.com/u/51196227?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/andreangelucci"><img src="https://avatars.githubusercontent.com/u/18552197?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/AlexS778"><img src="https://avatars.githubusercontent.com/u/98418121?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/noraj"><img src="https://avatars.githubusercontent.com/u/16578570?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/akkuman"><img src="https://avatars.githubusercontent.com/u/7813511?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zrquan"><img src="https://avatars.githubusercontent.com/u/33086594?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/1efty"><img src="https://avatars.githubusercontent.com/u/18194777?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rsrdesarrollo"><img src="https://avatars.githubusercontent.com/u/5142014?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/razin99"><img src="https://avatars.githubusercontent.com/u/44442082?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MetzinAround"><img src="https://avatars.githubusercontent.com/u/65838556?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vil02"><img src="https://avatars.githubusercontent.com/u/65706193?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mrschyte"><img src="https://avatars.githubusercontent.com/u/8571?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/PeterDaveHello"><img src="https://avatars.githubusercontent.com/u/3691490?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/parthmalhotra"><img src="https://avatars.githubusercontent.com/u/28601533?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/owenrumney"><img src="https://avatars.githubusercontent.com/u/3049157?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Ovi3"><img src="https://avatars.githubusercontent.com/u/29408109?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Bisstocuz"><img src="https://avatars.githubusercontent.com/u/42398278?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/daffainfo"><img src="https://avatars.githubusercontent.com/u/36522826?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mhmdiaa"><img src="https://avatars.githubusercontent.com/u/19687798?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MiryangJung"><img src="https://avatars.githubusercontent.com/u/48237511?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/0xmin"><img src="https://avatars.githubusercontent.com/u/44919834?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/maikthulhu"><img src="https://avatars.githubusercontent.com/u/680830?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sttlr"><img src="https://avatars.githubusercontent.com/u/40246850?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iamRjarpan"><img src="https://avatars.githubusercontent.com/u/45498226?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/leoloobeek"><img src="https://avatars.githubusercontent.com/u/8801754?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KristinnVikar"><img src="https://avatars.githubusercontent.com/u/93918469?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kant01ne"><img src="https://avatars.githubusercontent.com/u/5072452?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KeisukeYamashita"><img src="https://avatars.githubusercontent.com/u/23056537?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
</p>
|
||||
|
||||
## License
|
||||
|
||||
Do also check out the below similar open-source projects that may fit in your workflow:
|
||||
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md).
|
||||
|
||||
[FFuF](https://github.com/ffuf/ffuf), [Qsfuzz](https://github.com/ameenmaali/qsfuzz), [Inception](https://github.com/proabiral/inception), [Snallygaster](https://github.com/hannob/snallygaster), [Gofingerprint](https://github.com/Static-Flow/gofingerprint), [Sn1per](https://github.com/1N3/Sn1per/tree/master/templates), [Google tsunami](https://github.com/google/tsunami-security-scanner), [Jaeles](https://github.com/jaeles-project/jaeles), [ChopChop](https://github.com/michelin/ChopChop)
|
||||
|
||||
### License
|
||||
|
||||
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="static/Join-Discord.png" width="380" alt="Join Discord"></a> <a href="https://docs.projectdiscovery.io"><img src="static/check-nuclei-documentation.png" width="380" alt="Check Nuclei Documentation"></a>
|
||||
</h1>
|
||||
<img src="https://img.shields.io/badge/license-MIT-000000.svg?style=for-the-badge">
|
||||
@@ -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 />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -425,6 +425,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
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"),
|
||||
|
||||
@@ -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,29 +81,30 @@ 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
|
||||
@@ -209,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
|
||||
|
||||
@@ -845,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=
|
||||
@@ -879,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=
|
||||
@@ -899,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=
|
||||
@@ -1104,6 +1106,8 @@ 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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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] = ""
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
After Width: | Height: | Size: 799 KiB |
|
After Width: | Height: | Size: 799 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 1.0 MiB |