Compare commits

..
401 changed files with 4932 additions and 17834 deletions

No files matched your search

-79
View File
@@ -1,79 +0,0 @@
name: Bug Report
description: Create a report to help us to improve the Nuclei.
title: "[BUG] ..."
labels: ["Type: Bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
For support requests, FAQs or "How to" questions, please use the [GitHub Discussions](https://github.com/projectdiscovery/nuclei/discussions) section instead or join our [Discord server](https://discord.gg/projectdiscovery) to discuss the idea on the **#nuclei** channel.
:warning: **Issues missing important information may be closed without further investigation.**
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues.
required: true
- type: textarea
attributes:
label: Current Behavior
description: A concise description of what you're experiencing.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: |
Steps to reproduce the behavior, for example, commands to run Nuclei.
📝 For a more detailed output that could help in troubleshooting, you may want to run Nuclei with the **`-verbose`** or **`-debug`** flags. This will provide additional insights into what's happening under the hood.
:warning: **Please redact any literal target hosts/URLs or other sensitive information.**
placeholder: |
1. Run `nuclei -t ...`
validations:
required: true
- type: textarea
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
📝 For a more detailed output that could help in troubleshooting, you may want to run Nuclei with the **`-verbose`** or **`-debug`** flags. This will provide additional insights into what's happening under the hood.
:warning: **Please redact any literal target hosts/URLs or other sensitive information.**
render: shell
- type: textarea
attributes:
label: Environment
description: |
Examples:
- **OS**: Ubuntu 20.04
- **Nuclei** (`nuclei -version`): v3.3.1
- **Go** (`go version`): go1.22.0 _(only if you've installed it via the `go install` command)_
value: |
- OS:
- Nuclei:
- Go:
render: markdown
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Templates? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
@@ -1,37 +0,0 @@
name: Feature Request
description: Request feature to implement in the Nuclei.
title: "[FEATURE] ..."
labels: ["Type: Enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request!
Please make sure to provide a detailed description with all the relevant information that might be required to start working on this feature. In case you are not sure about your request or whether the particular feature is already supported or not, please [start a discussion](https://github.com/projectdiscovery/nuclei/discussions/categories/ideas) instead.
Join our [Discord server](https://discord.gg/projectdiscovery) to discuss the idea on the **#nuclei** channel.
- type: textarea
attributes:
label: Describe your feature request
description: A clear and concise description of feature to implement.
validations:
required: true
- type: textarea
attributes:
label: Describe the use case of the feature
description: A clear and concise description of the feature request's motivation and the use-cases in which it could be useful.
validations:
required: true
- type: textarea
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
attributes:
label: Additional context
description: Add any other context about the feature request here.
validations:
required: false
+21
View File
@@ -0,0 +1,21 @@
---
name: Feature request
about: Request feature to implement in this project
title: ""
labels: 'Type: Enhancement'
assignees: ''
---
<!--
1. Please make sure to provide a detailed description with all the relevant information that might be required to start working on this feature.
2. In case you are not sure about your request or whether the particular feature is already supported or not, please start a discussion instead.
3. GitHub Discussion: https://github.com/projectdiscovery/nuclei/discussions/categories/ideas
4. Join our discord server at https://discord.gg/projectdiscovery to discuss the idea on the #nuclei channel.
-->
### Please describe your feature request:
<!-- A clear and concise description of feature to implement -->
### Describe the use case of this feature:
<!-- A clear and concise description of the feature request's motivation and the use-cases in which it could be useful. -->
+36
View File
@@ -0,0 +1,36 @@
---
name: Issue report
about: Create a report to help us to improve the project
labels: 'Type: Bug'
---
<!--
1. Please search to see if an issue already exists for the bug you encountered.
2. For support requests, FAQs or "How to" questions, please use the GitHub Discussions section instead - https://github.com/projectdiscovery/nuclei/discussions or
3. Join our discord server at https://discord.gg/projectdiscovery and post the question on the #nuclei channel.
-->
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
### Nuclei version:
<!-- You can find current version of nuclei with "nuclei -version" -->
<!-- We only accept issues that are reproducible on the latest version of nuclei. -->
<!-- You can find the latest version of project at https://github.com/projectdiscovery/nuclei/releases/ -->
### Current Behavior:
<!-- A concise description of what you're experiencing. -->
### Expected Behavior:
<!-- A concise description of what you expected to happen. -->
### Steps To Reproduce:
<!--
Example: steps to reproduce the behavior:
1. Run 'nuclei -t ... -u ..'
2. See error...
-->
### Anything else:
<!-- Links? References? Screenshots? Anything that will give us more context about the issue that you are encountering! -->
-8
View File
@@ -1,8 +0,0 @@
addReviewers: true
reviewers:
- dogancanbakir
- dwisiswant0
numberOfReviewers: 1
skipKeywords:
- '@dependabot'
+21 -24
View File
@@ -1,5 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain dependencies for go modules
- package-ecosystem: "gomod"
directory: "/"
schedule:
@@ -8,33 +15,23 @@ updates:
commit-message:
prefix: "chore"
include: "scope"
labels:
- "Type: Maintenance"
allow:
- dependency-name: "github.com/projectdiscovery/*"
groups:
modules:
patterns: ["github.com/projectdiscovery/*"]
security:
applies-to: "security-updates"
patterns: ["*"]
exclude-patterns: ["github.com/projectdiscovery/*"]
labels:
- "Type: Maintenance"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
target-branch: "dev"
commit-message:
prefix: "chore"
include: "scope"
groups:
workflows:
patterns: ["*"]
exclude-patterns: ["projectdiscovery/actions/*"]
labels:
- "Type: Maintenance"
# # Maintain dependencies for GitHub Actions
# - package-ecosystem: "github-actions"
# directory: "/"
# schedule:
# interval: "weekly"
# target-branch: "dev"
# commit-message:
# prefix: "chore"
# include: "scope"
# labels:
# - "Type: Maintenance"
#
# # Maintain dependencies for docker
# - package-ecosystem: "docker"
# directory: "/"
+27
View File
@@ -0,0 +1,27 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 7
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
# exemptLabels:
# - pinned
# - security
# Only issues or pull requests with all of these labels are check if stale.
onlyLabels:
- "Status: Abandoned"
- "Type: Question"
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+72
View File
@@ -0,0 +1,72 @@
name: 🔨 Build Test
on:
pull_request:
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
jobs:
build:
name: Test Builds
strategy:
matrix:
go-version: [1.21.x]
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Set up Python # required for running python code in py-snippet.yaml integration test
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Check out code
uses: actions/checkout@v3
- name: Go Mod hygiene
run: |
go clean -modcache
go mod tidy
- name: Build
run: go build .
working-directory: cmd/nuclei/
- name: Test
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: go test ./...
- name: Integration Tests
timeout-minutes: 50
env:
GH_ACTION: true
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
chmod +x run.sh
bash run.sh ${{ matrix.os }}
working-directory: integration_tests/
- name: Race Condition Tests
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
working-directory: cmd/nuclei/
- name: Example SDK Simple
run: go run .
working-directory: examples/simple/
- name: Example SDK Advanced
run: go run .
working-directory: examples/advanced/
- name: Example SDK with speed control
run: go run .
working-directory: examples/with_speed_control/
+39
View File
@@ -0,0 +1,39 @@
name: 🚨 CodeQL Analysis
on:
pull_request:
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest-16-cores
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
-19
View File
@@ -1,19 +0,0 @@
name: ♾️ Compatibility Checks
on:
pull_request:
types: [opened, synchronize]
branches:
- dev
jobs:
check:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go/compat-checks@v1
with:
release-test: true
@@ -1,12 +1,10 @@
name: 🤖 Auto Merge
name: 🤖 dep auto merge
on:
pull_request_review:
types: [submitted]
workflow_run:
workflows: ["♾️ Compatibility Check"]
types:
- completed
pull_request:
branches:
- dev
workflow_dispatch:
permissions:
pull-requests: write
@@ -14,11 +12,11 @@ permissions:
repository-projects: write
jobs:
auto-merge:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
token: ${{ secrets.DEPENDABOT_PAT }}
+47
View File
@@ -0,0 +1,47 @@
name: 🌥 Docker Push
on:
workflow_run:
workflows: ["🎉 Release Binary"]
types:
- completed
workflow_dispatch:
jobs:
docker:
runs-on: ubuntu-latest-16-cores
steps:
- name: Git Checkout
uses: actions/checkout@v3
- name: Get GitHub tag
id: meta
run: |
curl --silent "https://api.github.com/repos/projectdiscovery/nuclei/releases/latest" | jq -r .tag_name | xargs -I {} echo TAG={} >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: projectdiscovery/nuclei:latest,projectdiscovery/nuclei:${{ steps.meta.outputs.TAG }}
- name: Update DockerHub Description
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
repository: projectdiscovery/nuclei
+33
View File
@@ -0,0 +1,33 @@
name: 🧪 Functional Test
on:
pull_request:
paths:
- '**.go'
workflow_dispatch:
jobs:
functional:
name: Functional Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Check out code
uses: actions/checkout@v3
- name: Functional Tests
env:
GH_ACTION: true
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
chmod +x run.sh
bash run.sh ${{ matrix.os }}
working-directory: cmd/functional-test
-27
View File
@@ -1,27 +0,0 @@
name: ⏰ Generate Docs
on:
push:
branches:
- dev
workflow_dispatch:
jobs:
publish-docs:
if: "${{ !endsWith(github.actor, '[bot]') }}"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/setup/git@v1
- run: make syntax-docs
- run: git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
id: status
- uses: projectdiscovery/actions/commit@v1
if: steps.status.outputs.CHANGES > 0
with:
files: |
SYNTAX-REFERENCE.md
nuclei-jsonschema.json
message: 'docs: update syntax & JSON schema 🤖'
- run: git push origin $GITHUB_REF
-55
View File
@@ -1,55 +0,0 @@
name: 👤 Generate PGO
on:
push:
branches: ["dev"]
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# TODO(dwisiswant0): https://go.dev/doc/pgo#merging-profiles
jobs:
pgo:
strategy:
matrix:
targets: [150]
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
permissions:
contents: write
env:
PGO_FILE: "cmd/nuclei/default.pgo"
LIST_FILE: "/tmp/targets-${{ matrix.targets }}.txt"
PROFILE_MEM: "/tmp/nuclei-profile-${{ matrix.targets }}-targets"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/git@v1
- uses: projectdiscovery/actions/setup/go@v1
- name: Generate list
run: for i in {1..${{ matrix.targets }}}; do echo "https://honey.scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
# NOTE(dwisiswant0): use `-no-mhe` flag to get better samples.
- run: go run . -l "${LIST_FILE}" -profile-mem="${PROFILE_MEM}" -no-mhe
working-directory: cmd/nuclei/
- run: mv "${PROFILE_MEM}.cpu" ${PGO_FILE}
# NOTE(dwisiswant0): shall we prune $PGO_FILE git history?
# if we prune it, this won't be linear since it requires a force-push.
# if we don't, the git objects will just keep growing bigger.
#
# Ref:
# - https://go.dev/blog/pgo#:~:text=We%20recommend%20committing%20default.pgo%20files%20to%20your%20repository
# - https://gist.github.com/nottrobin/5758221
- uses: projectdiscovery/actions/commit@v1
with:
files: "${PGO_FILE}"
message: "build: update PGO profile :robot:"
- run: git push origin $GITHUB_REF
- uses: actions/upload-artifact@v4
with:
name: "pgo"
path: "${{ env.PGO_FILE }}"
-26
View File
@@ -1,26 +0,0 @@
name: 🐛 govulncheck
on:
schedule:
- cron: '0 0 * * 0' # Weekly
workflow_dispatch:
jobs:
govulncheck:
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
permissions:
actions: read
contents: read
security-events: write
env:
OUTPUT: "/tmp/results.sarif"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: go install golang.org/x/vuln/cmd/govulncheck@latest
- run: govulncheck -scan package -format sarif ./... > $OUTPUT
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "${{ env.OUTPUT }}"
category: "govulncheck"
+27
View File
@@ -0,0 +1,27 @@
name: 🙏🏻 Lint Test
on:
pull_request:
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
jobs:
lint:
name: Lint Test
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Checkout code
uses: actions/checkout@v3
- name: Run golangci-lint
uses: golangci/[email protected]
with:
version: latest
args: --timeout 5m
-38
View File
@@ -1,38 +0,0 @@
name: 🔨 Performance Regression
on:
workflow_call:
workflow_dispatch:
jobs:
perf-regression:
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
env:
BENCH_OUT: "/tmp/bench.out"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: make build-test
- run: ./bin/nuclei.test -test.run - -test.bench=. -test.benchmem ./cmd/nuclei/ | tee $BENCH_OUT
env:
DISABLE_STDOUT: "1"
- uses: actions/cache/restore@v4
with:
path: ./cache
key: ${{ runner.os }}-benchmark
- uses: benchmark-action/github-action-benchmark@v1
with:
name: 'RunEnumeration Benchmark'
tool: 'go'
output-file-path: ${{ env.BENCH_OUT }}
external-data-json-path: ./cache/benchmark-data.json
fail-on-alert: false
github-token: ${{ secrets.GITHUB_TOKEN }}
comment-on-alert: true
summary-always: true
- uses: actions/cache/save@v4
if: github.event_name == 'push'
with:
path: ./cache
key: ${{ runner.os }}-benchmark
-43
View File
@@ -1,43 +0,0 @@
name: 🔨 Performance Test
on:
schedule:
- cron: '0 0 * * 0' # Weekly
workflow_dispatch:
jobs:
perf-test:
strategy:
matrix:
count: [50, 100, 150]
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
env:
LIST_FILE: "/tmp/targets-${{ matrix.count }}.txt"
PROFILE_MEM: "/tmp/nuclei-perf-test-${{ matrix.count }}"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: make verify
- name: Generate list
run: for i in {1..${{ matrix.count }}}; do echo "https://honey.scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
- run: go run . -l "${LIST_FILE}" -profile-mem="${PROFILE_MEM}"
env:
NUCLEI_ARGS: host-error-stats
working-directory: cmd/nuclei/
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-cpu
with:
profile: "${{ env.PROFILE_MEM }}.cpu"
name: "${{ env.FLAMEGRAPH_NAME }} CPU profiles"
continue-on-error: true
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-mem
with:
profile: "${{ env.PROFILE_MEM }}.mem"
name: "${{ env.FLAMEGRAPH_NAME }} memory profiles"
continue-on-error: true
- if: ${{ steps.flamegraph-mem.outputs.message == '' }}
run: |
echo "::notice::CPU flamegraph: ${{ steps.flamegraph-cpu.outputs.url }}"
echo "::notice::Memory (heap) flamegraph: ${{ steps.flamegraph-mem.outputs.url }}"
+36
View File
@@ -0,0 +1,36 @@
name: 🔨 Performance Test
on:
workflow_dispatch:
schedule:
# Weekly
- cron: '0 0 * * 0'
jobs:
build:
name: Test Performance
strategy:
matrix:
go-version: [1.21.x]
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
if: github.repository == 'projectdiscovery/nuclei'
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Check out code
uses: actions/checkout@v3
- name: Go Mod hygine
run: |
go clean -modcache
go mod tidy
# Max GH exection time 6H => timeout after that
- name: Running performance with big list
run: go run -race . -l ../functional-test/targets-150.txt
working-directory: cmd/nuclei/
+48
View File
@@ -0,0 +1,48 @@
name: ⏰ Publish Docs
on:
push:
branches:
- dev
workflow_dispatch:
jobs:
docs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: "Set up Go"
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Generate YAML Syntax Documentation
id: generate-docs
run: |
if ! which dstdocgen > /dev/null; then
echo -e "Command dstdocgen not found! Installing\c"
go install github.com/projectdiscovery/yamldoc-go/cmd/docgen/dstdocgen@main
fi
go generate pkg/templates/templates.go
go build -o "cmd/docgen/docgen" cmd/docgen/docgen.go
./cmd/docgen/docgen SYNTAX-REFERENCE.md nuclei-jsonschema.json
git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
- name: Commit files
if: steps.generate-docs.outputs.CHANGES > 0
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add SYNTAX-REFERENCE.md nuclei-jsonschema.json
git commit -m "Auto Generate Syntax Docs + JSONSchema [$(date)] :robot:" -a
- name: Push changes
if: steps.generate-docs.outputs.CHANGES > 0
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
@@ -1,4 +1,4 @@
name: 🎉 Release
name: 🎉 Release Binary
on:
push:
@@ -9,20 +9,22 @@ on:
jobs:
release:
runs-on: ubuntu-latest-16-cores
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: projectdiscovery/actions/setup/go@v1
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- uses: projectdiscovery/actions/goreleaser@v1
- uses: actions/setup-go@v4
with:
release: true
go-version: 1.21.x
- uses: goreleaser/goreleaser-action@v4
with:
args: "release --rm-dist"
version: latest
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"
DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}"
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
+28
View File
@@ -0,0 +1,28 @@
name: 🔨 Release Test
on:
pull_request:
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
jobs:
release-test:
runs-on: ubuntu-latest-16-cores
steps:
- name: "Check out code"
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: release test
uses: goreleaser/goreleaser-action@v4
with:
args: "release --clean --snapshot"
version: latest
-41
View File
@@ -1,41 +0,0 @@
name: 💤 Stale
on:
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
stale:
runs-on: ubuntu-latest
permissions:
actions: write
contents: write # only for delete-branch option
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
days-before-stale: 90
days-before-close: 7
stale-issue-label: "Status: Stale"
stale-pr-label: "Status: Stale"
stale-issue-message: >
This issue has been automatically marked as stale because it has not
had recent activity. It will be closed in 7 days if no further
activity occurs. Thank you for your contributions!
stale-pr-message: >
This pull request has been automatically marked as stale due to
inactivity. It will be closed in 7 days if no further activity
occurs. Please update if you wish to keep it open.
close-issue-message: >
This issue has been automatically closed due to inactivity. If you
think this is a mistake or would like to continue the discussion,
please comment or feel free to reopen it.
close-pr-message: >
This pull request has been automatically closed due to inactivity.
If you think this is a mistake or would like to continue working on
it, please comment or feel free to reopen it.
close-issue-label: "Status: Abandoned"
close-pr-label: "Status: Abandoned"
exempt-issue-labels: "Status: Abandoned"
exempt-pr-labels: "Status: Abandoned"
+23
View File
@@ -0,0 +1,23 @@
name: 🛠 Template Validate
on:
pull_request:
paths:
- '**.go'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest-16-cores
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Template Validation
run: |
go run . -ut
go run . -validate
go run . -validate -w workflows
working-directory: cmd/nuclei/
-177
View File
@@ -1,177 +0,0 @@
name: 🔨 Tests
on:
push:
branches: ["dev"]
paths:
- '**.go'
- '**.mod'
pull_request:
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: "Lint"
if: "${{ !endsWith(github.actor, '[bot]') }}"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/golangci-lint@v1
tests:
name: "Tests"
needs: ["lint"]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: "${{ matrix.os }}"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: make vet
- run: make build
- run: make test
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
- run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
working-directory: cmd/nuclei/
sdk:
name: "Run example SDK"
needs: ["tests"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- name: "Simple"
run: go run .
working-directory: examples/simple/
# - run: go run . # Temporarily disabled very flaky in github actions
# working-directory: examples/advanced/
- name: "with Speed Control"
run: go run .
working-directory: examples/with_speed_control/
integration:
name: "Integration tests"
needs: ["tests"]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/setup/python@v1
- run: bash run.sh "${{ matrix.os }}"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
timeout-minutes: 50
working-directory: integration_tests/
functional:
name: "Functional tests"
needs: ["tests"]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/setup/python@v1
- run: bash run.sh
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
working-directory: cmd/functional-test/
validate:
name: "Template validate"
needs: ["tests"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: make template-validate
codeql:
name: "CodeQL analysis"
needs: ["tests"]
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: 'go'
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
release:
name: "Release test"
needs: ["tests"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/goreleaser@v1
flamegraph:
name: "Flamegraph"
needs: ["tests"]
env:
PROFILE_MEM: "/tmp/nuclei"
TARGET_URL: "http://scanme.sh/a/?b=c"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build
- name: "Setup environment (push)"
if: ${{ github.event_name == 'push' }}
run: |
echo "PROFILE_MEM=${PROFILE_MEM}-${GITHUB_REF_NAME}-${GITHUB_SHA}" >> $GITHUB_ENV
echo "FLAMEGRAPH_NAME=nuclei-${GITHUB_REF_NAME} (${GITHUB_SHA})" >> $GITHUB_ENV
- name: "Setup environment (pull_request)"
if: ${{ github.event_name == 'pull_request' }}
run: |
echo "PROFILE_MEM=${PROFILE_MEM}-pr-${{ github.event.number }}" >> $GITHUB_ENV
echo "FLAMEGRAPH_NAME=nuclei (PR #${{ github.event.number }})" >> $GITHUB_ENV
- run: ./bin/nuclei -silent -update-templates
- run: ./bin/nuclei -silent -u "${TARGET_URL}" -profile-mem="${PROFILE_MEM}"
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-cpu
with:
profile: "${{ env.PROFILE_MEM }}.cpu"
name: "${{ env.FLAMEGRAPH_NAME }} CPU profiles"
continue-on-error: true
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-mem
with:
profile: "${{ env.PROFILE_MEM }}.mem"
name: "${{ env.FLAMEGRAPH_NAME }} memory profiles"
continue-on-error: true
- if: ${{ steps.flamegraph-mem.outputs.message == '' }}
run: |
echo "::notice::CPU flamegraph: ${{ steps.flamegraph-cpu.outputs.url }}"
echo "::notice::Memory (heap) flamegraph: ${{ steps.flamegraph-mem.outputs.url }}"
perf-regression:
needs: ["tests"]
uses: ./.github/workflows/perf-regression.yaml
+35 -45
View File
@@ -1,53 +1,43 @@
# Misc
**/*-cache
**/*-config
**/.cache
**/*.DS_Store
**/*.exe
.devcontainer
.gitignore
.idea
.vscode
# Binaries
/bin/*
/bindgen
/debug-*
/docgen
/functional-test
/fuzzplayground
/integration-test
/jsdocgen
/main
/memogen
/nuclei
/nuclei-stats*
/nuclei_dev
/nuclei_main
/scan-charts
/scrapefunc
/scrapefuncs
/tsgen
# Templates
/*.yaml
# Generated docs
/dsl.md
# Junk
.devcontainer
vendor
dist
integration_tests/nuclei
integration_tests/.cache
integration_tests/integration-test
cmd/nuclei/main
cmd/nuclei/nuclei
cmd/integration-test/nuclei
cmd/functional-test/nuclei_dev
cmd/functional-test/nuclei_main
cmd/functional-test/functional-test
cmd/docgen/docgen
pkg/protocols/common/helpers/deserialization/testdata/Deserialize.class
pkg/protocols/common/helpers/deserialization/testdata/ValueObject.class
pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
vendor
*.exe
.gitignore
pkg/js/devtools/bindgen/cmd/bindgen/bindgen
pkg/js/devtools/jsdocgen/jsdocgen
pkg/js/devtools/tsgen/tsgen
pkg/js/devtools/tsgen/cmd/tsgen/tsgen
*.DS_Store
pkg/protocols/headless/engine/.cache
/nuclei
/bindgen
/jsdocgen
/tsgen
/scrapefuncs
/integration_tests/.cache/
/*.yaml
**/*-config
**/*-cache
/fuzzplayground
integration_tests/fuzzplayground
/dsl.md
/nuclei-stats
/nuclei-stats-*
/scan-charts
# Headless `screenshot` action
*.png
# Profiling & tracing
*.prof
*.pprof
*.trace
*.mem
*.cpu
+24 -94
View File
@@ -1,31 +1,27 @@
version: 2
before:
hooks:
- go mod download
- go mod verify
- go mod tidy
builds:
- main: cmd/nuclei/main.go
binary: nuclei
id: nuclei-cli
env:
- CGO_ENABLED=0
goos: [windows,linux,darwin]
goarch: [amd64,'386',arm,arm64]
ignore:
- goos: darwin
goarch: '386'
- goos: windows
goarch: arm
- goos: windows
goarch: arm64
flags:
- -trimpath
- -pgo=auto
ldflags:
- -s
- -w
- main: cmd/nuclei/main.go
binary: nuclei
id: nuclei-cli
env:
- CGO_ENABLED=0
goos: [windows,linux,darwin]
goarch: [amd64,386,arm,arm64]
ignore:
- goos: darwin
goarch: 386
- goos: windows
goarch: arm
- goos: windows
goarch: arm64
flags:
- -trimpath
#- main: cmd/tmc/main.go
# binary: tmc
@@ -38,80 +34,14 @@ builds:
# goarch: [amd64]
archives:
- format: zip
id: nuclei
builds: [nuclei-cli]
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}'
- format: zip
id: nuclei
builds: [nuclei-cli]
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}'
checksum:
algorithm: sha256
dockers:
- image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:latest-amd64"
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.ref.name={{ .Tag }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
goarch: amd64
- image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:latest-arm64"
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.ref.name={{ .Tag }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
goarch: arm64
# # NOTE(dwisiswant0): chromium doesn't support 32-bit on alpine
# - image_templates:
# - "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-386"
# - "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-386"
# - "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-386"
# - "projectdiscovery/{{ .ProjectName }}:latest-386"
# dockerfile: Dockerfile.goreleaser
# use: buildx
# build_flag_templates:
# - "--pull"
# - "--platform=linux/386"
# - "--label=org.opencontainers.image.created={{ .Date }}"
# - "--label=org.opencontainers.image.ref.name={{ .Tag }}"
# - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
# - "--label=org.opencontainers.image.version={{ .Version }}"
# goarch: "386"
docker_manifests:
- name_template: "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:latest"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:latest-amd64"
- "projectdiscovery/{{ .ProjectName }}:latest-arm64"
announce:
slack:
enabled: true
+11 -41
View File
@@ -381,7 +381,7 @@ func (r *Request) Type() templateTypes.ProtocolType {
}
```
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, `GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
`eventcreator` package offers `CreateEventWithAdditionalOptions` function which can be used to create result events after doing request execution.
@@ -457,55 +457,25 @@ 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 and Tracing
## Profiling Instructions
To analyze Nuclei's performance and resource usage, you can generate CPU & memory profiles and trace files using the `-profile-mem` flag:
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.
```bash
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
```console
$ nuclei -t nuclei-templates/ -u https://example.com -profile-mem mem.pprof
```
This command creates three files:
To view profile data in pprof, first install pprof. Then run the below command -
* `nuclei.cpu`: CPU profile
* `nuclei.mem`: Memory (heap) profile
* `nuclei.trace`: Execution trace
### Analyzing the CPU/Memory Profiles
* View the profile in the terminal:
```bash
go tool pprof nuclei.{cpu,mem}
```console
$ go tool pprof mem.pprof
```
* Display overall CPU time for processing $$N$$ targets:
To open a web UI on a port to visualize debug data, the below command can be used.
```console
$ go tool pprof -http=:8081 mem.pprof
```
go tool pprof -top nuclei.cpu | grep "Total samples"
```
* Display top memory consumers:
```bash
go tool pprof -top nuclei.mem | grep "$(go list -m)" | head -10
```
* Visualize the profile in a web browser:
```bash
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.{cpu,mem}
```
### 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
+9 -9
View File
@@ -1,16 +1,16 @@
# Build
FROM golang:1.23-alpine AS builder
FROM golang:1.21-alpine AS build-env
RUN apk add build-base
WORKDIR /app
COPY . /app
RUN make verify
RUN make build
WORKDIR /app
RUN go mod download
RUN go build ./cmd/nuclei
# Release
FROM alpine:latest
FROM alpine:3.18.6
RUN apk -U upgrade --no-cache \
&& apk add --no-cache bind-tools chromium ca-certificates
COPY --from=build-env /app/nuclei /usr/local/bin/
RUN apk add --no-cache bind-tools chromium ca-certificates
COPY --from=builder /app/bin/nuclei /usr/local/bin/
ENTRYPOINT ["nuclei"]
ENTRYPOINT ["nuclei"]
-12
View File
@@ -1,12 +0,0 @@
FROM alpine:latest
LABEL org.opencontainers.image.authors="ProjectDiscovery"
LABEL org.opencontainers.image.description="Nuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations."
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.title="nuclei"
LABEL org.opencontainers.image.url="https://github.com/projectdiscovery/nuclei"
RUN apk add --no-cache bind-tools chromium ca-certificates
COPY nuclei /usr/local/bin/
ENTRYPOINT ["nuclei"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 ProjectDiscovery, Inc.
Copyright (c) 2022 ProjectDiscovery, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+41 -129
View File
@@ -1,150 +1,62 @@
# Go parameters
GOCMD := go
GOBUILD := $(GOCMD) build
GOBUILD_OUTPUT :=
GOBUILD_PACKAGES :=
GOBUILD_ADDITIONAL_ARGS :=
GOMOD := $(GOCMD) mod
GOTEST := $(GOCMD) test
GOCMD=go
GOBUILD=$(GOCMD) build
GOMOD=$(GOCMD) mod
GOTEST=$(GOCMD) test
GOFLAGS := -v
# This should be disabled if the binary uses pprof
LDFLAGS := -s -w
ifneq ($(shell go env GOOS),darwin)
LDFLAGS += -extldflags "-static"
LDFLAGS := -extldflags "-static"
endif
.PHONY: all build build-stats clean devtools-all devtools-bindgen devtools-scrapefuncs
.PHONY: devtools-tsgen docs docgen dsl-docs functional fuzzplayground go-build syntax-docs
.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test
.PHONY: tidy ts verify download vet template-validate
.PHONY: all build build-stats scan-charts docs test integration functional tidy devtools jsupdate ts fuzzplayground memogen dsl-docs
all: build
clean:
rm -f '${GOBUILD_OUTPUT}' 2>/dev/null
go-build: clean
go-build:
CGO_ENABLED=0 $(GOBUILD) -trimpath $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
-o '${GOBUILD_OUTPUT}' $(GOBUILD_PACKAGES)
build: GOFLAGS = -v -pgo=auto
build: GOBUILD_OUTPUT = ./bin/nuclei
build: GOBUILD_PACKAGES = cmd/nuclei/main.go
build: go-build
build-test: GOFLAGS = -v -pgo=auto
build-test: GOBUILD_OUTPUT = ./bin/nuclei.test
build-test: GOBUILD_PACKAGES = ./cmd/nuclei/
build-test: clean
build-test:
CGO_ENABLED=0 $(GOCMD) test -c -trimpath $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
-o '${GOBUILD_OUTPUT}' ${GOBUILD_PACKAGES}
build-stats: GOBUILD_OUTPUT = ./bin/nuclei-stats
build-stats: GOBUILD_PACKAGES = cmd/nuclei/main.go
build-stats: GOBUILD_ADDITIONAL_ARGS = -tags=stats
build-stats: go-build
scan-charts: GOBUILD_OUTPUT = ./bin/scan-charts
scan-charts: GOBUILD_PACKAGES = cmd/scan-charts/main.go
scan-charts: go-build
template-signer: GOBUILD_OUTPUT = ./bin/template-signer
template-signer: GOBUILD_PACKAGES = cmd/tools/signer/main.go
template-signer: go-build
docgen: GOBUILD_OUTPUT = ./bin/docgen
docgen: GOBUILD_PACKAGES = cmd/docgen/docgen.go
docgen: bin = dstdocgen
docgen:
@if ! which $(bin) >/dev/null; then \
echo "Command $(bin) not found! Installing..."; \
go install -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/$(bin)@latest; \
fi
# TODO: FIX THIS PANIC
$(GOCMD) generate pkg/templates/templates.go
$(GOBUILD) -o "${GOBUILD_OUTPUT}" $(GOBUILD_PACKAGES)
docs: docgen
build:
rm -f nuclei 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "nuclei" cmd/nuclei/main.go
build-stats:
rm -f nuclei-stats 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -tags=stats -o "nuclei-stats" cmd/nuclei/main.go
scan-charts:
rm -f scan-charts 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scan-charts" cmd/scan-charts/main.go
docs:
./bin/docgen docs.md nuclei-jsonschema.json
syntax-docs: docgen
syntax-docs:
./bin/docgen SYNTAX-REFERENCE.md nuclei-jsonschema.json
test: GOFLAGS = -race -v
if ! which dstdocgen > /dev/null; then
echo -e "Command not found! Install? (y/n) \c"
go get -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/dstdocgen
fi
$(GOCMD) generate pkg/templates/templates.go
$(GOBUILD) -o "cmd/docgen/docgen" cmd/docgen/docgen.go
./cmd/docgen/docgen docs.md nuclei-jsonschema.json
test:
$(GOTEST) $(GOFLAGS) ./...
integration:
cd integration_tests; bash run.sh
functional:
cd cmd/functional-test; bash run.sh
tidy:
$(GOMOD) tidy
download:
$(GOMOD) download
verify: download
$(GOMOD) verify
vet: verify
$(GOCMD) vet ./...
devtools-bindgen: GOBUILD_OUTPUT = ./bin/bindgen
devtools-bindgen: GOBUILD_PACKAGES = pkg/js/devtools/bindgen/cmd/bindgen/main.go
devtools-bindgen: go-build
devtools-tsgen: GOBUILD_OUTPUT = ./bin/tsgen
devtools-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
devtools-tsgen: go-build
devtools-scrapefuncs: GOBUILD_OUTPUT = ./bin/scrapefuncs
devtools-scrapefuncs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
devtools-scrapefuncs: go-build
devtools-all: devtools-bindgen devtools-tsgen devtools-scrapefuncs
jsupdate-bindgen: GOBUILD_OUTPUT = ./bin/bindgen
jsupdate-bindgen: GOBUILD_PACKAGES = pkg/js/devtools/bindgen/cmd/bindgen/main.go
jsupdate-bindgen: go-build
jsupdate-bindgen:
./$(GOBUILD_OUTPUT) -dir pkg/js/libs -out pkg/js/generated
jsupdate-tsgen: GOBUILD_OUTPUT = ./bin/tsgen
jsupdate-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
jsupdate-tsgen: go-build
jsupdate-tsgen:
./$(GOBUILD_OUTPUT) -dir pkg/js/libs -out pkg/js/generated/ts
jsupdate-all: jsupdate-bindgen jsupdate-tsgen
ts: jsupdate-tsgen
fuzzplayground: GOBUILD_OUTPUT = ./bin/fuzzplayground
fuzzplayground: GOBUILD_PACKAGES = cmd/tools/fuzzplayground/main.go
fuzzplayground: LDFLAGS = -s -w
fuzzplayground: go-build
memogen: GOBUILD_OUTPUT = ./bin/memogen
memogen: GOBUILD_PACKAGES = cmd/memogen/memogen.go
memogen: go-build
devtools:
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "bindgen" pkg/js/devtools/bindgen/cmd/bindgen/main.go
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "tsgen" pkg/js/devtools/tsgen/cmd/tsgen/main.go
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scrapefuncs" pkg/js/devtools/scrapefuncs/main.go
jsupdate:
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "bindgen" pkg/js/devtools/bindgen/cmd/bindgen/main.go
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "tsgen" pkg/js/devtools/tsgen/cmd/tsgen/main.go
./bindgen -dir pkg/js/libs -out pkg/js/generated
./tsgen -dir pkg/js/libs -out pkg/js/generated/ts
ts:
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "tsgen" pkg/js/devtools/tsgen/cmd/tsgen/main.go
./tsgen -dir pkg/js/libs -out pkg/js/generated/ts
fuzzplayground:
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "fuzzplayground" cmd/tools/fuzzplayground/main.go
memogen:
./$(GOBUILD_OUTPUT) -src pkg/js/libs -tpl cmd/memogen/function.tpl
dsl-docs: GOBUILD_OUTPUT = ./bin/scrapefuncs
dsl-docs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "memogen" cmd/memogen/memogen.go
./memogen -src pkg/js/libs -tpl cmd/memogen/function.tpl
dsl-docs:
./$(GOBUILD_OUTPUT) -out dsl.md
template-validate: build
template-validate:
./bin/nuclei -ut
./bin/nuclei -validate -et http/technologies
./bin/nuclei -validate -w workflows -et http/technologies
rm -f dsl.md scrapefuncs 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scrapefuncs" pkg/js/devtools/scrapefuncs/main.go
./scrapefuncs -out dsl.md
+139 -429
View File
@@ -1,136 +1,110 @@
![nuclei](/static/nuclei-cover-image.png)
<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>
<div align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">`English`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">`中文`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">`Korean`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">`Indonesia`</a> •
<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> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">`Portuguese`</a>
</div>
<p align="center">
<img src="https://img.shields.io/badge/go-1.22-%2300ADD8.svg?style=for-the-badge&logo=go&logoColor=white">
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
&nbsp;&nbsp;
<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>
<hr>
<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>
<br>
<p align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
</p>
**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.**
---
- 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.
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.
<br>
<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.
## Table of Contents
## How it works
- [**`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-heart) ❤
- [**`License`**](#license)
<br>
<br>
<h3 align="center">
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
</h3>
## Get Started
### **1. Nuclei CLI**
| :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. |
_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:_
# Install Nuclei
- Store and visualize your vulnerability findings
- Write and manage your nuclei templates
- Access latest nuclei templates
- Discover and store your targets
> [!Important]
> |**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. |
<br>
### **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:_
- 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
[**`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.
<br>
<br>
## 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).
<div align="center">
<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>
</div>
<br>
### Installation
`nuclei` requires **go1.23** to install successfully. Run the following command to get the repo:
Nuclei requires **go1.21** to install successfully. Run the following command to install the latest version -
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
```
To learn more about installing nuclei, see `https://docs.projectdiscovery.io/tools/nuclei/install`.
<details>
<summary>Brew</summary>
```sh
brew install nuclei
```
</details>
<details>
<summary>Docker</summary>
```sh
docker pull projectdiscovery/nuclei:latest
```
</details>
### Command Line Flags
**More installation [methods can be found here](https://docs.projectdiscovery.io/tools/nuclei/install).**
To display all the flags for the tool:
<table>
<tr>
<td>
### Nuclei Templates
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.
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/).
The YAML DSL reference syntax is available [here](SYNTAX-REFERENCE.md).
</td>
</tr>
</table>
### Usage
```sh
nuclei -h
```
<details>
<summary>Expand full help flags</summary>
This will display help for the tool. Here are all the switches it supports.
```yaml
```console
Nuclei is a fast, template based vulnerability scanner focusing
on extensive configurability, massive extensibility and ease of use.
@@ -157,20 +131,15 @@ TEMPLATES:
-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)
-ai, -prompt string generate and run template using ai prompt
-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
-esc, -enable-self-contained enable loading self-contained templates
-egm, -enable-global-matchers enable loading global matchers templates
-file enable loading file templates
FILTERING:
-a, -author string[] templates to run based on authors (comma-separated, file)
@@ -206,12 +175,9 @@ OUTPUT:
-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)
@@ -231,17 +197,17 @@ CONFIGURATIONS:
-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)
-dt, -dialer-timeout value timeout for network requests.
-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
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
-rss, -response-size-save int max response size to read in bytes (default 1048576)
-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)
@@ -253,39 +219,28 @@ INTERACTSH:
-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
-dts, -dast-server enable dast server mode (live fuzzing)
-dtr, -dast-report write dast scan report to file
-dtst, -dast-server-token string dast server token (optional)
-dtsa, -dast-server-address string dast server address (default "localhost:9055")
-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")
-cs, -fuzz-scope string[] in scope url regex to be followed by fuzzer
-cos, -fuzz-out-scope string[] out of scope url regex to be excluded by fuzzer
-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 only run DAST templates
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)
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (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)
-rlm, -rate-limit-minute int maximum number of requests to send per minute
-bs, -bulk-size int maximum number of hosts to be analyzed in parallel per template (default 25)
-c, -concurrency int maximum number of templates to be executed in parallel (default 25)
-hbs, -headless-bulk-size int maximum number of headless hosts to be analyzed in parallel per template (default 10)
-headc, -headless-concurrency int maximum number of headless templates to be executed in parallel (default 10)
-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)
@@ -312,24 +267,23 @@ 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 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
-debug show all requests and responses
-dreq, -debug-req show all sent requests
-dresp, -debug-resp show all received responses
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
-pi, -proxy-internal proxy all internal requests
-ldf, -list-dsl-function list all supported DSL function signatures
-tlog, -trace-log string file to write sent requests trace log
-elog, -error-log string file to write sent requests error log
-version show nuclei version
-hm, -hang-monitor enable nuclei hang monitoring
-v, -verbose show verbose output
-profile-mem string optional nuclei memory profile dump file
-vv display templates loaded for scan
-svd, -show-var-dump show variables dump for debugging
-ep, -enable-pprof enable pprof debugging server
-tv, -templates-version shows the version of the installed nuclei-templates
-hc, -health-check run diagnostic check up
UPDATE:
-up, -update update nuclei engine to the latest released version
@@ -342,16 +296,11 @@ STATISTICS:
-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)
-hps, -http-stats enable http status capturing (experimental)
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 [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
-auth configure projectdiscovery cloud (pdcp) api key
-cup, -cloud-upload upload scan results to pdcp dashboard
-sid, -scan-id string upload scan results to given scan id
AUTHENTICATION:
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
@@ -360,298 +309,59 @@ 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
```
Additional documentation is available at: [**`docs.nuclei.sh/getting-started/running`**](https://docs.nuclei.sh/getting-started/running?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme)
### Running Nuclei
</details>
See https://docs.projectdiscovery.io/tools/nuclei/running for details on running Nuclei
### Single target scan
### Using Nuclei From Go Code
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 -list 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).
<br>
<br>
## 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).
Complete guide of using Nuclei as Library/SDK is available at [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme)
<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>
### Resources
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)
See https://docs.projectdiscovery.io/tools/nuclei/resources for more resources and videos about Nuclei!
### Credits
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>
#### Examples
Visit [**our documentation**](https://docs.projectdiscovery.io/templates/introduction) for use cases and ideas.
Do also check out the below similar open-source projects that may fit in your workflow:
| 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)** |
[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
<br>
<br>
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)
## 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/).
<br>
<br>
## 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:
<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/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>
<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>
<a href="https://github.com/1hehaq"><img src="https://avatars.githubusercontent.com/u/162917546?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
</p>
<br>
<br>
<br>
<div align="center">
<sub>**`nuclei`** is distributed under [**MIT License**](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)</sub>
</div>
<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>
+2 -4
View File
@@ -32,9 +32,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
</p>
---
@@ -59,7 +57,7 @@ Nuclei使用零误报的定制模板向目标发送请求,同时可以对主
# 安装Nuclei
Nuclei需要 **go1.22** 才能安装成功。执行下列命令安装最新版本的Nuclei
Nuclei需要 **go1.21** 才能安装成功。执行下列命令安装最新版本的Nuclei
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
-370
View File
@@ -1,370 +0,0 @@
<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">Escáner de vulnerabilidades rápido y personalizable basado en un sencillo DSL basado en YAML.</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">Cómo funciona</a> •
<a href="#install-nuclei">Instalación</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/">Documentación</a> •
<a href="#credits">Créditos</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Preguntas Frecuentes</a> •
<a href="https://discord.gg/projectdiscovery">Únete a Discord</a>
</p>
<p align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
---
Nuclei se utiliza para enviar peticiones a múltiples objetivos basándose en una plantilla, lo que resulta en cero falsos positivos y proporciona un escaneo rápido en un gran número de hosts. Nuclei ofrece escaneos para una variedad de protocolos, incluyendo TCP, DNS, HTTP, SSL, File, Whois, Websocket, Headless, Code, etc. Con plantillas potentes y flexibles, Nuclei puede utilizarse para modelar todo tipo de comprobaciones de seguridad.
Tenemos un [repositorio dedicado](https://github.com/projectdiscovery/nuclei-templates) que alberga varios tipos de plantillas de vulnerabilidades, contribuidas por **más de 300** investigadores y ingenieros de seguridad.
## Cómo funciona
<h3 align="center">
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
</h3>
| :exclamation: **Descargo de responsabilidad** |
|---------------------------------|
| **Este proyecto está en desarrollo activo**. Es de esperar que se produzcan cambios importantes con las nuevas versiones. Consulte el registro de cambios de la versión antes de actualizar. |
| Este proyecto fue principalmente desarrollado para ser utilizado como una herramienta CLI independiente. **Ejecutar nuclei como un servicio puede suponer riesgos de seguridad.** Se recomienda utilizarlo con precaución y tomar medidas de seguridad adicionales. |
# Instalación de Nuclei
Nuclei requiere **go1.22** para instalarse correctamente. Ejecute el siguiente comando para instalar la última versión -
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
```
<details>
<summary>Brew</summary>
```sh
brew install nuclei
```
</details>
<details>
<summary>Docker</summary>
```sh
docker pull projectdiscovery/nuclei:latest
```
</details>
**Más métodos de instalación [pueden encontrarse aquí](https://docs.projectdiscovery.io/tools/nuclei/install).**
<table>
<tr>
<td>
### Plantillas de Nuclei
Nuclei cuenta con soporte incorporado para la descarga/actualización automática de plantillas desde la versión [v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2) en adelante. El proyecto [**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates) proporciona una lista de plantillas listas para usar, aportadas por la comunidad, y que se actualizan constantemente.
También puedes utilizar la bandera `update-templates` para actualizar las plantillas de Nuclei en cualquier momento; puedes escribir tus propias pruebas para tu flujo de trabajo y necesidades individuales siguiendo la [guía de plantillas](https://docs.projectdiscovery.io/templates/) de Nuclei.
La sintaxis de referencia YAML DSL está disponible [aquí](SYNTAX-REFERENCE.md).
</td>
</tr>
</table>
### Uso
```sh
nuclei -h
```
Esto mostrará ayuda sobre la herramienta. Aquí están todas las opciones que soporta.
```console
Nuclei es un escáner de vulnerabilidades rápido y basado en plantillas
que se centra en su amplia configurabilidad, extensibilidad y facilidad de uso.
Usage:
./nuclei [flags]
Flags:
TARGET:
-u, -target string[] URLs/hosts a escanear
-l, -list string ruta al archivo que contiene la lista de URLs/hosts a escanear (uno por línea)
-eh, -exclude-hosts string[] hosts a excluir para escanear de la lista de entrada (ip, cidr, hostname)
-resume string reanudar el escaneo usando resume.cfg (la clusterización quedará inhabilitada)
-sa, -scan-all-ips escanear todas las IP asociadas al registro dns
-iv, -ip-version string[] versión IP a escanear del nombre de host (4,6) - (por defecto 4)
TARGET-FORMAT:
-im, -input-mode string modo del archivo de entrada (list, burp, jsonl, yaml, openapi, swagger) (por defecto "list")
-ro, -required-only utilizar solo campos requeridos en el formato de entrada al generar peticiones
-sfv, -skip-format-validation saltar la validación de formato (como variables faltantes) al procesar el archivo de entrada
TEMPLATES:
-nt, -new-templates ejecutar sólo las nuevas plantillas añadidas en la última versión de nuclei-templates
-ntv, -new-templates-version string[] ejecutar las nuevas plantillas añadidas en la versión especificada
-as, -automatic-scan escaneo web automático utilizando la detección de tecnología de wappalyzer para mapeo de etiquetas
-t, -templates string[] lista de plantillas o directorio de plantillas a ejecutar (separadas por comas, file)
-turl, -template-url string[] url de plantilla o lista que contiene urls de plantillas a ejecutar (separadas por comas, file)
-w, -workflows string[] lista de flujos de trabajo o directorio de flujos de trabajo a ejecutar (separadas por comas, file)
-wurl, -workflow-url string[] url de flujo de trabajo o lista que contiene urls de flujo de trabajo para ejecutar (separadas por comas, file)
-validate valida las plantillas pasadas a nuclei
-nss, -no-strict-syntax deshabilita la comprobación de sintaxis estricta en las plantillas
-td, -template-display muestra el contenido de las plantillas
-tl lista todas las plantillas disponibles
-tgl lista todas las etiquetas disponibles
-sign firma las plantillas con la clave privada definida en la variable de entorno NUCLEI_SIGNATURE_PRIVATE_KEY
-code habilita la carga de plantillas basadas en protocolos de código
-dut, -disable-unsigned-templates deshabilita la ejecución de plantillas no firmadas o plantillas con firma no coincidente
FILTERING:
-a, -author string[] plantillas a ejecutar basadas en autores (separadas por comas, file)
-tags string[] plantillas a ejecutar basadas en etiquetas (separadas por comas, file)
-etags, -exclude-tags string[] plantillas a excluir basadas en etiquetas (separadas por comas, file)
-itags, -include-tags string[] etiquetas a ejecutar incluso si están excluidas ya sea por defecto o por configuración
-id, -template-id string[] plantillas a ejecutar basadas en IDs de plantilla (comma-separated, file, allow-wildcard)
-eid, -exclude-id string[] plantillas a excluir basadas en IDs de plantilla (separadas por comas, file)
-it, -include-templates string[] ruta al archivo de plantilla o directorio a ejecutar incluso si están excluidas ya sea por defecto o por configuración
-et, -exclude-templates string[] ruta al archivo de plantilla o directorio a excluir (separadas por comas, file)
-em, -exclude-matchers string[] matchers de plantilla a excluir en el resultado
-s, -severity value[] plantillas a ejecutar basadas en criticidad. Valores posibles: info, bajo, medio, alto, crítico, desconocido
-es, -exclude-severity value[] plantillas a excluir basadas en criticidad. Valores posibles: info, bajo, medio, alto, crítico, desconocido
-pt, -type value[] plantillas a ejecutar basadas en tipo de protocolo. Valores posibles: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-ept, -exclude-type value[] plantillas a excluir basadas en tipo de protocolo. Valores posibles: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-tc, -template-condition string[] plantillas a ejecutar basadas en condición de expresión
OUTPUT:
-o, -output string archivo de salida donde guardar las incidencias/vulnerabilidades detectadas
-sresp, -store-resp almacenar todas las peticiones/respuestas enviadas por nuclei en el directorio de salida
-srd, -store-resp-dir string almacenar todas las peticiones/respuestas enviadas por nuclei en un directorio personalizado (por defecto "output")
-silent mostrar resultados únicamente
-nc, -no-color deshabilitar la coloración del contenido de salida (códigos de escape ANSI)
-j, -jsonl escribir la salida en formato JSONL(ines)
-irr, -include-rr -omit-raw incluir pares peticiones/respuesta en las salidas JSON, JSONL y Markdown (sólo para hallazgos) [OBSOLETO usar -omit-raw] (por defecto true)
-or, -omit-raw omitir los pares peticiones/respuesta en las salidas JSON, JSONL y Markdown (sólo para hallazgos)
-ot, -omit-template omitir plantilla codificada en la salida JSON, JSONL
-nm, -no-meta deshabilitar la impresión de metadatos de resultados en la salida cli
-ts, -timestamp habilitar la impresión de la marca de tiempo en la salida cli
-rdb, -report-db string base de datos de informes de nuclei (utilizarla siempre para persistir los datos de los informes)
-ms, -matcher-status mostrar el estado de fallo de coincidencia
-me, -markdown-export string directorio para exportar resultados en formato markdown
-se, -sarif-export string archivo para exportar resultados en formato SARIF
-je, -json-export string archivo para exportar resultados en formato JSON
-jle, -jsonl-export string archivo para exportar resultados en formato JSONL(ines)
CONFIGURATIONS:
-config string ruta al archivo de configuración de nuclei
-fr, -follow-redirects habilitar el seguimiento de redirecciones para plantillas http
-fhr, -follow-host-redirects seguir redirecciones en el mismo host
-mr, -max-redirects int número máximo de redirecciones a seguir para plantillas http (por defecto 10)
-dr, -disable-redirects deshabilitar redirecciones para plantillas http
-rc, -report-config string archivo de configuración del módulo de informes de nuclei
-H, -header string[] encabezado/cookie personalizado a incluir en todas las peticiones http en formato header:value (cli, file)
-V, -var value variables personalizadas en formato key=value
-r, -resolvers string archivo que contiene lista de resolutores para nuclei
-sr, -system-resolvers utilizar resolución de DNS del sistema como fallback de error
-dc, -disable-clustering deshabilitar la clusterización de peticiones
-passive habilitar el modo de procesamiento pasivo de respuestas HTTP
-fh2, -force-http2 forzar la conexión http2 en las peticiones
-ev, -env-vars habilitar el uso de variables de entorno en la plantilla
-cc, -client-cert string archivo de certificado de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
-ck, -client-key string archivo de clave de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
-ca, -client-ca string archivo de autoridad de certificación de cliente (codificado en PEM) utilizado para autenticarse contra los hosts escaneados
-sml, -show-match-line mostrar líneas de coincidencia para plantillas de archivo, funciona solo con extractores
-ztls utilizar la biblioteca ztls con autofallback a estándar para tls13 [Obsoleto] autofallback a ztls está habilitado por defecto
-sni string nombre de host tls sni a usar (por defecto: nombre de dominio de entrada)
-dt, -dialer-timeout value tiempo de espera para peticiones de red
-dka, -dialer-keep-alive value duración de keep-alive para peticiones de red
-lfa, -allow-local-file-access permite el acceso a archivos (carga útil) en cualquier lugar del sistema
-lna, -restrict-local-network-access bloquea conexiones a la red local / privada
-i, -interface string interfaz de red a usar para el escaneo de red
-at, -attack-type string tipo de combinaciones de carga útil a realizar (batteringram, pitchfork, clusterbomb)
-sip, -source-ip string dirección ip de origen a usar para el escaneo de red
-rsr, -response-size-read int tamaño máximo de respuesta a leer en bytes (por defecto 10485760)
-rss, -response-size-save int tamaño máximo de respuesta a guardar en bytes (por defecto 1048576)
-reset reset elimina todos los archivos de configuración y datos de nuclei (incluidas las nuclei-templates)
-tlsi, -tls-impersonate habilitar client hello (ja3) tls randomization experimental
INTERACTSH:
-iserver, -interactsh-server string url del servidor interactsh para instancia autoalojada (por defecto: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
-itoken, -interactsh-token string token de autenticación del servidor interactsh autoalojado
-interactions-cache-size int número de peticiones a mantener en la caché de interacciones (por defecto 5000)
-interactions-eviction int número de segundos a esperar antes de eliminar las solicitudes de la caché (por defecto 60)
-interactions-poll-duration int número de segundos a esperar antes de cada solicitud de polling de interacciones (por defecto 5)
-interactions-cooldown-period int tiempo adicional para el polling de interacciones antes de salir (por defecto 5)
-ni, -no-interactsh desactivar el servidor interactsh para pruebas OAST, excluir plantillas basadas en OAST
FUZZING:
-ft, -fuzzing-type string sobrescribe el tipo de fuzzing establecido en la plantilla (replace, prefix, postfix, infix)
-fm, -fuzzing-mode string sobrescribe el modo de fuzzing establecido en la plantilla (multiple, single)
-fuzz habilita la carga de plantillas de fuzzing (Obsoleto: usar -dast en su lugar)
-dast solo ejecuta plantillas DAST
UNCOVER:
-uc, -uncover habilita el motor uncover
-uq, -uncover-query string[] consulta de búsqueda uncover
-ue, -uncover-engine string[] motor de búsqueda uncover (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (por defecto shodan)
-uf, -uncover-field string campos uncover a devolver (ip,port,host) (por defecto "ip:port")
-ul, -uncover-limit int resultados uncover a devolver (por defecto 100)
-ur, -uncover-ratelimit int sobrescribe el límite de velocidad de los motores con el límite de velocidad del motor uncover (por defecto 60 req/min) (por defecto 60)
RATE-LIMIT:
-rl, -rate-limit int número máximo de peticiones a enviar por segundo (por defecto 150)
-rlm, -rate-limit-minute int número máximo de peticiones a enviar por minuto
-bs, -bulk-size int número máximo de hosts a ser analizados en paralelo por plantilla (por defecto 25)
-c, -concurrency int número máximo de plantillas a ejecutar en paralelo (por defecto 25)
-hbs, -headless-bulk-size int número máximo de hosts headless a ser analizados en paralelo por plantilla (por defecto 10)
-headc, -headless-concurrency int número máximo de plantillas headless a ejecutar en paralelo (por defecto 10)
-jsc, -js-concurrency int número máximo de entornos de ejecución de JavaScript a ejecutar en paralelo (por defecto 120)
-pc, -payload-concurrency int concurrencia máxima de carga útil para cada plantilla (por defecto 25)
OPTIMIZATIONS:
-timeout int tiempo de espera en segundos (por defecto 10)
-retries int número de veces que se reintenta una petición fallida (por defecto 1)
-ldp, -leave-default-ports dejar puertos HTTP/HTTPS predeterminados (por ejemplo, host:80,host:443)
-mhe, -max-host-error int errores máximos para un host antes de omitirlo del escaneo (por defecto 30)
-te, -track-error string[] agrega el error dado a la lista de seguimiento de errores máximos por host (standard, file)
-nmhe, -no-mhe deshabilita la omisión del host del escaneo basado en errores
-project utiliza una carpeta de proyecto para evitar enviar la misma petición varias veces
-project-path string establece una ruta de proyecto específica (por defecto "/tmp")
-spm, -stop-at-first-match detiene el procesamiento de las peticiones HTTP después de la primera coincidencia (puede romper la lógica de la plantilla/flujo de trabajo)
-stream modo transmisión - comienza a trabajar sin ordenar la entrada
-ss, -scan-strategy value estrategia a utilizar mientras se escanea (auto/host-spray/template-spray) (por defecto auto)
-irt, -input-read-timeout value tiempo de espera en la lectura de entrada (por defecto 3m0s)
-nh, -no-httpx deshabilita análisis httpx para entradas que no son URL
-no-stdin deshabilita el procesamiento de la entrada estándar
HEADLESS:
-headless habilita las plantillas que requieren soporte de navegadores sin interfaz gráfica (headless browser) (el usuario root en Linux deshabilitará el sandbox)
-page-timeout int segundos para esperar cada página en modo sin interfaz (por defecto 20)
-sb, -show-browser muestra el navegador en la pantalla al ejecutar plantillas con modo sin interfaz
-ho, -headless-options string[] inicia Chrome en modo sin interfaz con opciones adicionales
-sc, -system-chrome utiliza el navegador Chrome instalado localmente en lugar del instalado por nuclei
-lha, -list-headless-action lista de acciones sin interfaz disponibles
DEBUG:
-debug muestra todas las peticiones y respuestas
-dreq, -debug-req muestra todas las peticiones enviadas
-dresp, -debug-resp muestra todas las respuestas recibidas
-p, -proxy string[] lista de proxies http/socks5 a utilizar (separados por comas o archivo de entrada)
-pi, -proxy-internal proxy para todas las peticiones internas
-ldf, -list-dsl-function lista todas las firmas de función DSL admitidas
-tlog, -trace-log string archivo a escribir el registro de traza de peticiones enviadas
-elog, -error-log string archivo a escribir el registro de error de peticiones enviadas
-version muestra la versión de nuclei
-hm, -hang-monitor habilita la monitorización de bloqueos de nuclei
-v, -verbose muestra salida detallada
-profile-mem string archivo opcional de volcado de memoria de nuclei
-vv muestra las plantillas cargadas para el escaneo
-svd, -show-var-dump muestra el volcado de variables para depuración
-ep, -enable-pprof habilita el servidor de depuración pprof
-tv, -templates-version muestra la versión de las plantillas nuclei (nuclei-templates) instaladas
-hc, -health-check ejecuta comprobación de diagnóstico
UPDATE:
-up, -update actualiza el motor de nuclei a la última versión lanzada
-ut, -update-templates actualiza nuclei-templates a la última versión lanzada
-ud, -update-template-dir string directorio personalizado para instalar/actualizar nuclei-templates
-duc, -disable-update-check deshabilita la comprobación automática de actualizaciones de nuclei/templates
STATISTICS:
-stats muestra estadísticas sobre el escaneo en ejecución
-sj, -stats-json muestra estadísticas en formato JSONL(ines)
-si, -stats-interval int número de segundos a esperar entre mostrar una actualización de estadísticas (por defecto 5)
-mp, -metrics-port int puerto para exponer métricas de nuclei (por defecto 9092)
CLOUD:
-auth configura la clave de API del cloud de projectdiscovery (pdcp)
-cup, -cloud-upload sube los resultados del escaneo al dashboard de pdcp
-sid, -scan-id string sube los resultados del escaneo al ID de escaneo dado
AUTHENTICATION:
-sf, -secret-file string[] ruta al archivo de configuración que contiene los secrets para el escaneo autenticado de nuclei
-ps, -prefetch-secrets precarga los secrets del archivo de secrets
EXAMPLES:
Ejecutar nuclei en un solo host:
$ nuclei -target example.com
Ejecutar nuclei con directorios de plantillas específicos:
$ nuclei -target example.com -t http/cves/ -t ssl
Ejecutar nuclei contra una lista de hosts:
$ nuclei -list hosts.txt
Ejecutar nuclei con una salida JSON:
$ nuclei -target example.com -json-export output.json
Ejecutar nuclei con salidas Markdown ordenadas (con variables de entorno):
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
Documentación adicional disponible en: https://docs.nuclei.sh/getting-started/running
```
### Ejecutando Nuclei
Consulta https://docs.projectdiscovery.io/tools/nuclei/running para obtener detalles sobre cómo ejecutar Nuclei.
### Uso de Nuclei desde código Go
La guía completa sobre cómo usar Nuclei como biblioteca/SDK está disponible en [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme).
### Recursos
Puedes acceder a la documentación principal de Nuclei en https://docs.projectdiscovery.io/tools/nuclei/, y obtener más información sobre Nuclei en la nube con [ProjectDiscovery Cloud Platform](https://cloud.projectdiscovery.io).
¡Consulta https://docs.projectdiscovery.io/tools/nuclei/resources para obtener más recursos y videos sobre Nuclei!
### Créditos
Gracias a todos los increíbles [contribuyentes de la comunidad que enviaron PRs](https://github.com/projectdiscovery/nuclei/graphs/contributors) y mantienen este proyecto actualizado. :heart:
Si tienes una idea o algún tipo de mejora, eres bienvenido a contribuir y participar en el Proyecto, siéntete libre de enviar tu 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>
También echa un vistazo a los siguientes proyectos de código abierto similares que pueden adaptarse a tu flujo de trabajo:
[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)
### Licencia
Nuclei se distribuye bajo la [Licencia MIT](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>
+2 -4
View File
@@ -32,9 +32,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
</p>
---
@@ -54,7 +52,7 @@ Kami memiliki [repositori khusus](https://github.com/projectdiscovery/nuclei-tem
# Instalasi Nuclei
Nuclei membutuhkan **go1.22** agar dapat diinstall. Jalankan perintah berikut untuk menginstal versi terbaru -
Nuclei membutuhkan **go1.21** agar dapat diinstall. Jalankan perintah berikut untuk menginstal versi terbaru -
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
-173
View File
@@ -1,173 +0,0 @@
<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">シンプルなYAMLベースの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">動作原理</a> •
<a href="#install-nuclei">インストール</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/">ドキュメント</a> •
<a href="#credits">クレジット</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQ</a> •
<a href="https://discord.gg/projectdiscovery">Discordに参加</a>
</p>
<p align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">英語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中国語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">韓国語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">インドネシア語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">ポルトガル語</a>
</p>
---
Nucleiは、テンプレートに基づいてターゲット間でリクエストを送信するために使用され、偽陽性がゼロであり、多数のホストで高速なスキャンを提供します。Nucleiは、TCP、DNS、HTTP、SSL、ファイル、Whois、Websocket、Headless、Codeなど、さまざまなプロトコルのスキャンを提供します。強力で柔軟なテンプレートを使用して、Nucleiはすべての種類のセキュリティチェックをモデル化するために使用できます。
**300人以上の** セキュリティ研究者およびエンジニアが提供するさまざまなタイプの脆弱性テンプレートを収容する[専用リポジトリ](https://github.com/projectdiscovery/nuclei-templates)を持っています。
## 動作原理
<h3 align="center">
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
</h3>
| :exclamation: **免責事項** |
|---------------------------------|
| **このプロジェクトは積極的に開発されています**。リリースによって重大な変更が発生することがあります。更新する前にリリースの変更ログを確認してください。 |
| このプロジェクトは主にスタンドアロンのCLIツールとして使用されることを目的として構築されました。**Nucleiをサービスとして実行すると、セキュリティリスクが生じる可能性があります。**注意して使用し、追加のセキュリティ対策を講じることをお勧めします。 |
# Nucleiのインストール
Nucleiを正常にインストールするには、**go1.22**が必要です。以下のコマンドを実行して最新バージョンをインストールしてください -
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
```
<details>
<summary>Brew</summary>
```sh
brew install nuclei
```
</details>
<details>
<summary>Docker</summary>
```sh
docker pull projectdiscovery/nuclei:latest
```
</details>
**より多くのインストール方法は[こちら](https://docs.projectdiscovery.io/tools/nuclei/install)で見つけることができます。**
<table>
<tr>
<td>
### Nucleiテンプレート
Nucleiは、バージョン[v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2)以降、デフォルトでテンプレートの自動ダウンロード/更新をサポートしています。[**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates)プロジェクトは、常に更新されるコミュニティ提供の即時使用可能なテンプレートのリストを提供します。
`update-templates`フラグを使用して、いつでもNucleiテンプレートを更新することができます。Nucleiの[テンプレートガイド](https://docs.projectdiscovery.io/templates/)に従って、個々のワークフローとニーズに合わせた独自のチェックを作成することができます。
YAML DSLの構文リファレンスは[こちら](SYNTAX-REFERENCE.md)で確認できます。
</td>
</tr>
</table>
### 使用方法
```sh
nuclei -h
```
これにより、ツールのヘルプが表示されます。ここには、サポートされているすべてのスイッチがあります。
```console
Nucleiは、広範な設定可能性、大規模な拡張性、および使いやすさに焦点を当てた、
高速でテンプレートベースの脆弱性スキャナーです。
使用法:
./nuclei [flags]
フラグ:
ターゲット:
-u, -target string[] スキャンする対象のURL/ホスト
-l, -list string スキャンする対象のURL/ホストのリストが含まれているファイルへのパス(1行に1つ)
-resume string resume.cfgを使用してスキャンを再開(クラスタリングは無効になります)
-sa, -scan-all-ips DNSレコードに関連付けられているすべてのIPをスキャン
-iv, -ip-version string[] ホスト名のスキャンするIPバージョン(4,6)-(デフォルトは4)
テンプレート:
-nt, -new-templates 最新のnuclei-templatesリリースに追加された新しいテンプレートのみを実行
-ntv, -new-templates-version string[] 特定のバージョンに追加された新しいテンプレートを実行
-as, -automatic-scan wappalyzer技術検出をタグマッピングに使用した自動Webスキャン
-t, -templates string[] 実行するテンプレートまたはテンプレートディレクトリのリスト(カンマ区切り、ファイル)
-turl, -template-url string[] 実行するテンプレートのURLまたはテンプレートURLのリスト(カンマ区切り、ファイル)
-w, -workflows string[] 実行するワークフローまたはワークフローディレクトリのリスト(カンマ区切り、ファイル)
-wurl, -workflow-url string[] 実行するワークフローのURLまたはワークフローURLのリスト(カンマ区切り、ファイル)
-validate Nucleiに渡されたテンプレートを検証
-nss, -no-strict-syntax テンプレートで厳密な構文チェックを無効にする
-td, -template-display テンプレートの内容を表示
-tl 利用可能なすべてのテンプレートをリスト
-sign NUCLEI_SIGNATURE_PRIVATE_KEY環境変数で定義された秘密鍵でテンプレートに署名
-code コードプロトコルベースのテンプレートのロードを有効にする
フィルタリング:
-a, -author string[] 作者に基づいて実行するテンプレート(カンマ区切り、ファイル)
-tags string[] タグに基づいて実行するテンプレート(カンマ区切り、ファイル)
-etags, -exclude-tags string[] タグに基づいて除外するテンプレート(カンマ区切り、ファイル)
-itags, -include-tags string[] デフォルトまたは設定によって除外されている場合でも実行する必要があるタグ
-id, -template-id string[] テンプレートIDに基づいて実行するテンプレート(カンマ区切り、ファイル)
-eid, -exclude-id string[] テンプレートIDに基づいて除外するテンプレート(カンマ区切り、ファイル)
-it, -include-templates string[] デフォルトまたは設定によって除外されている場合でも実行する必要があるテンプレート
-et, -exclude-templates string[] 除外するテンプレートまたはテンプレートディレクトリへのパス(カンマ区切り、ファイル)
-em, -exclude-matchers string[] 結果で除外するテンプレートマッチャー
-s, -severity value[] 重大度に基づいて実行するテンプレート。可能な値:info, low, medium, high, critical, unknown
-es, -exclude-severity value[] 重大度に基づいて除外するテンプレート。可能な値:info, low, medium, high, critical, unknown
-pt, -type value[] プロトコルタイプに基づいて実行するテンプレート。可能な値:dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-ept, -exclude-type value[] プロトコルタイプに基づいて除外するテンプレート。可能な値:dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-tc, -template-condition string[] 式条件に基づいて実行するテンプレート
出力:
-o, -output string 発見された問題/脆弱性を書き込む出力ファイル
-sresp, -store-resp Nucleiを通じて渡されたすべてのリクエスト/レスポンスを出力ディレクトリに保存
-srd, -store-resp-dir string Nucleiを通じて渡されたすべてのリクエスト/レスポンスをカスタムディレクトリに保存(デフォルトは「output」)
-silent 結果のみを表示
-nc, -no-color 出力内容の着色を無効にする(ANSIエスケープコード)
-j, -jsonl JSONL(ines)形式で出力を書き込む
-irr, -include-rr -omit-raw JSON、JSONL、Markdown出力にリクエスト/レスポンスペアを含める(発見のみ)[非推奨 -omit-raw使用](デフォルトはtrue)
-or, -omit-raw JSON、JSONL、Markdown出力でリクエスト/レスポンスペアを省略する(発見のみ)
-ot, -omit-template JSON、JSONL出力でエンコードされたテンプレートを省略
-nm, -no-meta CLI出力で結果のメタデータの印刷を無効にする
-ts, -timestamp CLI出力にタイムスタンプを印刷することを有効にする
-rdb, -report-db string Nucleiレポートデータベース(レポートデータを永続化するために常にこれを使用)
-ms, -matcher-status マッチ失敗のステータスを表示
-me, -markdown-export string Markdown形式で結果をエクスポートするディレクトリ
-se, -sarif-export string SARIF形式で結果をエクスポートするファイル
-je, -json-export string JSON形式で結果をエクスポートするファイル
-jle, -jsonl-export string JSONL(ine)形式で結果をエクスポートするファイル
設定:
-config string Nucleiの設定ファイルへのパス
-fr, -follow-redirects HTTPテンプレートのリダイレクトをフォローすることを有効にする
-fhr, -follow-host-redirects
+2 -4
View File
@@ -30,9 +30,7 @@
<p align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">포르투갈어</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a>
</p>
---
@@ -52,7 +50,7 @@ Nuclei는 템플릿을 기반으로 대상 간에 요청을 보내기 위해 사
# 설치
Nuclei를 성공적으로 설치하기 위해서 **go1.22**가 필요합니다. 다음 명령을 실행하여 최신 버전을 설치합니다.
Nuclei를 성공적으로 설치하기 위해서 **go1.21**가 필요합니다. 다음 명령을 실행하여 최신 버전을 설치합니다.
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
-370
View File
@@ -1,370 +0,0 @@
<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">Scanner de vulnerabilidades rápido e personalizável baseado em uma DSL simples baseada em YAML.</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="#como-funciona">Como funciona</a> •
<a href="#instalacao-do-nuclei">Instalação</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/">Documentação</a> •
<a href="#créditos">Créditos</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Perguntas Frequentes</a> •
<a href="https://discord.gg/projectdiscovery">Junte-se ao Discord</a>
</p>
<p align="center">
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
---
O Nuclei é utilizado para enviar solicitações para vários alvos baseados em um modelo, resultando em zero falsos positivos e proporcionando uma varredura rápida em um grande número de hosts. O Nuclei oferece suporte a uma variedade de protocolos, incluindo TCP, DNS, HTTP, SSL, Arquivo, Whois, Websocket, Headless, Código, entre outros. Com modelos poderosos e flexíveis, o Nuclei pode ser usado para modelar todos os tipos de verificações de segurança.
Temos um [repositório dedicado](https://github.com/projectdiscovery/nuclei-templates) que abriga vários tipos de modelos de vulnerabilidades, contribuídos por **mais de 300** pesquisadores e engenheiros de segurança.
## Como funciona
<h3 align="center">
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
</h3>
| :exclamation: **Aviso** |
|---------------------------------|
| **Este projeto está em desenvolvimento ativo**. Alterações significativas são esperadas em versões futuras. Consulte o changelog antes de atualizar. |
| Este projeto foi desenvolvido principalmente para ser usado como uma ferramenta CLI independente. **Executar o Nuclei como um serviço pode implicar riscos de segurança.** É recomendável utilizá-lo com precaução e medidas de segurança adicionais. |
# Instalação do Nuclei
O Nuclei requer **go1.22** para ser instalado corretamente. Execute o seguinte comando para instalar a versão mais recente:
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
```
<details>
<summary>Brew</summary>
```sh
brew install nuclei
```
</details>
<details>
<summary>Docker</summary>
```sh
docker pull projectdiscovery/nuclei:latest
```
</details>
**Mais métodos de instalação [podem ser encontrados aqui](https://docs.projectdiscovery.io/tools/nuclei/install).**
<table>
<tr>
<td>
### Modelos do Nuclei
O Nuclei possui suporte integrado para download/atualização automática de modelos a partir da versão [v2.5.2](https://github.com/projectdiscovery/nuclei/releases/tag/v2.5.2). O projeto [**Nuclei-Templates**](https://github.com/projectdiscovery/nuclei-templates) fornece uma lista de modelos prontos para uso, atualizados constantemente pela comunidade.
Você também pode usar a flag `update-templates` para atualizar os modelos do Nuclei a qualquer momento; também pode criar seus próprios testes para seu fluxo de trabalho e necessidades específicas seguindo o [guia de modelos](https://docs.projectdiscovery.io/templates/) do Nuclei.
A referência de sintaxe YAML DSL está disponível [aqui](SYNTAX-REFERENCE.md).
</td>
</tr>
</table>
### Uso
```sh
nuclei -h
```
Isso mostrará ajuda sobre a ferramenta. Aqui estão todas as opções que ela suporta.
```console
Nuclei é um scanner de vulnerabilidades rápido e baseado em templates
que se concentra em sua ampla configurabilidade, extensibilidade e facilidade de uso.
Usage:
./nuclei [flags]
Flags:
TARGET:
-u, -target string[] URLs/hosts a serem escaneados
-l, -list string caminho do arquivo contendo a lista de URLs/hosts a serem escaneados (um por linha)
-eh, -exclude-hosts string[] hosts a serem excluídos do escaneamento na lista de entrada (ip, cidr, hostname)
-resume string retomar o escaneamento usando resume.cfg (a clusterização será desabilitada)
-sa, -scan-all-ips escanear todos os IPs associados ao registro DNS
-iv, -ip-version string[] versão de IP a escanear do nome do host (4,6) - (padrão 4)
TARGET-FORMAT:
-im, -input-mode string modo do arquivo de entrada (list, burp, jsonl, yaml, openapi, swagger) (padrão "list")
-ro, -required-only usar apenas campos obrigatórios no formato de entrada ao gerar requisições
-sfv, -skip-format-validation pular a validação de formato (como variáveis ausentes) ao processar o arquivo de entrada
TEMPLATES:
-nt, -new-templates executar apenas os novos templates adicionados na última versão de nuclei-templates
-ntv, -new-templates-version string[] executar os novos templates adicionados na versão especificada
-as, -automatic-scan escaneamento da web automático utilizando a detecção de tecnologia do Wappalyzer para mapeamento de tags
-t, -templates string[] lista de templates ou diretório de templates a executar (separados por vírgulas, arquivo)
-turl, -template-url string[] URL de template ou lista contendo URLs de templates a executar (separados por vírgulas, arquivo)
-w, -workflows string[] lista de fluxos de trabalho ou diretório de fluxos de trabalho a executar (separados por vírgulas, arquivo)
-wurl, -workflow-url string[] URL de fluxo de trabalho ou lista contendo URLs de fluxos de trabalho para executar (separados por vírgulas, arquivo)
-validate valida os templates passados para o nuclei
-nss, -no-strict-syntax desativa a verificação de sintaxe estrita nos templates
-td, -template-display exibe o conteúdo dos templates
-tl lista todos os templates disponíveis
-tgl lista todas as tags disponíveis
-sign assina os templates com a chave privada definida na variável de ambiente NUCLEI_SIGNATURE_PRIVATE_KEY
-code habilita o carregamento de templates baseados em protocolos de código
-dut, -disable-unsigned-templates desativa a execução de templates não assinados ou com assinatura incompatível
FILTERING:
-a, -author string[] templates a serem executados com base nos autores (separados por vírgulas, arquivo)
-tags string[] templates a serem executados com base em tags (separados por vírgulas, arquivo)
-etags, -exclude-tags string[] templates a excluir com base em tags (separados por vírgulas, arquivo)
-itags, -include-tags string[] tags a executar mesmo que estejam excluídas por padrão ou configuração
-id, -template-id string[] templates a serem executados com base em IDs de template (separados por vírgulas, arquivo, permitem curingas)
-eid, -exclude-id string[] templates a excluir com base em IDs de template (separados por vírgulas, arquivo)
-it, -include-templates string[] caminho do arquivo de template ou diretório a executar mesmo que estejam excluídos por padrão ou configuração
-et, -exclude-templates string[] caminho do arquivo de template ou diretório a excluir (separados por vírgulas, arquivo)
-em, -exclude-matchers string[] matchers de template a excluir no resultado
-s, -severity value[] templates a executar com base na criticidade. Valores possíveis: info, baixo, médio, alto, crítico, desconhecido
-es, -exclude-severity value[] templates a excluir com base na criticidade. Valores possíveis: info, baixo, médio, alto, crítico, desconhecido
-pt, -type value[] templates a executar com base no tipo de protocolo. Valores possíveis: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-ept, -exclude-type value[] templates a excluir com base no tipo de protocolo. Valores possíveis: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
-tc, -template-condition string[] templates a executar com base em condição de expressão
OUTPUT:
-o, -output string arquivo de saída para salvar as ocorrências/vulnerabilidades detectadas
-sresp, -store-resp armazenar todas as solicitações/respostas enviadas pelo nuclei no diretório de saída
-srd, -store-resp-dir string armazenar todas as solicitações/respostas enviadas pelo nuclei em um diretório personalizado (padrão "output")
-silent exibir apenas os resultados
-nc, -no-color desativar a coloração do conteúdo de saída (códigos de escape ANSI)
-j, -jsonl salvar a saída no formato JSONL(ines)
-irr, -include-rr -omit-raw incluir pares solicitação/resposta nas saídas JSON, JSONL e Markdown (apenas para achados) [OBSOLETO usar -omit-raw] (padrão true)
-or, -omit-raw omitir os pares solicitação/resposta nas saídas JSON, JSONL e Markdown (apenas para achados)
-ot, -omit-template omitir o template codificado na saída JSON, JSONL
-nm, -no-meta desativar a exibição de metadados dos resultados na saída CLI
-ts, -timestamp ativar a exibição do carimbo de data/hora na saída CLI
-rdb, -report-db string banco de dados de relatórios do nuclei (usar sempre para persistir os dados dos relatórios)
-ms, -matcher-status exibir o estado de falha de correspondência
-me, -markdown-export string diretório para exportar resultados no formato Markdown
-se, -sarif-export string arquivo para exportar resultados no formato SARIF
-je, -json-export string arquivo para exportar resultados no formato JSON
-jle, -jsonl-export string arquivo para exportar resultados no formato JSONL(ines)
CONFIGURATIONS:
-config string caminho do arquivo de configuração do nuclei
-fr, -follow-redirects ativar o acompanhamento de redirecionamentos para templates HTTP
-fhr, -follow-host-redirects seguir redirecionamentos no mesmo host
-mr, -max-redirects int número máximo de redirecionamentos a seguir para templates HTTP (padrão 10)
-dr, -disable-redirects desativar redirecionamentos para templates HTTP
-rc, -report-config string arquivo de configuração do módulo de relatórios do nuclei
-H, -header string[] cabeçalho/cookie personalizado a incluir em todas as solicitações HTTP no formato header:value (CLI, arquivo)
-V, -var value variáveis personalizadas no formato key=value
-r, -resolvers string arquivo contendo uma lista de resolvers para o nuclei
-sr, -system-resolvers usar resolução DNS do sistema como fallback em caso de erro
-dc, -disable-clustering desativar o agrupamento de solicitações
-passive ativar o modo de processamento passivo de respostas HTTP
-fh2, -force-http2 forçar conexões HTTP2 nas solicitações
-ev, -env-vars ativar o uso de variáveis de ambiente no template
-cc, -client-cert string arquivo de certificado de cliente (codificado em PEM) usado para autenticar-se contra os hosts escaneados
-ck, -client-key string arquivo de chave de cliente (codificado em PEM) usado para autenticar-se contra os hosts escaneados
-ca, -client-ca string arquivo de autoridade de certificação de cliente (codificado em PEM) usado para autenticar-se contra os hosts escaneados
-sml, -show-match-line exibir linhas de correspondência para templates de arquivo, funciona apenas com extratores
-ztls usar a biblioteca ztls com fallback automático para padrão no tls13 [OBSOLETO] fallback automático para ztls já está ativado por padrão
-sni string nome de host tls sni a ser usado (padrão: nome de domínio de entrada)
-dt, -dialer-timeout value tempo limite para solicitações de rede
-dka, -dialer-keep-alive value duração do keep-alive para solicitações de rede
-lfa, -allow-local-file-access permitir acesso a arquivos (payload) em qualquer lugar do sistema
-lna, -restrict-local-network-access bloquear conexões à rede local/privada
-i, -interface string interface de rede a ser usada para o escaneamento de rede
-at, -attack-type string tipo de combinações de payload a realizar (batteringram, pitchfork, clusterbomb)
-sip, -source-ip string endereço IP de origem a ser usado para o escaneamento de rede
-rsr, -response-size-read int tamanho máximo de resposta a ser lido em bytes (padrão 10485760)
-rss, -response-size-save int tamanho máximo de resposta a ser salvo em bytes (padrão 1048576)
-reset remove todos os arquivos de configuração e dados do nuclei (incluindo os nuclei-templates)
-tlsi, -tls-impersonate ativar randomização experimental do client hello (ja3) tls
INTERACTSH:
-iserver, -interactsh-server string URL do servidor interactsh para instância auto-hospedada (padrão: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
-itoken, -interactsh-token string token de autenticação para o servidor interactsh auto-hospedado
-interactions-cache-size int número de solicitações a serem mantidas no cache de interações (padrão 5000)
-interactions-eviction int número de segundos a esperar antes de remover solicitações do cache (padrão 60)
-interactions-poll-duration int número de segundos a esperar antes de cada solicitação de polling de interações (padrão 5)
-interactions-cooldown-period int tempo adicional para o polling de interações antes de encerrar (padrão 5)
-ni, -no-interactsh desativar o servidor interactsh para testes OAST, excluir templates baseados em OAST
FUZZING:
-ft, -fuzzing-type string sobrescreve o tipo de fuzzing definido no template (replace, prefix, postfix, infix)
-fm, -fuzzing-mode string sobrescreve o modo de fuzzing definido no template (multiple, single)
-fuzz habilita o carregamento de templates de fuzzing (Obsoleto: usar -dast em vez disso)
-dast executa apenas templates DAST
UNCOVER:
-uc, -uncover ativa o motor uncover
-uq, -uncover-query string[] consulta de busca uncover
-ue, -uncover-engine string[] motor de busca uncover (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (padrão shodan)
-uf, -uncover-field string campos uncover a serem retornados (ip,port,host) (padrão "ip:port")
-ul, -uncover-limit int resultados uncover a serem retornados (padrão 100)
-ur, -uncover-ratelimit int sobrescreve o limite de taxa dos motores com o limite de taxa do motor uncover (padrão 60 req/min)
RATE-LIMIT:
-rl, -rate-limit int número máximo de solicitações a serem enviadas por segundo (padrão 150)
-rlm, -rate-limit-minute int número máximo de solicitações a serem enviadas por minuto
-bs, -bulk-size int número máximo de hosts a serem analisados em paralelo por template (padrão 25)
-c, -concurrency int número máximo de templates a serem executados em paralelo (padrão 25)
-hbs, -headless-bulk-size int número máximo de hosts headless a serem analisados em paralelo por template (padrão 10)
-headc, -headless-concurrency int número máximo de templates headless a serem executados em paralelo (padrão 10)
-jsc, -js-concurrency int número máximo de ambientes de execução de JavaScript a serem executados em paralelo (padrão 120)
-pc, -payload-concurrency int concorrência máxima de payload para cada template (padrão 25)
OPTIMIZATIONS:
-timeout int tempo limite em segundos (padrão 10)
-retries int número de tentativas para solicitações com falha (padrão 1)
-ldp, -leave-default-ports manter as portas HTTP/HTTPS padrão (exemplo: host:80, host:443)
-mhe, -max-host-error int número máximo de erros para um host antes de ignorá-lo no scan (padrão 30)
-te, -track-error string[] adiciona o erro especificado à lista de rastreamento de erros máximos por host (standard, file)
-nmhe, -no-mhe desativa a exclusão de hosts do scan com base em erros
-project utiliza uma pasta de projeto para evitar enviar a mesma solicitação várias vezes
-project-path string define um caminho específico para o projeto (padrão "/tmp")
-spm, -stop-at-first-match interrompe o processamento de solicitações HTTP após a primeira correspondência (pode quebrar a lógica de templates/fluxos de trabalho)
-stream modo de transmissão - começa a trabalhar sem ordenar a entrada
-ss, -scan-strategy value estratégia a ser usada durante o scan (auto/host-spray/template-spray) (padrão auto)
-irt, -input-read-timeout value tempo limite para leitura da entrada (padrão 3m0s)
-nh, -no-httpx desativa a análise httpx para entradas que não sejam URLs
-no-stdin desativa o processamento de entrada padrão
HEADLESS:
-headless habilita templates que requerem suporte para navegadores sem interface gráfica (headless browser) (o usuário root no Linux desativará o sandbox)
-page-timeout int segundos para esperar cada página no modo headless (padrão 20)
-sb, -show-browser exibe o navegador na tela ao executar templates no modo headless
-ho, -headless-options string[] inicia o Chrome no modo headless com opções adicionais
-sc, -system-chrome utiliza o navegador Chrome instalado localmente em vez do instalado pelo nuclei
-lha, -list-headless-action lista ações disponíveis para o modo headless
DEBUG:
-debug exibe todas as solicitações e respostas
-dreq, -debug-req exibe todas as solicitações enviadas
-dresp, -debug-resp exibe todas as respostas recebidas
-p, -proxy string[] lista de proxies HTTP/SOCKS5 a serem usados (separados por vírgulas ou arquivo de entrada)
-pi, -proxy-internal proxy para todas as solicitações internas
-ldf, -list-dsl-function lista todas as assinaturas de funções DSL suportadas
-tlog, -trace-log string arquivo para gravar o log de rastreamento de solicitações enviadas
-elog, -error-log string arquivo para gravar o log de erros de solicitações enviadas
-version exibe a versão do nuclei
-hm, -hang-monitor ativa o monitoramento de travamentos do nuclei
-v, -verbose exibe saída detalhada
-profile-mem string arquivo opcional para despejo de memória do nuclei
-vv exibe os templates carregados para o scan
-svd, -show-var-dump exibe o dump de variáveis para depuração
-ep, -enable-pprof ativa o servidor de depuração pprof
-tv, -templates-version exibe a versão dos templates do nuclei (nuclei-templates) instalados
-hc, -health-check executa verificações de diagnóstico
UPDATE:
-up, -update atualiza o mecanismo do nuclei para a última versão lançada
-ut, -update-templates atualiza os nuclei-templates para a última versão lançada
-ud, -update-template-dir string diretório personalizado para instalar/atualizar os nuclei-templates
-duc, -disable-update-check desativa a verificação automática de atualizações do nuclei/templates
STATISTICS:
-stats exibe estatísticas sobre o scan em execução
-sj, -stats-json exibe estatísticas no formato JSONL(ines)
-si, -stats-interval int número de segundos a esperar entre as atualizações de estatísticas (padrão 5)
-mp, -metrics-port int porta para expor métricas do nuclei (padrão 9092)
CLOUD:
-auth configura a chave de API do cloud do ProjectDiscovery (pdcp)
-cup, -cloud-upload faz upload dos resultados do scan para o dashboard do pdcp
-sid, -scan-id string faz upload dos resultados do scan para o ID de scan fornecido
AUTHENTICATION:
-sf, -secret-file string[] caminho para o arquivo de configuração contendo os secrets para o scan autenticado do nuclei
-ps, -prefetch-secrets pré-carrega os secrets do arquivo de secrets
EXAMPLES:
Executar nuclei em um único host:
$ nuclei -target example.com
Executar nuclei com diretórios específicos de templates:
$ nuclei -target example.com -t http/cves/ -t ssl
Executar nuclei contra uma lista de hosts:
$ nuclei -list hosts.txt
Executar nuclei com saída JSON:
$ nuclei -target example.com -json-export output.json
Executar nuclei com saídas Markdown organizadas (com variáveis de ambiente):
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
Documentação adicional disponível em: https://docs.nuclei.sh/getting-started/running
```
### Executando Nuclei
Consulte https://docs.projectdiscovery.io/tools/nuclei/running para obter detalhes sobre como executar o Nuclei.
### Uso de Nuclei com código Go
O guia completo sobre como usar o Nuclei como biblioteca/SDK está disponível em [godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme).
### Recursos
Você pode acessar a documentação principal do Nuclei em https://docs.projectdiscovery.io/tools/nuclei/ e obter mais informações sobre o Nuclei na nuvem com a [ProjectDiscovery Cloud Platform](https://cloud.projectdiscovery.io).
Consulte https://docs.projectdiscovery.io/tools/nuclei/resources para acessaar mais recursos e vídeos sobre o Nuclei!
### Créditos
Obrigado a todos os incríveis [contribuidores da comunidade que enviaram em PRs](https://github.com/projectdiscovery/nuclei/graphs/contributors) e mantêm este projeto atualizado. :heart:
Se você tem uma ideia ou algum tipo de melhoria, sinta-se à vontade para contribuir e participar do projeto. Envie seu 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>
Confira também os seguintes projetos de código aberto que podem se adequar ao seu fluxo de trabalho:
[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)
### Licença
O Nuclei é distribuído sob a [Licença MIT](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>
+16 -179
View File
@@ -1373,19 +1373,6 @@ Fuzzing describes schema to fuzz http requests
<div class="dd">
<code>analyzer</code> <i><a href="#analyzersanalyzertemplate">analyzers.AnalyzerTemplate</a></i>
</div>
<div class="dt">
Analyzer is an analyzer to use for matching the response.
</div>
<hr />
<div class="dd">
<code>self-contained</code> <i>bool</i>
</div>
@@ -1417,19 +1404,6 @@ Valid values:
<div class="dd">
<code>skip-secret-file</code> <i>bool</i>
</div>
<div class="dt">
SkipSecretFile skips the authentication or authorization configured in the secret file.
</div>
<hr />
<div class="dd">
<code>cookie-reuse</code> <i>bool</i>
</div>
@@ -1664,19 +1638,6 @@ 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 />
@@ -1839,50 +1800,13 @@ Valid values:
Part is the part of request to fuzz.
Valid values:
- <code>query</code>
- <code>header</code>
- <code>path</code>
- <code>body</code>
- <code>cookie</code>
- <code>request</code>
</div>
<hr />
<div class="dd">
<code>parts</code> <i>[]string</i>
</div>
<div class="dt">
Parts is the list of parts to fuzz. If multiple parts need to be
defined while excluding some, this should be used instead of singular part.
query fuzzes the query part of url. More parts will be added later.
Valid values:
- <code>query</code>
- <code>header</code>
- <code>path</code>
- <code>body</code>
- <code>cookie</code>
- <code>request</code>
</div>
<hr />
@@ -2038,59 +1962,6 @@ Appears in:
## analyzers.AnalyzerTemplate
AnalyzerTemplate is the template for the analyzer
Appears in:
- <code><a href="#httprequest">http.Request</a>.analyzer</code>
<hr />
<div class="dd">
<code>name</code> <i>string</i>
</div>
<div class="dt">
Name is the name of the analyzer to use
Valid values:
- <code>time_delay</code>
</div>
<hr />
<div class="dd">
<code>parameters</code> <i>map[string]interface{}</i>
</div>
<div class="dt">
Parameters is the parameters for the analyzer
Parameters are different for each analyzer. For example, you can customize
time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
to the docs for each analyzer to get an idea about parameters.
</div>
<hr />
## SignatureTypeHolder
SignatureTypeHolder is used to hold internal type of the signature
@@ -3289,19 +3160,6 @@ 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 />
@@ -3756,18 +3614,8 @@ Enum Values:
- <code>files</code>
- <code>waitdom</code>
- <code>waitfcp</code>
- <code>waitfmp</code>
- <code>waitidle</code>
- <code>waitload</code>
- <code>waitstable</code>
- <code>getresource</code>
- <code>extract</code>
@@ -3784,8 +3632,6 @@ Enum Values:
- <code>waitevent</code>
- <code>dialog</code>
- <code>keyboard</code>
- <code>debug</code>
@@ -3856,33 +3702,11 @@ Appears in:
Part Definitions:
- <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
- <code>host</code> - Host is the input to the template
- <code>matched</code> - Matched is the input which was matched upon
<hr />
@@ -4478,6 +4302,19 @@ Code contains code to execute for the javascript request.
<div class="dd">
<code>timeout</code> <i>int</i>
</div>
<div class="dt">
Timeout in seconds is optional timeout for each javascript script execution (i.e init, pre-condition, code)
</div>
<hr />
<div class="dd">
<code>stop-at-first-match</code> <i>bool</i>
</div>
+28 -33
View File
@@ -2,62 +2,57 @@ package main
import (
"bytes"
"encoding/json"
"log"
"os"
"reflect"
"regexp"
"strings"
"github.com/invopop/jsonschema"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
)
var pathRegex = regexp.MustCompile(`github\.com/projectdiscovery/nuclei/v3/(?:internal|pkg)/(?:.*/)?([A-Za-z.]+)`)
func writeToFile(filename string, data []byte) {
file, err := os.Create(filename)
if err != nil {
log.Fatalf("Could not create file %s: %s\n", filename, err)
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
log.Fatalf("Could not write to file %s: %s\n", filename, err)
}
}
func main() {
if len(os.Args) < 3 {
log.Fatalf("syntax: %s md-docs-file jsonschema-file\n", os.Args[0])
}
// Generate YAML documentation
// Generate yaml syntax documentation
data, err := templates.GetTemplateDoc().Encode()
if err != nil {
log.Fatalf("Could not encode docs: %s\n", err)
}
writeToFile(os.Args[1], data)
// Generate JSON Schema
r := &jsonschema.Reflector{
Namer: func(t reflect.Type) string {
if t.Kind() == reflect.Slice {
return ""
}
return t.String()
},
if len(os.Args) < 3 {
log.Fatalf("syntax: %s md-docs-file jsonschema-file\n", os.Args[0])
}
err = os.WriteFile(os.Args[1], data, 0644)
if err != nil {
log.Fatalf("Could not write docs: %s\n", err)
}
// Generate jsonschema
r := &jsonschema.Reflector{}
r.Namer = func(r reflect.Type) string {
if r.Kind() == reflect.Slice {
return ""
}
return r.String()
}
jsonschemaData := r.Reflect(&templates.Template{})
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetIndent("", " ")
if err := encoder.Encode(jsonschemaData); err != nil {
log.Fatalf("Could not encode JSON schema: %s\n", err)
}
_ = encoder.Encode(jsonschemaData)
schema := pathRegex.ReplaceAllString(buf.String(), "$1")
writeToFile(os.Args[2], []byte(schema))
schema := buf.String()
for _, match := range pathRegex.FindAllStringSubmatch(schema, -1) {
schema = strings.ReplaceAll(schema, match[0], match[1])
}
err = os.WriteFile(os.Args[2], []byte(schema), 0644)
if err != nil {
log.Fatalf("Could not write jsonschema: %s\n", err)
}
}
+5 -5
View File
@@ -8,7 +8,6 @@ import (
"os"
"strings"
"github.com/kitabisa/go-ci"
"github.com/logrusorgru/aurora"
"github.com/pkg/errors"
@@ -16,8 +15,9 @@ import (
)
var (
success = aurora.Green("[✓]").String()
failed = aurora.Red("[✘]").String()
success = aurora.Green("[✓]").String()
failed = aurora.Red("[✘]").String()
githubAction = os.Getenv("GH_ACTION") == "true"
mainNucleiBinary = flag.String("main", "", "Main Branch Nuclei Binary")
devNucleiBinary = flag.String("dev", "", "Dev Branch Nuclei Binary")
@@ -27,7 +27,7 @@ var (
func main() {
flag.Parse()
debug := os.Getenv("DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1"
debug := os.Getenv("DEBUG") == "true"
if err, errored := runFunctionalTests(debug); err != nil {
log.Fatalf("Could not run functional tests: %s\n", err)
@@ -45,7 +45,7 @@ func runFunctionalTests(debug bool) (error, bool) {
errored, failedTestCases := runTestCases(file, debug)
if ci.IsCI() {
if githubAction {
fmt.Println("::group::Failed tests with debug")
for _, failedTestCase := range failedTestCases {
_ = runTestCase(failedTestCase, true)
+11 -27
View File
@@ -1,43 +1,27 @@
#!/bin/bash
if [ "${RUNNER_OS}" == "Windows" ]; then
EXT=".exe"
elif [ "${RUNNER_OS}" == "macOS" ]; then
if [ "${CI}" == "true" ]; then
sudo sysctl -w kern.maxfiles{,perproc}=524288
sudo launchctl limit maxfiles 65536 524288
fi
# reading os type from arguments
CURRENT_OS=$1
ORIGINAL_ULIMIT="$(ulimit -n)"
ulimit -n 65536 || true
if [ "${CURRENT_OS}" == "windows-latest" ];then
extension=.exe
fi
mkdir -p .nuclei-config/nuclei/
touch .nuclei-config/nuclei/.nuclei-ignore
echo "::group::Building functional-test binary"
go build -o "functional-test${EXT}"
go build -o functional-test$extension
echo "::endgroup::"
echo "::group::Building Nuclei binary from current branch"
go build -o "nuclei-dev${EXT}" ../nuclei
echo "::endgroup::"
echo "::group::Building latest release of nuclei"
go build -o "nuclei${EXT}" -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
go build -o nuclei_dev$extension ../nuclei
echo "::endgroup::"
echo "::group::Installing nuclei templates"
eval "./nuclei-dev${EXT} -update-templates"
./nuclei_dev$extension -update-templates
echo "::endgroup::"
echo "::group::Validating templates"
eval "./nuclei-dev${EXT} -validate"
echo "::group::Building latest release of nuclei"
go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
echo "::endgroup::"
echo "Starting Nuclei functional test"
eval "./functional-test${EXT} -main ./nuclei${EXT} -dev ./nuclei-dev${EXT} -testcases testcases.txt"
if [ "${RUNNER_OS}" == "macOS" ]; then
ulimit -n "${ORIGINAL_ULIMIT}" || true
fi
echo 'Starting Nuclei functional test'
./functional-test$extension -main ./nuclei$extension -dev ./nuclei_dev$extension -testcases testcases.txt
+1 -1
View File
@@ -99,7 +99,7 @@ type codePreCondition struct{}
// Execute executes a test case and returns an error if occurred
func (h *codePreCondition) Execute(filePath string) error {
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code", "-esc")
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
if err != nil {
return err
}
+3 -3
View File
@@ -15,7 +15,7 @@ type fileWithOrMatcher struct{}
// Execute executes a test case and returns an error if occurred
func (h *fileWithOrMatcher) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
if err != nil {
return err
}
@@ -27,7 +27,7 @@ type fileWithAndMatcher struct{}
// Execute executes a test case and returns an error if occurred
func (h *fileWithAndMatcher) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
if err != nil {
return err
}
@@ -39,7 +39,7 @@ type fileWithExtractor struct{}
// Execute executes a test case and returns an error if occurred
func (h *fileWithExtractor) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
if err != nil {
return err
}
+1 -1
View File
@@ -22,7 +22,7 @@ var flowTestcases = []TestCaseInfo{
type conditionalFlow struct{}
func (t *conditionalFlow) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "cloud.projectdiscovery.io", debug)
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "blog.projectdiscovery.io", debug)
if err != nil {
return err
}
+1 -28
View File
@@ -1,6 +1,7 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -9,7 +10,6 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
)
const (
@@ -18,7 +18,6 @@ const (
var fuzzingTestCases = []TestCaseInfo{
{Path: "fuzz/fuzz-mode.yaml", TestCase: &fuzzModeOverride{}},
{Path: "fuzz/fuzz-multi-mode.yaml", TestCase: &fuzzMultipleMode{}},
{Path: "fuzz/fuzz-type.yaml", TestCase: &fuzzTypeOverride{}},
{Path: "fuzz/fuzz-query.yaml", TestCase: &httpFuzzQuery{}},
{Path: "fuzz/fuzz-headless.yaml", TestCase: &HeadlessFuzzingQuery{}},
@@ -175,29 +174,3 @@ func (h *HeadlessFuzzingQuery) Execute(filePath string) error {
}
return expectResultsCount(got, 2)
}
type fuzzMultipleMode struct{}
// Execute executes a test case and returns an error if occurred
func (h *fuzzMultipleMode) Execute(filePath string) error {
router := httprouter.New()
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
xClientId := r.Header.Get("X-Client-Id")
xSecretId := r.Header.Get("X-Secret-Id")
if xClientId != "nuclei-v3" || xSecretId != "nuclei-v3" {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "text/html")
resp := fmt.Sprintf("<html><body><h1>This is multi-mode fuzzing test: %v <h1></body></html>", xClientId)
fmt.Fprint(w, resp)
})
ts := httptest.NewTLSServer(router)
defer ts.Close()
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-jsonl", "-fuzz")
if err != nil {
return err
}
return expectResultsCount(got, 1)
}
+1 -3
View File
@@ -1,7 +1,6 @@
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
@@ -14,7 +13,6 @@ import (
var headlessTestcases = []TestCaseInfo{
{Path: "protocols/headless/headless-basic.yaml", TestCase: &headlessBasic{}},
{Path: "protocols/headless/headless-waitevent.yaml", TestCase: &headlessBasic{}},
{Path: "protocols/headless/headless-dsl.yaml", TestCase: &headlessBasic{}},
{Path: "protocols/headless/headless-self-contained.yaml", TestCase: &headlessSelfContained{}},
{Path: "protocols/headless/headless-header-action.yaml", TestCase: &headlessHeaderActions{}},
{Path: "protocols/headless/headless-extract-values.yaml", TestCase: &headlessExtractValues{}},
@@ -32,7 +30,7 @@ type headlessBasic struct{}
func (h *headlessBasic) Execute(filePath string) error {
router := httprouter.New()
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
_, _ = fmt.Fprintf(w, "<html><body>%s</body></html>", r.URL.Query().Get("_"))
_, _ = w.Write([]byte("<html><body></body></html>"))
})
ts := httptest.NewServer(router)
defer ts.Close()
+6 -7
View File
@@ -1,6 +1,7 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
@@ -17,13 +18,11 @@ import (
"gopkg.in/yaml.v2"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
errorutil "github.com/projectdiscovery/utils/errors"
logutil "github.com/projectdiscovery/utils/log"
sliceutil "github.com/projectdiscovery/utils/slice"
stringsutil "github.com/projectdiscovery/utils/strings"
unitutils "github.com/projectdiscovery/utils/unit"
)
var httpTestcases = []TestCaseInfo{
@@ -155,7 +154,7 @@ func (h *httpInteractshRequest) Execute(filePath string) error {
return err
}
return expectResultsCount(results, 1, 2)
return expectResultsCount(results, 1)
}
type httpDefaultMatcherCondition struct{}
@@ -510,7 +509,7 @@ func (h *httpPostMultipartBody) Execute(filePath string) error {
var routerErr error
router.POST("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
if err := r.ParseMultipartForm(unitutils.Mega); err != nil {
if err := r.ParseMultipartForm(1 * 1024); err != nil {
routerErr = err
return
}
@@ -952,7 +951,7 @@ func (h *httpRequestSelfContained) Execute(filePath string) error {
}()
defer server.Close()
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
if err != nil {
return err
}
@@ -988,7 +987,7 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error {
}()
defer server.Close()
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
if err != nil {
return err
}
@@ -1031,7 +1030,7 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error {
}
defer FileLoc.Close()
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name(), "-esc")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name())
if err != nil {
return err
}
+8 -22
View File
@@ -7,7 +7,6 @@ import (
"runtime"
"strings"
"github.com/kitabisa/go-ci"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/gologger"
@@ -23,9 +22,10 @@ type TestCaseInfo struct {
}
var (
debug = os.Getenv("DEBUG") == "true"
customTests = os.Getenv("TESTS")
protocol = os.Getenv("PROTO")
debug = os.Getenv("DEBUG") == "true"
githubAction = os.Getenv("GH_ACTION") == "true"
customTests = os.Getenv("TESTS")
protocol = os.Getenv("PROTO")
success = aurora.Green("[✓]").String()
failed = aurora.Red("[✘]").String()
@@ -37,7 +37,6 @@ var (
"dns": dnsTestCases,
"workflow": workflowTestcases,
"loader": loaderTestcases,
"profile-loader": profileLoaderTestcases,
"websocket": websocketTestCases,
"headless": headlessTestcases,
"whois": whoisTestCases,
@@ -55,7 +54,6 @@ var (
"dsl": dslTestcases,
"flow": flowTestcases,
"javascript": jsTestcases,
"matcher-status": matcherStatusTestcases,
}
// flakyTests are run with a retry count of 3
flakyTests = map[string]bool{
@@ -103,23 +101,11 @@ func main() {
failedTestTemplatePaths := runTests(customTestsList)
if len(failedTestTemplatePaths) > 0 {
if ci.IsCI() {
// run failed tests again assuming they are flaky
// if they fail as well only then we assume that there is an actual issue
fmt.Println("::group::Running failed tests again")
failedTestTemplatePaths = runTests(failedTestTemplatePaths)
if githubAction {
debug = true
fmt.Println("::group::Failed integration tests in debug mode")
_ = runTests(failedTestTemplatePaths)
fmt.Println("::endgroup::")
if len(failedTestTemplatePaths) > 0 {
debug = true
fmt.Println("::group::Failed integration tests in debug mode")
_ = runTests(failedTestTemplatePaths)
fmt.Println("::endgroup::")
} else {
fmt.Println("::group::All tests passed")
fmt.Println("::endgroup::")
os.Exit(0)
}
}
os.Exit(1)
+1 -1
View File
@@ -128,7 +128,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
}
store.Load()
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
_ = engine.Execute(store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
engine.WorkPool().Wait() // Wait for the scan to finish
return results, nil
+2 -16
View File
@@ -172,14 +172,7 @@ func (h *nonExistentTemplateList) Execute(nonExistingTemplateList string) error
ts := httptest.NewServer(router)
defer ts.Close()
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
if err != nil {
return err
}
defer os.Remove("test-config.yaml")
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404", "-config", "test-config.yaml")
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404")
if err == nil {
return fmt.Errorf("expected error for nonexisting workflow url")
}
@@ -195,14 +188,7 @@ func (h *nonExistentWorkflowList) Execute(nonExistingWorkflowList string) error
ts := httptest.NewServer(router)
defer ts.Close()
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
if err != nil {
return err
}
defer os.Remove("test-config.yaml")
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404", "-config", "test-config.yaml")
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404")
if err == nil {
return fmt.Errorf("expected error for nonexisting workflow url")
}
-120
View File
@@ -1,120 +0,0 @@
package main
import (
"fmt"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
)
var matcherStatusTestcases = []TestCaseInfo{
{Path: "protocols/http/get.yaml", TestCase: &httpNoAccess{}},
{Path: "protocols/network/net-https.yaml", TestCase: &networkNoAccess{}},
{Path: "protocols/headless/headless-basic.yaml", TestCase: &headlessNoAccess{}},
{Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNoAccess{}},
{Path: "protocols/websocket/basic.yaml", TestCase: &websocketNoAccess{}},
{Path: "protocols/dns/a.yaml", TestCase: &dnsNoAccess{}},
}
type httpNoAccess struct{}
func (h *httpNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
expectedError := "no address found for host"
if !strings.Contains(event.Error, expectedError) {
return fmt.Errorf("unexpected result: expecting \"%s\" error but got \"%s\"", expectedError, event.Error)
}
return nil
}
type networkNoAccess struct{}
// Execute executes a test case and returns an error if occurred
func (h *networkNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
if event.Error != "no address found for host" {
return fmt.Errorf("unexpected result: expecting \"no address found for host\" error but got \"%s\"", event.Error)
}
return nil
}
type headlessNoAccess struct{}
// Execute executes a test case and returns an error if occurred
func (h *headlessNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-headless", "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
if event.Error == "" {
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
}
return nil
}
type javascriptNoAccess struct{}
// Execute executes a test case and returns an error if occurred
func (h *javascriptNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
if event.Error == "" {
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
}
return nil
}
type websocketNoAccess struct{}
// Execute executes a test case and returns an error if occurred
func (h *websocketNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "ws://trust_me_bro.real", debug, "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
if event.Error == "" {
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
}
return nil
}
type dnsNoAccess struct{}
// Execute executes a test case and returns an error if occurred
func (h *dnsNoAccess) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "trust_me_bro.real", debug, "-ms", "-j")
if err != nil {
return err
}
event := &output.ResultEvent{}
_ = json.Unmarshal([]byte(results[0]), event)
if event.Error == "" {
return fmt.Errorf("unexpected result: expecting an error but got \"%s\"", event.Error)
}
return nil
}
+1 -1
View File
@@ -14,7 +14,7 @@ type multiProtoDynamicExtractor struct{}
// Execute executes a test case and returns an error if occurred
func (h *multiProtoDynamicExtractor) Execute(templatePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "docs.projectdiscovery.io", debug)
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "blog.projectdiscovery.io", debug)
if err != nil {
return err
}
+1 -1
View File
@@ -119,7 +119,7 @@ func (h *networkRequestSelContained) Execute(filePath string) error {
_, _ = conn.Write([]byte("Authentication successful"))
})
defer ts.Close()
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
if err != nil {
return err
}
-54
View File
@@ -1,54 +0,0 @@
package main
import (
"fmt"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
errorutil "github.com/projectdiscovery/utils/errors"
)
var profileLoaderTestcases = []TestCaseInfo{
{Path: "profile-loader/load-with-filename", TestCase: &profileLoaderByRelFile{}},
{Path: "profile-loader/load-with-id", TestCase: &profileLoaderById{}},
{Path: "profile-loader/basic.yml", TestCase: &customProfileLoader{}},
}
type profileLoaderByRelFile struct{}
func (h *profileLoaderByRelFile) Execute(testName string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud.yml")
if err != nil {
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) <= 10 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
}
return nil
}
type profileLoaderById struct{}
func (h *profileLoaderById) Execute(testName string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud")
if err != nil {
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) <= 10 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
}
return nil
}
// this profile with load kevs
type customProfileLoader struct{}
func (h *customProfileLoader) Execute(filepath string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", filepath)
if err != nil {
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) < 1 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 1, len(results))
}
return nil
}
-25
View File
@@ -13,7 +13,6 @@ var sslTestcases = []TestCaseInfo{
{Path: "protocols/ssl/custom-cipher.yaml", TestCase: &sslCustomCipher{}},
{Path: "protocols/ssl/custom-version.yaml", TestCase: &sslCustomVersion{}},
{Path: "protocols/ssl/ssl-with-vars.yaml", TestCase: &sslWithVars{}},
{Path: "protocols/ssl/multi-req.yaml", TestCase: &sslMultiReq{}},
}
type sslBasic struct{}
@@ -119,27 +118,3 @@ func (h *sslWithVars) Execute(filePath string) error {
return expectResultsCount(results, 1)
}
type sslMultiReq struct{}
func (h *sslMultiReq) Execute(filePath string) error {
//nolint:staticcheck // SSLv3 is intentionally used for testing purposes
ts := testutils.NewTCPServer(&tls.Config{
MinVersion: tls.VersionSSL30,
MaxVersion: tls.VersionTLS11,
}, defaultStaticPort, func(conn net.Conn) {
defer conn.Close()
data := make([]byte, 4)
if _, err := conn.Read(data); err != nil {
return
}
})
defer ts.Close()
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-V")
if err != nil {
return err
}
return expectResultsCount(results, 2)
}
-40
View File
@@ -13,7 +13,6 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
sliceutil "github.com/projectdiscovery/utils/slice"
)
var workflowTestcases = []TestCaseInfo{
@@ -26,7 +25,6 @@ var workflowTestcases = []TestCaseInfo{
{Path: "workflow/dns-value-share-workflow.yaml", TestCase: &workflowDnsKeyValueShare{}},
{Path: "workflow/code-value-share-workflow.yaml", TestCase: &workflowCodeKeyValueShare{}, DisableOn: isCodeDisabled}, // isCodeDisabled declared in code.go
{Path: "workflow/multiprotocol-value-share-workflow.yaml", TestCase: &workflowMultiProtocolKeyValueShare{}},
{Path: "workflow/multimatch-value-share-workflow.yaml", TestCase: &workflowMultiMatchKeyValueShare{}},
{Path: "workflow/shared-cookie.yaml", TestCase: &workflowSharedCookies{}},
}
@@ -231,44 +229,6 @@ func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error {
return expectResultsCount(results, 2)
}
type workflowMultiMatchKeyValueShare struct{}
// Execute executes a test case and returns an error if occurred
func (h *workflowMultiMatchKeyValueShare) Execute(filePath string) error {
var receivedData []string
router := httprouter.New()
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "This is test matcher text")
})
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "href=\"test-value-%s\"", r.URL.Query().Get("v"))
})
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
body, _ := io.ReadAll(r.Body)
receivedData = append(receivedData, string(body))
fmt.Fprintf(w, "test-value")
})
ts := httptest.NewServer(router)
defer ts.Close()
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
if err != nil {
return err
}
// Check if we received the data from both request to /path1 and it is not overwritten by the later one.
// They will appear in brackets because of another bug: https://github.com/orgs/projectdiscovery/discussions/3766
if !sliceutil.Contains(receivedData, "[test-value-1]") || !sliceutil.Contains(receivedData, "[test-value-2]") {
return fmt.Errorf(
"incorrect data: did not receive both extracted data from the first request!\nReceived Data:\n\t%s\nResults:\n\t%s",
strings.Join(receivedData, "\n\t"),
strings.Join(results, "\n\t"),
)
}
// The number of expected results is 3: the workflow's Matcher Name based condition check forwards both match, and the other branch with simple subtemplates goes with one
return expectResultsCount(results, 3)
}
type workflowSharedCookies struct{}
// Execute executes a test case and returns an error if occurred
+1 -31
View File
@@ -142,34 +142,4 @@
# # Username for the elasticsearch instance
# username: test
# # Password is the password for elasticsearch instance
# password: test
#linear:
# # api-key is the API key for the linear account
# api-key: ""
# # allow-list sets a tracker level filter to only create issues for templates with
# # these severity labels or tags (does not affect exporters. set those globally)
# deny-list:
# severity: critical
# # deny-list sets a tracker level filter to never create issues for templates with
# # these severity labels or tags (does not affect exporters. set those globally)
# deny-list:
# severity: low
# # team-id is the ID of the team in Linear
# team-id: ""
# # project-id is the ID of the project in Linear
# project-id: ""
# # duplicate-issue-check flag to enable duplicate tracking issue check
# 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
# password: test
+26 -156
View File
@@ -9,11 +9,9 @@ import (
"path/filepath"
"runtime"
"runtime/pprof"
"runtime/trace"
"strings"
"time"
_pdcp "github.com/projectdiscovery/nuclei/v3/internal/pdcp"
"github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/env"
_ "github.com/projectdiscovery/utils/pprof"
@@ -40,15 +38,13 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/utils/monitor"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
unitutils "github.com/projectdiscovery/utils/unit"
updateutils "github.com/projectdiscovery/utils/update"
)
var (
cfgFile string
templateProfile string
memProfile string // optional profile file path
options = &types.Options{}
cfgFile string
memProfile string // optional profile file path
options = &types.Options{}
)
func main() {
@@ -104,63 +100,26 @@ func main() {
return
}
// Profiling & tracing related code
// Profiling related code
if memProfile != "" {
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile))
createProfileFile := func(ext, profileType string) *os.File {
f, err := os.Create(memProfile + ext)
if err != nil {
gologger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err)
}
return f
f, err := os.Create(memProfile)
if err != nil {
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
}
memProfileFile := createProfileFile(".mem", "memory")
cpuProfileFile := createProfileFile(".cpu", "CPU")
traceFile := createProfileFile(".trace", "trace")
oldMemProfileRate := runtime.MemProfileRate
old := runtime.MemProfileRate
runtime.MemProfileRate = 4096
// Start tracing
if err := trace.Start(traceFile); err != nil {
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
}
// Start CPU profiling
if err := pprof.StartCPUProfile(cpuProfileFile); err != nil {
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
}
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
defer func() {
// Start heap memory snapshot
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
gologger.Fatal().Msgf("profile: could not write memory profile: %v", err)
}
pprof.StopCPUProfile()
memProfileFile.Close()
traceFile.Close()
trace.Stop()
runtime.MemProfileRate = oldMemProfileRate
gologger.Info().Msgf("CPU profile saved at %q", cpuProfileFile.Name())
gologger.Info().Msgf("Memory usage snapshot saved at %q", memProfileFile.Name())
gologger.Info().Msgf("Traced at %q", traceFile.Name())
_ = pprof.Lookup("heap").WriteTo(f, 0)
f.Close()
runtime.MemProfileRate = old
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
}()
}
runner.ParseOptions(options)
if options.ScanUploadFile != "" {
if err := runner.UploadResultsToCloud(options); err != nil {
gologger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err)
}
return
}
nucleiRunner, err := runner.New(options)
if err != nil {
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
@@ -181,10 +140,7 @@ func main() {
nucleiRunner.Close()
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
err := nucleiRunner.SaveResumeConfig(resumeFileName)
if err != nil {
return errorutil.NewWithErr(err).Msgf("couldn't create crash resume file")
}
return nil
return errorutil.NewWithErr(err).Msgf("couldn't create crash resume file")
})
}
@@ -196,11 +152,6 @@ func main() {
go func() {
for range c {
gologger.Info().Msgf("CTRL+C pressed: Exiting\n")
if options.DASTServer {
nucleiRunner.Close()
os.Exit(1)
}
gologger.Info().Msgf("Attempting graceful shutdown...")
if options.EnableCloudUpload {
gologger.Info().Msgf("Uploading scan results to cloud...")
@@ -248,7 +199,7 @@ on extensive configurability, massive extensibility and ease of use.`)
*/
flagSet.CreateGroup("input", "Target",
flagSet.StringSliceVarP(&options.Targets, "target", "u", nil, "target URLs/hosts to scan", goflags.CommaSeparatedStringSliceOptions),
flagSet.StringSliceVarP(&options.Targets, "target", "u", nil, "target URLs/hosts to scan", goflags.StringSliceOptions),
flagSet.StringVarP(&options.TargetsFilePath, "list", "l", "", "path to file containing a list of target URLs/hosts to scan (one per line)"),
flagSet.StringSliceVarP(&options.ExcludeTargets, "exclude-hosts", "eh", nil, "hosts to exclude to scan from the input list (ip, cidr, hostname)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringVar(&options.Resume, "resume", "", "resume scan using resume.cfg (clustering will be disabled)"),
@@ -268,21 +219,16 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.BoolVarP(&options.AutomaticScan, "automatic-scan", "as", false, "automatic web scan using wappalyzer technology detection to tags mapping"),
flagSet.StringSliceVarP(&options.Templates, "templates", "t", nil, "list of template or template directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringSliceVarP(&options.TemplateURLs, "template-url", "turl", nil, "template url or list containing template urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringVarP(&options.AITemplatePrompt, "prompt", "ai", "", "generate and run template using ai prompt"),
flagSet.StringSliceVarP(&options.Workflows, "workflows", "w", nil, "list of workflow or workflow directory to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringSliceVarP(&options.WorkflowURLs, "workflow-url", "wurl", nil, "workflow url or list containing workflow urls to run (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.BoolVar(&options.Validate, "validate", false, "validate the passed templates to nuclei"),
flagSet.BoolVarP(&options.NoStrictSyntax, "no-strict-syntax", "nss", false, "disable strict syntax check on templates"),
flagSet.BoolVarP(&options.TemplateDisplay, "template-display", "td", false, "displays the templates content"),
flagSet.BoolVar(&options.TemplateList, "tl", false, "list all available templates"),
flagSet.BoolVar(&options.TagList, "tgl", false, "list all available tags"),
flagSet.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"cloud.projectdiscovery.io"}, "allowed domain list to load remote templates from"),
flagSet.BoolVar(&options.SignTemplates, "sign", false, "signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable"),
flagSet.BoolVar(&options.EnableCodeTemplates, "code", false, "enable loading code protocol-based templates"),
flagSet.BoolVarP(&options.DisableUnsignedTemplates, "disable-unsigned-templates", "dut", false, "disable running unsigned templates or templates with mismatched signature"),
flagSet.BoolVarP(&options.EnableSelfContainedTemplates, "enable-self-contained", "esc", false, "enable loading self-contained templates"),
flagSet.BoolVarP(&options.EnableGlobalMatchersTemplates, "enable-global-matchers", "egm", false, "enable loading global matchers templates"),
flagSet.BoolVar(&options.EnableFileTemplates, "file", false, "enable loading file templates"),
)
flagSet.CreateGroup("filters", "Filtering",
@@ -320,13 +266,10 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.StringVarP(&options.SarifExport, "sarif-export", "se", "", "file to export results in SARIF format"),
flagSet.StringVarP(&options.JSONExport, "json-export", "je", "", "file to export results in JSON format"),
flagSet.StringVarP(&options.JSONLExport, "jsonl-export", "jle", "", "file to export results in JSONL(ine) format"),
flagSet.StringSliceVarP(&options.Redact, "redact", "rd", nil, "redact given list of keys from query parameter, request header and body", goflags.CommaSeparatedStringSliceOptions),
)
flagSet.CreateGroup("configs", "Configurations",
flagSet.StringVar(&cfgFile, "config", "", "path to the nuclei configuration file"),
flagSet.StringVarP(&templateProfile, "profile", "tp", "", "template profile config file to run"),
flagSet.BoolVarP(&options.ListTemplateProfiles, "profile-list", "tpl", false, "list community template profiles"),
flagSet.BoolVarP(&options.FollowRedirects, "follow-redirects", "fr", false, "enable following redirects for http templates"),
flagSet.BoolVarP(&options.FollowHostRedirects, "follow-host-redirects", "fhr", false, "follow redirects on the same host"),
flagSet.IntVarP(&options.MaxRedirects, "max-redirects", "mr", 10, "max number of redirects to follow for http templates"),
@@ -346,17 +289,17 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13 [Deprecated] autofallback to ztls is enabled by default"), //nolint:all
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
flagSet.DurationVarP(&options.DialerTimeout, "dialer-timeout", "dt", 0, "timeout for network requests."),
flagSet.DurationVarP(&options.DialerKeepAlive, "dialer-keep-alive", "dka", 0, "keep-alive duration for network requests."),
flagSet.BoolVarP(&options.AllowLocalFileAccess, "allow-local-file-access", "lfa", false, "allows file (payload) access anywhere on the system"),
flagSet.BoolVarP(&options.RestrictLocalNetworkAccess, "restrict-local-network-access", "lna", false, "blocks connections to the local / private network"),
flagSet.StringVarP(&options.Interface, "interface", "i", "", "network interface to use for network scan"),
flagSet.StringVarP(&options.AttackType, "attack-type", "at", "", "type of payload combinations to perform (batteringram,pitchfork,clusterbomb)"),
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 0, "max response size to read in bytes"),
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", unitutils.Mega, "max response size to read in bytes"),
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 10*1024*1024, "max response size to read in bytes"),
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", 1*1024*1024, "max response size to read in bytes"),
flagSet.CallbackVar(resetCallback, "reset", "reset removes all nuclei configuration and data files (including nuclei-templates)"),
flagSet.BoolVarP(&options.TlsImpersonate, "tls-impersonate", "tlsi", false, "enable experimental client hello (ja3) tls randomization"),
flagSet.StringVarP(&options.HttpApiEndpoint, "http-api-endpoint", "hae", "", "experimental http api endpoint"),
)
flagSet.CreateGroup("interactsh", "interactsh",
@@ -374,15 +317,6 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.StringVarP(&options.FuzzingMode, "fuzzing-mode", "fm", "", "overrides fuzzing mode set in template (multiple, single)"),
flagSet.BoolVar(&fuzzFlag, "fuzz", false, "enable loading fuzzing templates (Deprecated: use -dast instead)"),
flagSet.BoolVar(&options.DAST, "dast", false, "enable / run dast (fuzz) nuclei templates"),
flagSet.BoolVarP(&options.DASTServer, "dast-server", "dts", false, "enable dast server mode (live fuzzing)"),
flagSet.BoolVarP(&options.DASTReport, "dast-report", "dtr", false, "write dast scan report to file"),
flagSet.StringVarP(&options.DASTServerToken, "dast-server-token", "dtst", "", "dast server token (optional)"),
flagSet.StringVarP(&options.DASTServerAddress, "dast-server-address", "dtsa", "localhost:9055", "dast server address"),
flagSet.BoolVarP(&options.DisplayFuzzPoints, "display-fuzz-points", "dfp", false, "display fuzz points in the output for debugging"),
flagSet.IntVar(&options.FuzzParamFrequency, "fuzz-param-frequency", 10, "frequency of uninteresting parameters for fuzzing before skipping"),
flagSet.StringVarP(&options.FuzzAggressionLevel, "fuzz-aggression", "fa", "low", "fuzzing aggression level controls payload count for fuzz (low, medium, high)"),
flagSet.StringSliceVarP(&options.Scope, "fuzz-scope", "cs", nil, "in scope url regex to be followed by fuzzer", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringSliceVarP(&options.OutOfScope, "fuzz-out-scope", "cos", nil, "out of scope url regex to be excluded by fuzzer", goflags.FileCommaSeparatedStringSliceOptions),
)
flagSet.CreateGroup("uncover", "Uncover",
@@ -448,10 +382,9 @@ 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", "", "generate memory (heap) profile & trace files"),
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
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"),
@@ -469,17 +402,12 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.BoolVarP(&options.StatsJSON, "stats-json", "sj", false, "display statistics in JSONL(ines) format"),
flagSet.IntVarP(&options.StatsInterval, "stats-interval", "si", 5, "number of seconds to wait between showing a statistics update"),
flagSet.IntVarP(&options.MetricsPort, "metrics-port", "mp", 9092, "port to expose nuclei metrics on"),
flagSet.BoolVarP(&options.HTTPStats, "http-stats", "hps", false, "enable http status capturing (experimental)"),
)
flagSet.CreateGroup("cloud", "Cloud",
flagSet.DynamicVar(&pdcpauth, "auth", "true", "configure projectdiscovery cloud (pdcp) api key"),
flagSet.StringVarP(&options.TeamID, "team-id", "tid", _pdcp.TeamIDEnv, "upload scan results to given team id (optional)"),
flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard [DEPRECATED use -dashboard]"),
flagSet.StringVarP(&options.ScanID, "scan-id", "sid", "", "upload scan results to existing scan id (optional)"),
flagSet.StringVarP(&options.ScanName, "scan-name", "sname", "", "scan name to set (optional)"),
flagSet.BoolVarP(&options.EnableCloudUpload, "dashboard", "pd", false, "upload / view nuclei results in projectdiscovery cloud (pdcp) UI dashboard"),
flagSet.StringVarP(&options.ScanUploadFile, "dashboard-upload", "pdu", "", "upload / view nuclei results file (jsonl) in projectdiscovery cloud (pdcp) UI dashboard"),
flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard"),
flagSet.StringVarP(&options.ScanID, "scan-id", "sid", "", "upload scan results to given scan id"),
)
flagSet.CreateGroup("Authentication", "Authentication",
@@ -487,6 +415,11 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.BoolVarP(&options.PreFetchSecrets, "prefetch-secrets", "ps", false, "prefetch secrets from the secrets file"),
)
flagSet.CreateGroup("tests", "Tests",
flagSet.BoolVarP(&options.AutogenerateTests, "autogenerate-tests", "agt", false, "enable autogeneration of nuclei test-cases (http only now)"),
flagSet.BoolVarP(&options.RunNucleiTests, "run-tests", "rts", false, "run generated nuclei test-cases"),
)
flagSet.SetCustomHelpText(`EXAMPLES:
Run nuclei on single host:
$ nuclei -target example.com
@@ -519,11 +452,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
options.DAST = true
}
// All cloud-based templates depend on both code and self-contained templates.
if options.EnableCodeTemplates {
options.EnableSelfContainedTemplates = true
}
// api key hierarchy: cli flag > env var > .pdcp/credential file
if pdcpauth == "true" {
runner.AuthWithPDCP()
@@ -537,15 +465,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
}
}
// guard cloud services with credentials
if options.AITemplatePrompt != "" {
h := &pdcp.PDCPCredHandler{}
_, err := h.GetCreds()
if err != nil {
gologger.Fatal().Msg("To utilize the `-ai` flag, please configure your API key with the `-auth` flag or set the `PDCP_API_KEY` environment variable")
}
}
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
if options.VerboseVerbose {
@@ -581,34 +500,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
config.DefaultConfig.SetTemplatesDir(options.NewTemplatesDirectory)
}
defaultProfilesPath := filepath.Join(config.DefaultConfig.GetTemplateDir(), "profiles")
if templateProfile != "" {
if filepath.Ext(templateProfile) == "" {
if tp := findProfilePathById(templateProfile, defaultProfilesPath); tp != "" {
templateProfile = tp
} else {
gologger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile)
}
}
if !filepath.IsAbs(templateProfile) {
if filepath.Dir(templateProfile) == "profiles" {
defaultProfilesPath = filepath.Join(config.DefaultConfig.GetTemplateDir())
}
currentDir, err := os.Getwd()
if err == nil && fileutil.FileExists(filepath.Join(currentDir, templateProfile)) {
templateProfile = filepath.Join(currentDir, templateProfile)
} else {
templateProfile = filepath.Join(defaultProfilesPath, templateProfile)
}
}
if !fileutil.FileExists(templateProfile) {
gologger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile)
}
if err := flagSet.MergeConfigFile(templateProfile); err != nil {
gologger.Fatal().Msgf("Could not read template profile: %s\n", err)
}
}
if len(options.SecretsFile) > 0 {
for _, secretFile := range options.SecretsFile {
if !fileutil.FileExists(secretFile) {
@@ -734,27 +625,6 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
os.Exit(0)
}
func findProfilePathById(profileId, templatesDir string) string {
var profilePath string
err := filepath.WalkDir(templatesDir, func(iterItem string, d fs.DirEntry, err error) error {
ext := filepath.Ext(iterItem)
isYaml := ext == extensions.YAML || ext == extensions.YML
if err != nil || d.IsDir() || !isYaml {
// skip non yaml files
return nil
}
if strings.TrimSuffix(filepath.Base(iterItem), ext) == profileId {
profilePath = iterItem
return fmt.Errorf("FOUND")
}
return nil
})
if err != nil && err.Error() != "FOUND" {
gologger.Error().Msgf("%s\n", err)
}
return profilePath
}
func init() {
// print stacktrace of errors in debug mode
if strings.EqualFold(os.Getenv("DEBUG"), "true") {
-87
View File
@@ -1,87 +0,0 @@
package main_test
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v3/internal/runner"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
)
func BenchmarkRunEnumeration(b *testing.B) {
dummyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}))
defer dummyServer.Close()
options := &types.Options{
RemoteTemplateDomainList: goflags.StringSlice{
"cloud.projectdiscovery.io",
},
ProjectPath: "/tmp",
Targets: goflags.StringSlice{dummyServer.URL},
StatsInterval: 5,
MetricsPort: 9092,
MaxHostError: 30,
NoHostErrors: true,
BulkSize: 25,
TemplateThreads: 25,
HeadlessBulkSize: 10,
HeadlessTemplateThreads: 10,
Timeout: 10,
Retries: 1,
RateLimit: 150,
RateLimitDuration: time.Duration(time.Second),
RateLimitMinute: 0,
PageTimeout: 20,
InteractionsCacheSize: 5000,
InteractionsPollDuration: 5,
InteractionsEviction: 60,
InteractionsCoolDownPeriod: 5,
MaxRedirects: 10,
Silent: true,
VarDumpLimit: 255,
JSONRequests: true,
StoreResponseDir: "output",
InputFileMode: "list",
ResponseReadSize: 0,
ResponseSaveSize: 1048576,
InputReadTimeout: time.Duration(3 * time.Minute),
UncoverField: "ip:port",
UncoverLimit: 100,
UncoverRateLimit: 60,
ScanStrategy: "auto",
FuzzAggressionLevel: "low",
FuzzParamFrequency: 10,
TeamID: "none",
JsConcurrency: 120,
PayloadConcurrency: 25,
ProbeConcurrency: 50,
LoadHelperFileFunction: types.DefaultOptions().LoadHelperFileFunction,
// DialerKeepAlive: time.Duration(0),
// DASTServerAddress: "localhost:9055",
}
runner.ParseOptions(options)
// Disable logging to reduce benchmark noise.
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
nucleiRunner, err := runner.New(options)
if err != nil {
b.Fatalf("failed to create runner: %s", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := nucleiRunner.RunEnumeration(); err != nil {
b.Fatalf("RunEnumeration failed: %s", err)
}
}
}
+8 -8
View File
@@ -2,6 +2,7 @@ package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"os"
@@ -21,7 +22,6 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
errorutil "github.com/projectdiscovery/utils/errors"
"gopkg.in/yaml.v3"
@@ -65,10 +65,10 @@ func init() {
allTagsRegex = append(allTagsRegex, re)
}
defaultOpts := types.DefaultOptions()
// need to set headless to true for headless templates
defaultOpts.Headless = true
defaultOpts.EnableCodeTemplates = true
defaultOpts.EnableSelfContainedTemplates = true
if err := protocolstate.Init(defaultOpts); err != nil {
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
}
@@ -131,7 +131,7 @@ func main() {
}
func process(opts options) error {
tempDir, err := os.MkdirTemp("", "nuclei-nvd")
tempDir, err := os.MkdirTemp("", "nuclei-nvd-%s")
if err != nil {
return err
}
@@ -162,7 +162,7 @@ func process(opts options) error {
var updated bool // if max-requests is updated
dataString, updated, err = parseAndAddMaxRequests(templateCatalog, path, dataString)
if err != nil {
gologger.Info().Label("max-request").Msg(logErrMsg(path, err, opts.debug, errFile))
gologger.Info().Label("max-request").Msgf(logErrMsg(path, err, opts.debug, errFile))
} else {
if updated {
gologger.Info().Label("max-request").Msgf("✅ updated template: %s\n", path)
@@ -255,7 +255,7 @@ func enhanceTemplate(data string) (string, bool, error) {
return data, false, errorutil.New("validation failed").WithTag("validate")
}
if templateResp.Error.Name != "" {
return data, false, errorutil.New("%s", templateResp.Error.Name)
return data, false, errorutil.New(templateResp.Error.Name)
}
if strings.TrimSpace(templateResp.Enhanced) == "" && !templateResp.Lint {
if templateResp.LintError.Reason != "" {
@@ -289,7 +289,7 @@ func formatTemplate(data string) (string, bool, error) {
return data, false, errorutil.New("validation failed").WithTag("validate")
}
if templateResp.Error.Name != "" {
return data, false, errorutil.New("%s", templateResp.Error.Name)
return data, false, errorutil.New(templateResp.Error.Name)
}
if strings.TrimSpace(templateResp.Updated) == "" && !templateResp.Lint {
if templateResp.LintError.Reason != "" {
@@ -300,7 +300,7 @@ func formatTemplate(data string) (string, bool, error) {
return data, false, errorutil.New("template format failed")
}
// lintTemplate lints template data using templateman lint api
// lintTemplateData lints template data using templateman lint api
func lintTemplate(data string) (bool, error) {
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/lint", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
if err != nil {
@@ -345,7 +345,7 @@ func validateTemplate(data string) (bool, error) {
return false, errorutil.New("validation failed").WithTag("validate")
}
if validateResp.Error.Name != "" {
return false, errorutil.New("%s", validateResp.Error.Name)
return false, errorutil.New(validateResp.Error.Name)
}
return false, errorutil.New("template validation failed")
}
-114
View File
@@ -1,114 +0,0 @@
package main
import (
"crypto/sha256"
"encoding/hex"
"flag"
"os"
"path/filepath"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
fileutil "github.com/projectdiscovery/utils/file"
folderutil "github.com/projectdiscovery/utils/folder"
)
var (
appConfigDir = folderutil.AppConfigDirOrDefault(".config", "nuclei")
defaultCertFile = filepath.Join(appConfigDir, "keys", "nuclei-user.crt")
defaultPrivKey = filepath.Join(appConfigDir, "keys", "nuclei-user-private-key.pem")
)
var (
template string
cert string
privKey string
)
func main() {
flag.StringVar(&template, "template", "", "template to sign (file only)")
flag.StringVar(&cert, "cert", defaultCertFile, "certificate file")
flag.StringVar(&privKey, "priv-key", defaultPrivKey, "private key file")
flag.Parse()
config.DefaultConfig.LogAllEvents = true
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
if template == "" {
gologger.Fatal().Msg("template is required")
}
if !fileutil.FileExists(template) {
gologger.Fatal().Msgf("template file %s does not exist or not a file", template)
}
// get signer
tmplSigner, err := signer.NewTemplateSignerFromFiles(cert, privKey)
if err != nil {
gologger.Fatal().Msgf("failed to create signer: %s", err)
}
gologger.Info().Msgf("Template Signer: %v\n", tmplSigner.Identifier())
// read file
bin, err := os.ReadFile(template)
if err != nil {
gologger.Fatal().Msgf("failed to read template file %s: %s", template, err)
}
// extract signature and content
sig, content := signer.ExtractSignatureAndContent(bin)
hash := sha256.Sum256(content)
gologger.Info().Msgf("Signature Details:")
gologger.Info().Msgf("----------------")
gologger.Info().Msgf("Signature: %s", sig)
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash[:]))
execOpts := defaultExecutorOpts(template)
tmpl, err := templates.Parse(template, nil, execOpts)
if err != nil {
gologger.Fatal().Msgf("failed to parse template: %s", err)
}
gologger.Info().Msgf("Template Verified: %v\n", tmpl.Verified)
if !tmpl.Verified {
gologger.Info().Msgf("------------------------")
gologger.Info().Msg("Template is not verified, signing template")
if err := templates.SignTemplate(tmplSigner, template); err != nil {
gologger.Fatal().Msgf("Failed to sign template: %s", err)
}
// verify again by reading file what the new signature and hash is
bin2, err := os.ReadFile(template)
if err != nil {
gologger.Fatal().Msgf("failed to read signed template file %s: %s", template, err)
}
sig2, content2 := signer.ExtractSignatureAndContent(bin2)
hash2 := sha256.Sum256(content2)
gologger.Info().Msgf("Updated Signature Details:")
gologger.Info().Msgf("------------------------")
gologger.Info().Msgf("Signature: %s", sig2)
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash2[:]))
}
gologger.Info().Msgf("✓ Template signed & verified successfully")
}
func defaultExecutorOpts(templatePath string) protocols.ExecutorOptions {
// use parsed options when initializing signer instead of default options
options := types.DefaultOptions()
templates.UseOptionsForSigner(options)
catalog := disk.NewCatalog(filepath.Dir(templatePath))
executerOpts := protocols.ExecutorOptions{
Catalog: catalog,
Options: options,
TemplatePath: templatePath,
Parser: templates.NewParser(),
}
return executerOpts
}
+1 -12
View File
@@ -1,24 +1,13 @@
package main
import (
"context"
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
"github.com/projectdiscovery/nuclei/v3/pkg/installer"
syncutil "github.com/projectdiscovery/utils/sync"
)
func main() {
ctx := context.Background()
// when running nuclei in parallel for first time it is a good practice to make sure
// templates exists first
tm := installer.TemplateManager{}
if err := tm.FreshInstallIfNotExists(); err != nil {
panic(err)
}
// create nuclei engine with options
ne, err := nuclei.NewThreadSafeNucleiEngineCtx(ctx)
ne, err := nuclei.NewThreadSafeNucleiEngine()
if err != nil {
panic(err)
}
+2 -6
View File
@@ -1,13 +1,9 @@
package main
import (
"context"
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
)
import nuclei "github.com/projectdiscovery/nuclei/v3/lib"
func main() {
ne, err := nuclei.NewNucleiEngineCtx(context.Background(),
ne, err := nuclei.NewNucleiEngine(
nuclei.WithTemplateFilters(nuclei.TemplateFilters{Tags: []string{"oast"}}),
nuclei.EnableStatsWithOpts(nuclei.StatsOptions{MetricServerPort: 6064}), // optionally enable metrics server for better observability
)
+4 -4
View File
@@ -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 ) |
+125 -128
View File
@@ -1,8 +1,6 @@
module github.com/projectdiscovery/nuclei/v3
go 1.23.0
toolchain go1.24.1
go 1.21
require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
@@ -10,7 +8,7 @@ require (
github.com/antchfx/htmlquery v1.3.0
github.com/bluele/gcache v0.0.2
github.com/go-playground/validator/v10 v10.14.1
github.com/go-rod/rod v0.116.2
github.com/go-rod/rod v0.114.0
github.com/gobwas/ws v1.2.1
github.com/google/go-github v17.0.0+incompatible
github.com/invopop/jsonschema v0.12.0
@@ -18,42 +16,41 @@ require (
github.com/json-iterator/go v1.1.12
github.com/julienschmidt/httprouter v1.3.0
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/miekg/dns v1.1.62
github.com/miekg/dns v1.1.57
github.com/olekukonko/tablewriter v0.0.5
github.com/pkg/errors v0.9.1
github.com/projectdiscovery/clistats v0.1.1
github.com/projectdiscovery/fastdialer v0.4.0
github.com/projectdiscovery/hmap v0.0.88
github.com/projectdiscovery/interactsh v1.2.4
github.com/projectdiscovery/rawhttp v0.1.90
github.com/projectdiscovery/retryabledns v1.0.99
github.com/projectdiscovery/retryablehttp-go v1.0.111
github.com/projectdiscovery/yamldoc-go v1.0.6
github.com/projectdiscovery/clistats v0.0.20
github.com/projectdiscovery/fastdialer v0.0.67
github.com/projectdiscovery/hmap v0.0.41
github.com/projectdiscovery/interactsh v1.1.9
github.com/projectdiscovery/rawhttp v0.1.45
github.com/projectdiscovery/retryabledns v1.0.58
github.com/projectdiscovery/retryablehttp-go v1.0.55
github.com/projectdiscovery/yamldoc-go v1.0.4
github.com/remeh/sizedwaitgroup v1.0.0
github.com/rs/xid v1.6.0
github.com/rs/xid v1.5.0
github.com/segmentio/ksuid v1.0.4
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/cast v1.5.1
github.com/syndtr/goleveldb v1.0.0
github.com/valyala/fasttemplate v1.2.2
github.com/weppos/publicsuffix-go v0.40.2
github.com/xanzy/go-gitlab v0.107.0
github.com/weppos/publicsuffix-go v0.30.2-0.20230730094716-a20f9abcc222
github.com/xanzy/go-gitlab v0.84.0
go.uber.org/multierr v1.11.0
golang.org/x/net v0.39.0
golang.org/x/oauth2 v0.22.0
golang.org/x/text v0.24.0
golang.org/x/net v0.24.0
golang.org/x/oauth2 v0.11.0
golang.org/x/text v0.14.0
gopkg.in/yaml.v2 v2.4.0
)
require (
code.gitea.io/sdk/gitea v0.17.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0
github.com/DataDog/gostackparse v0.6.0
github.com/Masterminds/semver/v3 v3.2.1
github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057
github.com/alitto/pond v1.9.2
github.com/antchfx/xmlquery v1.3.17
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/aws/aws-sdk-go-v2 v1.19.0
@@ -61,58 +58,53 @@ require (
github.com/aws/aws-sdk-go-v2/credentials v1.13.27
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72
github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0
github.com/bytedance/sonic v1.12.8
github.com/cespare/xxhash v1.1.0
github.com/charmbracelet/glamour v0.8.0
github.com/charmbracelet/glamour v0.6.0
github.com/clbanning/mxj/v2 v2.7.0
github.com/denisenkom/go-mssqldb v0.12.3
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c
github.com/docker/go-units v0.5.0
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204
github.com/fatih/structs v1.1.0
github.com/getkin/kin-openapi v0.126.0
github.com/go-git/go-git/v5 v5.13.0
github.com/getkin/kin-openapi v0.123.0
github.com/go-git/go-git/v5 v5.11.0
github.com/go-ldap/ldap/v3 v3.4.5
github.com/go-pg/pg v8.0.7+incompatible
github.com/go-sql-driver/mysql v1.7.1
github.com/goccy/go-json v0.10.5
github.com/goccy/go-yaml v1.11.3
github.com/h2non/filetype v1.1.3
github.com/invopop/yaml v0.3.1
github.com/kitabisa/go-ci v1.0.3
github.com/labstack/echo/v4 v4.13.3
github.com/labstack/echo/v4 v4.10.2
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa
github.com/lib/pq v1.10.9
github.com/lib/pq v1.10.1
github.com/mattn/go-sqlite3 v1.14.22
github.com/mholt/archives v0.1.0
github.com/microsoft/go-mssqldb v1.6.0
github.com/mholt/archiver v3.1.1+incompatible
github.com/ory/dockertest/v3 v3.10.0
github.com/praetorian-inc/fingerprintx v1.1.9
github.com/projectdiscovery/dsl v0.4.3
github.com/projectdiscovery/dsl v0.0.52
github.com/projectdiscovery/fasttemplate v0.0.2
github.com/projectdiscovery/freeport v0.0.5
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
github.com/projectdiscovery/goflags v0.1.74
github.com/projectdiscovery/gologger v1.1.54
github.com/projectdiscovery/goflags v0.1.48
github.com/projectdiscovery/gologger v1.1.12
github.com/projectdiscovery/gostruct v0.0.2
github.com/projectdiscovery/gozero v0.0.3
github.com/projectdiscovery/httpx v1.7.0
github.com/projectdiscovery/mapcidr v1.1.34
github.com/projectdiscovery/gozero v0.0.2
github.com/projectdiscovery/httpx v1.6.0
github.com/projectdiscovery/mapcidr v1.1.16
github.com/projectdiscovery/martian/v3 v3.0.0-20240219194442-fed3b744f477
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
github.com/projectdiscovery/ratelimit v0.0.80
github.com/projectdiscovery/proxify v0.0.13-0.20240407134611-de309e8af9ca
github.com/projectdiscovery/ratelimit v0.0.35
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
github.com/projectdiscovery/sarif v0.0.1
github.com/projectdiscovery/tlsx v1.1.9
github.com/projectdiscovery/uncover v1.0.10
github.com/projectdiscovery/useragent v0.0.100
github.com/projectdiscovery/utils v0.4.19
github.com/projectdiscovery/wappalyzergo v0.2.28
github.com/projectdiscovery/tlsx v1.1.6
github.com/projectdiscovery/uncover v1.0.7
github.com/projectdiscovery/useragent v0.0.40
github.com/projectdiscovery/utils v0.0.88
github.com/projectdiscovery/wappalyzergo v0.0.116
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.10.0
github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9
github.com/yassinebenaid/godump v0.10.0
github.com/stretchr/testify v1.9.0
github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706
go.mongodb.org/mongo-driver v1.17.0
golang.org/x/term v0.31.0
golang.org/x/term v0.19.0
gopkg.in/yaml.v3 v3.0.1
moul.io/http2curl v1.0.0
)
@@ -120,16 +112,16 @@ require (
require (
aead.dev/minisign v0.2.0 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/STARRY-S/zip v0.2.1 // indirect
github.com/Shopify/sarama v1.38.1 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
@@ -137,45 +129,44 @@ require (
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/bits-and-blooms/bitset v1.8.0 // indirect
github.com/bits-and-blooms/bloom/v3 v3.5.0 // indirect
github.com/bodgit/plumbing v1.3.0 // indirect
github.com/bodgit/sevenzip v1.6.0 // indirect
github.com/bodgit/windows v1.0.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/sonic/loader v0.2.2 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/lipgloss v0.13.0 // indirect
github.com/charmbracelet/x/ansi v0.3.2 // indirect
github.com/cheggaaa/pb/v3 v3.1.4 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cloudflare/cfssl v1.6.4 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/docker/cli v24.0.5+incompatible // indirect
github.com/docker/docker v24.0.9+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/eapache/channels v1.1.0 // indirect
github.com/eapache/go-resiliency v1.3.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230111030713-bf00bc1b83b6 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/elastic/go-elasticsearch/v7 v7.17.10 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/fgprof v0.9.5 // indirect
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gaissmai/bart v0.17.10 // indirect
github.com/geoffgarside/ber v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/swag v0.22.9 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/certificate-transparency-go v1.1.4 // indirect
github.com/google/go-github/v30 v30.1.0 // indirect
@@ -185,8 +176,10 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.6 // indirect
github.com/haxii/fastproxy v0.5.37 // indirect
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
@@ -195,46 +188,46 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kataras/jwt v0.1.10 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/logrusorgru/aurora/v4 v4.0.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mackerelio/go-osstat v0.2.4 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mholt/archiver/v3 v3.5.1 // indirect
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
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/nwaples/rardecode/v2 v2.0.1 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.14 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/projectdiscovery/asnmap v1.1.1 // indirect
github.com/projectdiscovery/cdncheck v1.1.17 // indirect
github.com/projectdiscovery/freeport v0.0.7 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/projectdiscovery/asnmap v1.1.0 // indirect
github.com/projectdiscovery/cdncheck v1.0.9 // 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
github.com/sashabaranov/go-openai v1.37.0 // indirect
github.com/projectdiscovery/roundrobin v0.0.6 // indirect
github.com/projectdiscovery/stringsutil v0.0.2 // indirect
github.com/projectdiscovery/tinydns v0.0.31 // indirect
github.com/quic-go/quic-go v0.42.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/refraction-networking/utls v1.6.1 // indirect
github.com/sashabaranov/go-openai v1.15.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/sorairolake/lzip-go v0.3.5 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/tidwall/btree v1.7.0 // indirect
github.com/tidwall/buntdb v1.3.1 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/buntdb v1.3.0 // indirect
github.com/tidwall/gjson v1.17.0 // indirect
github.com/tidwall/grect v0.1.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
@@ -244,23 +237,18 @@ 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.40.0 // indirect
github.com/yuin/goldmark v1.7.4 // indirect
github.com/yuin/goldmark-emoji v1.0.3 // indirect
github.com/ysmood/got v0.34.1 // indirect
github.com/yuin/goldmark v1.5.4 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
github.com/zcalusic/sysinfo v1.0.2 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/goleak v1.3.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
mellium.im/sasl v0.3.1 // indirect
)
@@ -268,32 +256,33 @@ require (
require (
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect
github.com/PuerkitoBio/goquery v1.10.3 // indirect
github.com/PuerkitoBio/goquery v1.8.1 // indirect
github.com/akrylysov/pogreb v0.10.2 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/antchfx/xpath v1.2.4
github.com/aymerick/douceur v0.2.0 // indirect
github.com/caddyserver/certmagic v0.19.2 // indirect
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/goburrow/cache v0.1.4 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.6.0
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
github.com/hdm/jarm-go v0.0.7 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
@@ -302,45 +291,47 @@ require (
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mholt/acmez v1.2.0 // indirect
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/projectdiscovery/blackrock v0.0.1 // indirect
github.com/projectdiscovery/networkpolicy v0.1.14
github.com/rivo/uniseg v0.4.7 // indirect
github.com/projectdiscovery/networkpolicy v0.0.8
github.com/rivo/uniseg v0.4.6 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/trivago/tgo v1.0.7
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/yl2chen/cidranger v1.0.2 // indirect
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/gson v0.7.3 // indirect
github.com/ysmood/leakless v0.9.0 // indirect
github.com/ysmood/leakless v0.8.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect
github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect
go.etcd.io/bbolt v1.3.10 // indirect
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c // indirect
go.etcd.io/bbolt v1.3.8 // indirect
go.uber.org/zap v1.25.0 // indirect
goftp.io/server/v2 v2.0.1 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.29.0
google.golang.org/protobuf v1.34.2 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.17.0
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
)
require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/ProtonMail/go-crypto v1.1.0-alpha.0-proton // indirect
github.com/alecthomas/chroma v0.10.0
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect
@@ -355,17 +346,23 @@ require (
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-echarts/go-echarts/v2 v2.3.3
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
// https://go.dev/ref/mod#go-mod-file-retract
retract v3.2.0 // retract due to broken js protocol issue
replace github.com/go-echarts/go-echarts/v2 => github.com/tarunKoyalwar/go-echarts/v2 v2.1.1
+309 -331
View File
File diff suppressed because it is too large. Load diff
+3 -4
View File
@@ -1,7 +1,6 @@
{{- if .Values.interactsh.ingress.enabled -}}
{{- $fullName := include "nuclei.fullname" . -}}
{{- $svcPort := .Values.interactsh.service.port -}}
{{- $svcName := .Values.interactsh.service.name -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.interactsh.ingress.className (not (semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class" .Values.interactsh.ingress.className}}
@@ -50,11 +49,11 @@ spec:
backend:
{{- if semverCompare ">=1.20-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $svcName }}
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $svcName }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
+2 -2
View File
@@ -14,7 +14,7 @@ dns:
matchers:
- type: word
words:
- ".vercel-dns.com"
- "ghost.io"
internal: true
http:
@@ -25,4 +25,4 @@ http:
matchers:
- type: word
words:
- "html>"
- "ghost.io"
@@ -1,27 +0,0 @@
id: fuzz-multi-mode-test
info:
name: multi-mode fuzzing test
author: pdteam
severity: info
http:
- payloads:
inject:
- nuclei-v1
- nuclei-v2
- nuclei-v3
fuzzing:
- part: header
type: replace
mode: multiple
fuzz:
X-Client-Id: "{{inject}}"
X-Secret-Id: "{{inject}}"
matchers-condition: or
matchers:
- type: word
words:
- "nuclei-v3"
+5 -2
View File
@@ -15,18 +15,21 @@ http:
- type: dsl
dsl:
- 'method == "GET"'
- regex("/(.*?/)([0-9]+)(/.*)?",path)
condition: and
payloads:
pathsqli:
- "'OR1=1"
- '%20OR%20True'
fuzzing:
- part: path
type: postfix
type: replace-regex
mode: single
replace-regex: '/(.*?/)([0-9]+)(/.*)?'
fuzz:
- '{{pathsqli}}'
- '/${1}${2}{{pathsqli}}${3}'
matchers:
- type: status
@@ -1,2 +0,0 @@
tags:
- kev
@@ -23,4 +23,4 @@ code:
- type: dsl
dsl:
- true
# digest: 490a00463044022048c083c338c0195f5012122d40c1009d2e2030c583e56558e0d6249a41e6f3f4022070656adf748f4874018d7a01fce116db10a3acd1f9b03e12a83906fb625b5c50:4a3eb6b4988d95847d4203be25ed1d46
# digest: 490a004630440220192fb8f704b078c2885047b85ac1a0491be86485c033a976d201599683a35aab0220604b1c3781e9d97079d0e5c23c18e6a2d87493c8e2b930536e692ee7d06e9247:4a3eb6b4988d95847d4203be25ed1d46
@@ -20,4 +20,4 @@ code:
- type: word
words:
- "hello from input baz"
# digest: 4b0a00483046022100cbbdb7214f669d111b671d271110872dc8af2ab41cf5c312b6e4f64126f55337022100a60547952a0c2bea58388f2d2effe8ad73cd6b6fc92e73eb3c8f88beab6105ec:4a3eb6b4988d95847d4203be25ed1d46
# digest: 4a0a00473045022033f72f1b9d5143f58a2dc79c2597000f34080251ac3702c36c3fad00917dfeeb0221009ba05c715c9e2e36dba471be6c0106a09ae3822d8a3e9e4bcf377e9f4a395a01:4a3eb6b4988d95847d4203be25ed1d46
@@ -18,4 +18,4 @@ code:
- type: word
words:
- "hello from input"
# digest: 4a0a00473045022032b81e8bb7475abf27639b0ced71355497166d664698021f26498e7031d62a23022100e99ccde578bfc0b658f16427ae9a3d18922849d3ba3e022032ea0d2a8e77fadb:4a3eb6b4988d95847d4203be25ed1d46
# digest: 4a0a004730450220377128cb11d9f6f0fee1f4dbd841e46783de26e90a216fa55a7609ee2bc823c60221009166ee0f85e3a1811588ab19e73ea96ab3d582dc8180dbcbbad0ea9ab7e9025d:4a3eb6b4988d95847d4203be25ed1d46
@@ -26,4 +26,4 @@ code:
part: interactsh_protocol
words:
- "http"
# digest: 4a0a0047304502201a5dd0eddfab4f02588a5a8ac1947a5fa41fed80b59d698ad5cc00456296efb6022100fe6e608e38c060964800f5f863a7cdc93f686f2d0f4b52854f73948b808b4511:4a3eb6b4988d95847d4203be25ed1d46
# digest: 4b0a00483046022100d472d50bd83117d334f5217c7a40dcdf34138e90029eaace51697d902296bf37022100a393b49420a96f60d6d89b79b5135ee2233b2468d374851890eea114b08195d1:4a3eb6b4988d95847d4203be25ed1d46
@@ -21,4 +21,4 @@ code:
- type: word
words:
- "hello from input"
# digest: 4b0a00483046022100ced1702728cc68f906c4c7d2c4d05ed071bfabee1e36eec7ebecbeca795a170c022100d20fd41796f130a8f9c4972fee85386d67d61eb5fc1119b1afe2a851eb2f3e65:4a3eb6b4988d95847d4203be25ed1d46
# digest: 4b0a004830460221008886054bb5dd6345e434e30f31c8fddce3c484a4f33aa6321b5185675866029d022100d188a83d0fde029f8b586061c65ab72b43755c3fb10fdd59501bb9bbadbb1ff7:4a3eb6b4988d95847d4203be25ed1d46
@@ -1,18 +0,0 @@
id: headless-dsl
info:
name: Headless DSL
author: dwisiswant0
severity: info
tags: headless
headless:
- steps:
- action: navigate
args:
url: "{{BaseURL}}/?_={{urlencode(concat('foo', '-', 'bar'))}}"
- action: waitload
matchers:
- type: word
words:
- "foo-bar"
@@ -13,7 +13,7 @@ dns:
- type: dsl
name: blogid
dsl:
- trim_suffix(cname,'.vercel-dns.com')
- trim_suffix(cname,'.ghost.io')
internal: true
http:
@@ -24,6 +24,6 @@ http:
matchers:
- type: dsl
dsl:
- contains(body,'home') # check for http string
- blogid == 'cname' # check for cname (extracted information from dns response)
- contains(body,'ProjectDiscovery.io') # check for http string
- blogid == 'projectdiscovery' # check for cname (extracted information from dns response)
condition: and
@@ -7,7 +7,7 @@ info:
variables:
cname_filtered: '{{trim_suffix(dns_cname,".vercel-dns.com")}}'
cname_filtered: '{{trim_suffix(dns_cname,".ghost.io")}}'
dns:
- name: "{{FQDN}}" # DNS Request
@@ -24,7 +24,7 @@ http:
matchers:
- type: dsl
dsl:
- contains(http_body,'home') # check for http string
- cname_filtered == 'cname' # check for cname (extracted information from dns response)
- ssl_subject_cn == 'docs.projectdiscovery.io'
- contains(http_body,'ProjectDiscovery.io') # check for http string
- cname_filtered == 'projectdiscovery' # check for cname (extracted information from dns response)
- ssl_subject_cn == 'blog.projectdiscovery.io'
condition: and
@@ -20,7 +20,7 @@ http:
matchers:
- type: dsl
dsl:
- contains(http_body,'home') # check for http string
- trim_suffix(dns_cname,'.vercel-dns.com') == 'cname' # check for cname (extracted information from dns response)
- ssl_subject_cn == 'docs.projectdiscovery.io'
- contains(http_body,'ProjectDiscovery.io') # check for http string
- trim_suffix(dns_cname,'.ghost.io') == 'projectdiscovery' # check for cname (extracted information from dns response)
- ssl_subject_cn == 'blog.projectdiscovery.io'
condition: and
@@ -1,34 +0,0 @@
id: multi-req
info:
name: Multi-Request
author: pdteam
severity: info
ssl:
- address: "{{Host}}:{{Port}}"
min_version: ssl30
max_version: ssl30
extractors:
- type: json
json:
- " .tls_version"
- address: "{{Host}}:{{Port}}"
min_version: tls10
max_version: tls10
extractors:
- type: json
json:
- " .tls_version"
- address: "{{Host}}:{{Port}}"
min_version: tls11
max_version: tls11
extractors:
- type: json
json:
- " .tls_version"
@@ -19,4 +19,4 @@ code:
regex:
- 'hello from (.*)'
group: 1
# digest: 490a0046304402206b3648e8d393ac4df82c7d59b1a6ee3731c66c249dbd4d9bf31f0b7f176b37ec02203184d36373e516757c7d708b5799bc16edb1cebc0a64f3442d13ded4b33c42fb:4a3eb6b4988d95847d4203be25ed1d46
# digest: 490a0046304402202c63d47bb0acdd40b3b852d95490d492ff5741b84071b2a8a40371be7797c13602202b6b977e157edf2ef70a402a2e57d4eb5a67c5ca91f0a2f9a10a966e8485ebaf:4a3eb6b4988d95847d4203be25ed1d46
@@ -18,4 +18,4 @@ code:
- type: word
words:
- "hello from first"
# digest: 490a0046304402204cbb1bdf8370e49bb930b17460fb35e15f285a3b48b165736ac0e7ba2f9bc0fb022067c134790c4a2cf646b195aa4488e2c222266436e6bda47931908a28807bdb81:4a3eb6b4988d95847d4203be25ed1d46
# digest: 490a00463044022025661eab353b7f359c0d428a86b6287545d7f759375e8025cc8c9c77b616ca6502200bc2c019059622df3c88e7caa6dd7d1fb9b956010aa0de2ee2b9f7dd0a3c4954:4a3eb6b4988d95847d4203be25ed1d46
@@ -1,23 +0,0 @@
id: multimatch-value-share-template
info:
name: MultiMatch Value Share Template
author: tovask
severity: info
http:
- path:
- "{{BaseURL}}/path1?v=1"
- "{{BaseURL}}/path1?v=2"
matchers:
- type: word
name: test-matcher
words:
- "href"
extractors:
- type: regex
part: body
name: extracted
regex:
- 'href="(.*)"'
group: 1
@@ -1,21 +0,0 @@
id: multimatch-value-share-workflow
info:
name: MultiMatch Value Share Workflow
author: tovask
severity: info
description: Workflow to test value sharing when multiple matches occur in the extractor template
workflows:
- template: workflow/multimatch-value-share-template.yaml
subtemplates:
- template: workflow/match-1.yaml
subtemplates:
- template: workflow/http-value-share-template-2.yaml
- template: workflow/multimatch-value-share-template.yaml
matchers:
- name: test-matcher
subtemplates:
- template: workflow/match-1.yaml
subtemplates:
- template: workflow/http-value-share-template-2.yaml
-112
View File
@@ -1,112 +0,0 @@
package httpapi
import (
"net/http"
"time"
"github.com/projectdiscovery/nuclei/v3/pkg/js/compiler"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
)
type Concurrency struct {
BulkSize int `json:"bulk_size"`
Threads int `json:"threads"`
RateLimit int `json:"rate_limit"`
RateLimitDuration string `json:"rate_limit_duration"`
PayloadConcurrency int `json:"payload_concurrency"`
ProbeConcurrency int `json:"probe_concurrency"`
JavascriptConcurrency int `json:"javascript_concurrency"`
}
// Server represents the HTTP server that handles the concurrency settings endpoints.
type Server struct {
addr string
config *types.Options
}
// New creates a new instance of Server.
func New(addr string, config *types.Options) *Server {
return &Server{
addr: addr,
config: config,
}
}
// Start initializes the server and its routes, then starts listening on the specified address.
func (s *Server) Start() error {
http.HandleFunc("/api/concurrency", s.handleConcurrency)
if err := http.ListenAndServe(s.addr, nil); err != nil {
return err
}
return nil
}
// handleConcurrency routes the request based on its method to the appropriate handler.
func (s *Server) handleConcurrency(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
s.getSettings(w, r)
case http.MethodPut:
s.updateSettings(w, r)
default:
http.Error(w, "Unsupported HTTP method", http.StatusMethodNotAllowed)
}
}
// GetSettings handles GET requests and returns the current concurrency settings
func (s *Server) getSettings(w http.ResponseWriter, _ *http.Request) {
concurrencySettings := Concurrency{
BulkSize: s.config.BulkSize,
Threads: s.config.TemplateThreads,
RateLimit: s.config.RateLimit,
RateLimitDuration: s.config.RateLimitDuration.String(),
PayloadConcurrency: s.config.PayloadConcurrency,
ProbeConcurrency: s.config.ProbeConcurrency,
JavascriptConcurrency: compiler.PoolingJsVmConcurrency,
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(concurrencySettings); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// UpdateSettings handles PUT requests to update the concurrency settings
func (s *Server) updateSettings(w http.ResponseWriter, r *http.Request) {
var newSettings Concurrency
if err := json.NewDecoder(r.Body).Decode(&newSettings); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if newSettings.RateLimitDuration != "" {
if duration, err := time.ParseDuration(newSettings.RateLimitDuration); err == nil {
s.config.RateLimitDuration = duration
} else {
http.Error(w, "Invalid duration format", http.StatusBadRequest)
return
}
}
if newSettings.BulkSize > 0 {
s.config.BulkSize = newSettings.BulkSize
}
if newSettings.Threads > 0 {
s.config.TemplateThreads = newSettings.Threads
}
if newSettings.RateLimit > 0 {
s.config.RateLimit = newSettings.RateLimit
}
if newSettings.PayloadConcurrency > 0 {
s.config.PayloadConcurrency = newSettings.PayloadConcurrency
}
if newSettings.ProbeConcurrency > 0 {
s.config.ProbeConcurrency = newSettings.ProbeConcurrency
}
if newSettings.JavascriptConcurrency > 0 {
compiler.PoolingJsVmConcurrency = newSettings.JavascriptConcurrency
s.config.JsConcurrency = newSettings.JavascriptConcurrency // no-op on speed change
}
w.WriteHeader(http.StatusOK)
}
+1 -9
View File
@@ -5,17 +5,9 @@ import (
urlutil "github.com/projectdiscovery/utils/url"
)
func getScanDashBoardURL(id string, teamID string) string {
func getScanDashBoardURL(id string) string {
ux, _ := urlutil.Parse(pdcpauth.DashBoardURL)
ux.Path = "/scans/" + id
if ux.Params == nil {
ux.Params = urlutil.NewOrderedParams()
}
if teamID != "" {
ux.Params.Add("team_id", teamID)
} else {
ux.Params.Add("team_id", NoneTeamID)
}
ux.Update()
return ux.String()
}
+11 -51
View File
@@ -4,23 +4,20 @@ import (
"bufio"
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
"sync/atomic"
"time"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
pdcpauth "github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/env"
errorutil "github.com/projectdiscovery/utils/errors"
unitutils "github.com/projectdiscovery/utils/unit"
updateutils "github.com/projectdiscovery/utils/update"
urlutil "github.com/projectdiscovery/utils/url"
)
@@ -28,19 +25,11 @@ import (
const (
uploadEndpoint = "/v1/scans/import"
appendEndpoint = "/v1/scans/%s/import"
flushTimer = time.Minute
MaxChunkSize = 4 * unitutils.Mega // 4 MB
xidRe = `^[a-z0-9]{20}$`
teamIDHeader = "X-Team-Id"
NoneTeamID = "none"
flushTimer = time.Duration(1) * time.Minute
MaxChunkSize = 1024 * 1024 * 4 // 4 MB
)
var (
xidRegex = regexp.MustCompile(xidRe)
_ output.Writer = &UploadWriter{}
// teamID if given
TeamIDEnv = env.GetEnvOrDefault("PDCP_TEAM_ID", NoneTeamID)
)
var _ output.Writer = &UploadWriter{}
// UploadWriter is a writer that uploads its output to pdcp
// server to enable web dashboard and more
@@ -52,9 +41,7 @@ type UploadWriter struct {
cancel context.CancelFunc
done chan struct{}
scanID string
scanName string
counter atomic.Int32
TeamID string
}
// NewUploadWriter creates a new upload writer
@@ -63,9 +50,8 @@ func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*Upl
return nil, fmt.Errorf("no credentials provided")
}
u := &UploadWriter{
creds: creds,
done: make(chan struct{}, 1),
TeamID: NoneTeamID,
creds: creds,
done: make(chan struct{}, 1),
}
var err error
reader, writer := io.Pipe()
@@ -100,25 +86,8 @@ func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*Upl
}
// SetScanID sets the scan id for the upload writer
func (u *UploadWriter) SetScanID(id string) error {
if !xidRegex.MatchString(id) {
return fmt.Errorf("invalid scan id provided")
}
func (u *UploadWriter) SetScanID(id string) {
u.scanID = id
return nil
}
// SetScanName sets the scan name for the upload writer
func (u *UploadWriter) SetScanName(name string) {
u.scanName = name
}
func (u *UploadWriter) SetTeamID(id string) {
if id == "" {
u.TeamID = NoneTeamID
} else {
u.TeamID = id
}
}
func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) {
@@ -147,13 +116,13 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) {
if u.scanID == "" {
gologger.Verbose().Msgf("Scan results upload to cloud skipped, no results found to upload")
} else {
gologger.Info().Msgf("%v Scan results uploaded to cloud, you can view scan results at %v", u.counter.Load(), getScanDashBoardURL(u.scanID, u.TeamID))
gologger.Info().Msgf("%v Scan results uploaded to cloud, you can view scan results at %v", u.counter.Load(), getScanDashBoardURL(u.scanID))
}
}()
// temporary buffer to store the results
buff := &bytes.Buffer{}
ticker := time.NewTicker(flushTimer)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
@@ -200,7 +169,7 @@ func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error {
// if successful, reset the buffer
buff.Reset()
// log in verbose mode
gologger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID, u.TeamID))
gologger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID))
return nil
}
@@ -251,17 +220,8 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) {
return nil, errorutil.NewWithErr(err).Msgf("could not create cloud upload request")
}
// add pdtm meta params
req.URL.Params.Merge(updateutils.GetpdtmParams(config.Version))
// if it is upload endpoint also include name if it exists
if u.scanName != "" && req.URL.Path == uploadEndpoint {
req.URL.Params.Add("name", u.scanName)
}
req.URL.Update()
req.URL.RawQuery = updateutils.GetpdtmParams(config.Version)
req.Header.Set(pdcpauth.ApiKeyHeaderName, u.creds.APIKey)
if u.TeamID != NoneTeamID && u.TeamID != "" {
req.Header.Set(teamIDHeader, u.TeamID)
}
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Accept", "application/json")
return req, nil
+12 -11
View File
@@ -1,7 +1,6 @@
package runner
import (
"context"
"sync/atomic"
"time"
@@ -17,6 +16,8 @@ import (
syncutil "github.com/projectdiscovery/utils/sync"
)
var GlobalProbeBulkSize = 50
// initializeTemplatesHTTPInput initializes the http form of input
// for any loaded http templates if input is in non-standard format.
func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
@@ -30,12 +31,12 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
}
gologger.Info().Msgf("Running httpx on input host")
httpxOptions := httpx.DefaultOptions
if r.options.AliveHttpProxy != "" {
httpxOptions.Proxy = r.options.AliveHttpProxy
} else if r.options.AliveSocksProxy != "" {
httpxOptions.Proxy = r.options.AliveSocksProxy
var bulkSize = GlobalProbeBulkSize
if r.options.BulkSize > GlobalProbeBulkSize {
bulkSize = r.options.BulkSize
}
httpxOptions := httpx.DefaultOptions
httpxOptions.RetryMax = r.options.Retries
httpxOptions.Timeout = time.Duration(r.options.Timeout) * time.Second
httpxOptions.NetworkPolicy = protocolstate.NetworkPolicy
@@ -44,8 +45,10 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
return nil, errors.Wrap(err, "could not create httpx client")
}
shouldFollowGlobalProbeBulkSize := bulkSize == GlobalProbeBulkSize
// Probe the non-standard URLs and store them in cache
swg, err := syncutil.New(syncutil.WithSize(r.options.BulkSize))
swg, err := syncutil.New(syncutil.WithSize(bulkSize))
if err != nil {
return nil, errors.Wrap(err, "could not create adaptive group")
}
@@ -55,10 +58,8 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
return true
}
if r.options.ProbeConcurrency > 0 && swg.Size != r.options.ProbeConcurrency {
if err := swg.Resize(context.Background(), r.options.ProbeConcurrency); err != nil {
gologger.Error().Msgf("Could not resize workpool: %s\n", err)
}
if shouldFollowGlobalProbeBulkSize && swg.Size != GlobalProbeBulkSize {
swg.Resize(GlobalProbeBulkSize)
}
swg.Add()
+3 -33
View File
@@ -1,9 +1,7 @@
package runner
import (
"context"
"fmt"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
@@ -11,12 +9,9 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/writer"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/env"
errorutil "github.com/projectdiscovery/utils/errors"
)
@@ -55,7 +50,6 @@ func GetAuthTmplStore(opts types.Options, catalog catalog.Catalog, execOpts prot
opts.ExcludeProtocols = nil
opts.IncludeConditions = nil
cfg := loader.NewConfig(&opts, catalog, execOpts)
cfg.StoreId = loader.AuthStoreId
store, err := loader.New(cfg)
if err != nil {
return nil, errorutil.NewWithErr(err).Msgf("failed to initialize dynamic auth templates store")
@@ -77,27 +71,8 @@ func GetLazyAuthFetchCallback(opts *AuthLazyFetchOptions) authx.LazyFetchSecret
tmpl := tmpls[0]
// add args to tmpl here
vars := map[string]interface{}{}
mainCtx := context.Background()
ctx := scan.NewScanContext(mainCtx, contextargs.NewWithInput(mainCtx, d.Input))
cliVars := map[string]interface{}{}
if opts.ExecOpts.Options != nil {
// gets variables passed from cli -v and -env-vars
cliVars = generators.BuildPayloadFromOptions(opts.ExecOpts.Options)
}
ctx := scan.NewScanContext(contextargs.NewWithInput(d.Input))
for _, v := range d.Variables {
// Check if the template has any env variables and expand them
if strings.HasPrefix(v.Value, "$") {
env.ExpandWithEnv(&v.Value)
}
if strings.Contains(v.Value, "{{") {
// if variables had value like {{username}}, then replace it with the value from cliVars
// variables:
// - key: username
// value: {{username}}
v.Value = replacer.Replace(v.Value, cliVars)
}
vars[v.Key] = v.Value
ctx.Input.Add(v.Key, v.Value)
}
@@ -114,13 +89,8 @@ func GetLazyAuthFetchCallback(opts *AuthLazyFetchOptions) authx.LazyFetchSecret
}
// dynamic values
for k, v := range e.OperatorsResult.DynamicValues {
// Iterate through all the values and choose the
// largest value as the extracted value
for _, value := range v {
oldVal, ok := data[k]
if !ok || len(value) > len(oldVal.(string)) {
data[k] = value
}
if len(v) > 0 {
data[k] = v[0]
}
}
// named extractors
+30 -73
View File
@@ -3,7 +3,6 @@ package runner
import (
"bufio"
"fmt"
"io/fs"
"os"
"path/filepath"
"strconv"
@@ -26,7 +25,7 @@ import (
"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/sarif"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/extensions"
"github.com/projectdiscovery/nuclei/v3/pkg/testing"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/yaml"
fileutil "github.com/projectdiscovery/utils/file"
@@ -52,6 +51,8 @@ func ConfigureOptions() error {
return nil
}
var proxyServer *testing.ProxyServer
// ParseOptions parses the command line flags provided by a user
func ParseOptions(options *types.Options) {
// Check if stdin pipe was given
@@ -68,7 +69,6 @@ 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: ")
@@ -77,31 +77,6 @@ func ParseOptions(options *types.Options) {
}
os.Exit(0)
}
defaultProfilesPath := filepath.Join(config.DefaultConfig.GetTemplateDir(), "profiles")
if options.ListTemplateProfiles {
gologger.Print().Msgf(
"\nListing available %v nuclei template profiles for %v",
config.DefaultConfig.TemplateVersion,
config.DefaultConfig.TemplatesDirectory,
)
templatesRootDir := config.DefaultConfig.GetTemplateDir()
err := filepath.WalkDir(defaultProfilesPath, func(iterItem string, d fs.DirEntry, err error) error {
ext := filepath.Ext(iterItem)
isYaml := ext == extensions.YAML || ext == extensions.YML
if err != nil || d.IsDir() || !isYaml {
return nil
}
if profileRelPath, err := filepath.Rel(templatesRootDir, iterItem); err == nil {
gologger.Print().Msgf("%s (%s)\n", profileRelPath, strings.TrimSuffix(filepath.Base(iterItem), ext))
}
return nil
})
if err != nil {
gologger.Error().Msgf("%s\n", err)
}
os.Exit(0)
}
if options.StoreResponseDir != DefaultDumpTrafficOutputFolder && !options.StoreResponse {
gologger.Debug().Msgf("Store response directory specified, enabling \"store-resp\" flag automatically\n")
options.StoreResponse = true
@@ -111,6 +86,19 @@ func ParseOptions(options *types.Options) {
if err := ValidateOptions(options); err != nil {
gologger.Fatal().Msgf("Program exiting: %s\n", err)
}
if options.AutogenerateTests {
ps, err := testing.NewProxyServer()
if err != nil {
gologger.Fatal().Msgf("Could not create proxy server: %s\n", err)
}
proxyServer = ps
// Add the proxy server to the options
proxyURL := fmt.Sprintf("http://%s", proxyServer.ListenAddr)
options.Proxy = goflags.StringSlice([]string{proxyURL})
types.ProxyURL = proxyURL
gologger.Info().Msgf("Using %s as proxy server for automatic test-generation\n", proxyServer.ListenAddr)
}
// Load the resolvers if user asked for them
loadResolvers(options)
@@ -171,11 +159,6 @@ func ValidateOptions(options *types.Options) error {
if options.Validate {
validateTemplatePaths(config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows)
}
if options.DAST {
if err := validateDASTOptions(options); err != nil {
return err
}
}
// Verify if any of the client certificate options were set since it requires all three to work properly
if options.HasClientCertificates() {
@@ -235,25 +218,15 @@ func validateMissingS3Options(options *types.Options) []string {
if options.AwsBucketName == "" {
missing = append(missing, "AWS_TEMPLATE_BUCKET")
}
if options.AwsProfile == "" {
var missingCreds []string
if options.AwsAccessKey == "" {
missingCreds = append(missingCreds, "AWS_ACCESS_KEY")
}
if options.AwsSecretKey == "" {
missingCreds = append(missingCreds, "AWS_SECRET_KEY")
}
if options.AwsRegion == "" {
missingCreds = append(missingCreds, "AWS_REGION")
}
missing = append(missing, missingCreds...)
if len(missingCreds) > 0 {
missing = append(missing, "AWS_PROFILE")
}
if options.AwsAccessKey == "" {
missing = append(missing, "AWS_ACCESS_KEY")
}
if options.AwsSecretKey == "" {
missing = append(missing, "AWS_SECRET_KEY")
}
if options.AwsRegion == "" {
missing = append(missing, "AWS_REGION")
}
return missing
}
@@ -289,14 +262,6 @@ func validateMissingGitLabOptions(options *types.Options) []string {
return missing
}
func validateDASTOptions(options *types.Options) error {
// Ensure the DAST server token meets minimum length requirement
if len(options.DASTServerToken) > 0 && len(options.DASTServerToken) < 16 {
return fmt.Errorf("DAST server token must be at least 16 characters long")
}
return nil
}
func createReportingOptions(options *types.Options) (*reporting.Options, error) {
var reportingOptions = &reporting.Options{}
if options.ReportingConfig != "" {
@@ -327,17 +292,10 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error)
OmitRaw: options.OmitRawRequests,
}
}
// Combine options.
if options.JSONLExport != "" {
// Combine the CLI options with the config file options with the CLI options taking precedence
if reportingOptions.JSONLExporter != nil {
reportingOptions.JSONLExporter.File = options.JSONLExport
reportingOptions.JSONLExporter.OmitRaw = options.OmitRawRequests
} else {
reportingOptions.JSONLExporter = &jsonl.Options{
File: options.JSONLExport,
OmitRaw: options.OmitRawRequests,
}
reportingOptions.JSONLExporter = &jsonl.Options{
File: options.JSONLExport,
OmitRaw: options.OmitRawRequests,
}
}
@@ -347,6 +305,9 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error)
// configureOutput configures the output logging levels to be displayed on the screen
func configureOutput(options *types.Options) {
// disable standard logger (ref: https://github.com/golang/go/issues/19895)
defer logutil.DisableDefaultLogger()
if options.NoColor {
gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true))
}
@@ -365,9 +326,6 @@ func configureOutput(options *types.Options) {
if options.Silent {
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
}
// disable standard logger (ref: https://github.com/golang/go/issues/19895)
logutil.DisableDefaultLogger()
}
// loadResolvers loads resolvers from both user-provided flags and file
@@ -459,7 +417,6 @@ func readEnvInputVars(options *types.Options) {
options.AwsSecretKey = os.Getenv("AWS_SECRET_KEY")
options.AwsBucketName = os.Getenv("AWS_TEMPLATE_BUCKET")
options.AwsRegion = os.Getenv("AWS_REGION")
options.AwsProfile = os.Getenv("AWS_PROFILE")
// Azure options for downloading templates from an Azure Blob Storage container
options.AzureContainerName = os.Getenv("AZURE_CONTAINER_NAME")
+5 -7
View File
@@ -14,10 +14,6 @@ import (
proxyutils "github.com/projectdiscovery/utils/proxy"
)
const (
HTTP_PROXY_ENV = "HTTP_PROXY"
)
// loadProxyServers load list of proxy servers from file or comma separated
func loadProxyServers(options *types.Options) error {
if len(options.Proxy) == 0 {
@@ -52,13 +48,15 @@ func loadProxyServers(options *types.Options) error {
return errorutil.WrapfWithNil(err, "failed to parse proxy got %v", err)
}
if options.ProxyInternal {
os.Setenv(HTTP_PROXY_ENV, proxyURL.String())
os.Setenv(types.HTTP_PROXY_ENV, proxyURL.String())
}
if proxyURL.Scheme == proxyutils.HTTP || proxyURL.Scheme == proxyutils.HTTPS {
types.ProxyURL = proxyURL.String()
types.ProxySocksURL = ""
gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String())
options.AliveHttpProxy = proxyURL.String()
} else if proxyURL.Scheme == proxyutils.SOCKS5 {
options.AliveSocksProxy = proxyURL.String()
types.ProxyURL = ""
types.ProxySocksURL = proxyURL.String()
gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String())
}
return nil
+184 -270
View File
@@ -2,7 +2,11 @@ package runner
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
_ "net/http/pprof"
"os"
"path/filepath"
"reflect"
@@ -11,21 +15,17 @@ import (
"time"
"github.com/projectdiscovery/nuclei/v3/internal/pdcp"
"github.com/projectdiscovery/nuclei/v3/internal/server"
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider"
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/frequency"
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider"
"github.com/projectdiscovery/nuclei/v3/pkg/installer"
"github.com/projectdiscovery/nuclei/v3/pkg/loader/parser"
outputstats "github.com/projectdiscovery/nuclei/v3/pkg/output/stats"
"github.com/projectdiscovery/nuclei/v3/pkg/testing"
"github.com/projectdiscovery/nuclei/v3/pkg/scan/events"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
uncoverlib "github.com/projectdiscovery/uncover"
pdcpauth "github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/env"
fileutil "github.com/projectdiscovery/utils/file"
permissionutil "github.com/projectdiscovery/utils/permission"
pprofutil "github.com/projectdiscovery/utils/pprof"
updateutils "github.com/projectdiscovery/utils/update"
"github.com/logrusorgru/aurora"
@@ -34,14 +34,12 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/internal/colorizer"
"github.com/projectdiscovery/nuclei/v3/internal/httpapi"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
"github.com/projectdiscovery/nuclei/v3/pkg/core"
"github.com/projectdiscovery/nuclei/v3/pkg/external/customtemplates"
fuzzStats "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/stats"
"github.com/projectdiscovery/nuclei/v3/pkg/input"
parsers "github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
@@ -50,14 +48,12 @@ 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"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/uncover"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/excludematchers"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/headless/engine"
httpProtocol "github.com/projectdiscovery/nuclei/v3/pkg/protocols/http"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
@@ -78,32 +74,28 @@ var (
// Runner is a client for running the enumeration process.
type Runner struct {
output output.Writer
interactsh *interactsh.Client
options *types.Options
projectFile *projectfile.ProjectFile
catalog catalog.Catalog
progress progress.Progress
colorizer aurora.Aurora
issuesClient reporting.Client
browser *engine.Browser
rateLimiter *ratelimit.Limiter
hostErrors hosterrorscache.CacheInterface
resumeCfg *types.ResumeCfg
pprofServer *pprofutil.PprofServer
pdcpUploadErrMsg string
inputProvider provider.InputProvider
fuzzFrequencyCache *frequency.Tracker
httpStats *outputstats.Tracker
output output.Writer
interactsh *interactsh.Client
options *types.Options
projectFile *projectfile.ProjectFile
catalog catalog.Catalog
progress progress.Progress
colorizer aurora.Aurora
issuesClient reporting.Client
browser *engine.Browser
rateLimiter *ratelimit.Limiter
hostErrors hosterrorscache.CacheInterface
resumeCfg *types.ResumeCfg
pprofServer *http.Server
pdcpUploadErrMsg string
inputProvider provider.InputProvider
//general purpose temporary directory
tmpDir string
parser parser.Parser
httpApiEndpoint *httpapi.Server
fuzzStats *fuzzStats.Tracker
dastServer *server.DASTServer
tmpDir string
parser parser.Parser
}
const pprofServerAddress = "127.0.0.1:8086"
// New creates a new client for running the enumeration process.
func New(options *types.Options) (*Runner, error) {
runner := &Runner{
@@ -186,7 +178,7 @@ func New(options *types.Options) (*Runner, error) {
runner.catalog = disk.NewCatalog(config.DefaultConfig.TemplatesDirectory)
var httpclient *retryablehttp.Client
if options.ProxyInternal && options.AliveHttpProxy != "" || options.AliveSocksProxy != "" {
if options.ProxyInternal && types.ProxyURL != "" || types.ProxySocksURL != "" {
var err error
httpclient, err = httpclientpool.Get(options, &httpclientpool.Configuration{})
if err != nil {
@@ -220,18 +212,14 @@ func New(options *types.Options) (*Runner, error) {
templates.SeverityColorizer = colorizer.New(runner.colorizer)
if options.EnablePprof {
runner.pprofServer = pprofutil.NewPprofServer()
runner.pprofServer.Start()
}
if options.HttpApiEndpoint != "" {
apiServer := httpapi.New(options.HttpApiEndpoint, options)
gologger.Info().Msgf("Listening api endpoint on: %s", options.HttpApiEndpoint)
runner.httpApiEndpoint = apiServer
server := &http.Server{
Addr: pprofServerAddress,
Handler: http.DefaultServeMux,
}
gologger.Info().Msgf("Listening pprof debug server on: %s", pprofServerAddress)
runner.pprofServer = server
go func() {
if err := apiServer.Start(); err != nil {
gologger.Error().Msgf("Failed to start API server: %s", err)
}
_ = server.ListenAndServe()
}()
}
@@ -253,10 +241,6 @@ func New(options *types.Options) (*Runner, error) {
}
// setup a proxy writer to automatically upload results to PDCP
runner.output = runner.setupPDCPUpload(outputWriter)
if options.HTTPStats {
runner.httpStats = outputstats.NewTracker()
runner.output = output.NewMultiWriter(runner.output, output.NewTrackerWriter(runner.httpStats))
}
if options.JSONL && options.EnableProgressBar {
options.StatsJSON = true
@@ -297,34 +281,6 @@ func New(options *types.Options) (*Runner, error) {
}
runner.resumeCfg = resumeCfg
if options.DASTReport || options.DASTServer {
var err error
runner.fuzzStats, err = fuzzStats.NewTracker()
if err != nil {
return nil, errors.Wrap(err, "could not create fuzz stats db")
}
if !options.DASTServer {
dastServer, err := server.NewStatsServer(runner.fuzzStats)
if err != nil {
return nil, errors.Wrap(err, "could not create dast server")
}
runner.dastServer = dastServer
}
}
if runner.fuzzStats != nil {
outputWriter.JSONLogRequestHook = func(request *output.JSONLogRequest) {
if request.Error == "none" || request.Error == "" {
return
}
runner.fuzzStats.RecordErrorEvent(fuzzStats.ErrorEvent{
TemplateID: request.Template,
URL: request.Input,
Error: request.Error,
})
}
}
opts := interactsh.DefaultOptions(runner.output, runner.issuesClient, runner.progress)
opts.Debug = runner.options.Debug
opts.NoColor = runner.options.NoColor
@@ -391,15 +347,8 @@ func (r *Runner) runStandardEnumeration(executerOpts protocols.ExecutorOptions,
// Close releases all the resources and cleans up
func (r *Runner) Close() {
if r.dastServer != nil {
r.dastServer.Close()
}
if r.httpStats != nil {
r.httpStats.DisplayTopStats(r.options.NoColor)
}
// dump hosterrors cache
if r.hostErrors != nil {
r.hostErrors.Close()
if proxyServer != nil {
proxyServer.Close()
}
if r.output != nil {
r.output.Close()
@@ -415,7 +364,7 @@ func (r *Runner) Close() {
}
protocolinit.Close()
if r.pprofServer != nil {
r.pprofServer.Stop()
_ = r.pprofServer.Shutdown(context.Background())
}
if r.rateLimiter != nil {
r.rateLimiter.Stop()
@@ -427,9 +376,6 @@ func (r *Runner) Close() {
if r.tmpDir != "" {
_ = os.RemoveAll(r.tmpDir)
}
//this is no-op unless nuclei is built with stats build tag
events.Close()
}
// setupPDCPUpload sets up the PDCP upload writer
@@ -459,14 +405,7 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer {
return writer
}
if r.options.ScanID != "" {
// ignore and use empty scan id if invalid
_ = uploadWriter.SetScanID(r.options.ScanID)
}
if r.options.ScanName != "" {
uploadWriter.SetScanName(r.options.ScanName)
}
if r.options.TeamID != "" {
uploadWriter.SetTeamID(r.options.TeamID)
uploadWriter.SetScanID(r.options.ScanID)
}
return output.NewMultiWriter(writer, uploadWriter)
}
@@ -474,41 +413,6 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer {
// RunEnumeration sets up the input layer for giving input nuclei.
// binary and runs the actual enumeration
func (r *Runner) RunEnumeration() error {
// If the user has asked for DAST server mode, run the live
// DAST fuzzing server.
if r.options.DASTServer {
execurOpts := &server.NucleiExecutorOptions{
Options: r.options,
Output: r.output,
Progress: r.progress,
Catalog: r.catalog,
IssuesClient: r.issuesClient,
RateLimiter: r.rateLimiter,
Interactsh: r.interactsh,
ProjectFile: r.projectFile,
Browser: r.browser,
Colorizer: r.colorizer,
Parser: r.parser,
TemporaryDirectory: r.tmpDir,
FuzzStatsDB: r.fuzzStats,
}
dastServer, err := server.New(&server.Options{
Address: r.options.DASTServerAddress,
Templates: r.options.Templates,
OutputWriter: r.output,
Verbose: r.options.Verbose,
Token: r.options.DASTServerToken,
InScope: r.options.Scope,
OutScope: r.options.OutOfScope,
NucleiExecutorOptions: execurOpts,
})
if err != nil {
return err
}
r.dastServer = dastServer
return dastServer.Start()
}
// If user asked for new templates to be executed, collect the list from the templates' directory.
if r.options.NewTemplates {
if arr := config.DefaultConfig.GetNewAdditions(); len(arr) > 0 {
@@ -527,32 +431,27 @@ func (r *Runner) RunEnumeration() error {
r.options.ExcludedTemplates = append(r.options.ExcludedTemplates, ignoreFile.Files...)
}
fuzzFreqCache := frequency.New(frequency.DefaultMaxTrackCount, r.options.FuzzParamFrequency)
r.fuzzFrequencyCache = fuzzFreqCache
// Create the executor options which will be used throughout the execution
// stage by the nuclei engine modules.
executorOpts := protocols.ExecutorOptions{
Output: r.output,
Options: r.options,
Progress: r.progress,
Catalog: r.catalog,
IssuesClient: r.issuesClient,
RateLimiter: r.rateLimiter,
Interactsh: r.interactsh,
ProjectFile: r.projectFile,
Browser: r.browser,
Colorizer: r.colorizer,
ResumeCfg: r.resumeCfg,
ExcludeMatchers: excludematchers.New(r.options.ExcludeMatchers),
InputHelper: input.NewHelper(),
TemporaryDirectory: r.tmpDir,
Parser: r.parser,
FuzzParamsFrequency: fuzzFreqCache,
GlobalMatchers: globalmatchers.New(),
Output: r.output,
Options: r.options,
Progress: r.progress,
Catalog: r.catalog,
IssuesClient: r.issuesClient,
RateLimiter: r.rateLimiter,
Interactsh: r.interactsh,
ProjectFile: r.projectFile,
Browser: r.browser,
Colorizer: r.colorizer,
ResumeCfg: r.resumeCfg,
ExcludeMatchers: excludematchers.New(r.options.ExcludeMatchers),
InputHelper: input.NewHelper(),
TemporaryDirectory: r.tmpDir,
Parser: r.parser,
}
if config.DefaultConfig.IsDebugArgEnabled(config.DebugExportURLPattern) {
if env.GetEnvOrDefault("NUCLEI_ARGS", "") == "req_url_pattern=true" {
// Go StdLib style experimental/debug feature switch
executorOpts.ExportReqURLPattern = true
}
@@ -576,17 +475,8 @@ func (r *Runner) RunEnumeration() error {
}
if r.options.ShouldUseHostError() {
maxHostError := r.options.MaxHostError
if r.options.TemplateThreads > maxHostError {
gologger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", r.colorizer.BrightYellow("WRN"))
gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", r.options.TemplateThreads)
maxHostError = r.options.TemplateThreads
}
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, r.options.TrackError)
cache := hosterrorscache.New(r.options.MaxHostError, hosterrorscache.DefaultMaxHostsCount, r.options.TrackError)
cache.SetVerbose(r.options.Verbose)
r.hostErrors = cache
executorOpts.HostErrorsCache = cache
}
@@ -611,23 +501,6 @@ func (r *Runner) RunEnumeration() error {
return errors.Wrap(err, "Could not create loader.")
}
// list all templates or tags as specified by user.
// This uses a separate parser to reduce time taken as
// normally nuclei does a lot of compilation and stuff
// for templates, which we don't want for these simp
if r.options.TemplateList || r.options.TemplateDisplay || r.options.TagList {
if err := store.LoadTemplatesOnlyMetadata(); err != nil {
return err
}
if r.options.TagList {
r.listAvailableStoreTags(store)
} else {
r.listAvailableStoreTemplates(store)
}
os.Exit(0)
}
if r.options.Validate {
if err := store.ValidateTemplates(); err != nil {
return err
@@ -640,6 +513,14 @@ func (r *Runner) RunEnumeration() error {
return nil // exit
}
store.Load()
if len(store.Templates()) > 1 && r.options.AutogenerateTests {
return errors.New("autogenerate-tests flag can only be used with a single template")
}
if r.inputProvider.Count() > 1 && r.options.AutogenerateTests {
return errors.New("autogenerate-tests flag can only be used with a single input")
}
// TODO: remove below functions after v3 or update warning messages
disk.PrintDeprecatedPathsMsgIfApplicable(r.options.Silent)
templates.PrintDeprecatedProtocolNameMsgIfApplicable(r.options.Silent, r.options.Verbose)
@@ -658,9 +539,26 @@ func (r *Runner) RunEnumeration() error {
_ = r.inputProvider.SetWithExclusions(host)
}
}
// list all templates
if r.options.TemplateList || r.options.TemplateDisplay {
r.listAvailableStoreTemplates(store)
os.Exit(0)
}
// display execution info like version , templates used etc
r.displayExecutionInfo(store)
// If prompted, we need to run the tests for all the loaded
// templates by first trying to detect test definitions and then
// executing them with the relevant inputs.
if r.options.RunNucleiTests {
gologger.Info().Msgf("Running nuclei-templates mock-generated tests")
if err := r.runNucleiTests(store, executorEngine); err != nil {
return errors.Wrap(err, "could not run nuclei tests")
}
return nil
}
// prefetch secrets if enabled
if executorOpts.AuthProvider != nil && r.options.PreFetchSecrets {
gologger.Info().Msgf("Pre-fetching secrets from authprovider[s]")
@@ -694,15 +592,6 @@ func (r *Runner) RunEnumeration() error {
Retries: r.options.Retries,
}, "")
if r.dastServer != nil {
go func() {
if err := r.dastServer.Start(); err != nil {
gologger.Error().Msgf("could not start dast server: %v", err)
}
}()
}
now := time.Now()
enumeration := false
var results *atomic.Bool
results, err = r.runStandardEnumeration(executorOpts, store, executorEngine)
@@ -712,31 +601,28 @@ func (r *Runner) RunEnumeration() error {
return err
}
if executorOpts.FuzzStatsDB != nil {
executorOpts.FuzzStatsDB.Close()
}
var isInteractMatcher bool
if r.interactsh != nil {
matched := r.interactsh.Close()
if matched {
results.CompareAndSwap(false, true)
isInteractMatcher = true
}
}
if r.options.AutogenerateTests && proxyServer != nil {
if err := r.handleTestAutogenerate(results, isInteractMatcher, store); err != nil {
return err
}
}
if executorOpts.InputHelper != nil {
_ = executorOpts.InputHelper.Close()
}
r.fuzzFrequencyCache.Close()
r.progress.Stop()
timeTaken := time.Since(now)
// todo: error propagation without canonical straight error check is required by cloud?
// use safe dereferencing to avoid potential panics in case of previous unchecked errors
if v := ptrutil.Safe(results); !v.Load() {
gologger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken))
} else {
matchCount := r.output.ResultCount()
gologger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount)
gologger.Info().Msgf("No results found. Better luck next time!")
}
// check if a passive scan was requested but no target was provided
if r.options.OfflineHTTP && len(r.options.Targets) == 0 && r.options.TargetsFilePath == "" {
return errors.Wrap(err, "missing required input (http response) to run passive templates")
@@ -745,22 +631,106 @@ func (r *Runner) RunEnumeration() error {
return err
}
func shortDur(d time.Duration) string {
if d < time.Minute {
return d.String()
func (r *Runner) runNucleiTests(store *loader.Store, engine *core.Engine) error {
// For each loaded template, check to see if there's
// a corresponding test file for that template with extension
// .nuclei_test
testFiles := make(map[string]string)
templatePathToTemplates := make(map[string]*templates.Template)
for _, template := range store.Templates() {
testFile := fmt.Sprintf("%s.nuclei_test", template.Path)
if !fileutil.FileExists(testFile) {
continue
}
testFiles[template.Path] = testFile
templatePathToTemplates[template.Path] = template
gologger.Verbose().Msgf("Found test file for template %s: %s", template.ID, filepath.Base(testFile))
}
// Truncate to the nearest minute
d = d.Truncate(time.Minute)
s := d.String()
if len(testFiles) == 0 {
gologger.Info().Msgf("No test files found for nuclei-templates")
return nil
}
if strings.HasSuffix(s, "m0s") {
s = s[:len(s)-2]
gologger.Info().Msgf("Loaded %d test files for nuclei-templates", len(testFiles))
for templatePath, testFile := range testFiles {
testTemplate, err := testing.ReadNucleiTestTemplate(testFile)
if err != nil {
return errors.Wrap(err, "could not read nuclei test template")
}
mockHandler, err := testTemplate.MockServer()
if err != nil {
return errors.Wrap(err, "could not create mock handler for template")
}
testServer := httptest.NewServer(mockHandler)
template, ok := templatePathToTemplates[templatePath]
if !ok {
testServer.Close()
return errors.Errorf("no template found for path %s", templatePath)
}
// If we have interactsh matcher, we need to handle it separately
// by creating a new interactsh client and closing it after the test
// waiting for callbacks.
// TODO: Parallelize
if testTemplate.IsInteractshMatcher {
interactClient, err := interactsh.New(interactsh.DefaultOptions(r.output, r.issuesClient, r.progress))
if err != nil {
testServer.Close()
return errors.Wrap(err, "could not create interactsh client")
}
template.Options.Interactsh = interactClient
}
results := engine.ExecuteScanWithOpts([]*templates.Template{template}, provider.NewSimpleInputProviderWithUrls(testServer.URL), r.options.DisableClustering)
if !results.Load() && !testTemplate.IsInteractshMatcher {
testServer.Close()
return errors.Errorf("no results found for template %s", template.ID)
}
if testTemplate.IsInteractshMatcher {
matched := template.Options.Interactsh.Close()
if !matched {
testServer.Close()
return errors.Errorf("no results found for template %s", template.ID)
}
}
}
if strings.HasSuffix(s, "h0m") {
s = s[:len(s)-2]
gologger.Info().Msgf("All tests passed successfully")
return nil
}
func (r *Runner) handleTestAutogenerate(results *atomic.Bool, isInteractMatcher bool, store *loader.Store) error {
if !results.Load() {
return errors.New("no results found to autogenerate tests")
}
return s
intercepted := proxyServer.Intercepted()
if len(intercepted) == 0 {
return errors.New("no intercepted requests")
}
gologger.Verbose().Msgf("Intercepted requests and responses (%d)", len(intercepted))
for _, pair := range intercepted {
if r.options.Debug {
fmt.Printf("Pair: %+v\n", pair)
}
}
var gotInput string
r.inputProvider.Iterate(func(value *contextargs.MetaInput) bool {
gotInput = value.Input
return false
})
err := testing.GenerateTestsFromPair(intercepted, store.Templates()[0], gotInput, isInteractMatcher)
if err != nil {
return errors.Wrap(err, "could not generate tests from intercepted requests")
}
return nil
}
func (r *Runner) isInputNonHTTP() bool {
@@ -818,7 +788,7 @@ func (r *Runner) executeTemplatesInput(store *loader.Store, engine *core.Engine)
if r.inputProvider == nil {
return nil, errors.New("no input provider found")
}
results := engine.ExecuteScanWithOpts(context.Background(), finalTemplates, r.inputProvider, r.options.DisableClustering)
results := engine.ExecuteScanWithOpts(finalTemplates, r.inputProvider, r.options.DisableClustering)
return results, nil
}
@@ -836,8 +806,6 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
stats.ForceDisplayWarning(templates.ExcludedCodeTmplStats)
stats.ForceDisplayWarning(templates.ExludedDastTmplStats)
stats.ForceDisplayWarning(templates.TemplatesExcludedStats)
stats.ForceDisplayWarning(templates.ExcludedFileStats)
stats.ForceDisplayWarning(templates.ExcludedSelfContainedStats)
}
if tmplCount == 0 && workflowCount == 0 {
@@ -849,22 +817,14 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
} else {
stats.DisplayAsWarning(templates.SkippedCodeTmplTamperedStats)
}
stats.DisplayAsWarning(httpProtocol.SetThreadToCountZero)
stats.ForceDisplayWarning(templates.SkippedUnsignedStats)
stats.ForceDisplayWarning(templates.SkippedRequestSignatureStats)
cfg := config.DefaultConfig
updateutils.Aurora = r.colorizer
versionInfo := func(version, latestVersion, versionType string) string {
if !cfg.CanCheckForUpdates() {
return fmt.Sprintf("Current %s version: %v (%s) - remove '-duc' flag to enable update checks", versionType, version, r.colorizer.BrightYellow("unknown"))
}
return fmt.Sprintf("Current %s version: %v %v", versionType, version, updateutils.GetVersionDescription(version, latestVersion))
}
gologger.Info().Msgf(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei"))
gologger.Info().Msgf(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates"))
gologger.Info().Msgf("Current nuclei version: %v %v", config.Version, updateutils.GetVersionDescription(config.Version, cfg.LatestNucleiVersion))
gologger.Info().Msgf("Current nuclei-templates version: %v %v", cfg.TemplateVersion, updateutils.GetVersionDescription(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion))
if !HideAutoSaveMsg {
if r.pdcpUploadErrMsg != "" {
gologger.Print().Msgf("%s", r.pdcpUploadErrMsg)
@@ -913,52 +873,6 @@ func (r *Runner) SaveResumeConfig(path string) error {
return os.WriteFile(path, data, permissionutil.ConfigFilePermission)
}
// upload existing scan results to cloud with progress
func UploadResultsToCloud(options *types.Options) error {
h := &pdcpauth.PDCPCredHandler{}
creds, err := h.GetCreds()
if err != nil {
return errors.Wrap(err, "could not get credentials for cloud upload")
}
ctx := context.TODO()
uploadWriter, err := pdcp.NewUploadWriter(ctx, creds)
if err != nil {
return errors.Wrap(err, "could not create upload writer")
}
if options.ScanID != "" {
_ = uploadWriter.SetScanID(options.ScanID)
}
if options.ScanName != "" {
uploadWriter.SetScanName(options.ScanName)
}
if options.TeamID != "" {
uploadWriter.SetTeamID(options.TeamID)
}
// Open file to count the number of results first
file, err := os.Open(options.ScanUploadFile)
if err != nil {
return errors.Wrap(err, "could not open scan upload file")
}
defer file.Close()
gologger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile)
dec := json.NewDecoder(file)
for dec.More() {
var r output.ResultEvent
err := dec.Decode(&r)
if err != nil {
gologger.Warning().Msgf("Could not decode jsonl: %s\n", err)
continue
}
if err = uploadWriter.Write(&r); err != nil {
gologger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err)
}
}
uploadWriter.Close()
return nil
}
type WalkFunc func(reflect.Value, reflect.StructField)
// Walk traverses a struct and executes a callback function on each value in the struct.
-36
View File
@@ -3,11 +3,9 @@ package runner
import (
"bytes"
"path/filepath"
"sort"
"strings"
"github.com/alecthomas/chroma/quick"
jsoniter "github.com/json-iterator/go"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
@@ -73,40 +71,6 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) {
}
}
func (r *Runner) listAvailableStoreTags(store *loader.Store) {
gologger.Print().Msgf(
"\nListing available %v nuclei tags for %v",
config.DefaultConfig.TemplateVersion,
config.DefaultConfig.TemplatesDirectory,
)
tagsMap := make(map[string]int)
for _, tpl := range store.Templates() {
for _, tag := range tpl.Info.Tags.ToSlice() {
tagsMap[tag]++
}
}
type kv struct {
Key string `json:"tag"`
Value int `json:"count"`
}
var tagsList []kv
for k, v := range tagsMap {
tagsList = append(tagsList, kv{k, v})
}
sort.Slice(tagsList, func(i, j int) bool {
return tagsList[i].Value > tagsList[j].Value
})
for _, tag := range tagsList {
if r.options.JSONL {
marshalled, _ := jsoniter.Marshal(tag)
gologger.Silent().Msgf("%s\n", string(marshalled))
} else {
gologger.Silent().Msgf("%s (%d)\n", tag.Key, tag.Value)
}
}
}
func (r *Runner) highlightTemplate(body *[]byte) ([]byte, error) {
var buf bytes.Buffer
// YAML lexer, true color terminal formatter and monokai style
-122
View File
@@ -1,122 +0,0 @@
package server
import (
"crypto/sha256"
"encoding/hex"
"net/url"
"sort"
"strings"
"sync"
"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
mapsutil "github.com/projectdiscovery/utils/maps"
)
var dynamicHeaders = map[string]bool{
"date": true,
"if-modified-since": true,
"if-unmodified-since": true,
"cache-control": true,
"if-none-match": true,
"if-match": true,
"authorization": true,
"cookie": true,
"x-csrf-token": true,
"content-length": true,
"content-md5": true,
"host": true,
"x-request-id": true,
"x-correlation-id": true,
"user-agent": true,
"referer": true,
}
type requestDeduplicator struct {
hashes map[string]struct{}
lock *sync.RWMutex
}
func newRequestDeduplicator() *requestDeduplicator {
return &requestDeduplicator{
hashes: make(map[string]struct{}),
lock: &sync.RWMutex{},
}
}
func (r *requestDeduplicator) isDuplicate(req *types.RequestResponse) bool {
hash, err := hashRequest(req)
if err != nil {
return false
}
r.lock.RLock()
_, ok := r.hashes[hash]
r.lock.RUnlock()
if ok {
return true
}
r.lock.Lock()
r.hashes[hash] = struct{}{}
r.lock.Unlock()
return false
}
func hashRequest(req *types.RequestResponse) (string, error) {
normalizedURL, err := normalizeURL(req.URL.URL)
if err != nil {
return "", err
}
var hashContent strings.Builder
hashContent.WriteString(req.Request.Method)
hashContent.WriteString(normalizedURL)
headers := sortedNonDynamicHeaders(req.Request.Headers)
for _, header := range headers {
hashContent.WriteString(header.Key)
hashContent.WriteString(header.Value)
}
if len(req.Request.Body) > 0 {
hashContent.Write([]byte(req.Request.Body))
}
// Calculate the SHA256 hash
hash := sha256.Sum256([]byte(hashContent.String()))
return hex.EncodeToString(hash[:]), nil
}
func normalizeURL(u *url.URL) (string, error) {
query := u.Query()
sortedQuery := make(url.Values)
for k, v := range query {
sort.Strings(v)
sortedQuery[k] = v
}
u.RawQuery = sortedQuery.Encode()
if u.Path == "" {
u.Path = "/"
}
return u.String(), nil
}
type header struct {
Key string
Value string
}
func sortedNonDynamicHeaders(headers mapsutil.OrderedMap[string, string]) []header {
var result []header
headers.Iterate(func(k, v string) bool {
if !dynamicHeaders[strings.ToLower(k)] {
result = append(result, header{Key: k, Value: v})
}
return true
})
sort.Slice(result, func(i, j int) bool {
return result[i].Key < result[j].Key
})
return result
}
-199
View File
@@ -1,199 +0,0 @@
package server
import (
"context"
"fmt"
_ "net/http/pprof"
"strings"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/frequency"
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/stats"
"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider/http"
"github.com/projectdiscovery/nuclei/v3/pkg/projectfile"
"gopkg.in/yaml.v3"
"github.com/pkg/errors"
"github.com/projectdiscovery/ratelimit"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
"github.com/projectdiscovery/nuclei/v3/pkg/core"
"github.com/projectdiscovery/nuclei/v3/pkg/input"
"github.com/projectdiscovery/nuclei/v3/pkg/loader/parser"
parsers "github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/progress"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"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"
browserEngine "github.com/projectdiscovery/nuclei/v3/pkg/protocols/headless/engine"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
)
type nucleiExecutor struct {
engine *core.Engine
store *loader.Store
options *NucleiExecutorOptions
executorOpts protocols.ExecutorOptions
}
type NucleiExecutorOptions struct {
Options *types.Options
Output output.Writer
Progress progress.Progress
Catalog catalog.Catalog
IssuesClient reporting.Client
RateLimiter *ratelimit.Limiter
Interactsh *interactsh.Client
ProjectFile *projectfile.ProjectFile
Browser *browserEngine.Browser
FuzzStatsDB *stats.Tracker
Colorizer aurora.Aurora
Parser parser.Parser
TemporaryDirectory string
}
func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) {
fuzzFreqCache := frequency.New(frequency.DefaultMaxTrackCount, opts.Options.FuzzParamFrequency)
resumeCfg := types.NewResumeCfg()
// Create the executor options which will be used throughout the execution
// stage by the nuclei engine modules.
executorOpts := protocols.ExecutorOptions{
Output: opts.Output,
Options: opts.Options,
Progress: opts.Progress,
Catalog: opts.Catalog,
IssuesClient: opts.IssuesClient,
RateLimiter: opts.RateLimiter,
Interactsh: opts.Interactsh,
ProjectFile: opts.ProjectFile,
Browser: opts.Browser,
Colorizer: opts.Colorizer,
ResumeCfg: resumeCfg,
ExcludeMatchers: excludematchers.New(opts.Options.ExcludeMatchers),
InputHelper: input.NewHelper(),
TemporaryDirectory: opts.TemporaryDirectory,
Parser: opts.Parser,
FuzzParamsFrequency: fuzzFreqCache,
GlobalMatchers: globalmatchers.New(),
FuzzStatsDB: opts.FuzzStatsDB,
}
if opts.Options.ShouldUseHostError() {
maxHostError := opts.Options.MaxHostError
if maxHostError == 30 {
maxHostError = 100 // auto adjust for fuzzings
}
if opts.Options.TemplateThreads > maxHostError {
gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads)
maxHostError = opts.Options.TemplateThreads
}
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, opts.Options.TrackError)
cache.SetVerbose(opts.Options.Verbose)
executorOpts.HostErrorsCache = cache
}
executorEngine := core.New(opts.Options)
executorEngine.SetExecuterOptions(executorOpts)
workflowLoader, err := parsers.NewLoader(&executorOpts)
if err != nil {
return nil, errors.Wrap(err, "Could not create loader options.")
}
executorOpts.WorkflowLoader = workflowLoader
// If using input-file flags, only load http fuzzing based templates.
loaderConfig := loader.NewConfig(opts.Options, opts.Catalog, executorOpts)
if !strings.EqualFold(opts.Options.InputFileMode, "list") || opts.Options.DAST || opts.Options.DASTServer {
// if input type is not list (implicitly enable fuzzing)
opts.Options.DAST = true
}
store, err := loader.New(loaderConfig)
if err != nil {
return nil, errors.Wrap(err, "Could not create loader options.")
}
store.Load()
return &nucleiExecutor{
engine: executorEngine,
store: store,
options: opts,
executorOpts: executorOpts,
}, nil
}
// proxifyRequest is a request for proxify
type proxifyRequest struct {
URL string `json:"url"`
Request struct {
Header map[string]string `json:"header"`
Body string `json:"body"`
Raw string `json:"raw"`
} `json:"request"`
}
func (n *nucleiExecutor) ExecuteScan(target PostRequestsHandlerRequest) error {
finalTemplates := []*templates.Template{}
finalTemplates = append(finalTemplates, n.store.Templates()...)
finalTemplates = append(finalTemplates, n.store.Workflows()...)
if len(finalTemplates) == 0 {
return errors.New("no templates provided for scan")
}
payload := proxifyRequest{
URL: target.URL,
Request: struct {
Header map[string]string `json:"header"`
Body string `json:"body"`
Raw string `json:"raw"`
}{
Raw: target.RawHTTP,
},
}
marshalledYaml, err := yaml.Marshal(payload)
if err != nil {
return fmt.Errorf("error marshalling yaml: %s", err)
}
inputProvider, err := http.NewHttpInputProvider(&http.HttpMultiFormatOptions{
InputContents: string(marshalledYaml),
InputMode: "yaml",
Options: formats.InputFormatOptions{
Variables: make(map[string]interface{}),
},
})
if err != nil {
return errors.Wrap(err, "could not create input provider")
}
// We don't care about the result as its a boolean
// stating whether we got matches or not
_ = n.engine.ExecuteScanWithOpts(context.Background(), finalTemplates, inputProvider, true)
return nil
}
func (n *nucleiExecutor) Close() {
if n.executorOpts.FuzzStatsDB != nil {
n.executorOpts.FuzzStatsDB.Close()
}
if n.options.Interactsh != nil {
_ = n.options.Interactsh.Close()
}
if n.executorOpts.InputHelper != nil {
_ = n.executorOpts.InputHelper.Close()
}
}
-58
View File
@@ -1,58 +0,0 @@
package server
import (
"path"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/internal/server/scope"
"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
)
func (s *DASTServer) consumeTaskRequest(req PostRequestsHandlerRequest) {
defer s.endpointsInQueue.Add(-1)
parsedReq, err := types.ParseRawRequestWithURL(req.RawHTTP, req.URL)
if err != nil {
gologger.Warning().Msgf("Could not parse raw request: %s\n", err)
return
}
if parsedReq.URL.Scheme != "http" && parsedReq.URL.Scheme != "https" {
gologger.Warning().Msgf("Invalid scheme: %s\n", parsedReq.URL.Scheme)
return
}
// Check filenames and don't allow non-interesting files
extension := path.Base(parsedReq.URL.Path)
if extension != "/" && extension != "" && scope.IsUninterestingPath(extension) {
gologger.Warning().Msgf("Uninteresting path: %s\n", parsedReq.URL.Path)
return
}
inScope, err := s.scopeManager.Validate(parsedReq.URL.URL)
if err != nil {
gologger.Warning().Msgf("Could not validate scope: %s\n", err)
return
}
if !inScope {
gologger.Warning().Msgf("Request is out of scope: %s %s\n", parsedReq.Request.Method, parsedReq.URL.String())
return
}
if s.deduplicator.isDuplicate(parsedReq) {
gologger.Warning().Msgf("Duplicate request detected: %s %s\n", parsedReq.Request.Method, parsedReq.URL.String())
return
}
gologger.Verbose().Msgf("Fuzzing request: %s %s\n", parsedReq.Request.Method, parsedReq.URL.String())
s.endpointsBeingTested.Add(1)
defer s.endpointsBeingTested.Add(-1)
// Fuzz the request finally
err = s.nucleiExecutor.ExecuteScan(req)
if err != nil {
gologger.Warning().Msgf("Could not run nuclei: %s\n", err)
return
}
}
Loaded 100 of 401 files, more files were not shown because too many files have changed in this diff. Show more