mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 04:35:24 +00:00
Merge branch 'dev' into code_smells
This commit is contained in:
commit
0cabce518f
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: 1.17
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
2
.github/workflows/functional-test.yml
vendored
2
.github/workflows/functional-test.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.15
|
||||
go-version: 1.17
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
8
.github/workflows/publish-docs.yaml
vendored
8
.github/workflows/publish-docs.yaml
vendored
@ -1,6 +1,8 @@
|
||||
name: ⏰ Publish Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@ -17,7 +19,7 @@ jobs:
|
||||
- name: "Set up Go"
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: 1.17
|
||||
|
||||
- name: Generate YAML Syntax Documentation
|
||||
id: generate-docs
|
||||
@ -28,7 +30,7 @@ jobs:
|
||||
fi
|
||||
go generate pkg/templates/templates.go
|
||||
go build -o "cmd/docgen/docgen" cmd/docgen/docgen.go
|
||||
./cmd/docgen/docgen syntax-reference.md nuclei-jsonschema.json
|
||||
./cmd/docgen/docgen ../SYNTAX-REFERENCE.md ../nuclei-jsonschema.json
|
||||
echo "::set-output name=changes::$(git status -s | wc -l)"
|
||||
working-directory: v2
|
||||
|
||||
@ -37,7 +39,7 @@ jobs:
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add v2/syntax-reference.md v2/nuclei-jsonschema.json
|
||||
git add SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
git commit -m "Auto Generate Syntax Docs + JSONSchema [$(date)] :robot:" -a
|
||||
|
||||
- name: Push changes
|
||||
|
||||
2
.github/workflows/release-binary.yml
vendored
2
.github/workflows/release-binary.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
name: "Set up Go"
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: 1.17
|
||||
-
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
14
README.md
14
README.md
@ -80,7 +80,7 @@ Nuclei is a fast, template based vulnerability scanner focusing
|
||||
on extensive configurability, massive extensibility and ease of use.
|
||||
|
||||
Usage:
|
||||
./nuclei [flags]
|
||||
nuclei [flags]
|
||||
|
||||
Flags:
|
||||
TARGET:
|
||||
@ -100,7 +100,7 @@ FILTERING:
|
||||
-etags, -exclude-tags string[] exclude templates with the provided tags
|
||||
-include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-exclude-templates, -exclude string[] template or template directory paths to exclude
|
||||
-severity, -impact string[] execute templates that match the provided severities only
|
||||
-severity, -impact value[] Templates to run based on severity. Possible values: info, low, medium, high, critical
|
||||
-author string[] execute templates that are (co-)created by the specified authors
|
||||
|
||||
OUTPUT:
|
||||
@ -111,7 +111,8 @@ OUTPUT:
|
||||
-nc, -no-color disable output content coloring (ANSI escape codes)
|
||||
-json write output in JSONL(ines) format
|
||||
-irr, -include-rr include request/response pairs in the JSONL output (for findings only)
|
||||
-nm, -no-meta don't display match metadata
|
||||
-nm, -no-meta don't display match metadata in CLI output
|
||||
-nts, -no-timestamp don't display timestamp metadata in CLI output
|
||||
-rdb, -report-db string local nuclei reporting database (always use this to persist report data)
|
||||
-me, -markdown-export string directory to export results in markdown format
|
||||
-se, -sarif-export string file to export results in SARIF format
|
||||
@ -124,7 +125,7 @@ CONFIGURATIONS:
|
||||
-r, -resolvers string file containing resolver list for nuclei
|
||||
-system-resolvers use system DNS resolving as error fallback
|
||||
-passive enable passive HTTP response processing mode
|
||||
-env-vars Enable environment variables support
|
||||
-env-vars enable environment variables support
|
||||
|
||||
INTERACTSH:
|
||||
-no-interactsh do not use interactsh server for blind interaction polling
|
||||
@ -143,8 +144,9 @@ RATE-LIMIT:
|
||||
OPTIMIZATIONS:
|
||||
-timeout int time to wait in seconds before timeout (default 5)
|
||||
-retries int number of times to retry a failed request (default 1)
|
||||
-max-host-error int max errors for a host before skipping from scan (default 30)
|
||||
-project use a project folder to avoid sending same request multiple times
|
||||
-project-path string set a specific project path (default "/var/folders/ml/m31ysb5x73l1s3kjlyn5g4180000gn/T/")
|
||||
-project-path string set a specific project path (default "$TMPDIR/")
|
||||
-spm, -stop-at-first-path stop processing HTTP requests after the first match (may break template/workflow logic)
|
||||
|
||||
HEADLESS:
|
||||
@ -165,7 +167,7 @@ DEBUG:
|
||||
UPDATE:
|
||||
-update update nuclei to the latest released version
|
||||
-ut, -update-templates update the community templates to latest released version
|
||||
-nut, -no-update-templates Do not check for nuclei-templates updates
|
||||
-nut, -no-update-templates do not check for nuclei-templates updates
|
||||
-ud, -update-directory string overwrite the default nuclei-templates directory (default "$HOME/nuclei-templates")
|
||||
|
||||
STATISTICS:
|
||||
|
||||
@ -33,8 +33,10 @@
|
||||
|
||||
# jira contains configuration options for jira issue tracker
|
||||
#jira:
|
||||
# # Cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||
# # cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||
# cloud: true
|
||||
# # update-existing is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
||||
# update-existing: false
|
||||
# # URL is the jira application url
|
||||
# url: ""
|
||||
# # account-id is the account-id of the jira user or username in case of on-prem Jira
|
||||
|
||||
@ -127,7 +127,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
createGroup(flagSet, "optimization", "Optimizations",
|
||||
flagSet.IntVar(&options.Timeout, "timeout", 5, "time to wait in seconds before timeout"),
|
||||
flagSet.IntVar(&options.Retries, "retries", 1, "number of times to retry a failed request"),
|
||||
flagSet.IntVar(&options.HostMaxErrors, "host-max-error", 30, "max errors for a host before skipping from scan"),
|
||||
flagSet.IntVar(&options.MaxHostError, "max-host-error", 30, "max errors for a host before skipping from scan"),
|
||||
|
||||
flagSet.BoolVar(&options.Project, "project", false, "use a project folder to avoid sending same request multiple times"),
|
||||
flagSet.StringVar(&options.ProjectPath, "project-path", os.TempDir(), "set a specific project path"),
|
||||
|
||||
@ -13,6 +13,7 @@ require (
|
||||
github.com/bluele/gcache v0.0.2
|
||||
github.com/c4milo/unpackit v0.1.0 // indirect
|
||||
github.com/corpix/uarand v0.1.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/go-rod/rod v0.91.1
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/gosuri/uilive v0.0.4 // indirect
|
||||
@ -23,6 +24,7 @@ require (
|
||||
github.com/karlseguin/ccache v2.0.3+incompatible
|
||||
github.com/karrick/godirwalk v1.16.1
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/miekg/dns v1.1.43
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/owenrumney/go-sarif v1.0.11
|
||||
@ -58,5 +60,7 @@ require (
|
||||
go.uber.org/ratelimit v0.2.0
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d
|
||||
golang.org/x/oauth2 v0.0.0-20210817223510-7df4dd6e12ab
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
14
v2/go.sum
14
v2/go.sum
@ -96,6 +96,7 @@ github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U=
|
||||
github.com/corpix/uarand v0.1.1/go.mod h1:SFKZvkcRoLqVRFZ4u25xPmp6m9ktANfbpXZ7SJ0/FNU=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/dave/dst v0.26.2 h1:lnxLAKI3tx7MgLNVDirFCsDTlTG9nKTk7GcptKcWSwY=
|
||||
github.com/dave/dst v0.26.2/go.mod h1:UMDJuIRPfyUCC78eFuB+SV/WI8oDeyFDvM/JR6NI3IU=
|
||||
github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ=
|
||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||
@ -228,6 +229,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA=
|
||||
github.com/itchyny/gojq v0.12.4 h1:8zgOZWMejEWCLjbF/1mWY7hY7QEARm7dtuhC6Bp4R8o=
|
||||
@ -274,6 +276,7 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
@ -281,6 +284,8 @@ github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1y
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
@ -359,6 +364,8 @@ github.com/projectdiscovery/yamldoc-go v1.0.2/go.mod h1:7uSxfMXaBmzvw8m5EhOEjB6n
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
@ -501,6 +508,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -608,6 +616,8 @@ golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210601080250-7ecdf8ef093b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -666,6 +676,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -696,6 +707,8 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@ -779,6 +792,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
mvdan.cc/gofumpt v0.1.1 h1:bi/1aS/5W00E2ny5q65w9SnKpWEF/UIOqDYBILpo9rA=
|
||||
mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
|
||||
@ -20,6 +20,6 @@ func showBanner() {
|
||||
gologger.Print().Msgf("%s\n", banner)
|
||||
gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n")
|
||||
|
||||
gologger.Warning().Msgf("Use with caution. You are responsible for your actions\n")
|
||||
gologger.Warning().Msgf("Developers assume no liability and are not responsible for any misuse or damage.\n")
|
||||
gologger.Error().Label("WRN").Msgf("Use with caution. You are responsible for your actions\n")
|
||||
gologger.Error().Label("WRN").Msgf("Developers assume no liability and are not responsible for any misuse or damage.\n")
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils/stats"
|
||||
)
|
||||
|
||||
// Runner is a client for running the enumeration process.
|
||||
@ -71,6 +72,9 @@ func New(options *types.Options) (*Runner, error) {
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
if options.Validate {
|
||||
parsers.ShouldValidate = true
|
||||
}
|
||||
if err := runner.updateTemplates(); err != nil {
|
||||
gologger.Warning().Msgf("Could not update templates: %s\n", err)
|
||||
}
|
||||
@ -297,8 +301,8 @@ func (r *Runner) RunEnumeration() error {
|
||||
r.options.ExcludedTemplates = append(r.options.ExcludedTemplates, ignoreFile.Files...)
|
||||
|
||||
var cache *hosterrorscache.Cache
|
||||
if r.options.HostMaxErrors > 0 {
|
||||
cache = hosterrorscache.New(r.options.HostMaxErrors, hosterrorscache.DefaultMaxHostsCount).SetVerbose(r.options.Verbose)
|
||||
if r.options.MaxHostError > 0 {
|
||||
cache = hosterrorscache.New(r.options.MaxHostError, hosterrorscache.DefaultMaxHostsCount).SetVerbose(r.options.Verbose)
|
||||
}
|
||||
r.hostErrors = cache
|
||||
executerOpts := protocols.ExecuterOptions{
|
||||
@ -339,14 +343,23 @@ func (r *Runner) RunEnumeration() error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not load templates from config")
|
||||
}
|
||||
store.Load()
|
||||
|
||||
if r.options.Validate {
|
||||
if err := store.ValidateTemplates(r.options.Templates, r.options.Workflows); err != nil {
|
||||
return err
|
||||
}
|
||||
gologger.Info().Msgf("All templates validated successfully\n")
|
||||
if stats.GetValue(parsers.SyntaxErrorStats) == 0 && stats.GetValue(parsers.SyntaxWarningStats) == 0 {
|
||||
gologger.Info().Msgf("All templates validated successfully\n")
|
||||
} else {
|
||||
return errors.New("encountered errors while performing template validation")
|
||||
}
|
||||
return nil // exit
|
||||
}
|
||||
store.Load()
|
||||
|
||||
// Display stats for any loaded templates syntax warnings or errors
|
||||
stats.Display(parsers.SyntaxWarningStats)
|
||||
stats.Display(parsers.SyntaxErrorStats)
|
||||
|
||||
builder := &strings.Builder{}
|
||||
if r.templatesConfig != nil && r.templatesConfig.NucleiLatestVersion != "" {
|
||||
@ -386,10 +399,11 @@ func (r *Runner) RunEnumeration() error {
|
||||
gologger.Info().Msgf("Using Interactsh Server %s", r.options.InteractshURL)
|
||||
}
|
||||
if len(store.Templates()) > 0 {
|
||||
gologger.Info().Msgf("Templates loaded: %d (New: %d)", len(store.Templates()), r.countNewTemplates())
|
||||
gologger.Info().Msgf("Templates added in last update: %d", r.countNewTemplates())
|
||||
gologger.Info().Msgf("Templates loaded for scan: %d", len(store.Templates()))
|
||||
}
|
||||
if len(store.Workflows()) > 0 {
|
||||
gologger.Info().Msgf("Workflows loaded: %d", len(store.Workflows()))
|
||||
gologger.Info().Msgf("Workflows loaded for scan: %d", len(store.Workflows()))
|
||||
}
|
||||
|
||||
// pre-parse all the templates, apply filters
|
||||
|
||||
@ -309,12 +309,12 @@
|
||||
},
|
||||
"class": {
|
||||
"enum": [
|
||||
"INET",
|
||||
"CSNET",
|
||||
"CHAOS",
|
||||
"HESIOD",
|
||||
"NONE",
|
||||
"ANY"
|
||||
"inet",
|
||||
"csnet",
|
||||
"chaos",
|
||||
"hesiod",
|
||||
"none",
|
||||
"any"
|
||||
],
|
||||
"type": "string",
|
||||
"title": "class of DNS request",
|
||||
@ -662,6 +662,11 @@
|
||||
"type": "boolean",
|
||||
"title": "preserve request history",
|
||||
"description": "Automatically assigns numbers to requests and preserves their history"
|
||||
},
|
||||
"stop-at-first-match": {
|
||||
"type": "boolean",
|
||||
"title": "stop at first match",
|
||||
"description": "Stop the execution after a match is found"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -28,7 +28,7 @@ type Config struct {
|
||||
const nucleiConfigFilename = ".templates-config.json"
|
||||
|
||||
// Version is the current version of nuclei
|
||||
const Version = `2.4.4-dev`
|
||||
const Version = `2.5.0`
|
||||
|
||||
func getConfigDetails() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
|
||||
@ -107,18 +107,18 @@ func (store *Store) ValidateTemplates(templatesList, workflowsList []string) err
|
||||
}
|
||||
|
||||
func areWorkflowsValid(store *Store, filteredWorkflowPaths map[string]struct{}) bool {
|
||||
return areWorkflowOrTemplatesValid(store, filteredWorkflowPaths, func(templatePath string, tagFilter *filter.TagFilter) (bool, error) {
|
||||
return areWorkflowOrTemplatesValid(store, filteredWorkflowPaths, true, func(templatePath string, tagFilter *filter.TagFilter) (bool, error) {
|
||||
return parsers.LoadWorkflow(templatePath)
|
||||
})
|
||||
}
|
||||
|
||||
func areTemplatesValid(store *Store, filteredTemplatePaths map[string]struct{}) bool {
|
||||
return areWorkflowOrTemplatesValid(store, filteredTemplatePaths, func(templatePath string, tagFilter *filter.TagFilter) (bool, error) {
|
||||
return areWorkflowOrTemplatesValid(store, filteredTemplatePaths, false, func(templatePath string, tagFilter *filter.TagFilter) (bool, error) {
|
||||
return parsers.LoadTemplate(templatePath, store.tagFilter, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func areWorkflowOrTemplatesValid(store *Store, filteredTemplatePaths map[string]struct{}, load func(templatePath string, tagFilter *filter.TagFilter) (bool, error)) bool {
|
||||
func areWorkflowOrTemplatesValid(store *Store, filteredTemplatePaths map[string]struct{}, isWorkflow bool, load func(templatePath string, tagFilter *filter.TagFilter) (bool, error)) bool {
|
||||
areTemplatesValid := true
|
||||
for templatePath := range filteredTemplatePaths {
|
||||
if _, err := load(templatePath, store.tagFilter); err != nil {
|
||||
@ -128,10 +128,15 @@ func areWorkflowOrTemplatesValid(store *Store, filteredTemplatePaths map[string]
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := templates.Parse(templatePath, store.preprocessor, store.config.ExecutorOptions); err != nil {
|
||||
template, err := templates.Parse(templatePath, store.preprocessor, store.config.ExecutorOptions)
|
||||
if err != nil {
|
||||
if isParsingError("Error occurred parsing template %s: %s\n", templatePath, err) {
|
||||
areTemplatesValid = false
|
||||
}
|
||||
} else {
|
||||
if !isWorkflow && len(template.Workflows) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return areTemplatesValid
|
||||
|
||||
@ -22,6 +22,7 @@ type Info struct {
|
||||
// description: |
|
||||
// Author of the template.
|
||||
//
|
||||
// Multiple values can also be specified separated by commas.
|
||||
// examples:
|
||||
// - value: "\"<username>\""
|
||||
Authors StringSlice `json:"author,omitempty" yaml:"author,omitempty" jsonschema:"title=author of the template,description=Author is the author of the template,example=username"`
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Knetic/govaluate"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/deserialization"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
"github.com/spaolacci/murmur3"
|
||||
@ -241,6 +242,11 @@ var functions = map[string]govaluate.ExpressionFunction{
|
||||
data := deserialization.GenerateJavaGadget(gadget, cmd, encoding)
|
||||
return data, nil
|
||||
},
|
||||
// for debug purposes
|
||||
"print_debug": func(args ...interface{}) (interface{}, error) {
|
||||
gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args))
|
||||
return true, nil
|
||||
},
|
||||
}
|
||||
|
||||
// HelperFunctions returns the dsl helper functions
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
type Extractor struct {
|
||||
// description: |
|
||||
// Name of the extractor. Name should be lowercase and must not contain
|
||||
// spaces or dashes (-).
|
||||
// spaces or underscores (_).
|
||||
// examples:
|
||||
// - value: "\"cookie-extractor\""
|
||||
Name string `yaml:"name,omitempty" jsonschema:"title=name of the extractor,description=Name of the extractor"`
|
||||
@ -48,18 +48,22 @@ type Extractor struct {
|
||||
regexCompiled []*regexp.Regexp
|
||||
|
||||
// description: |
|
||||
// kval contains the key-value pairs required in the response.
|
||||
// kval contains the key-value pairs present in the HTTP response header.
|
||||
// kval extractor can be used to extract HTTP response header and cookie key-value pairs.
|
||||
// kval extractor inputs are case insensitive, and does not support dash (-) in input which can replaced with underscores (_)
|
||||
// For example, Content-Type should be replaced with content_type
|
||||
//
|
||||
// Each protocol exposes a lot of different data in response. The kval
|
||||
// extractor can be used to extract those key-value pairs. A list of
|
||||
// supported parts is available in docs for request types.
|
||||
// A list of supported parts is available in docs for request types.
|
||||
// examples:
|
||||
// - name: Extract Server Header From HTTP Response
|
||||
// value: >
|
||||
// []string{"Server"}
|
||||
// []string{"server"}
|
||||
// - name: Extracting value of PHPSESSID Cookie
|
||||
// value: >
|
||||
// []string{"PHPSESSID"}
|
||||
// []string{"phpsessid"}
|
||||
// - name: Extracting value of Content-Type Cookie
|
||||
// value: >
|
||||
// []string{"content_type"}
|
||||
KVal []string `yaml:"kval,omitempty" jsonschema:"title=kval pairs to extract from response,description=Kval pairs to extract from response"`
|
||||
|
||||
// description: |
|
||||
@ -77,8 +81,6 @@ type Extractor struct {
|
||||
// examples:
|
||||
// - value: >
|
||||
// []string{"/html/body/div/p[2]/a"}
|
||||
// - value: >
|
||||
// []string{".batters | .batter | .[] | .id"}
|
||||
XPath []string `yaml:"xpath,omitempty" jsonschema:"title=html xpath expressions to extract data,description=XPath allows using xpath expressions to extract items from html response"`
|
||||
// description: |
|
||||
// Attribute is an optional attribute to extract from response XPath.
|
||||
|
||||
@ -43,7 +43,7 @@ type Matcher struct {
|
||||
|
||||
// description: |
|
||||
// Name of the matcher. Name should be lowercase and must not contain
|
||||
// spaces or dashes (-).
|
||||
// spaces or underscores (_).
|
||||
// examples:
|
||||
// - value: "\"cookie-matcher\""
|
||||
Name string `yaml:"name,omitempty" jsonschema:"title=name of the matcher,description=Name of the matcher"`
|
||||
|
||||
@ -4,14 +4,17 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/loader/filter"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates/cache"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/utils/stats"
|
||||
)
|
||||
|
||||
const mandatoryFieldMissingTemplate = "mandatory '%s' field is missing"
|
||||
@ -83,10 +86,23 @@ func validateMandatoryInfoFields(info *model.Info) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var parsedTemplatesCache *cache.Templates
|
||||
var (
|
||||
parsedTemplatesCache *cache.Templates
|
||||
ShouldValidate bool
|
||||
fieldErrorRegexp = regexp.MustCompile(`not found in`)
|
||||
)
|
||||
|
||||
const (
|
||||
SyntaxWarningStats = "syntax-warnings"
|
||||
SyntaxErrorStats = "syntax-errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
parsedTemplatesCache = cache.New()
|
||||
|
||||
stats.NewEntry(SyntaxWarningStats, "Found %d templates with syntax warning (use -validate flag for further examination)")
|
||||
stats.NewEntry(SyntaxErrorStats, "Found %d templates with syntax error (use -validate flag for further examination)")
|
||||
}
|
||||
|
||||
// ParseTemplate parses a template and returns a *templates.Template structure
|
||||
@ -107,8 +123,18 @@ func ParseTemplate(templatePath string) (*templates.Template, error) {
|
||||
}
|
||||
|
||||
template := &templates.Template{}
|
||||
if err := yaml.Unmarshal(data, template); err != nil {
|
||||
return nil, err
|
||||
if err := yaml.UnmarshalStrict(data, template); err != nil {
|
||||
errString := err.Error()
|
||||
if !fieldErrorRegexp.MatchString(errString) {
|
||||
stats.Increment(SyntaxErrorStats)
|
||||
return nil, err
|
||||
}
|
||||
stats.Increment(SyntaxWarningStats)
|
||||
if ShouldValidate {
|
||||
gologger.Error().Msgf("Syntax warnings for template %s: %s", templatePath, err)
|
||||
} else {
|
||||
gologger.Warning().Msgf("Syntax warnings for template %s: %s", templatePath, err)
|
||||
}
|
||||
}
|
||||
parsedTemplatesCache.Store(templatePath, template, nil)
|
||||
return template, nil
|
||||
|
||||
@ -16,7 +16,7 @@ import (
|
||||
// It uses an LRU cache internally for skipping unresponsive hosts
|
||||
// that remain so for a duration.
|
||||
type Cache struct {
|
||||
hostMaxErrors int
|
||||
MaxHostError int
|
||||
verbose bool
|
||||
failedTargets gcache.Cache
|
||||
}
|
||||
@ -24,11 +24,11 @@ type Cache struct {
|
||||
const DefaultMaxHostsCount = 10000
|
||||
|
||||
// New returns a new host max errors cache
|
||||
func New(hostMaxErrors, maxHostsCount int) *Cache {
|
||||
func New(MaxHostError, maxHostsCount int) *Cache {
|
||||
gc := gcache.New(maxHostsCount).
|
||||
ARC().
|
||||
Build()
|
||||
return &Cache{failedTargets: gc, hostMaxErrors: hostMaxErrors}
|
||||
return &Cache{failedTargets: gc, MaxHostError: MaxHostError}
|
||||
}
|
||||
|
||||
// SetVerbose sets the cache to log at verbose level
|
||||
@ -88,7 +88,7 @@ func (c *Cache) Check(value string) bool {
|
||||
if numberOfErrors == -1 {
|
||||
return true
|
||||
}
|
||||
if numberOfErrorsValue >= c.hostMaxErrors {
|
||||
if numberOfErrorsValue >= c.MaxHostError {
|
||||
_ = c.failedTargets.Set(finalValue, -1)
|
||||
if c.verbose {
|
||||
gologger.Verbose().Msgf("Skipping %s as previously unresponsive %d times", finalValue, numberOfErrorsValue)
|
||||
|
||||
@ -18,7 +18,7 @@ type Request struct {
|
||||
// Operators for the current request go here.
|
||||
operators.Operators `yaml:",inline"`
|
||||
|
||||
// ID is the ID of the request
|
||||
// ID is the the optional id of the request
|
||||
ID string `yaml:"id,omitempty" jsonschema:"title=id of the dns request,description=ID is the optional ID of the DNS Request"`
|
||||
|
||||
// description: |
|
||||
|
||||
@ -26,7 +26,7 @@ type Request struct {
|
||||
// - value: '[]string{".avi", ".mov", ".mp3"}'
|
||||
ExtensionDenylist []string `yaml:"denylist,omitempty" jsonschema:"title=extensions to deny match,description=List of file extensions to deny during matching"`
|
||||
|
||||
// ID is the ID of the request
|
||||
// ID is the the optional id of the request
|
||||
ID string `yaml:"id,omitempty" jsonschema:"title=id of the request,description=ID is the optional ID for the request"`
|
||||
|
||||
// description: |
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
|
||||
// Request contains a Headless protocol request to be made from a template
|
||||
type Request struct {
|
||||
// ID is the ID of the request
|
||||
// ID is the the optional id of the request
|
||||
ID string `yaml:"id,omitempty" jsonschema:"title=id of the request,description=Optional ID of the headless request"`
|
||||
|
||||
// description: |
|
||||
|
||||
@ -31,7 +31,7 @@ type Request struct {
|
||||
// value: |
|
||||
// []string{"GET /etc/passwd HTTP/1.1\nHost:\nContent-Length: 4", "POST /.%0d./.%0d./.%0d./.%0d./bin/sh HTTP/1.1\nHost: {{Hostname}}\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0\nContent-Length: 1\nConnection: close\n\necho\necho\ncat /etc/passwd 2>&1"}
|
||||
Raw []string `yaml:"raw,omitempty" jsonschema:"http requests in raw format,description=HTTP Requests in Raw Format"`
|
||||
// ID is the ID of the request
|
||||
// ID is the the optional id of the request
|
||||
ID string `yaml:"id,omitempty" jsonschema:"title=id for the http request,description=ID for the HTTP Request"`
|
||||
// description: |
|
||||
// Name is the optional name of the request.
|
||||
@ -162,7 +162,7 @@ type Request struct {
|
||||
// This allows matching on them later for multi-request conditions.
|
||||
ReqCondition bool `yaml:"req-condition,omitempty" jsonschema:"title=preserve request history,description=Automatically assigns numbers to requests and preserves their history"`
|
||||
// description: |
|
||||
// StopAtFirstMatch stops the execution of the requests as soon as a match is found.
|
||||
// StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
|
||||
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop the execution after a match is found"`
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
|
||||
// Request contains a Network protocol request to be made from a template
|
||||
type Request struct {
|
||||
// ID is the ID of the request
|
||||
// ID is the the optional id of the request
|
||||
ID string `yaml:"id,omitempty" jsonschema:"title=id of the request,description=ID of the network request"`
|
||||
|
||||
// description: |
|
||||
|
||||
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/andygrunwald/go-jira"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting/format"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||
@ -23,6 +23,8 @@ type Integration struct {
|
||||
type Options struct {
|
||||
// Cloud value is set to true when Jira cloud is used
|
||||
Cloud bool `yaml:"cloud"`
|
||||
// UpdateExisting value if true, the existing opened issue is updated
|
||||
UpdateExisting bool `yaml:"update-existing"`
|
||||
// URL is the URL of the jira server
|
||||
URL string `yaml:"url"`
|
||||
// AccountID is the accountID of the jira user.
|
||||
@ -54,8 +56,8 @@ func New(options *Options) (*Integration, error) {
|
||||
return &Integration{jira: jiraClient, options: options}, nil
|
||||
}
|
||||
|
||||
// CreateIssue creates an issue in the tracker
|
||||
func (i *Integration) CreateIssue(event *output.ResultEvent) error {
|
||||
// CreateNewIssue creates a new issue in the tracker
|
||||
func (i *Integration) CreateNewIssue(event *output.ResultEvent) error {
|
||||
summary := format.Summary(event)
|
||||
|
||||
fields := &jira.IssueFields{
|
||||
@ -92,6 +94,52 @@ func (i *Integration) CreateIssue(event *output.ResultEvent) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateIssue creates an issue in the tracker or updates the existing one
|
||||
func (i *Integration) CreateIssue(event *output.ResultEvent) error {
|
||||
if i.options.UpdateExisting {
|
||||
issueID, err := i.FindExistingIssue(event)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if issueID != "" {
|
||||
_, _, err = i.jira.Issue.AddComment(issueID, &jira.Comment{
|
||||
Body: jiraFormatDescription(event),
|
||||
})
|
||||
return err
|
||||
}
|
||||
}
|
||||
return i.CreateNewIssue(event)
|
||||
}
|
||||
|
||||
// FindExistingIssue checks if the issue already exists and returns its ID
|
||||
func (i *Integration) FindExistingIssue(event *output.ResultEvent) (string, error) {
|
||||
template := format.GetMatchedTemplate(event)
|
||||
jql := fmt.Sprintf("summary ~ \"%s\" AND summary ~ \"%s\" AND status = \"Open\"", template, event.Host)
|
||||
|
||||
searchOptions := &jira.SearchOptions{
|
||||
MaxResults: 1, // if any issue exists, then we won't create a new one
|
||||
}
|
||||
|
||||
chunk, resp, err := i.jira.Issue.Search(jql, searchOptions)
|
||||
if err != nil {
|
||||
var data string
|
||||
if resp != nil && resp.Body != nil {
|
||||
d, _ := ioutil.ReadAll(resp.Body)
|
||||
data = string(d)
|
||||
}
|
||||
return "", fmt.Errorf("%s => %s", err, data)
|
||||
}
|
||||
|
||||
switch resp.Total {
|
||||
case 0:
|
||||
return "", nil
|
||||
case 1:
|
||||
return chunk[0].ID, nil
|
||||
default:
|
||||
gologger.Warning().Msgf("Discovered multiple opened issues %s for the host %s: The issue [%s] will be updated.", template, event.Host, chunk[0].ID)
|
||||
return chunk[0].ID, nil
|
||||
}
|
||||
}
|
||||
|
||||
// jiraFormatDescription formats a short description of the generated
|
||||
// event by the nuclei scanner in Jira format.
|
||||
func jiraFormatDescription(event *output.ResultEvent) string { // TODO remove the code duplication: format.go <-> jira.go
|
||||
|
||||
@ -4,13 +4,11 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/executer"
|
||||
@ -21,7 +19,6 @@ import (
|
||||
|
||||
var (
|
||||
ErrCreateTemplateExecutor = errors.New("cannot create template executer")
|
||||
fieldErrorRegexp = regexp.MustCompile(`not found in`)
|
||||
)
|
||||
|
||||
var parsedTemplatesCache *cache.Templates
|
||||
@ -56,11 +53,8 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Execute
|
||||
data = preprocessor.Process(data)
|
||||
}
|
||||
|
||||
if err := yaml.UnmarshalStrict(data, template); err != nil {
|
||||
if !fieldErrorRegexp.MatchString(err.Error()) {
|
||||
return nil, err
|
||||
}
|
||||
gologger.Warning().Msgf("Unrecognized fields in template %s: %s", filePath, err)
|
||||
if err := yaml.Unmarshal(data, template); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if utils.IsBlank(template.Info.Name) {
|
||||
|
||||
@ -108,7 +108,7 @@ func init() {
|
||||
MODELInfoDoc.Fields[1].Name = "author"
|
||||
MODELInfoDoc.Fields[1].Type = "StringSlice"
|
||||
MODELInfoDoc.Fields[1].Note = ""
|
||||
MODELInfoDoc.Fields[1].Description = "Author of the template."
|
||||
MODELInfoDoc.Fields[1].Description = "Author of the template.\n\nMultiple values can also be specified separated by commas."
|
||||
MODELInfoDoc.Fields[1].Comments[encoder.LineComment] = "Author of the template."
|
||||
|
||||
MODELInfoDoc.Fields[1].AddExample("", "<username>")
|
||||
@ -188,7 +188,7 @@ func init() {
|
||||
FieldName: "requests",
|
||||
},
|
||||
}
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 24)
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 25)
|
||||
HTTPRequestDoc.Fields[0].Name = "matchers"
|
||||
HTTPRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
||||
HTTPRequestDoc.Fields[0].Note = ""
|
||||
@ -225,8 +225,8 @@ func init() {
|
||||
HTTPRequestDoc.Fields[5].Name = "id"
|
||||
HTTPRequestDoc.Fields[5].Type = "string"
|
||||
HTTPRequestDoc.Fields[5].Note = ""
|
||||
HTTPRequestDoc.Fields[5].Description = "ID is the ID of the request"
|
||||
HTTPRequestDoc.Fields[5].Comments[encoder.LineComment] = " ID is the ID of the request"
|
||||
HTTPRequestDoc.Fields[5].Description = "ID is the the optional id of the request"
|
||||
HTTPRequestDoc.Fields[5].Comments[encoder.LineComment] = " ID is the the optional id of the request"
|
||||
HTTPRequestDoc.Fields[6].Name = "name"
|
||||
HTTPRequestDoc.Fields[6].Type = "string"
|
||||
HTTPRequestDoc.Fields[6].Note = ""
|
||||
@ -349,6 +349,11 @@ func init() {
|
||||
HTTPRequestDoc.Fields[23].Note = ""
|
||||
HTTPRequestDoc.Fields[23].Description = "ReqCondition automatically assigns numbers to requests and preserves their history.\n\nThis allows matching on them later for multi-request conditions."
|
||||
HTTPRequestDoc.Fields[23].Comments[encoder.LineComment] = "ReqCondition automatically assigns numbers to requests and preserves their history."
|
||||
HTTPRequestDoc.Fields[24].Name = "stop-at-first-match"
|
||||
HTTPRequestDoc.Fields[24].Type = "bool"
|
||||
HTTPRequestDoc.Fields[24].Note = ""
|
||||
HTTPRequestDoc.Fields[24].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
HTTPRequestDoc.Fields[24].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
|
||||
MATCHERSMatcherDoc.Type = "matchers.Matcher"
|
||||
MATCHERSMatcherDoc.Comments[encoder.LineComment] = " Matcher is used to match a part in the output from a protocol."
|
||||
@ -415,7 +420,7 @@ func init() {
|
||||
MATCHERSMatcherDoc.Fields[4].Name = "name"
|
||||
MATCHERSMatcherDoc.Fields[4].Type = "string"
|
||||
MATCHERSMatcherDoc.Fields[4].Note = ""
|
||||
MATCHERSMatcherDoc.Fields[4].Description = "Name of the matcher. Name should be lowercase and must not contain\nspaces or dashes (-)."
|
||||
MATCHERSMatcherDoc.Fields[4].Description = "Name of the matcher. Name should be lowercase and must not contain\nspaces or underscores (_)."
|
||||
MATCHERSMatcherDoc.Fields[4].Comments[encoder.LineComment] = "Name of the matcher. Name should be lowercase and must not contain"
|
||||
|
||||
MATCHERSMatcherDoc.Fields[4].AddExample("", "cookie-matcher")
|
||||
@ -507,7 +512,7 @@ func init() {
|
||||
EXTRACTORSExtractorDoc.Fields[0].Name = "name"
|
||||
EXTRACTORSExtractorDoc.Fields[0].Type = "string"
|
||||
EXTRACTORSExtractorDoc.Fields[0].Note = ""
|
||||
EXTRACTORSExtractorDoc.Fields[0].Description = "Name of the extractor. Name should be lowercase and must not contain\nspaces or dashes (-)."
|
||||
EXTRACTORSExtractorDoc.Fields[0].Description = "Name of the extractor. Name should be lowercase and must not contain\nspaces or underscores (_)."
|
||||
EXTRACTORSExtractorDoc.Fields[0].Comments[encoder.LineComment] = "Name of the extractor. Name should be lowercase and must not contain"
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[0].AddExample("", "cookie-extractor")
|
||||
@ -525,8 +530,8 @@ func init() {
|
||||
EXTRACTORSExtractorDoc.Fields[2].Name = "regex"
|
||||
EXTRACTORSExtractorDoc.Fields[2].Type = "[]string"
|
||||
EXTRACTORSExtractorDoc.Fields[2].Note = ""
|
||||
EXTRACTORSExtractorDoc.Fields[2].Description = "Regex contains the regular expression patterns to exract from a part.\n\nGo regex engine does not supports lookaheads or lookbehinds, so as a result\nthey are also not supported in nuclei."
|
||||
EXTRACTORSExtractorDoc.Fields[2].Comments[encoder.LineComment] = "Regex contains the regular expression patterns to exract from a part."
|
||||
EXTRACTORSExtractorDoc.Fields[2].Description = "Regex contains the regular expression patterns to extract from a part.\n\nGo regex engine does not support lookaheads or lookbehinds, so as a result\nthey are also not supported in nuclei."
|
||||
EXTRACTORSExtractorDoc.Fields[2].Comments[encoder.LineComment] = "Regex contains the regular expression patterns to extract from a part."
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[2].AddExample("Braintree Access Token Regex", []string{"access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}"})
|
||||
|
||||
@ -541,12 +546,8 @@ func init() {
|
||||
EXTRACTORSExtractorDoc.Fields[4].Name = "kval"
|
||||
EXTRACTORSExtractorDoc.Fields[4].Type = "[]string"
|
||||
EXTRACTORSExtractorDoc.Fields[4].Note = ""
|
||||
EXTRACTORSExtractorDoc.Fields[4].Description = "kval contains the key-value pairs required in the response.\n\nEach protocol exposes a lot of different data in response. The kval\nextractor can be used to extract those key-value pairs. A list of\nsupported parts is available in docs for request types."
|
||||
EXTRACTORSExtractorDoc.Fields[4].Comments[encoder.LineComment] = "kval contains the key-value pairs required in the response."
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[4].AddExample("Extract Server Header From HTTP Response", []string{"Server"})
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[4].AddExample("Extracting value of PHPSESSID Cookie", []string{"PHPSESSID"})
|
||||
EXTRACTORSExtractorDoc.Fields[4].Description = "description: |\n kval contains the key-value pairs present in the HTTP response header.\n kval extractor can be used to extract HTTP response header and cookie key-value pairs.\n kval extractor inputs are case insensitive, and does not support dash (-) in input which can replaced with underscores (_)\n For example, Content-Type should be replaced with content_type\n\n A list of supported parts is available in docs for request types.\n examples:\n - name: Extract Server Header From HTTP Response\n value: >\n []string{\"server\"}\n - name: Extracting value of PHPSESSID Cookie\n value: >\n []string{\"phpsessid\"}\n - name: Extracting value of Content-Type Cookie\n value: >\n []string{\"content_type\"}"
|
||||
EXTRACTORSExtractorDoc.Fields[4].Comments[encoder.LineComment] = " description: |"
|
||||
EXTRACTORSExtractorDoc.Fields[5].Name = "json"
|
||||
EXTRACTORSExtractorDoc.Fields[5].Type = "[]string"
|
||||
EXTRACTORSExtractorDoc.Fields[5].Note = ""
|
||||
@ -563,8 +564,6 @@ func init() {
|
||||
EXTRACTORSExtractorDoc.Fields[6].Comments[encoder.LineComment] = "XPath allows using xpath expressions to extract items from html response"
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[6].AddExample("", []string{"/html/body/div/p[2]/a"})
|
||||
|
||||
EXTRACTORSExtractorDoc.Fields[6].AddExample("", []string{".batters | .batter | .[] | .id"})
|
||||
EXTRACTORSExtractorDoc.Fields[7].Name = "attribute"
|
||||
EXTRACTORSExtractorDoc.Fields[7].Type = "string"
|
||||
EXTRACTORSExtractorDoc.Fields[7].Note = ""
|
||||
@ -621,8 +620,8 @@ func init() {
|
||||
DNSRequestDoc.Fields[3].Name = "id"
|
||||
DNSRequestDoc.Fields[3].Type = "string"
|
||||
DNSRequestDoc.Fields[3].Note = ""
|
||||
DNSRequestDoc.Fields[3].Description = "ID is the ID of the request"
|
||||
DNSRequestDoc.Fields[3].Comments[encoder.LineComment] = " ID is the ID of the request"
|
||||
DNSRequestDoc.Fields[3].Description = "ID is the the optional id of the request"
|
||||
DNSRequestDoc.Fields[3].Comments[encoder.LineComment] = " ID is the the optional id of the request"
|
||||
DNSRequestDoc.Fields[4].Name = "name"
|
||||
DNSRequestDoc.Fields[4].Type = "string"
|
||||
DNSRequestDoc.Fields[4].Note = ""
|
||||
@ -652,12 +651,12 @@ func init() {
|
||||
DNSRequestDoc.Fields[6].Description = "Class is the class of the DNS request.\n\nUsually it's enough to just leave it as INET."
|
||||
DNSRequestDoc.Fields[6].Comments[encoder.LineComment] = "Class is the class of the DNS request."
|
||||
DNSRequestDoc.Fields[6].Values = []string{
|
||||
"INET",
|
||||
"CSNET",
|
||||
"CHAOS",
|
||||
"HESIOD",
|
||||
"NONE",
|
||||
"ANY",
|
||||
"inet",
|
||||
"csnet",
|
||||
"chaos",
|
||||
"hesiod",
|
||||
"none",
|
||||
"any",
|
||||
}
|
||||
DNSRequestDoc.Fields[7].Name = "retries"
|
||||
DNSRequestDoc.Fields[7].Type = "int"
|
||||
@ -720,8 +719,8 @@ func init() {
|
||||
FILERequestDoc.Fields[5].Name = "id"
|
||||
FILERequestDoc.Fields[5].Type = "string"
|
||||
FILERequestDoc.Fields[5].Note = ""
|
||||
FILERequestDoc.Fields[5].Description = "ID is the ID of the request"
|
||||
FILERequestDoc.Fields[5].Comments[encoder.LineComment] = " ID is the ID of the request"
|
||||
FILERequestDoc.Fields[5].Description = "ID is the the optional id of the request"
|
||||
FILERequestDoc.Fields[5].Comments[encoder.LineComment] = " ID is the the optional id of the request"
|
||||
FILERequestDoc.Fields[6].Name = "max-size"
|
||||
FILERequestDoc.Fields[6].Type = "int"
|
||||
FILERequestDoc.Fields[6].Note = ""
|
||||
@ -750,8 +749,8 @@ func init() {
|
||||
NETWORKRequestDoc.Fields[0].Name = "id"
|
||||
NETWORKRequestDoc.Fields[0].Type = "string"
|
||||
NETWORKRequestDoc.Fields[0].Note = ""
|
||||
NETWORKRequestDoc.Fields[0].Description = "ID is the ID of the request"
|
||||
NETWORKRequestDoc.Fields[0].Comments[encoder.LineComment] = " ID is the ID of the request"
|
||||
NETWORKRequestDoc.Fields[0].Description = "ID is the the optional id of the request"
|
||||
NETWORKRequestDoc.Fields[0].Comments[encoder.LineComment] = " ID is the the optional id of the request"
|
||||
NETWORKRequestDoc.Fields[1].Name = "host"
|
||||
NETWORKRequestDoc.Fields[1].Type = "[]string"
|
||||
NETWORKRequestDoc.Fields[1].Note = ""
|
||||
@ -862,8 +861,8 @@ func init() {
|
||||
HEADLESSRequestDoc.Fields[0].Name = "id"
|
||||
HEADLESSRequestDoc.Fields[0].Type = "string"
|
||||
HEADLESSRequestDoc.Fields[0].Note = ""
|
||||
HEADLESSRequestDoc.Fields[0].Description = "ID is the ID of the request"
|
||||
HEADLESSRequestDoc.Fields[0].Comments[encoder.LineComment] = " ID is the ID of the request"
|
||||
HEADLESSRequestDoc.Fields[0].Description = "ID is the the optional id of the request"
|
||||
HEADLESSRequestDoc.Fields[0].Comments[encoder.LineComment] = " ID is the the optional id of the request"
|
||||
HEADLESSRequestDoc.Fields[1].Name = "steps"
|
||||
HEADLESSRequestDoc.Fields[1].Type = "[]engine.Action"
|
||||
HEADLESSRequestDoc.Fields[1].Note = ""
|
||||
|
||||
@ -16,10 +16,10 @@ import (
|
||||
var (
|
||||
exampleInfoStructure = model.Info{
|
||||
Name: "Argument Injection in Ruby Dragonfly",
|
||||
Authors: model.StringSlice{[]string{"0xspara"}},
|
||||
Authors: model.StringSlice{"0xspara"},
|
||||
SeverityHolder: severity.SeverityHolder{severity.High},
|
||||
Reference: model.StringSlice{"https://zxsecurity.co.nz/research/argunment-injection-ruby-dragonfly/"},
|
||||
Tags: model.StringSlice{[]string{"cve,cve2021,rce,ruby"}},
|
||||
Tags: model.StringSlice{"cve,cve2021,rce,ruby"},
|
||||
}
|
||||
exampleNormalHTTPRequest = &http.Request{
|
||||
Method: "GET",
|
||||
|
||||
@ -65,8 +65,8 @@ type Options struct {
|
||||
StatsInterval int
|
||||
// MetricsPort is the port to show metrics on
|
||||
MetricsPort int
|
||||
// HostMaxErrors is the maximum number of errors allowed for a host
|
||||
HostMaxErrors int
|
||||
// MaxHostError is the maximum number of errors allowed for a host
|
||||
MaxHostError int
|
||||
// BulkSize is the of targets analyzed in parallel for each template
|
||||
BulkSize int
|
||||
// TemplateThreads is the number of templates executed in parallel
|
||||
|
||||
3
v2/pkg/utils/stats/doc.go
Normal file
3
v2/pkg/utils/stats/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package stats provides a storage mechanism for storing
|
||||
// and display vital statistics of the engine at various durations.
|
||||
package stats
|
||||
99
v2/pkg/utils/stats/stats.go
Normal file
99
v2/pkg/utils/stats/stats.go
Normal file
@ -0,0 +1,99 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
)
|
||||
|
||||
// Storage is a storage for storing statistics information
|
||||
// about the nuclei engine displaying it at user-defined intervals.
|
||||
type Storage struct {
|
||||
data map[string]*storageDataItem
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
type storageDataItem struct {
|
||||
description string
|
||||
value int64
|
||||
}
|
||||
|
||||
var Default *Storage
|
||||
|
||||
func init() {
|
||||
Default = New()
|
||||
}
|
||||
|
||||
// NewEntry creates a new entry in the storage object
|
||||
func NewEntry(name, description string) {
|
||||
Default.NewEntry(name, description)
|
||||
}
|
||||
|
||||
// Increment incrmements the value for a name string
|
||||
func Increment(name string) {
|
||||
Default.Increment(name)
|
||||
}
|
||||
|
||||
// Display displays the stats for a name
|
||||
func Display(name string) {
|
||||
Default.Display(name)
|
||||
}
|
||||
|
||||
// GetValue returns the value for a set variable
|
||||
func GetValue(name string) int64 {
|
||||
return Default.GetValue(name)
|
||||
}
|
||||
|
||||
// New creates a new storage object
|
||||
func New() *Storage {
|
||||
return &Storage{data: make(map[string]*storageDataItem), mutex: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// NewEntry creates a new entry in the storage object
|
||||
func (s *Storage) NewEntry(name, description string) {
|
||||
s.mutex.Lock()
|
||||
s.data[name] = &storageDataItem{description: description, value: 0}
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
// Increment incrmements the value for a name string
|
||||
func (s *Storage) Increment(name string) {
|
||||
s.mutex.RLock()
|
||||
data, ok := s.data[name]
|
||||
s.mutex.RUnlock()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
atomic.AddInt64(&data.value, 1)
|
||||
}
|
||||
|
||||
// Display displays the stats for a name
|
||||
func (s *Storage) Display(name string) {
|
||||
s.mutex.RLock()
|
||||
data, ok := s.data[name]
|
||||
s.mutex.RUnlock()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
dataValue := atomic.LoadInt64(&data.value)
|
||||
if dataValue == 0 {
|
||||
return // don't show for nil stats
|
||||
}
|
||||
gologger.Error().Label("WRN").Msgf(data.description, dataValue)
|
||||
}
|
||||
|
||||
// GetValue returns the value for a set variable
|
||||
func (s *Storage) GetValue(name string) int64 {
|
||||
s.mutex.RLock()
|
||||
data, ok := s.data[name]
|
||||
s.mutex.RUnlock()
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
dataValue := atomic.LoadInt64(&data.value)
|
||||
return dataValue
|
||||
}
|
||||
@ -60,10 +60,8 @@ Examples:
|
||||
```yaml
|
||||
info:
|
||||
name: Argument Injection in Ruby Dragonfly
|
||||
author:
|
||||
- 0xspara
|
||||
tags:
|
||||
- cve,cve2021,rce,ruby
|
||||
author: 0xspara
|
||||
tags: cve,cve2021,rce,ruby
|
||||
reference: https://zxsecurity.co.nz/research/argunment-injection-ruby-dragonfly/
|
||||
severity: high
|
||||
```
|
||||
@ -248,10 +246,8 @@ Appears in:
|
||||
|
||||
```yaml
|
||||
name: Argument Injection in Ruby Dragonfly
|
||||
author:
|
||||
- 0xspara
|
||||
tags:
|
||||
- cve,cve2021,rce,ruby
|
||||
author: 0xspara
|
||||
tags: cve,cve2021,rce,ruby
|
||||
reference: https://zxsecurity.co.nz/research/argunment-injection-ruby-dragonfly/
|
||||
severity: high
|
||||
```
|
||||
@ -294,6 +290,8 @@ name: Nagios Default Credentials Check
|
||||
|
||||
Author of the template.
|
||||
|
||||
Multiple values can also be specified separated by commas.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
@ -620,7 +618,7 @@ raw:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
ID is the ID of the request
|
||||
ID is the the optional id of the request
|
||||
|
||||
</div>
|
||||
|
||||
@ -1005,6 +1003,19 @@ This allows matching on them later for multi-request conditions.
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>stop-at-first-match</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1130,7 +1141,7 @@ It will only match if the condition is not true.
|
||||
<div class="dt">
|
||||
|
||||
Name of the matcher. Name should be lowercase and must not contain
|
||||
spaces or dashes (-).
|
||||
spaces or underscores (_).
|
||||
|
||||
|
||||
|
||||
@ -1373,7 +1384,7 @@ Appears in:
|
||||
<div class="dt">
|
||||
|
||||
Name of the extractor. Name should be lowercase and must not contain
|
||||
spaces or dashes (-).
|
||||
spaces or underscores (_).
|
||||
|
||||
|
||||
|
||||
@ -1420,9 +1431,9 @@ Valid values:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Regex contains the regular expression patterns to exract from a part.
|
||||
Regex contains the regular expression patterns to extract from a part.
|
||||
|
||||
Go regex engine does not supports lookaheads or lookbehinds, so as a result
|
||||
Go regex engine does not support lookaheads or lookbehinds, so as a result
|
||||
they are also not supported in nuclei.
|
||||
|
||||
|
||||
@ -1478,29 +1489,23 @@ group: 1
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
kval contains the key-value pairs required in the response.
|
||||
|
||||
Each protocol exposes a lot of different data in response. The kval
|
||||
extractor can be used to extract those key-value pairs. A list of
|
||||
supported parts is available in docs for request types.
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
```yaml
|
||||
# Extract Server Header From HTTP Response
|
||||
kval:
|
||||
- Server
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Extracting value of PHPSESSID Cookie
|
||||
kval:
|
||||
- PHPSESSID
|
||||
```
|
||||
description: |
|
||||
kval contains the key-value pairs present in the HTTP response header.
|
||||
kval extractor can be used to extract HTTP response header and cookie key-value pairs.
|
||||
kval extractor inputs are case insensitive, and does not support dash (-) in input which can replaced with underscores (_)
|
||||
For example, Content-Type should be replaced with content_type
|
||||
|
||||
A list of supported parts is available in docs for request types.
|
||||
examples:
|
||||
- name: Extract Server Header From HTTP Response
|
||||
value: >
|
||||
[]string{"server"}
|
||||
- name: Extracting value of PHPSESSID Cookie
|
||||
value: >
|
||||
[]string{"phpsessid"}
|
||||
- name: Extracting value of Content-Type Cookie
|
||||
value: >
|
||||
[]string{"content_type"}
|
||||
|
||||
</div>
|
||||
|
||||
@ -1554,11 +1559,6 @@ xpath:
|
||||
- /html/body/div/p[2]/a
|
||||
```
|
||||
|
||||
```yaml
|
||||
xpath:
|
||||
- .batters | .batter | .[] | .id
|
||||
```
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@ -1718,7 +1718,7 @@ Valid values:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
ID is the ID of the request
|
||||
ID is the the optional id of the request
|
||||
|
||||
</div>
|
||||
|
||||
@ -1798,17 +1798,17 @@ Usually it's enough to just leave it as INET.
|
||||
Valid values:
|
||||
|
||||
|
||||
- <code>INET</code>
|
||||
- <code>inet</code>
|
||||
|
||||
- <code>CSNET</code>
|
||||
- <code>csnet</code>
|
||||
|
||||
- <code>CHAOS</code>
|
||||
- <code>chaos</code>
|
||||
|
||||
- <code>HESIOD</code>
|
||||
- <code>hesiod</code>
|
||||
|
||||
- <code>NONE</code>
|
||||
- <code>none</code>
|
||||
|
||||
- <code>ANY</code>
|
||||
- <code>any</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
@ -1988,7 +1988,7 @@ denylist:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
ID is the ID of the request
|
||||
ID is the the optional id of the request
|
||||
|
||||
</div>
|
||||
|
||||
@ -2068,7 +2068,7 @@ matchers:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
ID is the ID of the request
|
||||
ID is the the optional id of the request
|
||||
|
||||
</div>
|
||||
|
||||
@ -2374,7 +2374,7 @@ Appears in:
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
ID is the ID of the request
|
||||
ID is the the optional id of the request
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user