mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-08 02:08:33 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3be6ccf28a | ||
|
|
55a4be4b6d |
No files matched your search
+21
-20
@@ -1,5 +1,12 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# Maintain dependencies for go modules
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -8,29 +15,23 @@ updates:
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "Type: Maintenance"
|
||||
allow:
|
||||
- dependency-name: "github.com/projectdiscovery/*"
|
||||
groups:
|
||||
modules:
|
||||
patterns: ["github.com/projectdiscovery/*"]
|
||||
labels:
|
||||
- "Type: Maintenance"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
target-branch: "dev"
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
include: "scope"
|
||||
groups:
|
||||
workflows:
|
||||
patterns: ["*"]
|
||||
exclude-patterns: ["projectdiscovery/actions/*"]
|
||||
labels:
|
||||
- "Type: Maintenance"
|
||||
|
||||
# # Maintain dependencies for GitHub Actions
|
||||
# - package-ecosystem: "github-actions"
|
||||
# directory: "/"
|
||||
# schedule:
|
||||
# interval: "weekly"
|
||||
# target-branch: "dev"
|
||||
# commit-message:
|
||||
# prefix: "chore"
|
||||
# include: "scope"
|
||||
# labels:
|
||||
# - "Type: Maintenance"
|
||||
#
|
||||
# # Maintain dependencies for docker
|
||||
# - package-ecosystem: "docker"
|
||||
# directory: "/"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
name: 🔨 Build Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test Builds
|
||||
strategy:
|
||||
matrix:
|
||||
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
|
||||
|
||||
# required for running python code in py-snippet.yaml integration test
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Verify Go modules
|
||||
run: make verify
|
||||
|
||||
- name: Build
|
||||
run: go build .
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
run: go test ./...
|
||||
|
||||
- name: Integration Tests
|
||||
timeout-minutes: 50
|
||||
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 }}
|
||||
working-directory: integration_tests/
|
||||
|
||||
- name: Race Condition Tests
|
||||
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
|
||||
run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
- name: Example SDK Simple
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
|
||||
# Temporarily disabled very flaky in github actions
|
||||
# - name: Example SDK Advanced
|
||||
# run: go run .
|
||||
# working-directory: examples/advanced/
|
||||
|
||||
- name: Example SDK with speed control
|
||||
run: go run .
|
||||
working-directory: examples/with_speed_control/
|
||||
@@ -0,0 +1,39 @@
|
||||
name: 🚨 CodeQL Analysis
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -1,19 +0,0 @@
|
||||
name: ♾️ Compatibility Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
branches:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: go mod download && go mod verify && go vet ./...
|
||||
@@ -1,12 +1,10 @@
|
||||
name: 🤖 Auto Merge
|
||||
name: 🤖 dep auto merge
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
workflow_run:
|
||||
workflows: ["♾️ Compatibility Check"]
|
||||
types:
|
||||
- completed
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
@@ -14,11 +12,11 @@ permissions:
|
||||
repository-projects: write
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
automerge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.DEPENDABOT_PAT }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 🐳 Docker Push
|
||||
name: 🌥 Docker Push
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: Git Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get GitHub tag
|
||||
id: meta
|
||||
@@ -20,19 +20,19 @@ jobs:
|
||||
curl --silent "https://api.github.com/repos/projectdiscovery/nuclei/releases/latest" | jq -r .tag_name | xargs -I {} echo TAG={} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
tags: projectdiscovery/nuclei:latest,projectdiscovery/nuclei:${{ steps.meta.outputs.TAG }}
|
||||
|
||||
- name: Update DockerHub Description
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
uses: peter-evans/dockerhub-description@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
name: 🧪 Functional Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
functional:
|
||||
name: Functional Test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: Functional Tests
|
||||
env:
|
||||
GH_ACTION: true
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
run: |
|
||||
chmod +x run.sh
|
||||
bash run.sh ${{ matrix.os }}
|
||||
working-directory: cmd/functional-test
|
||||
@@ -1,27 +0,0 @@
|
||||
name: ⏰ Generate Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish-docs:
|
||||
if: "${{ !endsWith(github.actor, '[bot]') }}"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/setup/git@v1
|
||||
- run: make syntax-docs
|
||||
- run: git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
|
||||
id: status
|
||||
- uses: projectdiscovery/actions/commit@v1
|
||||
if: steps.status.outputs.CHANGES > 0
|
||||
with:
|
||||
files: |
|
||||
SYNTAX-REFERENCE.md
|
||||
nuclei-jsonschema.json
|
||||
message: 'docs: update syntax & JSON schema 🤖'
|
||||
- run: git push origin $GITHUB_REF
|
||||
@@ -0,0 +1,22 @@
|
||||
name: 🙏🏻 Lint Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
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
|
||||
|
||||
- name: Run golangci-lint
|
||||
uses: projectdiscovery/actions/golangci-lint@v1
|
||||
@@ -1,25 +0,0 @@
|
||||
name: 🔨 Performance Test
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Weekly
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
perf-test:
|
||||
strategy:
|
||||
matrix:
|
||||
count: [50, 100, 150]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'projectdiscovery/nuclei'
|
||||
env:
|
||||
LIST_FILE: "/tmp/targets-${{ matrix.count }}.txt"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make verify
|
||||
- name: Generate list
|
||||
run: for i in {1..${{ matrix.count }}}; do echo "https://scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
|
||||
- run: go run -race . -l "${LIST_FILE}"
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
name: 🔨 Performance Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Weekly
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test Performance
|
||||
strategy:
|
||||
matrix:
|
||||
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
|
||||
|
||||
- name: Verify Go modules
|
||||
run: make verify
|
||||
|
||||
# Max GH exection time 6H => timeout after that
|
||||
- name: Running performance with big list
|
||||
run: go run -race . -l ../functional-test/targets-150.txt
|
||||
working-directory: cmd/nuclei/
|
||||
@@ -0,0 +1,47 @@
|
||||
name: ⏰ Publish Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: "Set up Go"
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: "Set up Git"
|
||||
uses: projectdiscovery/actions/setup/git@v1
|
||||
|
||||
- name: Generate YAML Syntax Documentation
|
||||
id: generate-docs
|
||||
run: |
|
||||
if ! which dstdocgen > /dev/null; then
|
||||
echo -e "Command dstdocgen not found! Installing\c"
|
||||
go install github.com/projectdiscovery/yamldoc-go/cmd/docgen/dstdocgen@main
|
||||
fi
|
||||
go generate pkg/templates/templates.go
|
||||
go build -o "cmd/docgen/docgen" cmd/docgen/docgen.go
|
||||
./cmd/docgen/docgen SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit files
|
||||
if: steps.generate-docs.outputs.CHANGES > 0
|
||||
run: |
|
||||
git add SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
git commit -m "Auto Generate Syntax Docs + JSONSchema [$(date)] :robot:" -a
|
||||
|
||||
- name: Push changes
|
||||
if: steps.generate-docs.outputs.CHANGES > 0
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
@@ -1,4 +1,4 @@
|
||||
name: 🎉 Release
|
||||
name: 🎉 Release Binary
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -13,7 +13,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
with:
|
||||
release: true
|
||||
@@ -21,4 +24,4 @@ jobs:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"
|
||||
DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}"
|
||||
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
|
||||
DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
|
||||
@@ -0,0 +1,23 @@
|
||||
name: 🔨 Release Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release-test:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: "Check out code"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: Release snapshot
|
||||
uses: projectdiscovery/actions/goreleaser@v1
|
||||
@@ -0,0 +1,22 @@
|
||||
name: 🛠 Template Validate
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: Template Validation
|
||||
run: |
|
||||
go run . -ut
|
||||
go run . -validate
|
||||
go run . -validate -w workflows
|
||||
working-directory: cmd/nuclei/
|
||||
@@ -1,135 +0,0 @@
|
||||
name: 🔨 Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["dev"]
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '**.mod'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: "Lint"
|
||||
if: "${{ !endsWith(github.actor, '[bot]') }}"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/golangci-lint@v1
|
||||
|
||||
tests:
|
||||
name: "Tests"
|
||||
needs: ["lint"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make vet
|
||||
- run: make build
|
||||
- run: make test
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
- run: go run -race . -l ../functional-test/targets.txt -id tech-detect,tls-version
|
||||
if: ${{ matrix.os != 'windows-latest' }} # known issue: https://github.com/golang/go/issues/46099
|
||||
working-directory: cmd/nuclei/
|
||||
|
||||
sdk:
|
||||
name: "Run example SDK"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- name: "Simple"
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
# - run: go run . # Temporarily disabled very flaky in github actions
|
||||
# working-directory: examples/advanced/
|
||||
- name: "with Speed Control"
|
||||
run: go run .
|
||||
working-directory: examples/with_speed_control/
|
||||
|
||||
integration:
|
||||
name: "Integration tests"
|
||||
needs: ["tests"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- run: bash run.sh "${{ matrix.os }}"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
|
||||
timeout-minutes: 50
|
||||
working-directory: integration_tests/
|
||||
|
||||
functional:
|
||||
name: "Functional tests"
|
||||
needs: ["tests"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: bash run.sh "${{ matrix.os }}"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
working-directory: cmd/functional-test/
|
||||
|
||||
validate:
|
||||
name: "Template validate"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- run: make template-validate
|
||||
|
||||
codeql:
|
||||
name: "CodeQL analysis"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: 'go'
|
||||
- uses: github/codeql-action/autobuild@v3
|
||||
- uses: github/codeql-action/analyze@v3
|
||||
|
||||
release:
|
||||
name: "Release test"
|
||||
needs: ["tests"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
+19
-20
@@ -2,32 +2,31 @@
|
||||
**/*-cache
|
||||
**/*-config
|
||||
**/.cache
|
||||
**/*.DS_Store
|
||||
**/*.exe
|
||||
*.DS_Store
|
||||
*.exe
|
||||
.devcontainer
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
# Binaries
|
||||
/bin/*
|
||||
/bindgen
|
||||
/debug-*
|
||||
/docgen
|
||||
/functional-test
|
||||
/fuzzplayground
|
||||
/integration-test
|
||||
/jsdocgen
|
||||
/main
|
||||
/memogen
|
||||
/nuclei
|
||||
/nuclei-stats*
|
||||
/nuclei_dev
|
||||
/nuclei_main
|
||||
/scan-charts
|
||||
/scrapefunc
|
||||
/scrapefuncs
|
||||
/tsgen
|
||||
**/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
|
||||
|
||||
@@ -381,7 +381,7 @@ func (r *Request) Type() templateTypes.ProtocolType {
|
||||
}
|
||||
```
|
||||
|
||||
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, `GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
|
||||
Almost all of these protocols have boilerplate functions for which default implementations have been provided in the `providers` package. Examples are the implementation of `Match`, `Extract`, `MakeResultEvent`, GetCompiledOperators`, etc. which are almost same throughout Nuclei protocols code. It is enough to copy-paste them unless customization is required.
|
||||
|
||||
`eventcreator` package offers `CreateEventWithAdditionalOptions` function which can be used to create result events after doing request execution.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 ProjectDiscovery, Inc.
|
||||
Copyright (c) 2022 ProjectDiscovery, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -15,9 +15,8 @@ ifneq ($(shell go env GOOS),darwin)
|
||||
endif
|
||||
|
||||
.PHONY: all build build-stats clean devtools-all devtools-bindgen devtools-scrapefuncs
|
||||
.PHONY: devtools-tsgen docs docgen dsl-docs functional fuzzplayground go-build syntax-docs
|
||||
.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test
|
||||
.PHONY: tidy ts verify download vet template-validate
|
||||
.PHONY: 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
|
||||
|
||||
@@ -29,42 +28,42 @@ go-build:
|
||||
$(GOBUILD) $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
|
||||
-o '${GOBUILD_OUTPUT}' $(GOBUILD_PACKAGES)
|
||||
|
||||
build: GOBUILD_OUTPUT = ./bin/nuclei
|
||||
build: GOBUILD_OUTPUT = nuclei
|
||||
build: GOBUILD_PACKAGES = cmd/nuclei/main.go
|
||||
build: go-build
|
||||
|
||||
build-stats: GOBUILD_OUTPUT = ./bin/nuclei-stats
|
||||
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 = ./bin/scan-charts
|
||||
scan-charts: GOBUILD_OUTPUT = scan-charts
|
||||
scan-charts: GOBUILD_PACKAGES = cmd/scan-charts/main.go
|
||||
scan-charts: go-build
|
||||
|
||||
template-signer: GOBUILD_OUTPUT = ./bin/template-signer
|
||||
template-signer: GOBUILD_PACKAGES = cmd/tools/signer/main.go
|
||||
template-signer: go-build
|
||||
|
||||
docgen: GOBUILD_OUTPUT = ./bin/docgen
|
||||
docgen: GOBUILD_PACKAGES = cmd/docgen/docgen.go
|
||||
docgen: bin = dstdocgen
|
||||
docgen:
|
||||
@if ! which $(bin) >/dev/null; then \
|
||||
echo "Command $(bin) not found! Installing..."; \
|
||||
go install -v github.com/projectdiscovery/yamldoc-go/cmd/docgen/$(bin)@latest; \
|
||||
fi
|
||||
# TODO: FIX THIS PANIC
|
||||
$(GOCMD) generate pkg/templates/templates.go
|
||||
$(GOBUILD) -o "${GOBUILD_OUTPUT}" $(GOBUILD_PACKAGES)
|
||||
|
||||
docs: docgen
|
||||
docs: GOBUILD_OUTPUT = cmd/docgen/docgen
|
||||
docs: GOBUILD_PACKAGES = cmd/docgen/docgen.go
|
||||
docs: bin = dstdocgen
|
||||
docs:
|
||||
./bin/docgen docs.md nuclei-jsonschema.json
|
||||
@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 \
|
||||
fi
|
||||
|
||||
syntax-docs: docgen
|
||||
syntax-docs:
|
||||
./bin/docgen SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
# 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
|
||||
|
||||
test: GOFLAGS = -race -v
|
||||
test:
|
||||
@@ -79,36 +78,30 @@ functional:
|
||||
tidy:
|
||||
$(GOMOD) tidy
|
||||
|
||||
download:
|
||||
$(GOMOD) download
|
||||
|
||||
verify: download
|
||||
verify: tidy
|
||||
$(GOMOD) verify
|
||||
|
||||
vet: verify
|
||||
$(GOCMD) vet ./...
|
||||
|
||||
devtools-bindgen: GOBUILD_OUTPUT = ./bin/bindgen
|
||||
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 = ./bin/tsgen
|
||||
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 = ./bin/scrapefuncs
|
||||
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 = ./bin/bindgen
|
||||
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 = ./bin/tsgen
|
||||
jsupdate-tsgen: GOBUILD_OUTPUT = tsgen
|
||||
jsupdate-tsgen: GOBUILD_PACKAGES = pkg/js/devtools/tsgen/cmd/tsgen/main.go
|
||||
jsupdate-tsgen: go-build
|
||||
jsupdate-tsgen:
|
||||
@@ -118,24 +111,18 @@ jsupdate-all: jsupdate-bindgen jsupdate-tsgen
|
||||
|
||||
ts: jsupdate-tsgen
|
||||
|
||||
fuzzplayground: GOBUILD_OUTPUT = ./bin/fuzzplayground
|
||||
fuzzplayground: GOBUILD_OUTPUT = fuzzplayground
|
||||
fuzzplayground: GOBUILD_PACKAGES = cmd/tools/fuzzplayground/main.go
|
||||
fuzzplayground: LDFLAGS = -s -w
|
||||
fuzzplayground: go-build
|
||||
|
||||
memogen: GOBUILD_OUTPUT = ./bin/memogen
|
||||
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 = ./bin/scrapefuncs
|
||||
dsl-docs: GOBUILD_OUTPUT = scrapefuncs
|
||||
dsl-docs: GOBUILD_PACKAGES = pkg/js/devtools/scrapefuncs/main.go
|
||||
dsl-docs:
|
||||
./$(GOBUILD_OUTPUT) -out dsl.md
|
||||
|
||||
template-validate: build
|
||||
template-validate:
|
||||
./bin/nuclei -ut
|
||||
./bin/nuclei -validate
|
||||
./bin/nuclei -validate -w workflows
|
||||
@@ -24,7 +24,7 @@
|
||||
---
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
Nuclei is a modern, high-performance vulnerability scanner that leverages simple YAML-based templates. It empowers you to design custom vulnerability detection scenarios that mimic real-world conditions, leading to zero false positives.
|
||||
@@ -54,6 +54,12 @@ Nuclei is a modern, high-performance vulnerability scanner that leverages simple
|
||||
- [Contributors ❤️](#contributors-️)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
||||
| :exclamation: **Disclaimer** |
|
||||
|---------------------------------|
|
||||
| **This project is in active development**. Expect breaking changes with releases. Review the release changelog before updating. |
|
||||
| This project is primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
|
||||
## Get Started
|
||||
|
||||
@@ -66,11 +72,6 @@ Install Nuclei on your machine. Get started by following the installation guide
|
||||
- Access latest nuclei templates
|
||||
- Discover and store your targets
|
||||
|
||||
| :exclamation: **Disclaimer** |
|
||||
|:--------------------------------|
|
||||
| **This project is in active development**. Expect breaking changes with releases. Review the release changelog before updating. |
|
||||
| This project is primarily built to be used as a standalone CLI tool. **Running nuclei as a service may pose security risks.** It's recommended to use with caution and additional security measures. |
|
||||
|
||||
### **2. Pro and Enterprise Editions**
|
||||
|
||||
For security teams and enterprises, we provide a cloud-hosted service built on top of Nuclei OSS, fine-tuned to help you continuously run vulnerability scans at scale with your team and existing workflows:
|
||||
@@ -84,8 +85,6 @@ For security teams and enterprises, we provide a cloud-hosted service built on t
|
||||
- We're constantly [adding new features](https://feedback.projectdiscovery.io/changelog)!
|
||||
- **Ideal for:** Pentesters, security teams, and enterprises
|
||||
|
||||
[Sign up to Pro](https://projectdiscovery.io/pricing?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme) or [Talk to our team](https://projectdiscovery.io/request-demo?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme) if you have large organization and complex requirements.
|
||||
|
||||
## Documentation
|
||||
|
||||
Browse the full Nuclei [documentation here](https://docs.projectdiscovery.io/tools/nuclei/running). If you’re new to Nuclei, check out our [foundational Youtube series.](https://www.youtube.com/playlist?list=PLZRbR9aMzTTpItEdeNSulo8bYsvil80Rl)
|
||||
@@ -96,16 +95,6 @@ Browse the full Nuclei [documentation here](https://docs.projectdiscovery.io/too
|
||||
|
||||
</p>
|
||||
|
||||
### Installation
|
||||
|
||||
`nuclei` requires **go1.21** to install successfully. Run the following command to get the repo:
|
||||
|
||||
```sh
|
||||
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
|
||||
```
|
||||
|
||||
To learn more about installing nuclei, see https://docs.projectdiscovery.io/tools/nuclei/install.
|
||||
|
||||
### Command Line Flags
|
||||
|
||||
To display all the flags for the tool:
|
||||
@@ -289,23 +278,24 @@ HEADLESS:
|
||||
-lha, -list-headless-action list available headless actions
|
||||
|
||||
DEBUG:
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string optional nuclei memory profile dump file
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
-debug show all requests and responses
|
||||
-dreq, -debug-req show all sent requests
|
||||
-dresp, -debug-resp show all received responses
|
||||
-p, -proxy string[] list of http/socks5 proxy to use (comma separated or file input)
|
||||
-pi, -proxy-internal proxy all internal requests
|
||||
-ldf, -list-dsl-function list all supported DSL function signatures
|
||||
-tlog, -trace-log string file to write sent requests trace log
|
||||
-elog, -error-log string file to write sent requests error log
|
||||
-version show nuclei version
|
||||
-hm, -hang-monitor enable nuclei hang monitoring
|
||||
-v, -verbose show verbose output
|
||||
-profile-mem string generate memory (heap) profile & trace files
|
||||
-vv display templates loaded for scan
|
||||
-svd, -show-var-dump show variables dump for debugging
|
||||
-vdl, -var-dump-limit int limit the number of characters displayed in var dump (default 255)
|
||||
-ep, -enable-pprof enable pprof debugging server
|
||||
-tv, -templates-version shows the version of the installed nuclei-templates
|
||||
-hc, -health-check run diagnostic check up
|
||||
|
||||
UPDATE:
|
||||
-up, -update update nuclei engine to the latest released version
|
||||
@@ -350,7 +340,6 @@ 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
|
||||
|
||||
```
|
||||
|
||||
Additional documentation is available at: [https://docs.nuclei.sh/getting-started/running](https://docs.nuclei.sh/getting-started/running?utm_source=github&utm_medium=web&utm_campaign=nuclei_readme)
|
||||
@@ -378,7 +367,7 @@ nuclei -targets urls.txt
|
||||
This will scan the entire subnet for network-related issues, such as open ports or misconfigured services.
|
||||
|
||||
```sh
|
||||
nuclei -target 192.168.1.0/24
|
||||
nuclei -target 192.168.1.0/24
|
||||
```
|
||||
|
||||
### Scanning with your custom template
|
||||
@@ -471,100 +460,6 @@ Thanks to all the amazing [community contributors for sending PRs](https://githu
|
||||
<a href="https://github.com/geeknik"><img src="https://avatars.githubusercontent.com/u/466878?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/TerminalFi"><img src="https://avatars.githubusercontent.com/u/32599364?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/KaulSe"><img src="https://avatars.githubusercontent.com/u/45340011?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sullo"><img src="https://avatars.githubusercontent.com/u/1474884?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/wdahlenburg"><img src="https://avatars.githubusercontent.com/u/4451504?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ghost"><img src="https://avatars.githubusercontent.com/u/10137?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Nishan8583"><img src="https://avatars.githubusercontent.com/u/20457968?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jdk2588"><img src="https://avatars.githubusercontent.com/u/985054?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/nothinux"><img src="https://avatars.githubusercontent.com/u/17433202?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/CodFrm"><img src="https://avatars.githubusercontent.com/u/22783163?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/CasperGN"><img src="https://avatars.githubusercontent.com/u/5549643?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ankh2054"><img src="https://avatars.githubusercontent.com/u/6784287?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/revblock"><img src="https://avatars.githubusercontent.com/u/72813848?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/cn-kali-team"><img src="https://avatars.githubusercontent.com/u/30642514?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/EndPositive"><img src="https://avatars.githubusercontent.com/u/25148195?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jimen0"><img src="https://avatars.githubusercontent.com/u/6826244?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xstevens"><img src="https://avatars.githubusercontent.com/u/69216?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mjkim610"><img src="https://avatars.githubusercontent.com/u/17107206?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/organiccrap"><img src="https://avatars.githubusercontent.com/u/376317?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lu4nx"><img src="https://avatars.githubusercontent.com/u/3006875?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/souvikhazra1"><img src="https://avatars.githubusercontent.com/u/13842393?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tovask"><img src="https://avatars.githubusercontent.com/u/22732484?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Marmelatze"><img src="https://avatars.githubusercontent.com/u/199681?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/doug-threatmate"><img src="https://avatars.githubusercontent.com/u/127235272?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/yabeow"><img src="https://avatars.githubusercontent.com/u/21117771?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/olearycrew"><img src="https://avatars.githubusercontent.com/u/6044920?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/gano3s"><img src="https://avatars.githubusercontent.com/u/2551605?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/alizmhdi"><img src="https://avatars.githubusercontent.com/u/79321261?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hackerpain"><img src="https://avatars.githubusercontent.com/u/61242234?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lc"><img src="https://avatars.githubusercontent.com/u/19563282?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/savushkin-yauheni"><img src="https://avatars.githubusercontent.com/u/5173352?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/74616e696d"><img src="https://avatars.githubusercontent.com/u/97121933?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/edoardottt"><img src="https://avatars.githubusercontent.com/u/35783570?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/zt2"><img src="https://avatars.githubusercontent.com/u/7644862?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/moonD4rk"><img src="https://avatars.githubusercontent.com/u/24284231?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/wk8"><img src="https://avatars.githubusercontent.com/u/2536231?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mikerott"><img src="https://avatars.githubusercontent.com/u/857712?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/toufik-airane"><img src="https://avatars.githubusercontent.com/u/5610269?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hktalent"><img src="https://avatars.githubusercontent.com/u/18223385?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jturner"><img src="https://avatars.githubusercontent.com/u/1825202?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/gaby"><img src="https://avatars.githubusercontent.com/u/835733?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vavkamil"><img src="https://avatars.githubusercontent.com/u/47953210?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/leonjza"><img src="https://avatars.githubusercontent.com/u/1148127?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mionskowski-form3"><img src="https://avatars.githubusercontent.com/u/91873652?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/chenrui333"><img src="https://avatars.githubusercontent.com/u/1580956?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iamargus95"><img src="https://avatars.githubusercontent.com/u/77744293?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/shashikarsiddharth"><img src="https://avatars.githubusercontent.com/u/60960197?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/trypa11"><img src="https://avatars.githubusercontent.com/u/67585616?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Zeokat"><img src="https://avatars.githubusercontent.com/u/1313154?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/alban-stourbe-wmx"><img src="https://avatars.githubusercontent.com/u/159776828?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/anykno"><img src="https://avatars.githubusercontent.com/u/2528207?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ronaudinho"><img src="https://avatars.githubusercontent.com/u/10264710?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/boy-hack"><img src="https://avatars.githubusercontent.com/u/18695984?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/iuliu8899"><img src="https://avatars.githubusercontent.com/u/31680027?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/debasishbsws"><img src="https://avatars.githubusercontent.com/u/65381620?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/denysvitali-niantic"><img src="https://avatars.githubusercontent.com/u/157139422?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/fail-open"><img src="https://avatars.githubusercontent.com/u/72417455?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Xc1Ym"><img src="https://avatars.githubusercontent.com/u/29765332?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/XTeam-Wing"><img src="https://avatars.githubusercontent.com/u/25416365?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Weltolk"><img src="https://avatars.githubusercontent.com/u/40228052?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/tonghuaroot"><img src="https://avatars.githubusercontent.com/u/23011166?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/praetorian-thendrickson"><img src="https://avatars.githubusercontent.com/u/69640071?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/S0obi"><img src="https://avatars.githubusercontent.com/u/4180104?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/skahn007gl"><img src="https://avatars.githubusercontent.com/u/144735608?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/shouichi"><img src="https://avatars.githubusercontent.com/u/99586?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/seb-elttam"><img src="https://avatars.githubusercontent.com/u/111818823?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/AdallomRoy"><img src="https://avatars.githubusercontent.com/u/4046118?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rotemreiss"><img src="https://avatars.githubusercontent.com/u/9288082?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/oscarintherocks"><img src="https://avatars.githubusercontent.com/u/1785821?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/xxcdd"><img src="https://avatars.githubusercontent.com/u/42600601?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/chen2aaron"><img src="https://avatars.githubusercontent.com/u/9978183?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/voidz0r"><img src="https://avatars.githubusercontent.com/u/1032286?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/vince-isec"><img src="https://avatars.githubusercontent.com/u/149686094?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/true13"><img src="https://avatars.githubusercontent.com/u/18207552?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/skhalsa-sigsci"><img src="https://avatars.githubusercontent.com/u/68570441?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/ShuBo6"><img src="https://avatars.githubusercontent.com/u/41125338?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/seeyarh"><img src="https://avatars.githubusercontent.com/u/16869800?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/securibee"><img src="https://avatars.githubusercontent.com/u/51520913?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/sduc"><img src="https://avatars.githubusercontent.com/u/2879617?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/scottdharvey"><img src="https://avatars.githubusercontent.com/u/25498254?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/rykkard"><img src="https://avatars.githubusercontent.com/u/51889048?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/monitor403"><img src="https://avatars.githubusercontent.com/u/45124775?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/mlec1"><img src="https://avatars.githubusercontent.com/u/42201667?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/meme-lord"><img src="https://avatars.githubusercontent.com/u/17912559?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/LazyMaple"><img src="https://avatars.githubusercontent.com/u/12314941?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/lvyaoting"><img src="https://avatars.githubusercontent.com/u/166296299?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/llussy"><img src="https://avatars.githubusercontent.com/u/18432966?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/linchizhen"><img src="https://avatars.githubusercontent.com/u/170242051?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/kiokuless"><img src="https://avatars.githubusercontent.com/u/110003596?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/Jarnpher553"><img src="https://avatars.githubusercontent.com/u/10233873?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/c-f"><img src="https://avatars.githubusercontent.com/u/35263248?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/hanghuge"><img src="https://avatars.githubusercontent.com/u/166206050?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/testwill"><img src="https://avatars.githubusercontent.com/u/8717479?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/galoget"><img src="https://avatars.githubusercontent.com/u/8353133?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/fudancoder"><img src="https://avatars.githubusercontent.com/u/171416994?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/revolunet"><img src="https://avatars.githubusercontent.com/u/124937?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jsoref"><img src="https://avatars.githubusercontent.com/u/2119212?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/MachadoOtto"><img src="https://avatars.githubusercontent.com/u/93268441?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/jonathanwalker"><img src="https://avatars.githubusercontent.com/u/14978093?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
<a href="https://github.com/nHurD"><img src="https://avatars.githubusercontent.com/u/233374?v=4" width="50" height="50" alt="" style="max-width: 100%;"></a>
|
||||
|
||||
@@ -1373,19 +1373,6 @@ Fuzzing describes schema to fuzz http requests
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>analyzer</code> <i><a href="#analyzersanalyzertemplate">analyzers.AnalyzerTemplate</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Analyzer is an analyzer to use for matching the response.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>self-contained</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
@@ -2038,59 +2025,6 @@ Appears in:
|
||||
|
||||
|
||||
|
||||
## analyzers.AnalyzerTemplate
|
||||
AnalyzerTemplate is the template for the analyzer
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#httprequest">http.Request</a>.analyzer</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>name</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Name is the name of the analyzer to use
|
||||
|
||||
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>time_delay</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>parameters</code> <i>map[string]interface{}</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Parameters is the parameters for the analyzer
|
||||
|
||||
Parameters are different for each analyzer. For example, you can customize
|
||||
time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
|
||||
to the docs for each analyzer to get an idea about parameters.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## SignatureTypeHolder
|
||||
SignatureTypeHolder is used to hold internal type of the signature
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/kitabisa/go-ci"
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -16,8 +15,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
githubAction = os.Getenv("GH_ACTION") == "true"
|
||||
|
||||
mainNucleiBinary = flag.String("main", "", "Main Branch Nuclei Binary")
|
||||
devNucleiBinary = flag.String("dev", "", "Dev Branch Nuclei Binary")
|
||||
@@ -45,7 +45,7 @@ func runFunctionalTests(debug bool) (error, bool) {
|
||||
|
||||
errored, failedTestCases := runTestCases(file, debug)
|
||||
|
||||
if ci.IsCI() {
|
||||
if githubAction {
|
||||
fmt.Println("::group::Failed tests with debug")
|
||||
for _, failedTestCase := range failedTestCases {
|
||||
_ = runTestCase(failedTestCase, true)
|
||||
|
||||
@@ -99,7 +99,7 @@ type codePreCondition struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *codePreCondition) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code", "-esc")
|
||||
results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, getEnvValues(), "-t", filePath, "-u", "input", "-code")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ type fileWithOrMatcher struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithOrMatcher) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -27,7 +27,7 @@ type fileWithAndMatcher struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithAndMatcher) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,7 +39,7 @@ type fileWithExtractor struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *fileWithExtractor) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug, "-file")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "protocols/file/data/", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ var flowTestcases = []TestCaseInfo{
|
||||
type conditionalFlow struct{}
|
||||
|
||||
func (t *conditionalFlow) Execute(filePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "cloud.projectdiscovery.io", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "blog.projectdiscovery.io", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func (h *httpInteractshRequest) Execute(filePath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return expectResultsCount(results, 1, 2)
|
||||
return expectResultsCount(results, 1)
|
||||
}
|
||||
|
||||
type httpDefaultMatcherCondition struct{}
|
||||
@@ -952,7 +952,7 @@ func (h *httpRequestSelfContained) Execute(filePath string) error {
|
||||
}()
|
||||
defer server.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -988,7 +988,7 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error {
|
||||
}()
|
||||
defer server.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1031,7 +1031,7 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error {
|
||||
}
|
||||
defer FileLoc.Close()
|
||||
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name(), "-esc")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/kitabisa/go-ci"
|
||||
"github.com/logrusorgru/aurora"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
@@ -23,9 +22,10 @@ type TestCaseInfo struct {
|
||||
}
|
||||
|
||||
var (
|
||||
debug = os.Getenv("DEBUG") == "true"
|
||||
customTests = os.Getenv("TESTS")
|
||||
protocol = os.Getenv("PROTO")
|
||||
debug = os.Getenv("DEBUG") == "true"
|
||||
githubAction = os.Getenv("GH_ACTION") == "true"
|
||||
customTests = os.Getenv("TESTS")
|
||||
protocol = os.Getenv("PROTO")
|
||||
|
||||
success = aurora.Green("[✓]").String()
|
||||
failed = aurora.Red("[✘]").String()
|
||||
@@ -103,19 +103,11 @@ func main() {
|
||||
failedTestTemplatePaths := runTests(customTestsList)
|
||||
|
||||
if len(failedTestTemplatePaths) > 0 {
|
||||
if ci.IsCI() {
|
||||
// run failed tests again assuming they are flaky
|
||||
// if they fail as well only then we assume that there is an actual issue
|
||||
fmt.Println("::group::Running failed tests again")
|
||||
failedTestTemplatePaths = runTests(failedTestTemplatePaths)
|
||||
if githubAction {
|
||||
debug = true
|
||||
fmt.Println("::group::Failed integration tests in debug mode")
|
||||
_ = runTests(failedTestTemplatePaths)
|
||||
fmt.Println("::endgroup::")
|
||||
|
||||
if len(failedTestTemplatePaths) > 0 {
|
||||
debug = true
|
||||
fmt.Println("::group::Failed integration tests in debug mode")
|
||||
_ = runTests(failedTestTemplatePaths)
|
||||
fmt.Println("::endgroup::")
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
|
||||
@@ -14,7 +14,7 @@ type multiProtoDynamicExtractor struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *multiProtoDynamicExtractor) Execute(templatePath string) error {
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "docs.projectdiscovery.io", debug)
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "blog.projectdiscovery.io", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func (h *networkRequestSelContained) Execute(filePath string) error {
|
||||
_, _ = conn.Write([]byte("Authentication successful"))
|
||||
})
|
||||
defer ts.Close()
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc")
|
||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -263,9 +263,6 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVar(&options.SignTemplates, "sign", false, "signs the templates with the private key defined in NUCLEI_SIGNATURE_PRIVATE_KEY env variable"),
|
||||
flagSet.BoolVar(&options.EnableCodeTemplates, "code", false, "enable loading code protocol-based templates"),
|
||||
flagSet.BoolVarP(&options.DisableUnsignedTemplates, "disable-unsigned-templates", "dut", false, "disable running unsigned templates or templates with mismatched signature"),
|
||||
flagSet.BoolVarP(&options.EnableSelfContainedTemplates, "enable-self-contained", "esc", false, "enable loading self-contained templates"),
|
||||
flagSet.BoolVarP(&options.EnableGlobalMatchersTemplates, "enable-global-matchers", "egm", false, "enable loading global matchers templates"),
|
||||
flagSet.BoolVar(&options.EnableFileTemplates, "file", false, "enable loading file templates"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("filters", "Filtering",
|
||||
@@ -495,11 +492,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
options.DAST = true
|
||||
}
|
||||
|
||||
// All cloud-based templates depend on both code and self-contained templates.
|
||||
if options.EnableCodeTemplates {
|
||||
options.EnableSelfContainedTemplates = true
|
||||
}
|
||||
|
||||
// api key hierarchy: cli flag > env var > .pdcp/credential file
|
||||
if pdcpauth == "true" {
|
||||
runner.AuthWithPDCP()
|
||||
|
||||
@@ -69,7 +69,6 @@ func init() {
|
||||
// need to set headless to true for headless templates
|
||||
defaultOpts.Headless = true
|
||||
defaultOpts.EnableCodeTemplates = true
|
||||
defaultOpts.EnableSelfContainedTemplates = true
|
||||
if err := protocolstate.Init(defaultOpts); err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
fileutil "github.com/projectdiscovery/utils/file"
|
||||
folderutil "github.com/projectdiscovery/utils/folder"
|
||||
)
|
||||
|
||||
var (
|
||||
appConfigDir = folderutil.AppConfigDirOrDefault(".config", "nuclei")
|
||||
defaultCertFile = filepath.Join(appConfigDir, "keys", "nuclei-user.crt")
|
||||
defaultPrivKey = filepath.Join(appConfigDir, "keys", "nuclei-user-private-key.pem")
|
||||
)
|
||||
|
||||
var (
|
||||
template string
|
||||
cert string
|
||||
privKey string
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&template, "template", "", "template to sign (file only)")
|
||||
flag.StringVar(&cert, "cert", defaultCertFile, "certificate file")
|
||||
flag.StringVar(&privKey, "priv-key", defaultPrivKey, "private key file")
|
||||
flag.Parse()
|
||||
|
||||
config.DefaultConfig.LogAllEvents = true
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
|
||||
|
||||
if template == "" {
|
||||
gologger.Fatal().Msg("template is required")
|
||||
}
|
||||
if !fileutil.FileExists(template) {
|
||||
gologger.Fatal().Msgf("template file %s does not exist or not a file", template)
|
||||
}
|
||||
|
||||
// get signer
|
||||
tmplSigner, err := signer.NewTemplateSignerFromFiles(cert, privKey)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to create signer: %s", err)
|
||||
}
|
||||
gologger.Info().Msgf("Template Signer: %v\n", tmplSigner.Identifier())
|
||||
|
||||
// read file
|
||||
bin, err := os.ReadFile(template)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to read template file %s: %s", template, err)
|
||||
}
|
||||
|
||||
// extract signature and content
|
||||
sig, content := signer.ExtractSignatureAndContent(bin)
|
||||
hash := sha256.Sum256(content)
|
||||
|
||||
gologger.Info().Msgf("Signature Details:")
|
||||
gologger.Info().Msgf("----------------")
|
||||
gologger.Info().Msgf("Signature: %s", sig)
|
||||
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash[:]))
|
||||
|
||||
execOpts := defaultExecutorOpts(template)
|
||||
|
||||
tmpl, err := templates.Parse(template, nil, execOpts)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to parse template: %s", err)
|
||||
}
|
||||
gologger.Info().Msgf("Template Verified: %v\n", tmpl.Verified)
|
||||
|
||||
if !tmpl.Verified {
|
||||
gologger.Info().Msgf("------------------------")
|
||||
gologger.Info().Msg("Template is not verified, signing template")
|
||||
if err := templates.SignTemplate(tmplSigner, template); err != nil {
|
||||
gologger.Fatal().Msgf("Failed to sign template: %s", err)
|
||||
}
|
||||
// verify again by reading file what the new signature and hash is
|
||||
bin2, err := os.ReadFile(template)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("failed to read signed template file %s: %s", template, err)
|
||||
}
|
||||
sig2, content2 := signer.ExtractSignatureAndContent(bin2)
|
||||
hash2 := sha256.Sum256(content2)
|
||||
|
||||
gologger.Info().Msgf("Updated Signature Details:")
|
||||
gologger.Info().Msgf("------------------------")
|
||||
gologger.Info().Msgf("Signature: %s", sig2)
|
||||
gologger.Info().Msgf("Content Hash (SHA256): %s\n", hex.EncodeToString(hash2[:]))
|
||||
}
|
||||
gologger.Info().Msgf("✓ Template signed & verified successfully")
|
||||
}
|
||||
|
||||
func defaultExecutorOpts(templatePath string) protocols.ExecutorOptions {
|
||||
// use parsed options when initializing signer instead of default options
|
||||
options := types.DefaultOptions()
|
||||
templates.UseOptionsForSigner(options)
|
||||
catalog := disk.NewCatalog(filepath.Dir(templatePath))
|
||||
executerOpts := protocols.ExecutorOptions{
|
||||
Catalog: catalog,
|
||||
Options: options,
|
||||
TemplatePath: templatePath,
|
||||
Parser: templates.NewParser(),
|
||||
}
|
||||
return executerOpts
|
||||
}
|
||||
@@ -20,12 +20,12 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/projectdiscovery/clistats v0.1.1
|
||||
github.com/projectdiscovery/fastdialer v0.2.14
|
||||
github.com/projectdiscovery/hmap v0.0.73
|
||||
github.com/projectdiscovery/interactsh v1.2.2
|
||||
github.com/projectdiscovery/rawhttp v0.1.80
|
||||
github.com/projectdiscovery/retryabledns v1.0.91
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.93
|
||||
github.com/projectdiscovery/fastdialer v0.2.9
|
||||
github.com/projectdiscovery/hmap v0.0.62
|
||||
github.com/projectdiscovery/interactsh v1.2.0
|
||||
github.com/projectdiscovery/rawhttp v0.1.70
|
||||
github.com/projectdiscovery/retryabledns v1.0.80
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@@ -38,9 +38,9 @@ require (
|
||||
github.com/weppos/publicsuffix-go v0.30.2
|
||||
github.com/xanzy/go-gitlab v0.107.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/oauth2 v0.22.0
|
||||
golang.org/x/text v0.21.0
|
||||
golang.org/x/text v0.18.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@@ -81,33 +81,33 @@ require (
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/ory/dockertest/v3 v3.10.0
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9
|
||||
github.com/projectdiscovery/dsl v0.3.9
|
||||
github.com/projectdiscovery/dsl v0.3.0
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
||||
github.com/projectdiscovery/goflags v0.1.65
|
||||
github.com/projectdiscovery/gologger v1.1.38
|
||||
github.com/projectdiscovery/goflags v0.1.64
|
||||
github.com/projectdiscovery/gologger v1.1.28
|
||||
github.com/projectdiscovery/gostruct v0.0.2
|
||||
github.com/projectdiscovery/gozero v0.0.3
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32
|
||||
github.com/projectdiscovery/httpx v1.6.9
|
||||
github.com/projectdiscovery/mapcidr v1.1.34
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/ratelimit v0.0.67
|
||||
github.com/projectdiscovery/ratelimit v0.0.60
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.8
|
||||
github.com/projectdiscovery/tlsx v1.1.7
|
||||
github.com/projectdiscovery/uncover v1.0.9
|
||||
github.com/projectdiscovery/useragent v0.0.85
|
||||
github.com/projectdiscovery/utils v0.4.4
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.9
|
||||
github.com/projectdiscovery/useragent v0.0.71
|
||||
github.com/projectdiscovery/utils v0.2.15
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22
|
||||
github.com/redis/go-redis/v9 v9.1.0
|
||||
github.com/seh-msft/burpxml v1.0.1
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9
|
||||
github.com/yassinebenaid/godump v0.10.0
|
||||
github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706
|
||||
go.mongodb.org/mongo-driver v1.17.0
|
||||
golang.org/x/term v0.27.0
|
||||
golang.org/x/term v0.24.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
moul.io/http2curl v1.0.0
|
||||
)
|
||||
@@ -152,7 +152,6 @@ require (
|
||||
github.com/docker/docker v24.0.9+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.5 // indirect
|
||||
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gaissmai/bart v0.9.5 // indirect
|
||||
@@ -247,7 +246,7 @@ require (
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/goleak v1.3.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
|
||||
mellium.im/sasl v0.3.1 // indirect
|
||||
)
|
||||
@@ -273,11 +272,11 @@ require (
|
||||
github.com/goburrow/cache v0.1.4 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
@@ -314,10 +313,10 @@ require (
|
||||
go.etcd.io/bbolt v1.3.10 // indirect
|
||||
go.uber.org/zap v1.25.0 // indirect
|
||||
goftp.io/server/v2 v2.0.1 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
|
||||
@@ -237,18 +237,12 @@ github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
@@ -331,8 +325,6 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
@@ -435,8 +427,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
@@ -585,7 +577,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
@@ -680,7 +671,6 @@ github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa h1:KQKuQDgA3DZX6C396lt3WDYB9Um1gLITLbvficVbqXk=
|
||||
@@ -814,7 +804,6 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
|
||||
github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
@@ -856,30 +845,32 @@ github.com/projectdiscovery/cdncheck v1.1.0 h1:qDITidmJsejzpk3rMkauCh6sjI2GH9hW/
|
||||
github.com/projectdiscovery/cdncheck v1.1.0/go.mod h1:sZ8U4MjHSsyaTVjBbYWHT1cwUVvUYwDX1W+WvWRicIc=
|
||||
github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE=
|
||||
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
|
||||
github.com/projectdiscovery/dsl v0.3.9 h1:MYBOL0curYXJZmhO+FqHtQAwxdrMjU1PIvHTCzt9dQk=
|
||||
github.com/projectdiscovery/dsl v0.3.9/go.mod h1:A/xBvXbq4fD/oNK58l5wh4shX5E38dP024jInaqjIMI=
|
||||
github.com/projectdiscovery/fastdialer v0.2.14 h1:/cndy+5celjoYzbk4LksHYOCTpFGIJY8RF/EK31Opjs=
|
||||
github.com/projectdiscovery/fastdialer v0.2.14/go.mod h1:z5yKQ/YWaVrBMfdL6f5J7VytUx9wxc5vs/Lf51QelCw=
|
||||
github.com/projectdiscovery/dsl v0.3.0 h1:NzU6WcJ8GFQ676IVefrxC5nk/bvb7FCuhmp8tbNC9dQ=
|
||||
github.com/projectdiscovery/dsl v0.3.0/go.mod h1:GMVxLtQuQUc/RmSn3jQxGCI4yit3iyf2AoZxUoXbsb0=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9 h1:vDCqxVMCyUu3oVEizEK1K8K+CCcLkVDW3X2HfiWaVFA=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9/go.mod h1:mYv5QaNBDDSHlZO9DI0niRMw+G5hUzwIhs8QixSElUI=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
|
||||
github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk=
|
||||
github.com/projectdiscovery/freeport v0.0.7/go.mod h1:cOhWKvNBe9xM6dFJ3RrrLvJ5vXx2NQ36SecuwjenV2k=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG906Drtbpz4DwU5mhGIeOhRcktDH4cGQitGUMAsg=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY=
|
||||
github.com/projectdiscovery/goflags v0.1.65 h1:rjoj+5lP/FDzgeM0WILUTX9AOOnw0J0LXtl8P1SVeGE=
|
||||
github.com/projectdiscovery/goflags v0.1.65/go.mod h1:cg6+yrLlaekP1hnefBc/UXbH1YGWa0fuzEW9iS1aG4g=
|
||||
github.com/projectdiscovery/gologger v1.1.38 h1:juFhUMiGYD/jJ9bHsYnxdYuXCRVcZ9YBmm4/HyVWxtg=
|
||||
github.com/projectdiscovery/gologger v1.1.38/go.mod h1:5C0KgNniuyhYn94nPrYqVv5Tp+TQCtCQkbsk9vvW/98=
|
||||
github.com/projectdiscovery/goflags v0.1.64 h1:FDfwdt9N97Hi8OuhbkDlKtVttpc/CRMIWQVa08VsHsI=
|
||||
github.com/projectdiscovery/goflags v0.1.64/go.mod h1:3FyHIVQtnycNOc1LE3O1jj/XR5XuMdF9QfHd0ujhnX4=
|
||||
github.com/projectdiscovery/gologger v1.1.28 h1:3OYYnoEaHAYkPm2c2KgUifBDPy93JCQq1hl5ICtpJT8=
|
||||
github.com/projectdiscovery/gologger v1.1.28/go.mod h1:rB7xNi4tcx/HqpQu4QgpFIopIg8SNF/VBc6cTeQLqWQ=
|
||||
github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
|
||||
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
|
||||
github.com/projectdiscovery/gozero v0.0.3 h1:tsYkrSvWw4WdIUJyisd4MB1vRiw1X57TuVVk3p8Z3G8=
|
||||
github.com/projectdiscovery/gozero v0.0.3/go.mod h1:MpJ37Dsh94gy2EKqaemdeh+CzduGVB2SDfhr6Upsjew=
|
||||
github.com/projectdiscovery/hmap v0.0.73 h1:lo7TrYVuNKYVFoXeOyo0pl6kA3IfGXhkFhlrsQ4uIwA=
|
||||
github.com/projectdiscovery/hmap v0.0.73/go.mod h1:rTeJt3xg0gRo5txS4pdgdzh5MNNTRe2hYls3NwB/sXo=
|
||||
github.com/projectdiscovery/gozero v0.0.2 h1:8fJeaCjxL9tpm33uG/RsCQs6HGM/NE6eA3cjkilRQ+E=
|
||||
github.com/projectdiscovery/gozero v0.0.2/go.mod h1:d8bZvDWW07LWNYWrwjZ4OO1I0cpkfqaysyDfSs9ibK8=
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32 h1:PubQkk+F/BiW4+wqBhWiMwPEKYxi/LdYXjxUtHd/tpM=
|
||||
github.com/projectdiscovery/gozero v0.0.3-0.20241023095525-626f55f7bb32/go.mod h1:d8bZvDWW07LWNYWrwjZ4OO1I0cpkfqaysyDfSs9ibK8=
|
||||
github.com/projectdiscovery/hmap v0.0.62 h1:Pb3omgGQkRHB2EBDhgXniUXVC8Jz2CBzpSMKZYRUKFs=
|
||||
github.com/projectdiscovery/hmap v0.0.62/go.mod h1:pNheW3ukrLOcRUDFWrq8OAZiizhosDonIKRVg/4PGnM=
|
||||
github.com/projectdiscovery/httpx v1.6.9 h1:ihyFclesLjvQpiJpRIlAYeebapyIbOI/arDAvvy1ES8=
|
||||
github.com/projectdiscovery/httpx v1.6.9/go.mod h1:zQtX5CtcDYXzIRWne1ztCVtqG0sXCnx84tFwfMHoB8Q=
|
||||
github.com/projectdiscovery/interactsh v1.2.2 h1:h5PRurXUbG+wgt3lvbgz2ydWxiqYvlfNAeYo+DrtCoc=
|
||||
github.com/projectdiscovery/interactsh v1.2.2/go.mod h1:dYfVqXzAVy+UVGlsxw6KKgapw+GWlJPCpozW3hd5xqE=
|
||||
github.com/projectdiscovery/interactsh v1.2.0 h1:Al6jHiR+Usl9egYJDLJaWNHOcH8Rugk8gWMasc8Cmw8=
|
||||
github.com/projectdiscovery/interactsh v1.2.0/go.mod h1:Wxt0fnzxsfrAZQQlpVrf3xMatP4OXZaZbjuDkIQKdYY=
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8=
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb/go.mod h1:vmgC0DTFCfoCLp0RAfsfYTZZan0QMVs+cmTbH6blfjk=
|
||||
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 h1:ZScLodGSezQVwsQDtBSMFp72WDq0nNN+KE/5DHKY5QE=
|
||||
@@ -890,30 +881,30 @@ github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9 h1:IrlDoYZagNNO8y+7iZeHT8k5izE+nek7TdtvEBwCxqk=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9/go.mod h1:XFJ2Lnv8BE/ziQCFjBHMsH1w6VmkPiQtk+NlBpdMU7M=
|
||||
github.com/projectdiscovery/ratelimit v0.0.67 h1:gQt0x907tTcCWrjFIUXj6ZEb1Apsx44EY4Pn/GwRFkQ=
|
||||
github.com/projectdiscovery/ratelimit v0.0.67/go.mod h1:6Emhw9OlJK0BP99fy1Z39jM/TE0IGjEkDHEVMjFrGZY=
|
||||
github.com/projectdiscovery/rawhttp v0.1.80 h1:rJu6m8jzgvWiqzgjIDUCjf7czdnw9L05tZuQzzrkvqc=
|
||||
github.com/projectdiscovery/rawhttp v0.1.80/go.mod h1:400dpIXIcT3de0AAgIVSNyNwwsNSCvDfhOjUoF6WwOE=
|
||||
github.com/projectdiscovery/ratelimit v0.0.60 h1:8nz8gVPPIH7by8ZZKY4LnsjwrlKPkQzJiTACILIdqvo=
|
||||
github.com/projectdiscovery/ratelimit v0.0.60/go.mod h1:ld9toJ1gj8E92pJz5/WFClEaoa6ke5xS62JIYMbctGk=
|
||||
github.com/projectdiscovery/rawhttp v0.1.70 h1:tzCns5KLL98qLYJwSSCdjT41ljX8G58lDrL20gL1YZ8=
|
||||
github.com/projectdiscovery/rawhttp v0.1.70/go.mod h1:fv/488Z6p5ifZ9hl/MWGYOoaDvpR7lV7IOMwIl8mATo=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.91 h1:e1+SXPS2HHhp6k0ox7X6WXRdhXZ/aC+WI/VHMbYzFNg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.91/go.mod h1:nPDo8j37YibM5bYApSEmYKiBQrhtAMdVGiAJK7i8caE=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.93 h1:bGu2obVxBZ/a7uMVld6CBPwuohd6W51VjWvM4W+T2/w=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.93/go.mod h1:p5rZrpWH0m082jTm5pLhSV9WYg7DeN8Zg8EsdG9LAwo=
|
||||
github.com/projectdiscovery/retryabledns v1.0.80 h1:P1oqWHZdF/IMtxXV4mrtENTNsghYojVlrNcv8dZAMu8=
|
||||
github.com/projectdiscovery/retryabledns v1.0.80/go.mod h1:BdCE4+Lph6hkNx+f+EjOnG+K8Z6shFWs9ZiTj6YcNvU=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82 h1:XS+ZEKO291KGZVhHMO+RhvNvVE+IK8VHeM5i6CQ4Ixc=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.82/go.mod h1:JvlWId6aXT8en1ly22///wHoRQwSsMNAttdJ/YkhHHY=
|
||||
github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
|
||||
github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
|
||||
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
|
||||
github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0=
|
||||
github.com/projectdiscovery/tlsx v1.1.8 h1:Y+VkOp6JmUBb4tci1Fbz9U7ELEQ2irFhm+HS58tHruM=
|
||||
github.com/projectdiscovery/tlsx v1.1.8/go.mod h1:6u/dbLuMsLzmux58AWnAB24qh2+Trk0auCK2I9B17Vo=
|
||||
github.com/projectdiscovery/tlsx v1.1.7 h1:eSsl/SmTDL/z2CMeSrbssk4f/9oOotMP1SgXl3yynSM=
|
||||
github.com/projectdiscovery/tlsx v1.1.7/go.mod h1:g66QQ4/y4tLVjoGbzWIv+Q6xwFzxfJbEDx86Y1dYHDM=
|
||||
github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0JprejqLSopN9Y=
|
||||
github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U=
|
||||
github.com/projectdiscovery/useragent v0.0.85 h1:Iz4sIznlPoeyXfzdTRSC0+y2aYODLn2Zf4eUs1hma+A=
|
||||
github.com/projectdiscovery/useragent v0.0.85/go.mod h1:IocCR7mI9og8eIYWhz49/WjdsL1cbU2CyIYBM5lO3ZA=
|
||||
github.com/projectdiscovery/utils v0.4.4 h1:Sn81o3RgnKlKVqjTORmlgLBeewXRkS0+Fg/qRvK+8gg=
|
||||
github.com/projectdiscovery/utils v0.4.4/go.mod h1:qFD1wceFU5pzqWgU++hc29CG204m4dmzqPoJNcP7XcA=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.9 h1:V42606qdDF5KY/2+KO4HQwCH/tlXF7mw3M5uU4jCIOU=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.9/go.mod h1:Ic16RbUvVJF0EooqIjrbRMpICDlnvfR+OrJkzYrqM2E=
|
||||
github.com/projectdiscovery/useragent v0.0.71 h1:Q02L3LV15ztOQ6FfmVSqVmOd5QhvzI+yAgYOc/32Nvg=
|
||||
github.com/projectdiscovery/useragent v0.0.71/go.mod h1:DHPruFLCvCvkd2qqPwwQZrP9sziv0lxQJ0R1rE1fa8E=
|
||||
github.com/projectdiscovery/utils v0.2.15 h1:FO3n7uhLazHtat3qBxWIq0JCfLoR/IvP5JXAOSKaQ5w=
|
||||
github.com/projectdiscovery/utils v0.2.15/go.mod h1:2NAFRu8j/82bkVqx2TcsZFdgtUOnHEUi7u6s3lv79Lo=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22 h1:7QnpeZy/txsvVcQNlL1n4xIu8IXgMxEsda3w6k6bShY=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.22/go.mod h1:wnvmbC10pQTOoCKnCTmWKP20rpEtqrMJZvzuTuleeyw=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4/go.mod h1:8PIPRcUD55UbtQdcfFR1hpIGRWG0P7alClXNGt1TBik=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -1032,8 +1023,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 h1:GXIyLuIJ5Qk46lI8WJ83qHBZKUI3zhmMmuoY9HICUIQ=
|
||||
@@ -1223,8 +1214,8 @@ golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1317,8 +1308,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1343,8 +1334,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1419,8 +1410,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -1433,8 +1424,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1451,8 +1442,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -14,7 +14,7 @@ dns:
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- ".vercel-dns.com"
|
||||
- "ghost.io"
|
||||
internal: true
|
||||
|
||||
http:
|
||||
@@ -25,4 +25,4 @@ http:
|
||||
matchers:
|
||||
- type: word
|
||||
words:
|
||||
- "html>"
|
||||
- "ghost.io"
|
||||
@@ -23,4 +23,4 @@ code:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- true
|
||||
# digest: 490a00463044022048c083c338c0195f5012122d40c1009d2e2030c583e56558e0d6249a41e6f3f4022070656adf748f4874018d7a01fce116db10a3acd1f9b03e12a83906fb625b5c50:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4a0a0047304502200307590191cb7c766b6c21e5777d345bdddf7adf9d6da8f7d336d585d9ac4a8b022100fd30fb0c7722778eb3d861d60e721d805925b8d8df2b979ef2104c35ec57d5cb:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -20,4 +20,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input baz"
|
||||
# digest: 4b0a00483046022100cbbdb7214f669d111b671d271110872dc8af2ab41cf5c312b6e4f64126f55337022100a60547952a0c2bea58388f2d2effe8ad73cd6b6fc92e73eb3c8f88beab6105ec:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4a0a0047304502203fe1d7d52bc2a41886d576a90c82c3be42078baaa4b46e1f3d8519665d6f88b202210081feb82c41150c5b218e226fc4f299ded19f42ba01ef34ba60b0634b4ea6ee12:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -18,4 +18,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4a0a00473045022032b81e8bb7475abf27639b0ced71355497166d664698021f26498e7031d62a23022100e99ccde578bfc0b658f16427ae9a3d18922849d3ba3e022032ea0d2a8e77fadb:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4b0a00483046022100afb5ebff14a40e7f9b679ffc4d93ce7849e33eb398ebb47f2e757cd24831f9dd02210089ffa21b2763e99ebce95dfc5b91e1e62da4ccdc9d2ad5c48584fa350ba335af:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -26,4 +26,4 @@ code:
|
||||
part: interactsh_protocol
|
||||
words:
|
||||
- "http"
|
||||
# digest: 4a0a0047304502201a5dd0eddfab4f02588a5a8ac1947a5fa41fed80b59d698ad5cc00456296efb6022100fe6e608e38c060964800f5f863a7cdc93f686f2d0f4b52854f73948b808b4511:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4b0a00483046022100939f83e74d43932a5bd792b1fd2c100eec2df60f2b2a8dd56b5c8ef5faa92b17022100f93031b0de373af7d78e623968ea5a2d67c4561ef70e3e6da15aef7e5c853115:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -21,4 +21,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4b0a00483046022100ced1702728cc68f906c4c7d2c4d05ed071bfabee1e36eec7ebecbeca795a170c022100d20fd41796f130a8f9c4972fee85386d67d61eb5fc1119b1afe2a851eb2f3e65:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4a0a00473045022100b8e676ce0c57b60c233a0203539dec20457bbb5f1790d351a5d45405b6668b2602204b1f2fa18e7db099f05329009597ceb2d9b7337562c1a676e8d50ea2f1c6fcbe:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -13,7 +13,7 @@ dns:
|
||||
- type: dsl
|
||||
name: blogid
|
||||
dsl:
|
||||
- trim_suffix(cname,'.vercel-dns.com')
|
||||
- trim_suffix(cname,'.ghost.io')
|
||||
internal: true
|
||||
|
||||
http:
|
||||
@@ -24,6 +24,6 @@ http:
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(body,'introduction') # check for http string
|
||||
- blogid == 'cname' # check for cname (extracted information from dns response)
|
||||
- contains(body,'ProjectDiscovery.io') # check for http string
|
||||
- blogid == 'projectdiscovery' # check for cname (extracted information from dns response)
|
||||
condition: and
|
||||
@@ -7,7 +7,7 @@ info:
|
||||
|
||||
|
||||
variables:
|
||||
cname_filtered: '{{trim_suffix(dns_cname,".vercel-dns.com")}}'
|
||||
cname_filtered: '{{trim_suffix(dns_cname,".ghost.io")}}'
|
||||
|
||||
dns:
|
||||
- name: "{{FQDN}}" # DNS Request
|
||||
@@ -24,7 +24,7 @@ http:
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'introduction') # check for http string
|
||||
- cname_filtered == 'cname' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'docs.projectdiscovery.io'
|
||||
- contains(http_body,'ProjectDiscovery.io') # check for http string
|
||||
- cname_filtered == 'projectdiscovery' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'blog.projectdiscovery.io'
|
||||
condition: and
|
||||
@@ -20,7 +20,7 @@ http:
|
||||
matchers:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- contains(http_body,'introduction') # check for http string
|
||||
- trim_suffix(dns_cname,'.vercel-dns.com') == 'cname' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'docs.projectdiscovery.io'
|
||||
- contains(http_body,'ProjectDiscovery.io') # check for http string
|
||||
- trim_suffix(dns_cname,'.ghost.io') == 'projectdiscovery' # check for cname (extracted information from dns response)
|
||||
- ssl_subject_cn == 'blog.projectdiscovery.io'
|
||||
condition: and
|
||||
@@ -19,4 +19,4 @@ code:
|
||||
regex:
|
||||
- 'hello from (.*)'
|
||||
group: 1
|
||||
# digest: 490a0046304402206b3648e8d393ac4df82c7d59b1a6ee3731c66c249dbd4d9bf31f0b7f176b37ec02203184d36373e516757c7d708b5799bc16edb1cebc0a64f3442d13ded4b33c42fb:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 490a00463044022050da011362cf08c2cb81e812c7f86d7282afe0562d4bf00d390f1300d19bc910022029e9d305da69e941ac18797645aecb217abde6557f891e141301b48e89a3c0cd:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -18,4 +18,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from first"
|
||||
# digest: 490a0046304402204cbb1bdf8370e49bb930b17460fb35e15f285a3b48b165736ac0e7ba2f9bc0fb022067c134790c4a2cf646b195aa4488e2c222266436e6bda47931908a28807bdb81:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4b0a00483046022100b3b8759c0df028455eb59b1433ac240e5d4604b011bb0c63680bd3cc159ac6f0022100f44aa11b640d11ad0e2902897f4eb51666ab3cd83c31dfd2590f6e43391e39b0:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -3,7 +3,6 @@ package runner
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
|
||||
@@ -11,12 +10,9 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/writer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
"github.com/projectdiscovery/utils/env"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
)
|
||||
|
||||
@@ -79,25 +75,7 @@ func GetLazyAuthFetchCallback(opts *AuthLazyFetchOptions) authx.LazyFetchSecret
|
||||
vars := map[string]interface{}{}
|
||||
mainCtx := context.Background()
|
||||
ctx := scan.NewScanContext(mainCtx, contextargs.NewWithInput(mainCtx, d.Input))
|
||||
|
||||
cliVars := map[string]interface{}{}
|
||||
if opts.ExecOpts.Options != nil {
|
||||
// gets variables passed from cli -v and -env-vars
|
||||
cliVars = generators.BuildPayloadFromOptions(opts.ExecOpts.Options)
|
||||
}
|
||||
|
||||
for _, v := range d.Variables {
|
||||
// Check if the template has any env variables and expand them
|
||||
if strings.HasPrefix(v.Value, "$") {
|
||||
env.ExpandWithEnv(&v.Value)
|
||||
}
|
||||
if strings.Contains(v.Value, "{{") {
|
||||
// if variables had value like {{username}}, then replace it with the value from cliVars
|
||||
// variables:
|
||||
// - key: username
|
||||
// value: {{username}}
|
||||
v.Value = replacer.Replace(v.Value, cliVars)
|
||||
}
|
||||
vars[v.Key] = v.Value
|
||||
ctx.Input.Add(v.Key, v.Value)
|
||||
}
|
||||
|
||||
@@ -304,17 +304,10 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error)
|
||||
OmitRaw: options.OmitRawRequests,
|
||||
}
|
||||
}
|
||||
// Combine options.
|
||||
if options.JSONLExport != "" {
|
||||
// Combine the CLI options with the config file options with the CLI options taking precedence
|
||||
if reportingOptions.JSONLExporter != nil {
|
||||
reportingOptions.JSONLExporter.File = options.JSONLExport
|
||||
reportingOptions.JSONLExporter.OmitRaw = options.OmitRawRequests
|
||||
} else {
|
||||
reportingOptions.JSONLExporter = &jsonl.Options{
|
||||
File: options.JSONLExport,
|
||||
OmitRaw: options.OmitRawRequests,
|
||||
}
|
||||
reportingOptions.JSONLExporter = &jsonl.Options{
|
||||
File: options.JSONLExport,
|
||||
OmitRaw: options.OmitRawRequests,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,6 @@ import (
|
||||
proxyutils "github.com/projectdiscovery/utils/proxy"
|
||||
)
|
||||
|
||||
const (
|
||||
HTTP_PROXY_ENV = "HTTP_PROXY"
|
||||
)
|
||||
|
||||
// loadProxyServers load list of proxy servers from file or comma separated
|
||||
func loadProxyServers(options *types.Options) error {
|
||||
if len(options.Proxy) == 0 {
|
||||
@@ -52,13 +48,15 @@ func loadProxyServers(options *types.Options) error {
|
||||
return errorutil.WrapfWithNil(err, "failed to parse proxy got %v", err)
|
||||
}
|
||||
if options.ProxyInternal {
|
||||
os.Setenv(HTTP_PROXY_ENV, proxyURL.String())
|
||||
os.Setenv(types.HTTP_PROXY_ENV, proxyURL.String())
|
||||
}
|
||||
if proxyURL.Scheme == proxyutils.HTTP || proxyURL.Scheme == proxyutils.HTTPS {
|
||||
types.ProxyURL = proxyURL.String()
|
||||
types.ProxySocksURL = ""
|
||||
gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String())
|
||||
options.AliveHttpProxy = proxyURL.String()
|
||||
} else if proxyURL.Scheme == proxyutils.SOCKS5 {
|
||||
options.AliveSocksProxy = proxyURL.String()
|
||||
types.ProxyURL = ""
|
||||
types.ProxySocksURL = proxyURL.String()
|
||||
gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String())
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -182,7 +182,7 @@ func New(options *types.Options) (*Runner, error) {
|
||||
runner.catalog = disk.NewCatalog(config.DefaultConfig.TemplatesDirectory)
|
||||
|
||||
var httpclient *retryablehttp.Client
|
||||
if options.ProxyInternal && options.AliveHttpProxy != "" || options.AliveSocksProxy != "" {
|
||||
if options.ProxyInternal && types.ProxyURL != "" || types.ProxySocksURL != "" {
|
||||
var err error
|
||||
httpclient, err = httpclientpool.Get(options, &httpclientpool.Configuration{})
|
||||
if err != nil {
|
||||
@@ -392,9 +392,6 @@ func (r *Runner) Close() {
|
||||
if r.tmpDir != "" {
|
||||
_ = os.RemoveAll(r.tmpDir)
|
||||
}
|
||||
|
||||
//this is no-op unless nuclei is built with stats build tag
|
||||
events.Close()
|
||||
}
|
||||
|
||||
// setupPDCPUpload sets up the PDCP upload writer
|
||||
@@ -730,8 +727,6 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
|
||||
stats.ForceDisplayWarning(templates.ExcludedCodeTmplStats)
|
||||
stats.ForceDisplayWarning(templates.ExludedDastTmplStats)
|
||||
stats.ForceDisplayWarning(templates.TemplatesExcludedStats)
|
||||
stats.ForceDisplayWarning(templates.ExcludedFileStats)
|
||||
stats.ForceDisplayWarning(templates.ExcludedSelfContainedStats)
|
||||
}
|
||||
|
||||
if tmplCount == 0 && workflowCount == 0 {
|
||||
|
||||
+1
-58
@@ -286,23 +286,10 @@ func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions {
|
||||
if e.mode == threadSafe {
|
||||
return ErrOptionsNotSupported.Msgf("WithNetworkConfig")
|
||||
}
|
||||
e.opts.NoHostErrors = opts.DisableMaxHostErr
|
||||
e.opts.MaxHostError = opts.MaxHostError
|
||||
if e.opts.ShouldUseHostError() {
|
||||
maxHostError := opts.MaxHostError
|
||||
if e.opts.TemplateThreads > maxHostError {
|
||||
gologger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", e.executerOpts.Colorizer.BrightYellow("WRN"))
|
||||
gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads)
|
||||
maxHostError = e.opts.TemplateThreads
|
||||
e.opts.MaxHostError = maxHostError
|
||||
}
|
||||
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, e.opts.TrackError)
|
||||
cache.SetVerbose(e.opts.Verbose)
|
||||
e.hostErrCache = cache
|
||||
}
|
||||
e.opts.Timeout = opts.Timeout
|
||||
e.opts.Retries = opts.Retries
|
||||
e.opts.LeaveDefaultPorts = opts.LeaveDefaultPorts
|
||||
e.hostErrCache = hosterrorscache.New(opts.MaxHostError, hosterrorscache.DefaultMaxHostsCount, opts.TrackError)
|
||||
e.opts.Interface = opts.Interface
|
||||
e.opts.SourceIP = opts.SourceIP
|
||||
e.opts.SystemResolvers = opts.SystemResolvers
|
||||
@@ -393,31 +380,6 @@ func WithSandboxOptions(allowLocalFileAccess bool, restrictLocalNetworkAccess bo
|
||||
func EnableCodeTemplates() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.EnableCodeTemplates = true
|
||||
e.opts.EnableSelfContainedTemplates = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnableSelfContainedTemplates allows loading/executing self-contained templates
|
||||
func EnableSelfContainedTemplates() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.EnableSelfContainedTemplates = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnableGlobalMatchersTemplates allows loading/executing global-matchers templates
|
||||
func EnableGlobalMatchersTemplates() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.EnableGlobalMatchersTemplates = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnableFileTemplates allows loading/executing file protocol templates
|
||||
func EnableFileTemplates() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.EnableFileTemplates = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -430,25 +392,6 @@ func WithHeaders(headers []string) NucleiSDKOptions {
|
||||
}
|
||||
}
|
||||
|
||||
// WithVars allows setting custom variables to use in templates/workflows context
|
||||
func WithVars(vars []string) NucleiSDKOptions {
|
||||
// Create a goflags.RuntimeMap
|
||||
runtimeVars := goflags.RuntimeMap{}
|
||||
for _, v := range vars {
|
||||
err := runtimeVars.Set(v)
|
||||
if err != nil {
|
||||
return func(e *NucleiEngine) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.Vars = runtimeVars
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// EnablePassiveMode allows enabling passive HTTP response processing mode
|
||||
func EnablePassiveMode() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
|
||||
+1
-3
@@ -7,7 +7,6 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kitabisa/go-ci"
|
||||
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
|
||||
"github.com/remeh/sizedwaitgroup"
|
||||
)
|
||||
@@ -79,10 +78,9 @@ func ExampleThreadSafeNucleiEngine() {
|
||||
func TestMain(m *testing.M) {
|
||||
// this file only contains testtables examples https://go.dev/blog/examples
|
||||
// and actual functionality test are in sdk_test.go
|
||||
if ci.IsCI() {
|
||||
if os.Getenv("GH_ACTION") != "" || os.Getenv("CI") != "" {
|
||||
// no need to run this test on github actions
|
||||
return
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -40,10 +40,6 @@ func createEphemeralObjects(ctx context.Context, base *NucleiEngine, opts *types
|
||||
Colorizer: aurora.NewAurora(true),
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Parser: base.parser,
|
||||
Browser: base.browserInstance,
|
||||
}
|
||||
if opts.ShouldUseHostError() && base.hostErrCache != nil {
|
||||
u.executerOpts.HostErrorsCache = base.hostErrCache
|
||||
}
|
||||
if opts.RateLimitMinute > 0 {
|
||||
opts.RateLimit = opts.RateLimitMinute
|
||||
|
||||
-13
@@ -112,14 +112,6 @@ func (e *NucleiEngine) GetTemplates() []*templates.Template {
|
||||
return e.store.Templates()
|
||||
}
|
||||
|
||||
// GetWorkflows returns all nuclei workflows that are loaded
|
||||
func (e *NucleiEngine) GetWorkflows() []*templates.Template {
|
||||
if !e.templatesLoaded {
|
||||
_ = e.LoadAllTemplates()
|
||||
}
|
||||
return e.store.Workflows()
|
||||
}
|
||||
|
||||
// LoadTargets(urls/domains/ips only) adds targets to the nuclei engine
|
||||
func (e *NucleiEngine) LoadTargets(targets []string, probeNonHttp bool) {
|
||||
for _, target := range targets {
|
||||
@@ -279,11 +271,6 @@ func (e *NucleiEngine) Engine() *core.Engine {
|
||||
return e.engine
|
||||
}
|
||||
|
||||
// Store returns store of nuclei
|
||||
func (e *NucleiEngine) Store() *loader.Store {
|
||||
return e.store
|
||||
}
|
||||
|
||||
// NewNucleiEngineCtx creates a new nuclei engine instance with given context
|
||||
func NewNucleiEngineCtx(ctx context.Context, options ...NucleiSDKOptions) (*NucleiEngine, error) {
|
||||
// default options
|
||||
|
||||
+16
-19
@@ -3,12 +3,11 @@ package nuclei
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
@@ -73,7 +72,7 @@ func (e *NucleiEngine) applyRequiredDefaults(ctx context.Context) {
|
||||
if e.customProgress == nil {
|
||||
e.customProgress = &testutils.MockProgressClient{}
|
||||
}
|
||||
if e.hostErrCache == nil && e.opts.ShouldUseHostError() {
|
||||
if e.hostErrCache == nil {
|
||||
e.hostErrCache = hosterrorscache.New(30, hosterrorscache.DefaultMaxHostsCount, nil)
|
||||
}
|
||||
// setup interactsh
|
||||
@@ -120,7 +119,7 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
_ = protocolinit.Init(e.opts)
|
||||
})
|
||||
|
||||
if e.opts.ProxyInternal && e.opts.AliveHttpProxy != "" || e.opts.AliveSocksProxy != "" {
|
||||
if e.opts.ProxyInternal && types.ProxyURL != "" || types.ProxySocksURL != "" {
|
||||
httpclient, err := httpclientpool.Get(e.opts, &httpclientpool.Configuration{})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -161,21 +160,19 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
}
|
||||
|
||||
e.executerOpts = protocols.ExecutorOptions{
|
||||
Output: e.customWriter,
|
||||
Options: e.opts,
|
||||
Progress: e.customProgress,
|
||||
Catalog: e.catalog,
|
||||
IssuesClient: e.rc,
|
||||
RateLimiter: e.rateLimiter,
|
||||
Interactsh: e.interactshClient,
|
||||
Colorizer: aurora.NewAurora(true),
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Browser: e.browserInstance,
|
||||
Parser: e.parser,
|
||||
InputHelper: input.NewHelper(),
|
||||
}
|
||||
if e.opts.ShouldUseHostError() && e.hostErrCache != nil {
|
||||
e.executerOpts.HostErrorsCache = e.hostErrCache
|
||||
Output: e.customWriter,
|
||||
Options: e.opts,
|
||||
Progress: e.customProgress,
|
||||
Catalog: e.catalog,
|
||||
IssuesClient: e.rc,
|
||||
RateLimiter: e.rateLimiter,
|
||||
Interactsh: e.interactshClient,
|
||||
HostErrorsCache: e.hostErrCache,
|
||||
Colorizer: aurora.NewAurora(true),
|
||||
ResumeCfg: types.NewResumeCfg(),
|
||||
Browser: e.browserInstance,
|
||||
Parser: e.parser,
|
||||
InputHelper: input.NewHelper(),
|
||||
}
|
||||
if len(e.opts.SecretsFile) > 0 {
|
||||
authTmplStore, err := runner.GetAuthTmplStore(*e.opts, e.catalog, e.executerOpts)
|
||||
|
||||
@@ -133,37 +133,3 @@ func TestThreadSafeNuclei(t *testing.T) {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithVarsNuclei(t *testing.T) {
|
||||
fn := func() {
|
||||
defer func() {
|
||||
// resources like leveldb have a delay to commit in-memory resources
|
||||
// to disk, typically 1-2 seconds, so we wait for 2 seconds
|
||||
time.Sleep(2 * time.Second)
|
||||
goleak.VerifyNone(t, knownLeaks...)
|
||||
}()
|
||||
ne, err := nuclei.NewNucleiEngineCtx(
|
||||
context.TODO(),
|
||||
nuclei.EnableSelfContainedTemplates(),
|
||||
nuclei.WithTemplatesOrWorkflows(nuclei.TemplateSources{Templates: []string{"http/token-spray/api-1forge.yaml"}}),
|
||||
nuclei.WithVars([]string{"token=foobar"}),
|
||||
nuclei.WithVerbosity(nuclei.VerbosityOptions{Debug: true}),
|
||||
)
|
||||
require.Nil(t, err)
|
||||
ne.LoadTargets([]string{"scanme.sh"}, true) // probe http/https target is set to true here
|
||||
err = ne.ExecuteWithCallback(nil)
|
||||
require.Nil(t, err)
|
||||
defer ne.Close()
|
||||
}
|
||||
// this is shared test so needs to be run as seperate process
|
||||
if env.GetEnvOrDefault("TestWithVarsNuclei", false) {
|
||||
cmd := exec.Command(os.Args[0], "-test.run=TestWithVarsNuclei")
|
||||
cmd.Env = append(os.Environ(), "TestWithVarsNuclei=true")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("process ran with error %s, output: %s", err, out)
|
||||
}
|
||||
} else {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@
|
||||
"$id": "https://templates.-template",
|
||||
"$ref": "#/$defs/templates.Template",
|
||||
"$defs": {
|
||||
"analyzers.AnalyzerTemplate": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"parameters": {
|
||||
"$ref": "#/$defs/map[string]interface {}"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"code.Request": {
|
||||
"properties": {
|
||||
"matchers": {
|
||||
@@ -801,11 +785,6 @@
|
||||
"title": "fuzzin rules for http fuzzing",
|
||||
"description": "Fuzzing describes rule schema to fuzz http requests"
|
||||
},
|
||||
"analyzer": {
|
||||
"$ref": "#/$defs/analyzers.AnalyzerTemplate",
|
||||
"title": "analyzer for http request",
|
||||
"description": "Analyzer for HTTP Request"
|
||||
},
|
||||
"self-contained": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
CLIConfigFileName = "config.yaml"
|
||||
ReportingConfigFilename = "reporting-config.yaml"
|
||||
// Version is the current version of nuclei
|
||||
Version = `v3.3.8`
|
||||
Version = `v3.3.5`
|
||||
// Directory Names of custom templates
|
||||
CustomS3TemplatesDirName = "s3"
|
||||
CustomGitHubTemplatesDirName = "github"
|
||||
|
||||
@@ -298,27 +298,6 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
|
||||
|
||||
for templatePath := range validPaths {
|
||||
template, _, _ := templatesCache.Has(templatePath)
|
||||
|
||||
if len(template.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(template.RequestsCode) > 0 && !store.config.ExecutorOptions.Options.EnableCodeTemplates {
|
||||
continue
|
||||
}
|
||||
|
||||
if template.IsFuzzing() && !store.config.ExecutorOptions.Options.DAST {
|
||||
continue
|
||||
}
|
||||
|
||||
if template.SelfContained && !store.config.ExecutorOptions.Options.EnableSelfContainedTemplates {
|
||||
continue
|
||||
}
|
||||
|
||||
if template.HasFileProtocol() && !store.config.ExecutorOptions.Options.EnableFileTemplates {
|
||||
continue
|
||||
}
|
||||
|
||||
if template != nil {
|
||||
template.Path = templatePath
|
||||
store.templates = append(store.templates, template)
|
||||
@@ -373,7 +352,6 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
|
||||
if err != nil {
|
||||
if isParsingError("Error occurred parsing template %s: %s\n", templatePath, err) {
|
||||
areTemplatesValid = false
|
||||
continue
|
||||
}
|
||||
} else if template == nil {
|
||||
// NOTE(dwisiswant0): possibly global matchers template.
|
||||
@@ -393,9 +371,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
|
||||
if existingTemplatePath, found := templateIDPathMap[template.ID]; !found {
|
||||
templateIDPathMap[template.ID] = templatePath
|
||||
} else {
|
||||
// TODO: until https://github.com/projectdiscovery/nuclei-templates/issues/11324 is deployed
|
||||
// disable strict validation to allow GH actions to run
|
||||
// areTemplatesValid = false
|
||||
areTemplatesValid = false
|
||||
gologger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID)
|
||||
}
|
||||
if !isWorkflow && len(template.Workflows) > 0 {
|
||||
@@ -512,17 +488,6 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
stats.Increment(templates.SkippedUnsignedStats)
|
||||
return
|
||||
}
|
||||
|
||||
if parsed.SelfContained && !store.config.ExecutorOptions.Options.EnableSelfContainedTemplates {
|
||||
stats.Increment(templates.ExcludedSelfContainedStats)
|
||||
return
|
||||
}
|
||||
|
||||
if parsed.HasFileProtocol() && !store.config.ExecutorOptions.Options.EnableFileTemplates {
|
||||
stats.Increment(templates.ExcludedFileStats)
|
||||
return
|
||||
}
|
||||
|
||||
// if template has request signature like aws then only signed and verified templates are allowed
|
||||
if parsed.UsesRequestSignature() && !parsed.Verified {
|
||||
stats.Increment(templates.SkippedRequestSignatureStats)
|
||||
|
||||
+5
-31
@@ -137,59 +137,33 @@ getRepo:
|
||||
|
||||
// download the git repo to a given path
|
||||
func (ctr *customTemplateGitHubRepo) cloneRepo(clonePath, githubToken string) error {
|
||||
cloneOpts := &git.CloneOptions{
|
||||
URL: ctr.gitCloneURL,
|
||||
Auth: getAuth(ctr.owner, githubToken),
|
||||
SingleBranch: true,
|
||||
Depth: 1,
|
||||
}
|
||||
|
||||
err := cloneOpts.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := git.PlainClone(clonePath, false, cloneOpts)
|
||||
r, err := git.PlainClone(clonePath, false, &git.CloneOptions{
|
||||
URL: ctr.gitCloneURL,
|
||||
Auth: getAuth(ctr.owner, githubToken),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Errorf("%s/%s: %s", ctr.owner, ctr.reponame, err.Error())
|
||||
}
|
||||
|
||||
// Add the user as well in the config. By default, user is not set
|
||||
config, _ := r.Storer.Config()
|
||||
config.User.Name = ctr.owner
|
||||
|
||||
return r.SetConfig(config)
|
||||
}
|
||||
|
||||
// performs the git pull on given repo
|
||||
func (ctr *customTemplateGitHubRepo) pullChanges(repoPath, githubToken string) error {
|
||||
pullOpts := &git.PullOptions{
|
||||
RemoteName: "origin",
|
||||
Auth: getAuth(ctr.owner, githubToken),
|
||||
SingleBranch: true,
|
||||
Depth: 1,
|
||||
}
|
||||
|
||||
err := pullOpts.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := git.PlainOpen(repoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w, err := r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = w.Pull(pullOpts)
|
||||
err = w.Pull(&git.PullOptions{RemoteName: "origin", Auth: getAuth(ctr.owner, githubToken)})
|
||||
if err != nil {
|
||||
return errors.Errorf("%s/%s: %s", ctr.owner, ctr.reponame, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+10
-8
@@ -2,32 +2,34 @@ package customtemplates
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
osutils "github.com/projectdiscovery/utils/os"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDownloadCustomTemplatesFromGitHub(t *testing.T) {
|
||||
if osutils.IsOSX() {
|
||||
t.Skip("skipping on macos due to unknown failure (works locally)")
|
||||
}
|
||||
|
||||
gologger.DefaultLogger.SetWriter(&testutils.NoopWriter{})
|
||||
|
||||
templatesDirectory := t.TempDir()
|
||||
templatesDirectory, err := os.MkdirTemp("", "template-custom-*")
|
||||
require.Nil(t, err, "could not create temp directory")
|
||||
defer os.RemoveAll(templatesDirectory)
|
||||
|
||||
config.DefaultConfig.SetTemplatesDir(templatesDirectory)
|
||||
|
||||
options := testutils.DefaultOptions
|
||||
options.GitHubTemplateRepo = []string{"projectdiscovery/nuclei-templates-test"}
|
||||
options.GitHubTemplateRepo = []string{"projectdiscovery/nuclei-templates", "ehsandeep/nuclei-templates"}
|
||||
options.GitHubToken = os.Getenv("GITHUB_TOKEN")
|
||||
|
||||
ctm, err := NewCustomTemplatesManager(options)
|
||||
require.Nil(t, err, "could not create custom templates manager")
|
||||
|
||||
ctm.Download(context.Background())
|
||||
require.DirExists(t, filepath.Join(templatesDirectory, "github", "projectdiscovery", "nuclei-templates-test"), "cloned directory does not exists")
|
||||
|
||||
require.DirExists(t, filepath.Join(templatesDirectory, "github", "projectdiscovery", "nuclei-templates"), "cloned directory does not exists")
|
||||
require.DirExists(t, filepath.Join(templatesDirectory, "github", "ehsandeep", "nuclei-templates"), "cloned directory does not exists")
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package analyzers
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
)
|
||||
|
||||
// Analyzer is an interface for all the analyzers
|
||||
// that can be used for the fuzzer
|
||||
type Analyzer interface {
|
||||
// Name returns the name of the analyzer
|
||||
Name() string
|
||||
// ApplyTransformation applies the transformation to the initial payload.
|
||||
ApplyInitialTransformation(data string, params map[string]interface{}) string
|
||||
// Analyze is the main function for the analyzer
|
||||
Analyze(options *Options) (bool, string, error)
|
||||
}
|
||||
|
||||
// AnalyzerTemplate is the template for the analyzer
|
||||
type AnalyzerTemplate struct {
|
||||
// description: |
|
||||
// Name is the name of the analyzer to use
|
||||
// values:
|
||||
// - time_delay
|
||||
Name string `json:"name" yaml:"name"`
|
||||
// description: |
|
||||
// Parameters is the parameters for the analyzer
|
||||
//
|
||||
// Parameters are different for each analyzer. For example, you can customize
|
||||
// time_delay analyzer with sleep_duration, time_slope_error_range, etc. Refer
|
||||
// to the docs for each analyzer to get an idea about parameters.
|
||||
Parameters map[string]interface{} `json:"parameters" yaml:"parameters"`
|
||||
}
|
||||
|
||||
var (
|
||||
analyzers map[string]Analyzer
|
||||
)
|
||||
|
||||
// RegisterAnalyzer registers a new analyzer
|
||||
func RegisterAnalyzer(name string, analyzer Analyzer) {
|
||||
analyzers[name] = analyzer
|
||||
}
|
||||
|
||||
// GetAnalyzer returns the analyzer for a given name
|
||||
func GetAnalyzer(name string) Analyzer {
|
||||
return analyzers[name]
|
||||
}
|
||||
|
||||
func init() {
|
||||
analyzers = make(map[string]Analyzer)
|
||||
}
|
||||
|
||||
// Options contains the options for the analyzer
|
||||
type Options struct {
|
||||
FuzzGenerated fuzz.GeneratedRequest
|
||||
HttpClient *retryablehttp.Client
|
||||
ResponseTimeDelay time.Duration
|
||||
AnalyzerParameters map[string]interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
)
|
||||
|
||||
// ApplyPayloadTransformations applies the payload transformations to the payload
|
||||
// It supports the below payloads -
|
||||
// - [RANDNUM] => random number between 1000 and 9999
|
||||
// - [RANDSTR] => random string of 4 characters
|
||||
func ApplyPayloadTransformations(value string) string {
|
||||
randomInt := GetRandomInteger()
|
||||
randomStr := randStringBytesMask(4)
|
||||
|
||||
value = strings.ReplaceAll(value, "[RANDNUM]", strconv.Itoa(randomInt))
|
||||
value = strings.ReplaceAll(value, "[RANDSTR]", randomStr)
|
||||
return value
|
||||
}
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
const (
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
)
|
||||
|
||||
func randStringBytesMask(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := 0; i < n; {
|
||||
if idx := int(random.Int63() & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i++
|
||||
}
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// GetRandomInteger returns a random integer between 1000 and 9999
|
||||
func GetRandomInteger() int {
|
||||
return random.Intn(9000) + 1000
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http/httptrace"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
)
|
||||
|
||||
// Analyzer is a time delay analyzer for the fuzzer
|
||||
type Analyzer struct{}
|
||||
|
||||
const (
|
||||
DefaultSleepDuration = int(5)
|
||||
DefaultRequestsLimit = int(4)
|
||||
DefaultTimeCorrelationErrorRange = float64(0.15)
|
||||
DefaultTimeSlopeErrorRange = float64(0.30)
|
||||
|
||||
defaultSleepTimeDuration = 5 * time.Second
|
||||
)
|
||||
|
||||
var _ analyzers.Analyzer = &Analyzer{}
|
||||
|
||||
func init() {
|
||||
analyzers.RegisterAnalyzer("time_delay", &Analyzer{})
|
||||
}
|
||||
|
||||
// Name is the name of the analyzer
|
||||
func (a *Analyzer) Name() string {
|
||||
return "time_delay"
|
||||
}
|
||||
|
||||
// ApplyInitialTransformation applies the transformation to the initial payload.
|
||||
//
|
||||
// It supports the below payloads -
|
||||
// - [SLEEPTIME] => sleep_duration
|
||||
// - [INFERENCE] => Inference payload for time delay analyzer
|
||||
//
|
||||
// It also applies the payload transformations to the payload
|
||||
// which includes [RANDNUM] and [RANDSTR]
|
||||
func (a *Analyzer) ApplyInitialTransformation(data string, params map[string]interface{}) string {
|
||||
duration := DefaultSleepDuration
|
||||
if len(params) > 0 {
|
||||
if v, ok := params["sleep_duration"]; ok {
|
||||
duration, ok = v.(int)
|
||||
if !ok {
|
||||
duration = DefaultSleepDuration
|
||||
gologger.Warning().Msgf("Invalid sleep_duration parameter type, using default value: %d", duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
data = strings.ReplaceAll(data, "[SLEEPTIME]", strconv.Itoa(duration))
|
||||
data = analyzers.ApplyPayloadTransformations(data)
|
||||
|
||||
// Also support [INFERENCE] for the time delay analyzer
|
||||
if strings.Contains(data, "[INFERENCE]") {
|
||||
randInt := analyzers.GetRandomInteger()
|
||||
data = strings.ReplaceAll(data, "[INFERENCE]", fmt.Sprintf("%d=%d", randInt, randInt))
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (a *Analyzer) parseAnalyzerParameters(params map[string]interface{}) (int, int, float64, float64, error) {
|
||||
requestsLimit := DefaultRequestsLimit
|
||||
sleepDuration := DefaultSleepDuration
|
||||
timeCorrelationErrorRange := DefaultTimeCorrelationErrorRange
|
||||
timeSlopeErrorRange := DefaultTimeSlopeErrorRange
|
||||
|
||||
if len(params) == 0 {
|
||||
return requestsLimit, sleepDuration, timeCorrelationErrorRange, timeSlopeErrorRange, nil
|
||||
}
|
||||
var ok bool
|
||||
for k, v := range params {
|
||||
switch k {
|
||||
case "sleep_duration":
|
||||
sleepDuration, ok = v.(int)
|
||||
case "requests_limit":
|
||||
requestsLimit, ok = v.(int)
|
||||
case "time_correlation_error_range":
|
||||
timeCorrelationErrorRange, ok = v.(float64)
|
||||
case "time_slope_error_range":
|
||||
timeSlopeErrorRange, ok = v.(float64)
|
||||
}
|
||||
if !ok {
|
||||
return 0, 0, 0, 0, errors.Errorf("invalid parameter type for %s", k)
|
||||
}
|
||||
}
|
||||
return requestsLimit, sleepDuration, timeCorrelationErrorRange, timeSlopeErrorRange, nil
|
||||
}
|
||||
|
||||
// Analyze is the main function for the analyzer
|
||||
func (a *Analyzer) Analyze(options *analyzers.Options) (bool, string, error) {
|
||||
if options.ResponseTimeDelay < defaultSleepTimeDuration {
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
// Parse parameters for this analyzer if any or use default values
|
||||
requestsLimit, sleepDuration, timeCorrelationErrorRange, timeSlopeErrorRange, err :=
|
||||
a.parseAnalyzerParameters(options.AnalyzerParameters)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
gr := options.FuzzGenerated
|
||||
replaced := strings.ReplaceAll(gr.OriginalPayload, "[SLEEPTIME]", strconv.Itoa(delay))
|
||||
replaced = a.ApplyInitialTransformation(replaced, options.AnalyzerParameters)
|
||||
|
||||
if err := gr.Component.SetValue(gr.Key, replaced); err != nil {
|
||||
return 0, errors.Wrap(err, "could not set value in component")
|
||||
}
|
||||
|
||||
rebuilt, err := gr.Component.Rebuild()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not rebuild request")
|
||||
}
|
||||
gologger.Verbose().Msgf("[%s] Sending request with %d delay for: %s", a.Name(), delay, rebuilt.URL.String())
|
||||
|
||||
timeTaken, err := doHTTPRequestWithTimeTracing(rebuilt, options.HttpClient)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not do request with time tracing")
|
||||
}
|
||||
return timeTaken, nil
|
||||
}
|
||||
matched, matchReason, err := checkTimingDependency(
|
||||
requestsLimit,
|
||||
sleepDuration,
|
||||
timeCorrelationErrorRange,
|
||||
timeSlopeErrorRange,
|
||||
reqSender,
|
||||
)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
if matched {
|
||||
return true, matchReason, nil
|
||||
}
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
// doHTTPRequestWithTimeTracing does a http request with time tracing
|
||||
func doHTTPRequestWithTimeTracing(req *retryablehttp.Request, httpclient *retryablehttp.Client) (float64, error) {
|
||||
var ttfb time.Duration
|
||||
var start time.Time
|
||||
|
||||
trace := &httptrace.ClientTrace{
|
||||
GotFirstResponseByte: func() { ttfb = time.Since(start) },
|
||||
}
|
||||
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
|
||||
start = time.Now()
|
||||
resp, err := httpclient.Do(req)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not do request")
|
||||
}
|
||||
|
||||
_, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not read response body")
|
||||
}
|
||||
return ttfb.Seconds(), nil
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
// Package time implements a time delay analyzer using linear
|
||||
// regression heuristics inspired from ZAP to discover time
|
||||
// based issues.
|
||||
//
|
||||
// The approach is the one used in ZAP for timing based checks.
|
||||
// Advantages of this approach are many compared to the old approach of
|
||||
// heuristics of sleep time.
|
||||
//
|
||||
// As we are building a statistical model, we can predict if the delay
|
||||
// is random or not very quickly. Also, the payloads are alternated to send
|
||||
// a very high sleep and a very low sleep. This way the comparison is
|
||||
// faster to eliminate negative cases. Only legitimate cases are sent for
|
||||
// more verification.
|
||||
//
|
||||
// For more details on the algorithm, follow the links below:
|
||||
// - https://groups.google.com/g/zaproxy-develop/c/KGSkNHlLtqk
|
||||
// - https://github.com/zaproxy/zap-extensions/pull/5053
|
||||
//
|
||||
// This file has been implemented from its original version. It was originally licensed under the Apache License 2.0 (see LICENSE file for details).
|
||||
// The original algorithm is implemented in ZAP Active Scanner.
|
||||
package time
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type timeDelayRequestSender func(delay int) (float64, error)
|
||||
|
||||
// checkTimingDependency checks the timing dependency for a given request
|
||||
//
|
||||
// It alternates and sends first a high request, then a low request. Each time
|
||||
// it checks if the delay of the application can be predictably controlled.
|
||||
func checkTimingDependency(
|
||||
requestsLimit int,
|
||||
highSleepTimeSeconds int,
|
||||
correlationErrorRange float64,
|
||||
slopeErrorRange float64,
|
||||
requestSender timeDelayRequestSender,
|
||||
) (bool, string, error) {
|
||||
if requestsLimit < 2 {
|
||||
return false, "", errors.New("requests limit should be at least 2")
|
||||
}
|
||||
|
||||
regression := newSimpleLinearRegression()
|
||||
requestsLeft := requestsLimit
|
||||
|
||||
for {
|
||||
if requestsLeft <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
isCorrelationPossible, err := sendRequestAndTestConfidence(regression, highSleepTimeSeconds, requestSender)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
if !isCorrelationPossible {
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
isCorrelationPossible, err = sendRequestAndTestConfidence(regression, 1, requestSender)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
if !isCorrelationPossible {
|
||||
return false, "", nil
|
||||
}
|
||||
requestsLeft = requestsLeft - 2
|
||||
}
|
||||
|
||||
result := regression.IsWithinConfidence(correlationErrorRange, 1.0, slopeErrorRange)
|
||||
if result {
|
||||
resultReason := fmt.Sprintf(
|
||||
"[time_delay] made %d requests successfully, with a regression slope of %.2f and correlation %.2f",
|
||||
requestsLimit,
|
||||
regression.slope,
|
||||
regression.correlation,
|
||||
)
|
||||
return result, resultReason, nil
|
||||
}
|
||||
return result, "", nil
|
||||
}
|
||||
|
||||
// sendRequestAndTestConfidence sends a request and tests the confidence of delay
|
||||
func sendRequestAndTestConfidence(
|
||||
regression *simpleLinearRegression,
|
||||
delay int,
|
||||
requestSender timeDelayRequestSender,
|
||||
) (bool, error) {
|
||||
delayReceived, err := requestSender(delay)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if delayReceived < float64(delay) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
regression.AddPoint(float64(delay), delayReceived)
|
||||
|
||||
if !regression.IsWithinConfidence(0.3, 1.0, 0.5) {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// simpleLinearRegression is a simple linear regression model that can be updated at runtime.
|
||||
// It is based on the same algorithm in ZAP for doing timing checks.
|
||||
type simpleLinearRegression struct {
|
||||
count float64
|
||||
independentSum float64
|
||||
dependentSum float64
|
||||
|
||||
// Variances
|
||||
independentVarianceN float64
|
||||
dependentVarianceN float64
|
||||
sampleCovarianceN float64
|
||||
|
||||
slope float64
|
||||
intercept float64
|
||||
correlation float64
|
||||
}
|
||||
|
||||
func newSimpleLinearRegression() *simpleLinearRegression {
|
||||
return &simpleLinearRegression{
|
||||
slope: 1,
|
||||
correlation: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *simpleLinearRegression) AddPoint(x, y float64) {
|
||||
independentResidualAdjustment := x - o.independentSum/o.count
|
||||
dependentResidualAdjustment := y - o.dependentSum/o.count
|
||||
|
||||
o.count += 1
|
||||
o.independentSum += x
|
||||
o.dependentSum += y
|
||||
|
||||
if math.IsNaN(independentResidualAdjustment) {
|
||||
return
|
||||
}
|
||||
|
||||
independentResidual := x - o.independentSum/o.count
|
||||
dependentResidual := y - o.dependentSum/o.count
|
||||
|
||||
o.independentVarianceN += independentResidual * independentResidualAdjustment
|
||||
o.dependentVarianceN += dependentResidual * dependentResidualAdjustment
|
||||
o.sampleCovarianceN += independentResidual * dependentResidualAdjustment
|
||||
|
||||
o.slope = o.sampleCovarianceN / o.independentVarianceN
|
||||
o.correlation = o.slope * math.Sqrt(o.independentVarianceN/o.dependentVarianceN)
|
||||
o.correlation *= o.correlation
|
||||
|
||||
// NOTE: zap had the reverse formula, changed it to the correct one
|
||||
// for intercept. Verify if this is correct.
|
||||
o.intercept = o.dependentSum/o.count - o.slope*(o.independentSum/o.count)
|
||||
if math.IsNaN(o.correlation) {
|
||||
o.correlation = 1
|
||||
}
|
||||
}
|
||||
|
||||
func (o *simpleLinearRegression) Predict(x float64) float64 {
|
||||
return o.slope*x + o.intercept
|
||||
}
|
||||
|
||||
func (o *simpleLinearRegression) IsWithinConfidence(correlationErrorRange float64, expectedSlope float64, slopeErrorRange float64,
|
||||
) bool {
|
||||
return o.correlation > 1.0-correlationErrorRange &&
|
||||
math.Abs(expectedSlope-o.slope) < slopeErrorRange
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
// Tests ported from ZAP Java version of the algorithm
|
||||
|
||||
package time
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
correlationErrorRange = float64(0.1)
|
||||
slopeErrorRange = float64(0.2)
|
||||
)
|
||||
|
||||
var rng = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
func Test_should_generate_alternating_sequences(t *testing.T) {
|
||||
var generatedDelays []float64
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
generatedDelays = append(generatedDelays, float64(delay))
|
||||
return float64(delay), nil
|
||||
}
|
||||
matched, _, err := checkTimingDependency(4, 15, correlationErrorRange, slopeErrorRange, reqSender)
|
||||
require.NoError(t, err)
|
||||
require.True(t, matched)
|
||||
require.EqualValues(t, []float64{15, 1, 15, 1}, generatedDelays)
|
||||
}
|
||||
|
||||
func Test_should_giveup_non_injectable(t *testing.T) {
|
||||
var timesCalled int
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
timesCalled++
|
||||
return 0.5, nil
|
||||
}
|
||||
matched, _, err := checkTimingDependency(4, 15, correlationErrorRange, slopeErrorRange, reqSender)
|
||||
require.NoError(t, err)
|
||||
require.False(t, matched)
|
||||
require.Equal(t, 1, timesCalled)
|
||||
}
|
||||
|
||||
func Test_should_giveup_slow_non_injectable(t *testing.T) {
|
||||
var timesCalled int
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
timesCalled++
|
||||
return 10 + rng.Float64()*0.5, nil
|
||||
}
|
||||
matched, _, err := checkTimingDependency(4, 15, correlationErrorRange, slopeErrorRange, reqSender)
|
||||
require.NoError(t, err)
|
||||
require.False(t, matched)
|
||||
require.LessOrEqual(t, timesCalled, 3)
|
||||
}
|
||||
|
||||
func Test_should_giveup_slow_non_injectable_realworld(t *testing.T) {
|
||||
var timesCalled int
|
||||
var iteration = 0
|
||||
counts := []float64{21, 11, 21, 11}
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
timesCalled++
|
||||
iteration++
|
||||
return counts[iteration-1], nil
|
||||
}
|
||||
matched, _, err := checkTimingDependency(4, 15, correlationErrorRange, slopeErrorRange, reqSender)
|
||||
require.NoError(t, err)
|
||||
require.False(t, matched)
|
||||
require.LessOrEqual(t, timesCalled, 4)
|
||||
}
|
||||
|
||||
func Test_should_detect_dependence_with_small_error(t *testing.T) {
|
||||
reqSender := func(delay int) (float64, error) {
|
||||
return float64(delay) + rng.Float64()*0.5, nil
|
||||
}
|
||||
matched, reason, err := checkTimingDependency(4, 15, correlationErrorRange, slopeErrorRange, reqSender)
|
||||
require.NoError(t, err)
|
||||
require.True(t, matched)
|
||||
require.NotEmpty(t, reason)
|
||||
}
|
||||
|
||||
func Test_LinearRegression_Numerical_stability(t *testing.T) {
|
||||
variables := [][]float64{
|
||||
{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {1, 1}, {2, 2}, {2, 2}, {2, 2},
|
||||
}
|
||||
slope := float64(1)
|
||||
correlation := float64(1)
|
||||
|
||||
regression := newSimpleLinearRegression()
|
||||
for _, v := range variables {
|
||||
regression.AddPoint(v[0], v[1])
|
||||
}
|
||||
require.True(t, almostEqual(regression.slope, slope))
|
||||
require.True(t, almostEqual(regression.correlation, correlation))
|
||||
}
|
||||
|
||||
func Test_LinearRegression_exact_verify(t *testing.T) {
|
||||
variables := [][]float64{
|
||||
{1, 1}, {2, 3},
|
||||
}
|
||||
slope := float64(2)
|
||||
correlation := float64(1)
|
||||
|
||||
regression := newSimpleLinearRegression()
|
||||
for _, v := range variables {
|
||||
regression.AddPoint(v[0], v[1])
|
||||
}
|
||||
require.True(t, almostEqual(regression.slope, slope))
|
||||
require.True(t, almostEqual(regression.correlation, correlation))
|
||||
}
|
||||
|
||||
func Test_LinearRegression_known_verify(t *testing.T) {
|
||||
variables := [][]float64{
|
||||
{1, 1.348520581}, {2, 2.524046187}, {3, 3.276944688}, {4, 4.735374498}, {5, 5.150291657},
|
||||
}
|
||||
slope := float64(0.981487046)
|
||||
correlation := float64(0.979228906)
|
||||
|
||||
regression := newSimpleLinearRegression()
|
||||
for _, v := range variables {
|
||||
regression.AddPoint(v[0], v[1])
|
||||
}
|
||||
require.True(t, almostEqual(regression.slope, slope))
|
||||
require.True(t, almostEqual(regression.correlation, correlation))
|
||||
}
|
||||
|
||||
func Test_LinearRegression_nonlinear_verify(t *testing.T) {
|
||||
variables := [][]float64{
|
||||
{1, 2}, {2, 4}, {3, 8}, {4, 16}, {5, 32},
|
||||
}
|
||||
|
||||
regression := newSimpleLinearRegression()
|
||||
for _, v := range variables {
|
||||
regression.AddPoint(v[0], v[1])
|
||||
}
|
||||
require.Less(t, regression.correlation, 0.9)
|
||||
}
|
||||
|
||||
const float64EqualityThreshold = 1e-8
|
||||
|
||||
func almostEqual(a, b float64) bool {
|
||||
return math.Abs(a-b) <= float64EqualityThreshold
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/dataformat"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
"github.com/projectdiscovery/utils/maps"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
|
||||
+2
-18
@@ -50,11 +50,6 @@ type ExecuteRuleInput struct {
|
||||
BaseRequest *retryablehttp.Request
|
||||
// DisplayFuzzPoints is a flag to display fuzz points
|
||||
DisplayFuzzPoints bool
|
||||
|
||||
// ApplyPayloadInitialTransformation is an optional function
|
||||
// to transform the payload initially based on analyzer rules
|
||||
ApplyPayloadInitialTransformation func(string, map[string]interface{}) string
|
||||
AnalyzerParams map[string]interface{}
|
||||
}
|
||||
|
||||
// GeneratedRequest is a single generated request for rule
|
||||
@@ -69,15 +64,6 @@ type GeneratedRequest struct {
|
||||
Component component.Component
|
||||
// Parameter being fuzzed
|
||||
Parameter string
|
||||
|
||||
// Key is the key for the request
|
||||
Key string
|
||||
// Value is the value for the request
|
||||
Value string
|
||||
// OriginalValue is the original value for the request
|
||||
OriginalValue string
|
||||
// OriginalPayload is the original payload for the request
|
||||
OriginalPayload string
|
||||
}
|
||||
|
||||
// Execute executes a fuzzing rule accepting a callback on which
|
||||
@@ -230,9 +216,7 @@ func (rule *Rule) executeRuleValues(input *ExecuteRuleInput, ruleComponent compo
|
||||
// if we are only fuzzing values
|
||||
if len(rule.Fuzz.Value) > 0 {
|
||||
for _, value := range rule.Fuzz.Value {
|
||||
originalPayload := value
|
||||
|
||||
if err := rule.executePartRule(input, ValueOrKeyValue{Value: value, OriginalPayload: originalPayload}, ruleComponent); err != nil {
|
||||
if err := rule.executePartRule(input, ValueOrKeyValue{Value: value}, ruleComponent); err != nil {
|
||||
if component.IsErrSetValue(err) {
|
||||
// this are errors due to format restrictions
|
||||
// ex: fuzzing string value in a json int field
|
||||
@@ -273,7 +257,7 @@ func (rule *Rule) executeRuleValues(input *ExecuteRuleInput, ruleComponent compo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if gotErr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, "", "", "", "", "", ""); gotErr != nil {
|
||||
if gotErr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, "", ""); gotErr != nil {
|
||||
return gotErr
|
||||
}
|
||||
}
|
||||
|
||||
+13
-23
@@ -42,14 +42,14 @@ func (rule *Rule) executePartComponent(input *ExecuteRuleInput, payload ValueOrK
|
||||
return rule.executePartComponentOnKV(input, payload, ruleComponent.Clone())
|
||||
} else {
|
||||
// for value only fuzzing
|
||||
return rule.executePartComponentOnValues(input, payload.Value, payload.OriginalPayload, ruleComponent.Clone())
|
||||
return rule.executePartComponentOnValues(input, payload.Value, ruleComponent.Clone())
|
||||
}
|
||||
}
|
||||
|
||||
// executePartComponentOnValues executes this rule on a given component and payload
|
||||
// this supports both single and multiple [ruleType] modes
|
||||
// i.e if component has multiple values, they can be replaced once or all depending on mode
|
||||
func (rule *Rule) executePartComponentOnValues(input *ExecuteRuleInput, payloadStr, originalPayload string, ruleComponent component.Component) error {
|
||||
func (rule *Rule) executePartComponentOnValues(input *ExecuteRuleInput, payloadStr string, ruleComponent component.Component) error {
|
||||
finalErr := ruleComponent.Iterate(func(key string, value interface{}) error {
|
||||
valueStr := types.ToString(value)
|
||||
if !rule.matchKeyOrValue(key, valueStr) {
|
||||
@@ -57,13 +57,8 @@ func (rule *Rule) executePartComponentOnValues(input *ExecuteRuleInput, payloadS
|
||||
return nil
|
||||
}
|
||||
|
||||
var evaluated, originalEvaluated string
|
||||
var evaluated string
|
||||
evaluated, input.InteractURLs = rule.executeEvaluate(input, key, valueStr, payloadStr, input.InteractURLs)
|
||||
if input.ApplyPayloadInitialTransformation != nil {
|
||||
evaluated = input.ApplyPayloadInitialTransformation(evaluated, input.AnalyzerParams)
|
||||
originalEvaluated, _ = rule.executeEvaluate(input, key, valueStr, originalPayload, input.InteractURLs)
|
||||
}
|
||||
|
||||
if err := ruleComponent.SetValue(key, evaluated); err != nil {
|
||||
// gologger.Warning().Msgf("could not set value due to format restriction original(%s, %s[%T]) , new(%s,%s[%T])", key, valueStr, value, key, evaluated, evaluated)
|
||||
return nil
|
||||
@@ -75,7 +70,7 @@ func (rule *Rule) executePartComponentOnValues(input *ExecuteRuleInput, payloadS
|
||||
return err
|
||||
}
|
||||
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, key, valueStr, originalEvaluated, valueStr, key, evaluated); qerr != nil {
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, key, valueStr); qerr != nil {
|
||||
return qerr
|
||||
}
|
||||
// fmt.Printf("executed with value: %s\n", evaluated)
|
||||
@@ -97,7 +92,7 @@ func (rule *Rule) executePartComponentOnValues(input *ExecuteRuleInput, payloadS
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, "", "", "", "", "", ""); qerr != nil {
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, "", ""); qerr != nil {
|
||||
err = qerr
|
||||
return err
|
||||
}
|
||||
@@ -132,7 +127,7 @@ func (rule *Rule) executePartComponentOnKV(input *ExecuteRuleInput, payload Valu
|
||||
return err
|
||||
}
|
||||
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, key, value, "", "", "", ""); qerr != nil {
|
||||
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, key, value); qerr != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -151,13 +146,12 @@ func (rule *Rule) executePartComponentOnKV(input *ExecuteRuleInput, payload Valu
|
||||
}
|
||||
|
||||
// execWithInput executes a rule with input via callback
|
||||
func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp.Request, interactURLs []string, component component.Component, parameter, parameterValue, originalPayload, originalValue, key, value string) error {
|
||||
func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp.Request, interactURLs []string, component component.Component, parameter, parameterValue string) error {
|
||||
// If the parameter is a number, replace it with the parameter value
|
||||
// or if the parameter is empty and the parameter value is not empty
|
||||
// replace it with the parameter value
|
||||
actualParameter := parameter
|
||||
if _, err := strconv.Atoi(parameter); err == nil || (parameter == "" && parameterValue != "") {
|
||||
actualParameter = parameterValue
|
||||
parameter = parameterValue
|
||||
}
|
||||
// If the parameter is frequent, skip it if the option is enabled
|
||||
if rule.options.FuzzParamsFrequency != nil {
|
||||
@@ -170,15 +164,11 @@ func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp.
|
||||
}
|
||||
}
|
||||
request := GeneratedRequest{
|
||||
Request: httpReq,
|
||||
InteractURLs: interactURLs,
|
||||
DynamicValues: input.Values,
|
||||
Component: component,
|
||||
Parameter: actualParameter,
|
||||
Key: key,
|
||||
Value: value,
|
||||
OriginalValue: originalValue,
|
||||
OriginalPayload: originalPayload,
|
||||
Request: httpReq,
|
||||
InteractURLs: interactURLs,
|
||||
DynamicValues: input.Values,
|
||||
Component: component,
|
||||
Parameter: parameter,
|
||||
}
|
||||
if !input.Callback(request) {
|
||||
return types.ErrNoMoreRequests
|
||||
|
||||
@@ -19,8 +19,6 @@ var (
|
||||
type ValueOrKeyValue struct {
|
||||
Key string
|
||||
Value string
|
||||
|
||||
OriginalPayload string
|
||||
}
|
||||
|
||||
func (v *ValueOrKeyValue) IsKV() bool {
|
||||
|
||||
@@ -184,7 +184,7 @@ func (i *ListInputProvider) Set(value string) {
|
||||
continue
|
||||
}
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput.Input = value
|
||||
metaInput.CustomIP = ip
|
||||
i.setItem(metaInput)
|
||||
}
|
||||
|
||||
@@ -201,7 +201,6 @@ type ResultEvent struct {
|
||||
FuzzingMethod string `json:"fuzzing_method,omitempty"`
|
||||
FuzzingParameter string `json:"fuzzing_parameter,omitempty"`
|
||||
FuzzingPosition string `json:"fuzzing_position,omitempty"`
|
||||
AnalyzerDetails string `json:"analyzer_details,omitempty"`
|
||||
|
||||
FileToIndexPosition map[string]int `json:"-"`
|
||||
TemplateVerifier string `json:"-"`
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestStandardWriterRequest(t *testing.T) {
|
||||
fmt.Errorf("GET https://example.com/tcpconfig.html/tcpconfig.html giving up after 2 attempts: %w", errors.New("context deadline exceeded (Client.Timeout exceeded while awaiting headers)")),
|
||||
)
|
||||
|
||||
require.Equal(t, `{"template":"misconfiguration/tcpconfig.yaml","type":"http","input":"https://example.com/tcpconfig.html","address":"example.com:443","error":"cause=\"context deadline exceeded (Client.Timeout exceeded while awaiting headers)\"","kind":"unknown-error"}`, errorWriter.String())
|
||||
require.Equal(t, `{"template":"misconfiguration/tcpconfig.yaml","type":"http","input":"https://example.com/tcpconfig.html","address":"example.com:443","error":"context deadline exceeded (Client.Timeout exceeded while awaiting headers)","kind":"unknown-error"}`, errorWriter.String())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -86,12 +86,6 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
Args: request.Args,
|
||||
EarlyCloseFileDescriptor: true,
|
||||
}
|
||||
|
||||
if options.Options.Debug || options.Options.DebugResponse {
|
||||
// enable debug mode for gozero
|
||||
gozeroOptions.DebugMode = true
|
||||
}
|
||||
|
||||
engine, err := gozero.New(gozeroOptions)
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("[%s] engines '%s' not available on host", options.TemplateID, strings.Join(request.Engine, ","))
|
||||
@@ -245,22 +239,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
}
|
||||
|
||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||
gologger.Debug().MsgFunc(func() string {
|
||||
dashes := strings.Repeat("-", 15)
|
||||
sb := &strings.Builder{}
|
||||
sb.WriteString(fmt.Sprintf("[%s] Dumped Executed Source Code for input/stdin: '%v'", request.options.TemplateID, input.MetaInput.Input))
|
||||
sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Source Code:", dashes))
|
||||
sb.WriteString(interpretEnvVars(request.Source, allvars))
|
||||
sb.WriteString("\n")
|
||||
sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Command Executed:", dashes))
|
||||
sb.WriteString(interpretEnvVars(gOutput.Command, allvars))
|
||||
sb.WriteString("\n")
|
||||
sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Command Output:", dashes))
|
||||
sb.WriteString(gOutput.DebugData.String())
|
||||
sb.WriteString("\n")
|
||||
sb.WriteString("[WRN] Command Output here is stdout+sterr, in response variables they are seperate (use -v -svd flags for more details)")
|
||||
return sb.String()
|
||||
})
|
||||
gologger.Debug().Msgf("[%s] Dumped Executed Source Code for %v\n\n%v\n", request.options.TemplateID, input.MetaInput.Input, interpretEnvVars(request.Source, allvars))
|
||||
}
|
||||
|
||||
dataOutputString := fmtStdout(gOutput.Stdout.String())
|
||||
|
||||
@@ -39,3 +39,34 @@ func TestCodeProtocol(t *testing.T) {
|
||||
require.Nil(t, err, "could not run code request")
|
||||
require.NotEmpty(t, gotEvent, "could not get event items")
|
||||
}
|
||||
|
||||
func TestCodeProtocolForGO(t *testing.T) {
|
||||
options := testutils.DefaultOptions
|
||||
|
||||
testutils.Init(options)
|
||||
templateID := "testing-code"
|
||||
request := &Request{
|
||||
Engine: []string{"go"},
|
||||
Source: `package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("hello world")
|
||||
}`,
|
||||
}
|
||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||
ID: templateID,
|
||||
Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "hello-world"},
|
||||
})
|
||||
err := request.Compile(executerOpts)
|
||||
require.Nil(t, err, "could not compile code request")
|
||||
|
||||
var gotEvent output.InternalEvent
|
||||
ctxArgs := contextargs.NewWithInput(context.Background(), "")
|
||||
err = request.ExecuteWithResults(ctxArgs, nil, nil, func(event *output.InternalWrappedEvent) {
|
||||
gotEvent = event.InternalEvent
|
||||
})
|
||||
require.Nil(t, err, "could not run code request")
|
||||
require.NotEmpty(t, gotEvent, "could not get event items")
|
||||
}
|
||||
@@ -142,9 +142,6 @@ func (metaInput *MetaInput) Unmarshal(data string) error {
|
||||
}
|
||||
|
||||
func (metaInput *MetaInput) Clone() *MetaInput {
|
||||
metaInput.mu.Lock()
|
||||
defer metaInput.mu.Unlock()
|
||||
|
||||
input := NewMetaInput()
|
||||
input.Input = metaInput.Input
|
||||
input.CustomIP = metaInput.CustomIP
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/whois/rdapclientpool"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
_ "github.com/projectdiscovery/utils/global"
|
||||
)
|
||||
|
||||
// Init initializes the client pools for the protocols
|
||||
|
||||
@@ -19,7 +19,7 @@ var (
|
||||
)
|
||||
|
||||
func StartActiveMemGuardian(ctx context.Context) {
|
||||
if memguardian.DefaultMemGuardian == nil || memTimer != nil {
|
||||
if memguardian.DefaultMemGuardian == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -109,8 +109,8 @@ func Init(options *types.Options) error {
|
||||
},
|
||||
}
|
||||
}
|
||||
if options.AliveSocksProxy != "" {
|
||||
proxyURL, err := url.Parse(options.AliveSocksProxy)
|
||||
if types.ProxySocksURL != "" {
|
||||
proxyURL, err := url.Parse(types.ProxySocksURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/launcher"
|
||||
@@ -24,10 +23,8 @@ type Browser struct {
|
||||
tempDir string
|
||||
previousPIDs map[int32]struct{} // track already running PIDs
|
||||
engine *rod.Browser
|
||||
httpclient *http.Client
|
||||
options *types.Options
|
||||
// use getHTTPClient to get the http client
|
||||
httpClient *http.Client
|
||||
httpClientOnce *sync.Once
|
||||
}
|
||||
|
||||
// New creates a new nuclei headless browser module
|
||||
@@ -76,8 +73,8 @@ func New(options *types.Options) (*Browser, error) {
|
||||
} else {
|
||||
chromeLauncher = chromeLauncher.Headless(true)
|
||||
}
|
||||
if options.AliveHttpProxy != "" {
|
||||
chromeLauncher = chromeLauncher.Proxy(options.AliveHttpProxy)
|
||||
if types.ProxyURL != "" {
|
||||
chromeLauncher = chromeLauncher.Proxy(types.ProxyURL)
|
||||
}
|
||||
|
||||
for k, v := range options.ParseHeadlessOptionalArguments() {
|
||||
@@ -104,12 +101,17 @@ func New(options *types.Options) (*Browser, error) {
|
||||
}
|
||||
}
|
||||
|
||||
httpclient, err := newHttpClient(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
engine := &Browser{
|
||||
tempDir: dataStore,
|
||||
customAgent: customAgent,
|
||||
engine: browser,
|
||||
options: options,
|
||||
httpClientOnce: &sync.Once{},
|
||||
tempDir: dataStore,
|
||||
customAgent: customAgent,
|
||||
engine: browser,
|
||||
httpclient: httpclient,
|
||||
options: options,
|
||||
}
|
||||
engine.previousPIDs = previousPIDs
|
||||
return engine, nil
|
||||
@@ -119,7 +121,7 @@ func New(options *types.Options) (*Browser, error) {
|
||||
func MustDisableSandbox() bool {
|
||||
// linux with root user needs "--no-sandbox" option
|
||||
// https://github.com/chromium/chromium/blob/c4d3c31083a2e1481253ff2d24298a1dfe19c754/chrome/test/chromedriver/client/chromedriver.py#L209
|
||||
return osutils.IsLinux()
|
||||
return osutils.IsLinux() && os.Geteuid() == 0
|
||||
}
|
||||
|
||||
// SetUserAgent sets custom user agent to the browser
|
||||
@@ -132,14 +134,6 @@ func (b *Browser) UserAgent() string {
|
||||
return b.customAgent
|
||||
}
|
||||
|
||||
func (b *Browser) getHTTPClient() (*http.Client, error) {
|
||||
var err error
|
||||
b.httpClientOnce.Do(func() {
|
||||
b.httpClient, err = newHttpClient(b.options)
|
||||
})
|
||||
return b.httpClient, err
|
||||
}
|
||||
|
||||
// Close closes the browser engine
|
||||
func (b *Browser) Close() {
|
||||
b.engine.Close()
|
||||
|
||||
@@ -56,12 +56,12 @@ func newHttpClient(options *types.Options) (*http.Client, error) {
|
||||
MaxConnsPerHost: 500,
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
if options.AliveHttpProxy != "" {
|
||||
if proxyURL, err := url.Parse(options.AliveHttpProxy); err == nil {
|
||||
if types.ProxyURL != "" {
|
||||
if proxyURL, err := url.Parse(types.ProxyURL); err == nil {
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
} else if options.AliveSocksProxy != "" {
|
||||
socksURL, proxyErr := url.Parse(options.AliveSocksProxy)
|
||||
} else if types.ProxySocksURL != "" {
|
||||
socksURL, proxyErr := url.Parse(types.ProxySocksURL)
|
||||
if proxyErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -67,15 +67,10 @@ func (i *Instance) Run(input *contextargs.Context, actions []*Action, payloads m
|
||||
payloads: payloads,
|
||||
}
|
||||
|
||||
httpclient, err := i.browser.getHTTPClient()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// in case the page has request/response modification rules - enable global hijacking
|
||||
if createdPage.hasModificationRules() || containsModificationActions(actions...) {
|
||||
hijackRouter := page.HijackRequests()
|
||||
if err := hijackRouter.Add("*", "", createdPage.routingRuleHandler(httpclient)); err != nil {
|
||||
if err := hijackRouter.Add("*", "", createdPage.routingRuleHandler); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
createdPage.hijackRouter = hijackRouter
|
||||
|
||||
@@ -649,10 +649,7 @@ func testHeadless(t *testing.T, actions []*Action, timeout time.Duration, handle
|
||||
|
||||
_ = protocolstate.Init(opts)
|
||||
|
||||
browser, err := New(&types.Options{
|
||||
ShowBrowser: false,
|
||||
UseInstalledChrome: testheadless.HeadlessLocal,
|
||||
})
|
||||
browser, err := New(&types.Options{ShowBrowser: false, UseInstalledChrome: testheadless.HeadlessLocal})
|
||||
require.Nil(t, err, "could not create browser")
|
||||
defer browser.Close()
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
@@ -12,97 +11,95 @@ import (
|
||||
)
|
||||
|
||||
// routingRuleHandler handles proxy rule for actions related to request/response modification
|
||||
func (p *Page) routingRuleHandler(httpClient *http.Client) func(ctx *rod.Hijack) {
|
||||
return func(ctx *rod.Hijack) {
|
||||
// usually browsers don't use chunked transfer encoding, so we set the content-length nevertheless
|
||||
ctx.Request.Req().ContentLength = int64(len(ctx.Request.Body()))
|
||||
for _, rule := range p.rules {
|
||||
if rule.Part != "request" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rule.Action {
|
||||
case ActionSetMethod:
|
||||
rule.Do(func() {
|
||||
ctx.Request.Req().Method = rule.Args["method"]
|
||||
})
|
||||
case ActionAddHeader:
|
||||
ctx.Request.Req().Header.Add(rule.Args["key"], rule.Args["value"])
|
||||
case ActionSetHeader:
|
||||
ctx.Request.Req().Header.Set(rule.Args["key"], rule.Args["value"])
|
||||
case ActionDeleteHeader:
|
||||
ctx.Request.Req().Header.Del(rule.Args["key"])
|
||||
case ActionSetBody:
|
||||
body := rule.Args["body"]
|
||||
ctx.Request.Req().ContentLength = int64(len(body))
|
||||
ctx.Request.SetBody(body)
|
||||
}
|
||||
func (p *Page) routingRuleHandler(ctx *rod.Hijack) {
|
||||
// usually browsers don't use chunked transfer encoding, so we set the content-length nevertheless
|
||||
ctx.Request.Req().ContentLength = int64(len(ctx.Request.Body()))
|
||||
for _, rule := range p.rules {
|
||||
if rule.Part != "request" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rule.Action {
|
||||
case ActionSetMethod:
|
||||
rule.Do(func() {
|
||||
ctx.Request.Req().Method = rule.Args["method"]
|
||||
})
|
||||
case ActionAddHeader:
|
||||
ctx.Request.Req().Header.Add(rule.Args["key"], rule.Args["value"])
|
||||
case ActionSetHeader:
|
||||
ctx.Request.Req().Header.Set(rule.Args["key"], rule.Args["value"])
|
||||
case ActionDeleteHeader:
|
||||
ctx.Request.Req().Header.Del(rule.Args["key"])
|
||||
case ActionSetBody:
|
||||
body := rule.Args["body"]
|
||||
ctx.Request.Req().ContentLength = int64(len(body))
|
||||
ctx.Request.SetBody(body)
|
||||
}
|
||||
}
|
||||
|
||||
if !p.options.DisableCookie {
|
||||
// each http request is performed via the native go http client
|
||||
// we first inject the shared cookies
|
||||
if !p.options.DisableCookie {
|
||||
if cookies := p.input.CookieJar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
httpClient.Jar.SetCookies(ctx.Request.URL(), cookies)
|
||||
}
|
||||
if cookies := p.input.CookieJar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
p.instance.browser.httpclient.Jar.SetCookies(ctx.Request.URL(), cookies)
|
||||
}
|
||||
|
||||
// perform the request
|
||||
_ = ctx.LoadResponse(httpClient, true)
|
||||
|
||||
if !p.options.DisableCookie {
|
||||
// retrieve the updated cookies from the native http client and inject them into the shared cookie jar
|
||||
// keeps existing one if not present
|
||||
if cookies := httpClient.Jar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
p.input.CookieJar.SetCookies(ctx.Request.URL(), cookies)
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range p.rules {
|
||||
if rule.Part != "response" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rule.Action {
|
||||
case ActionAddHeader:
|
||||
ctx.Response.Headers().Add(rule.Args["key"], rule.Args["value"])
|
||||
case ActionSetHeader:
|
||||
ctx.Response.Headers().Set(rule.Args["key"], rule.Args["value"])
|
||||
case ActionDeleteHeader:
|
||||
ctx.Response.Headers().Del(rule.Args["key"])
|
||||
case ActionSetBody:
|
||||
body := rule.Args["body"]
|
||||
ctx.Response.Headers().Set("Content-Length", fmt.Sprintf("%d", len(body)))
|
||||
ctx.Response.SetBody(rule.Args["body"])
|
||||
}
|
||||
}
|
||||
|
||||
// store history
|
||||
req := ctx.Request.Req()
|
||||
var rawReq string
|
||||
if raw, err := httputil.DumpRequestOut(req, true); err == nil {
|
||||
rawReq = string(raw)
|
||||
}
|
||||
|
||||
// attempts to rebuild the response
|
||||
var rawResp strings.Builder
|
||||
respPayloads := ctx.Response.Payload()
|
||||
if respPayloads != nil {
|
||||
rawResp.WriteString(fmt.Sprintf("HTTP/1.1 %d %s\n", respPayloads.ResponseCode, respPayloads.ResponsePhrase))
|
||||
for _, header := range respPayloads.ResponseHeaders {
|
||||
rawResp.WriteString(header.Name + ": " + header.Value + "\n")
|
||||
}
|
||||
rawResp.WriteString("\n")
|
||||
rawResp.WriteString(ctx.Response.Body())
|
||||
}
|
||||
|
||||
// dump request
|
||||
historyData := HistoryData{
|
||||
RawRequest: rawReq,
|
||||
RawResponse: rawResp.String(),
|
||||
}
|
||||
p.addToHistory(historyData)
|
||||
}
|
||||
|
||||
// perform the request
|
||||
_ = ctx.LoadResponse(p.instance.browser.httpclient, true)
|
||||
|
||||
if !p.options.DisableCookie {
|
||||
// retrieve the updated cookies from the native http client and inject them into the shared cookie jar
|
||||
// keeps existing one if not present
|
||||
if cookies := p.instance.browser.httpclient.Jar.Cookies(ctx.Request.URL()); len(cookies) > 0 {
|
||||
p.input.CookieJar.SetCookies(ctx.Request.URL(), cookies)
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range p.rules {
|
||||
if rule.Part != "response" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rule.Action {
|
||||
case ActionAddHeader:
|
||||
ctx.Response.Headers().Add(rule.Args["key"], rule.Args["value"])
|
||||
case ActionSetHeader:
|
||||
ctx.Response.Headers().Set(rule.Args["key"], rule.Args["value"])
|
||||
case ActionDeleteHeader:
|
||||
ctx.Response.Headers().Del(rule.Args["key"])
|
||||
case ActionSetBody:
|
||||
body := rule.Args["body"]
|
||||
ctx.Response.Headers().Set("Content-Length", fmt.Sprintf("%d", len(body)))
|
||||
ctx.Response.SetBody(rule.Args["body"])
|
||||
}
|
||||
}
|
||||
|
||||
// store history
|
||||
req := ctx.Request.Req()
|
||||
var rawReq string
|
||||
if raw, err := httputil.DumpRequestOut(req, true); err == nil {
|
||||
rawReq = string(raw)
|
||||
}
|
||||
|
||||
// attempts to rebuild the response
|
||||
var rawResp strings.Builder
|
||||
respPayloads := ctx.Response.Payload()
|
||||
if respPayloads != nil {
|
||||
rawResp.WriteString(fmt.Sprintf("HTTP/1.1 %d %s\n", respPayloads.ResponseCode, respPayloads.ResponsePhrase))
|
||||
for _, header := range respPayloads.ResponseHeaders {
|
||||
rawResp.WriteString(header.Name + ": " + header.Value + "\n")
|
||||
}
|
||||
rawResp.WriteString("\n")
|
||||
rawResp.WriteString(ctx.Response.Body())
|
||||
}
|
||||
|
||||
// dump request
|
||||
historyData := HistoryData{
|
||||
RawRequest: rawReq,
|
||||
RawResponse: rawResp.String(),
|
||||
}
|
||||
p.addToHistory(historyData)
|
||||
}
|
||||
|
||||
// routingRuleHandlerNative handles native proxy rule
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
var _ protocols.Request = &Request{}
|
||||
|
||||
const errCouldNotGetHtmlElement = "could not get html element"
|
||||
const errCouldGetHtmlElement = "could get html element"
|
||||
|
||||
// Type returns the type of the protocol request
|
||||
func (request *Request) Type() templateTypes.ProtocolType {
|
||||
@@ -117,7 +117,7 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
if err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, input.MetaInput.Input, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return errors.Wrap(err, errCouldNotGetHtmlElement)
|
||||
return errors.Wrap(err, errCouldGetHtmlElement)
|
||||
}
|
||||
defer instance.Close()
|
||||
|
||||
@@ -130,7 +130,7 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
if _, err := url.Parse(input.MetaInput.Input); err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, input.MetaInput.Input, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return errors.Wrap(err, errCouldNotGetHtmlElement)
|
||||
return errors.Wrap(err, errCouldGetHtmlElement)
|
||||
}
|
||||
options := &engine.Options{
|
||||
Timeout: time.Duration(request.options.Options.PageTimeout) * time.Second,
|
||||
@@ -146,7 +146,7 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
if err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, input.MetaInput.Input, request.Type().String(), err)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return errors.Wrap(err, errCouldNotGetHtmlElement)
|
||||
return errors.Wrap(err, errCouldGetHtmlElement)
|
||||
}
|
||||
defer page.Close()
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
@@ -56,8 +55,6 @@ type generatedRequest struct {
|
||||
// requestURLPattern tracks unmodified request url pattern without values ( it is used for constant vuln_hash)
|
||||
// ex: {{BaseURL}}/api/exp?param={{randstr}}
|
||||
requestURLPattern string
|
||||
|
||||
fuzzGeneratedRequest fuzz.GeneratedRequest
|
||||
}
|
||||
|
||||
// setReqURLPattern sets the url request pattern for the generated request
|
||||
@@ -150,7 +147,9 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
|
||||
// skip creating template context if not available
|
||||
dynamicValues = generators.MergeMaps(dynamicValues, r.request.options.GetTemplateCtx(input.MetaInput).GetAll())
|
||||
}
|
||||
|
||||
if r.request.SelfContained {
|
||||
return r.makeSelfContainedRequest(ctx, reqData, payloads, dynamicValues)
|
||||
}
|
||||
isRawRequest := len(r.request.Raw) > 0
|
||||
// replace interactsh variables with actual interactsh urls
|
||||
if r.options.Interactsh != nil {
|
||||
@@ -164,10 +163,6 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
|
||||
}
|
||||
}
|
||||
|
||||
if r.request.SelfContained {
|
||||
return r.makeSelfContainedRequest(ctx, reqData, payloads, dynamicValues)
|
||||
}
|
||||
|
||||
// Parse target url
|
||||
parsed, err := urlutil.ParseAbsoluteURL(input.MetaInput.Input, false)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,18 +3,13 @@ package http
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/invopop/jsonschema"
|
||||
json "github.com/json-iterator/go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
_ "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers/time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
@@ -131,9 +126,6 @@ type Request struct {
|
||||
|
||||
// Fuzzing describes schema to fuzz http requests
|
||||
Fuzzing []*fuzz.Rule `yaml:"fuzzing,omitempty" json:"fuzzing,omitempty" jsonschema:"title=fuzzin rules for http fuzzing,description=Fuzzing describes rule schema to fuzz http requests"`
|
||||
// description: |
|
||||
// Analyzer is an analyzer to use for matching the response.
|
||||
Analyzer *analyzers.AnalyzerTemplate `yaml:"analyzer,omitempty" json:"analyzer,omitempty" jsonschema:"title=analyzer for http request,description=Analyzer for HTTP Request"`
|
||||
|
||||
CompiledOperators *operators.Operators `yaml:"-" json:"-"`
|
||||
|
||||
@@ -311,21 +303,6 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
},
|
||||
RedirectFlow: httpclientpool.DontFollowRedirect,
|
||||
}
|
||||
var customTimeout int
|
||||
if request.Analyzer != nil && request.Analyzer.Name == "time_delay" {
|
||||
var timeoutVal int
|
||||
if timeout, ok := request.Analyzer.Parameters["sleep_duration"]; ok {
|
||||
timeoutVal, _ = timeout.(int)
|
||||
} else {
|
||||
timeoutVal = 5
|
||||
}
|
||||
|
||||
// Add 3x buffer to the timeout
|
||||
customTimeout = int(math.Ceil(float64(timeoutVal) * 3))
|
||||
}
|
||||
if customTimeout > 0 {
|
||||
connectionConfiguration.Connection.CustomMaxTimeout = time.Duration(customTimeout) * time.Second
|
||||
}
|
||||
|
||||
if request.Redirects || options.Options.FollowRedirects {
|
||||
connectionConfiguration.RedirectFlow = httpclientpool.FollowAllRedirect
|
||||
@@ -392,12 +369,6 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
}
|
||||
}
|
||||
|
||||
if request.Analyzer != nil {
|
||||
if analyzer := analyzers.GetAnalyzer(request.Analyzer.Name); analyzer == nil {
|
||||
return errors.Errorf("analyzer %s not found", request.Analyzer.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve payload paths from vars if they exists
|
||||
for name, payload := range request.options.Options.Vars.AsMap() {
|
||||
payloadStr, ok := payload.(string)
|
||||
|
||||
@@ -3,7 +3,6 @@ package httpclientpool
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
@@ -26,7 +25,6 @@ import (
|
||||
"github.com/projectdiscovery/rawhttp"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -62,9 +60,6 @@ func Init(options *types.Options) error {
|
||||
type ConnectionConfiguration struct {
|
||||
// DisableKeepAlive of the connection
|
||||
DisableKeepAlive bool
|
||||
// CustomMaxTimeout is the custom timeout for the connection
|
||||
// This overrides all other timeouts and is used for accurate time based fuzzing.
|
||||
CustomMaxTimeout time.Duration
|
||||
cookiejar *cookiejar.Jar
|
||||
mu sync.RWMutex
|
||||
}
|
||||
@@ -140,10 +135,6 @@ func (c *Configuration) Hash() string {
|
||||
builder.WriteString(strconv.FormatBool(c.DisableCookie))
|
||||
builder.WriteString("c")
|
||||
builder.WriteString(strconv.FormatBool(c.Connection != nil))
|
||||
if c.Connection != nil && c.Connection.CustomMaxTimeout > 0 {
|
||||
builder.WriteString("k")
|
||||
builder.WriteString(c.Connection.CustomMaxTimeout.String())
|
||||
}
|
||||
builder.WriteString("r")
|
||||
builder.WriteString(strconv.FormatInt(int64(c.ResponseHeaderTimeout.Seconds()), 10))
|
||||
hash := builder.String()
|
||||
@@ -159,10 +150,10 @@ func (c *Configuration) HasStandardOptions() bool {
|
||||
func GetRawHTTP(options *protocols.ExecutorOptions) *rawhttp.Client {
|
||||
rawHttpClientOnce.Do(func() {
|
||||
rawHttpOptions := rawhttp.DefaultOptions
|
||||
if options.Options.AliveHttpProxy != "" {
|
||||
rawHttpOptions.Proxy = options.Options.AliveHttpProxy
|
||||
} else if options.Options.AliveSocksProxy != "" {
|
||||
rawHttpOptions.Proxy = options.Options.AliveSocksProxy
|
||||
if types.ProxyURL != "" {
|
||||
rawHttpOptions.Proxy = types.ProxyURL
|
||||
} else if types.ProxySocksURL != "" {
|
||||
rawHttpOptions.Proxy = types.ProxySocksURL
|
||||
} else if protocolstate.Dialer != nil {
|
||||
rawHttpOptions.FastDialer = protocolstate.Dialer
|
||||
}
|
||||
@@ -256,9 +247,6 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
if configuration.ResponseHeaderTimeout != 0 {
|
||||
responseHeaderTimeout = configuration.ResponseHeaderTimeout
|
||||
}
|
||||
if configuration.Connection != nil && configuration.Connection.CustomMaxTimeout > 0 {
|
||||
responseHeaderTimeout = configuration.Connection.CustomMaxTimeout
|
||||
}
|
||||
|
||||
transport := &http.Transport{
|
||||
ForceAttemptHTTP2: options.ForceAttemptHTTP2,
|
||||
@@ -280,12 +268,12 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
ResponseHeaderTimeout: responseHeaderTimeout,
|
||||
}
|
||||
|
||||
if options.AliveHttpProxy != "" {
|
||||
if proxyURL, err := url.Parse(options.AliveHttpProxy); err == nil {
|
||||
if types.ProxyURL != "" {
|
||||
if proxyURL, err := url.Parse(types.ProxyURL); err == nil {
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
} else if options.AliveSocksProxy != "" {
|
||||
socksURL, proxyErr := url.Parse(options.AliveSocksProxy)
|
||||
} else if types.ProxySocksURL != "" {
|
||||
socksURL, proxyErr := url.Parse(types.ProxySocksURL)
|
||||
if proxyErr != nil {
|
||||
return nil, proxyErr
|
||||
}
|
||||
@@ -325,9 +313,6 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
}
|
||||
if !configuration.NoTimeout {
|
||||
httpclient.Timeout = options.GetTimeouts().HttpTimeout
|
||||
if configuration.Connection != nil && configuration.Connection.CustomMaxTimeout > 0 {
|
||||
httpclient.Timeout = configuration.Connection.CustomMaxTimeout
|
||||
}
|
||||
}
|
||||
client := retryablehttp.NewWithHTTPClient(httpclient, retryableHttpOptions)
|
||||
if jar != nil {
|
||||
@@ -379,7 +364,7 @@ func makeCheckRedirectFunc(redirectType RedirectFlow, maxRedirects int) checkRed
|
||||
}
|
||||
}
|
||||
|
||||
func checkMaxRedirects(req *http.Request, via []*http.Request, maxRedirects int) error {
|
||||
func checkMaxRedirects(_ *http.Request, via []*http.Request, maxRedirects int) error {
|
||||
if maxRedirects == 0 {
|
||||
if len(via) > defaultMaxRedirects {
|
||||
return http.ErrUseLastResponse
|
||||
@@ -390,29 +375,5 @@ func checkMaxRedirects(req *http.Request, via []*http.Request, maxRedirects int)
|
||||
if len(via) > maxRedirects {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
// NOTE(dwisiswant0): rebuild request URL. See #5900.
|
||||
if u := req.URL.String(); !isURLEncoded(u) {
|
||||
parsed, err := urlutil.Parse(u)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %w", ErrRebuildURL, err)
|
||||
}
|
||||
|
||||
req.URL = parsed.URL
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isURLEncoded is an helper function to check if the URL is already encoded
|
||||
//
|
||||
// NOTE(dwisiswant0): shall we move this under `projectdiscovery/utils/urlutil`?
|
||||
func isURLEncoded(s string) bool {
|
||||
decoded, err := url.QueryUnescape(s)
|
||||
if err != nil {
|
||||
// If decoding fails, it may indicate a malformed URL/invalid encoding.
|
||||
return false
|
||||
}
|
||||
|
||||
return decoded != s
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package httpclientpool
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrRebuildURL = errors.New("could not rebuild request URL")
|
||||
)
|
||||
@@ -170,10 +170,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
if value, ok := wrapped.InternalEvent["global-matchers"]; ok {
|
||||
isGlobalMatchers = value.(bool)
|
||||
}
|
||||
var analyzerDetails string
|
||||
if value, ok := wrapped.InternalEvent["analyzer_details"]; ok {
|
||||
analyzerDetails = value.(string)
|
||||
}
|
||||
data := &output.ResultEvent{
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
@@ -197,7 +193,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
CURLCommand: types.ToString(wrapped.InternalEvent["curl-command"]),
|
||||
TemplateEncoded: request.options.EncodeTemplate(),
|
||||
Error: types.ToString(wrapped.InternalEvent["error"]),
|
||||
AnalyzerDetails: analyzerDetails,
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
|
||||
"github.com/projectdiscovery/fastdialer/fastdialer"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
@@ -928,26 +927,8 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
|
||||
matchedURL = responseURL
|
||||
}
|
||||
}
|
||||
|
||||
finalEvent := make(output.InternalEvent)
|
||||
|
||||
if request.Analyzer != nil {
|
||||
analyzer := analyzers.GetAnalyzer(request.Analyzer.Name)
|
||||
analysisMatched, analysisDetails, err := analyzer.Analyze(&analyzers.Options{
|
||||
FuzzGenerated: generatedRequest.fuzzGeneratedRequest,
|
||||
HttpClient: request.httpClient,
|
||||
ResponseTimeDelay: duration,
|
||||
AnalyzerParameters: request.Analyzer.Parameters,
|
||||
})
|
||||
if err != nil {
|
||||
gologger.Warning().Msgf("Could not analyze response: %v\n", err)
|
||||
}
|
||||
if analysisMatched {
|
||||
finalEvent["analyzer_details"] = analysisDetails
|
||||
finalEvent["analyzer"] = true
|
||||
}
|
||||
}
|
||||
|
||||
outputEvent := request.responseToDSLMap(respChain.Response(), input.MetaInput.Input, matchedURL, convUtil.String(dumpedRequest), respChain.FullResponse().String(), respChain.Body().String(), respChain.Headers().String(), duration, generatedRequest.meta)
|
||||
// add response fields to template context and merge templatectx variables to output event
|
||||
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent)
|
||||
|
||||
@@ -6,7 +6,6 @@ package http
|
||||
// -> request.executeGeneratedFuzzingRequest [execute final generated fuzzing request and get result]
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/operators/matchers"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
@@ -123,7 +121,7 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value
|
||||
default:
|
||||
}
|
||||
|
||||
input := &fuzz.ExecuteRuleInput{
|
||||
err := rule.Execute(&fuzz.ExecuteRuleInput{
|
||||
Input: input,
|
||||
DisplayFuzzPoints: request.options.Options.DisplayFuzzPoints,
|
||||
Callback: func(gr fuzz.GeneratedRequest) bool {
|
||||
@@ -137,14 +135,8 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value
|
||||
return request.executeGeneratedFuzzingRequest(gr, input, callback)
|
||||
},
|
||||
Values: values,
|
||||
BaseRequest: baseRequest.Clone(context.TODO()),
|
||||
}
|
||||
if request.Analyzer != nil {
|
||||
analyzer := analyzers.GetAnalyzer(request.Analyzer.Name)
|
||||
input.ApplyPayloadInitialTransformation = analyzer.ApplyInitialTransformation
|
||||
input.AnalyzerParams = request.Analyzer.Parameters
|
||||
}
|
||||
err := rule.Execute(input)
|
||||
BaseRequest: baseRequest.Clone(input.Context()),
|
||||
})
|
||||
if err == nil {
|
||||
applicable = true
|
||||
continue
|
||||
@@ -174,11 +166,10 @@ func (request *Request) executeGeneratedFuzzingRequest(gr fuzz.GeneratedRequest,
|
||||
}
|
||||
request.options.RateLimitTake()
|
||||
req := &generatedRequest{
|
||||
request: gr.Request,
|
||||
dynamicValues: gr.DynamicValues,
|
||||
interactshURLs: gr.InteractURLs,
|
||||
original: request,
|
||||
fuzzGeneratedRequest: gr,
|
||||
request: gr.Request,
|
||||
dynamicValues: gr.DynamicValues,
|
||||
interactshURLs: gr.InteractURLs,
|
||||
original: request,
|
||||
}
|
||||
var gotMatches bool
|
||||
requestErr := request.executeRequest(input, req, gr.DynamicValues, hasInteractMatchers, func(event *output.InternalWrappedEvent) {
|
||||
|
||||
@@ -56,7 +56,7 @@ const (
|
||||
Sd
|
||||
)
|
||||
|
||||
// GenerateVariablesWithContextArgs will create default variables with context args
|
||||
// GenerateVariables will create default variables with context args
|
||||
func GenerateVariablesWithContextArgs(input *contextargs.Context, trailingSlash bool) map[string]interface{} {
|
||||
parsed, err := urlutil.Parse(input.MetaInput.Input)
|
||||
if err != nil {
|
||||
|
||||
@@ -10,21 +10,16 @@ import (
|
||||
)
|
||||
|
||||
type Exporter struct {
|
||||
options *Options
|
||||
mutex *sync.Mutex
|
||||
rows []output.ResultEvent
|
||||
outputFile *os.File
|
||||
options *Options
|
||||
mutex *sync.Mutex
|
||||
rows []output.ResultEvent
|
||||
}
|
||||
|
||||
// Options contains the configuration options for JSONL exporter client
|
||||
type Options struct {
|
||||
// File is the file to export found JSONL result to
|
||||
File string `yaml:"file"`
|
||||
// OmitRaw whether to exclude the raw request and response from the output
|
||||
OmitRaw bool `yaml:"omit-raw"`
|
||||
// BatchSize the number of records to keep in memory before writing them out to the JSONL file or 0 to disable
|
||||
// batching (default)
|
||||
BatchSize int `yaml:"batch-size"`
|
||||
File string `yaml:"file"`
|
||||
OmitRaw bool `yaml:"omit-raw"`
|
||||
}
|
||||
|
||||
// New creates a new JSONL exporter integration client based on options.
|
||||
@@ -37,7 +32,8 @@ func New(options *Options) (*Exporter, error) {
|
||||
return exporter, nil
|
||||
}
|
||||
|
||||
// Export appends the passed result event to the list of objects to be exported to the resulting JSONL file
|
||||
// Export appends the passed result event to the list of objects to be exported to
|
||||
// the resulting JSONL file
|
||||
func (exporter *Exporter) Export(event *output.ResultEvent) error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
@@ -50,72 +46,40 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error {
|
||||
// Add the event to the rows
|
||||
exporter.rows = append(exporter.rows, *event)
|
||||
|
||||
// If the batch size is greater than 0 and the number of rows has reached the batch, flush it to the database
|
||||
if exporter.options.BatchSize > 0 && len(exporter.rows) >= exporter.options.BatchSize {
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteRows writes all rows from the rows list to JSONL file and removes them from the list
|
||||
func (exporter *Exporter) WriteRows() error {
|
||||
// Open the file for writing if it's not already.
|
||||
// This will recreate the file if it exists, but keep the file handle so that batched writes within the same
|
||||
// execution are appended to the same file.
|
||||
var err error
|
||||
if exporter.outputFile == nil {
|
||||
// Open the JSONL file for writing and create it if it doesn't exist
|
||||
exporter.outputFile, err = os.OpenFile(exporter.options.File, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create JSONL file")
|
||||
}
|
||||
// Close writes the in-memory data to the JSONL file specified by options.JSONLExport
|
||||
// and closes the exporter after operation
|
||||
func (exporter *Exporter) Close() error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
// Open the JSONL file for writing and create it if it doesn't exist
|
||||
f, err := os.OpenFile(exporter.options.File, os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create JSONL file")
|
||||
}
|
||||
|
||||
// Loop through the rows and write them, removing them as they're entered
|
||||
for len(exporter.rows) > 0 {
|
||||
row := exporter.rows[0]
|
||||
|
||||
// Loop through the rows and convert each to a JSON byte array and write to file
|
||||
for _, row := range exporter.rows {
|
||||
// Convert the row to JSON byte array and append a trailing newline. This is treated as a single line in JSONL
|
||||
obj, err := json.Marshal(row)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate row for JSONL report")
|
||||
}
|
||||
|
||||
// Add a trailing newline to the JSON byte array to confirm with the JSONL format
|
||||
obj = append(obj, '\n')
|
||||
|
||||
// Attempt to append the JSON line to file specified in options.JSONLExport
|
||||
if _, err = exporter.outputFile.Write(obj); err != nil {
|
||||
if _, err = f.Write(obj); err != nil {
|
||||
return errors.Wrap(err, "failed to append JSONL line")
|
||||
}
|
||||
|
||||
// Remove the item from the list
|
||||
exporter.rows = exporter.rows[1:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close writes the in-memory data to the JSONL file specified by options.JSONLExport and closes the exporter after
|
||||
// operation
|
||||
func (exporter *Exporter) Close() error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
// Write any remaining rows to the file
|
||||
// Write all pending rows
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
|
||||
// Close the file
|
||||
if err := exporter.outputFile.Close(); err != nil {
|
||||
if err := f.Close(); err != nil {
|
||||
return errors.Wrap(err, "failed to close JSONL file")
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
@@ -116,9 +115,7 @@ func createFileName(event *output.ResultEvent) string {
|
||||
filenameBuilder := &strings.Builder{}
|
||||
filenameBuilder.WriteString(event.TemplateID)
|
||||
filenameBuilder.WriteString("-")
|
||||
filenameBuilder.WriteString(event.Host)
|
||||
filenameBuilder.WriteString("-")
|
||||
filenameBuilder.WriteString(uuid.NewString())
|
||||
filenameBuilder.WriteString(stringsutil.ReplaceAll(event.Matched, "_", "/", ":"))
|
||||
|
||||
var suffix string
|
||||
if event.MatcherName != "" {
|
||||
|
||||
@@ -83,7 +83,7 @@ func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatte
|
||||
}
|
||||
}
|
||||
|
||||
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 || event.AnalyzerDetails != "" {
|
||||
if len(event.ExtractedResults) > 0 || len(event.Metadata) > 0 {
|
||||
builder.WriteString("\n")
|
||||
builder.WriteString(formatter.MakeBold("Extra Information"))
|
||||
builder.WriteString("\n\n")
|
||||
@@ -99,13 +99,6 @@ func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatte
|
||||
}
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
if event.AnalyzerDetails != "" {
|
||||
builder.WriteString(formatter.MakeBold("Analyzer Details:"))
|
||||
builder.WriteString("\n\n")
|
||||
|
||||
builder.WriteString(event.AnalyzerDetails)
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
if len(event.Metadata) > 0 {
|
||||
builder.WriteString(formatter.MakeBold("Metadata:"))
|
||||
builder.WriteString("\n\n")
|
||||
|
||||
@@ -197,7 +197,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// CreateConfigIfNotExists creates report-config if it doesn't exist
|
||||
// CreateConfigIfNotExists creates report-config if it doesn't exists
|
||||
func CreateConfigIfNotExists() error {
|
||||
reportingConfig := config.DefaultConfig.GetReportingConfigFilePath()
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown/util"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/format"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
@@ -62,9 +63,11 @@ func New(options *Options) (*Integration, error) {
|
||||
)
|
||||
tc := oauth2.NewClient(ctx, ts)
|
||||
|
||||
if options.HttpClient != nil && options.HttpClient.HTTPClient != nil {
|
||||
if tcTransport, ok := tc.Transport.(*http.Transport); ok {
|
||||
tcTransport.Proxy = options.HttpClient.HTTPClient.Transport.(*http.Transport).Proxy
|
||||
// patch transport to support proxy - only http
|
||||
// TODO: investigate if it's possible to reuse existing retryablehttp
|
||||
if types.ProxyURL != "" {
|
||||
if proxyURL, err := url.Parse(types.ProxyURL); err == nil {
|
||||
tc.Transport.(*http.Transport).Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,12 +101,13 @@ func (i *Integration) CreateIssue(event *output.ResultEvent) (*filters.CreateIss
|
||||
}
|
||||
if issue.State == "closed" {
|
||||
reopen := "reopen"
|
||||
_, _, err := i.client.Issues.UpdateIssue(i.options.ProjectName, issue.IID, &gitlab.UpdateIssueOptions{
|
||||
_, resp, err := i.client.Issues.UpdateIssue(i.options.ProjectName, issue.IID, &gitlab.UpdateIssueOptions{
|
||||
StateEvent: &reopen,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Sprintln(resp, err)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &filters.CreateIssueResponse{
|
||||
IssueID: strconv.FormatInt(int64(issue.ID), 10),
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/andygrunwald/go-jira"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/trivago/tgo/tcontainer"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
@@ -242,22 +241,18 @@ func (i *Integration) CreateIssue(event *output.ResultEvent) (*filters.CreateIss
|
||||
if i.options.UpdateExisting {
|
||||
issue, err := i.FindExistingIssue(event)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not find existing issue")
|
||||
return nil, err
|
||||
} else if issue.ID != "" {
|
||||
_, _, err = i.jira.Issue.AddComment(issue.ID, &jira.Comment{
|
||||
Body: format.CreateReportDescription(event, i, i.options.OmitRaw),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not add comment to existing issue")
|
||||
return nil, err
|
||||
}
|
||||
return getIssueResponseFromJira(&issue)
|
||||
}
|
||||
}
|
||||
resp, err := i.CreateNewIssue(event)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create new issue")
|
||||
}
|
||||
return resp, nil
|
||||
return i.CreateNewIssue(event)
|
||||
}
|
||||
|
||||
func (i *Integration) CloseIssue(event *output.ResultEvent) error {
|
||||
@@ -302,11 +297,7 @@ func (i *Integration) CloseIssue(event *output.ResultEvent) error {
|
||||
// FindExistingIssue checks if the issue already exists and returns its ID
|
||||
func (i *Integration) FindExistingIssue(event *output.ResultEvent) (jira.Issue, error) {
|
||||
template := format.GetMatchedTemplateName(event)
|
||||
project := i.options.ProjectName
|
||||
if i.options.ProjectID != "" {
|
||||
project = i.options.ProjectID
|
||||
}
|
||||
jql := fmt.Sprintf("summary ~ \"%s\" AND summary ~ \"%s\" AND status != \"%s\" AND project = \"%s\"", template, event.Host, i.options.StatusNot, project)
|
||||
jql := fmt.Sprintf("summary ~ \"%s\" AND summary ~ \"%s\" AND status != \"%s\" AND project = \"%s\"", template, event.Host, i.options.StatusNot, i.options.ProjectName)
|
||||
|
||||
searchOptions := &jira.SearchOptions{
|
||||
MaxResults: 1, // if any issue exists, then we won't create a new one
|
||||
|
||||
@@ -60,9 +60,6 @@ func New(options *Options) (*Integration, error) {
|
||||
Key: options.APIKey,
|
||||
},
|
||||
}
|
||||
if options.HttpClient != nil {
|
||||
httpClient.Transport = options.HttpClient.HTTPClient.Transport
|
||||
}
|
||||
|
||||
integration := &Integration{
|
||||
url: "https://api.linear.app/graphql",
|
||||
|
||||
Loaded 100 of 120 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user