mirror of https://github.com/daffainfo/nuclei.git
commit
d851ecdf05
|
@ -0,0 +1,29 @@
|
|||
name: 📑 Template-DB Indexer
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
index:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
|
||||
- name: Intalling Indexer
|
||||
run: |
|
||||
git config --global url."https://${{ secrets.ACCESS_TOKEN }}@github".insteadOf https://github
|
||||
git clone https://github.com/projectdiscovery/nucleish-api.git
|
||||
cd nucleish-api/cmd/generate-index/
|
||||
go install
|
||||
|
||||
- name: Generate Index
|
||||
env:
|
||||
AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
|
||||
AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }}
|
||||
run: |
|
||||
generate-index -mode changelog
|
|
@ -24,6 +24,7 @@ jobs:
|
|||
- name: Functional Tests
|
||||
env:
|
||||
GH_ACTION: true
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
run: |
|
||||
chmod +x run.sh
|
||||
bash run.sh ${{ matrix.os }}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: 🙏🏻 Lint Test
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
@ -9,10 +10,14 @@ jobs:
|
|||
name: Lint Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
uses: golangci/golangci-lint-action@v3.1.0
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 5m
|
||||
|
|
|
@ -95,7 +95,7 @@ Flags:
|
|||
TARGET:
|
||||
-u, -target string[] target URLs/hosts to scan
|
||||
-l, -list string path to file containing a list of target URLs/hosts to scan (one per line)
|
||||
-resume Resume scan using resume.cfg (clustering will be disabled)
|
||||
-resume string Resume scan using resume.cfg (clustering will be disabled)
|
||||
|
||||
TEMPLATES:
|
||||
-nt, -new-templates run only new templates added in latest nuclei-templates release
|
||||
|
@ -115,8 +115,8 @@ FILTERING:
|
|||
-eid, -exclude-id string[] templates to exclude based on template ids (comma-separated, file)
|
||||
-it, -include-templates string[] templates to be executed even if they are excluded either by default or configuration
|
||||
-et, -exclude-templates string[] template or template directory to exclude (comma-separated, file)
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical
|
||||
-s, -severity value[] templates to run based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-es, -exclude-severity value[] templates to exclude based on severity. Possible values: info, low, medium, high, critical, unknown
|
||||
-pt, -type value[] templates to run based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
-ept, -exclude-type value[] templates to exclude based on protocol type. Possible values: dns, file, http, headless, network, workflow, ssl, websocket, whois
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ Severity of the template.
|
|||
|
||||
<div class="dd">
|
||||
|
||||
<code>metadata</code> <i>map[string]string</i>
|
||||
<code>metadata</code> <i>map[string]interface{}</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
@ -633,6 +633,8 @@ Enum Values:
|
|||
- <code>high</code>
|
||||
|
||||
- <code>critical</code>
|
||||
|
||||
- <code>unknown</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
@ -1232,6 +1234,20 @@ all requests defined in raw section.
|
|||
|
||||
<div class="dd">
|
||||
|
||||
<code>read-all</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Enables force reading of the entire raw unsafe request body ignoring
|
||||
any specified content length headers.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>redirects</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
|
@ -3204,6 +3220,34 @@ Steps is the list of actions to run for headless request
|
|||
|
||||
<div class="dd">
|
||||
|
||||
<code>user_agent</code> <i><a href="#useragentuseragentholder">userAgent.UserAgentHolder</a></i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
descriptions: |
|
||||
User-Agent is the type of user-agent to use for the request.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>custom_user_agent</code> <i>string</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
description: |
|
||||
If UserAgent is set to custom, customUserAgent is the custom user-agent to use for the request.
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>matchers</code> <i>[]<a href="#matchersmatcher">matchers.Matcher</a></i>
|
||||
|
||||
</div>
|
||||
|
@ -3416,6 +3460,48 @@ Enum Values:
|
|||
|
||||
|
||||
|
||||
## userAgent.UserAgentHolder
|
||||
UserAgentHolder holds a UserAgent type. Required for un/marshalling purposes
|
||||
|
||||
Appears in:
|
||||
|
||||
|
||||
- <code><a href="#headlessrequest">headless.Request</a>.user_agent</code>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code></code> <i>UserAgent</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
|
||||
|
||||
|
||||
Enum Values:
|
||||
|
||||
|
||||
- <code>random</code>
|
||||
|
||||
- <code>off</code>
|
||||
|
||||
- <code>default</code>
|
||||
|
||||
- <code>custom</code>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## ssl.Request
|
||||
Request is a request for the SSL protocol
|
||||
|
||||
|
|
|
@ -6,12 +6,18 @@ cd ../v2/cmd/nuclei
|
|||
go build
|
||||
mv nuclei ../../../integration_tests/nuclei
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build nuclei integration-test"
|
||||
cd ../integration-test
|
||||
go build
|
||||
mv integration-test ../../../integration_tests/integration-test
|
||||
cd ../../../integration_tests
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Installing nuclei templates"
|
||||
./nuclei -update-templates
|
||||
echo "::endgroup::"
|
||||
|
||||
./integration-test
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"metadata": {
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
"type": "string"
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
|
@ -103,7 +103,8 @@
|
|||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"critical"
|
||||
"critical",
|
||||
"unknown"
|
||||
],
|
||||
"type": "string",
|
||||
"title": "severity of the template",
|
||||
|
@ -119,6 +120,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"userAgent.UserAgentHolder": {
|
||||
"enum": [
|
||||
"off",
|
||||
"default",
|
||||
"custom"
|
||||
],
|
||||
"type": "string",
|
||||
"title": "userAgent for the headless",
|
||||
"description": "userAgent for the headless http request"
|
||||
},
|
||||
"extractors.Extractor": {
|
||||
"required": [
|
||||
"type"
|
||||
|
@ -531,6 +542,17 @@
|
|||
"title": "list of actions for headless request",
|
||||
"description": "List of actions to run for headless request"
|
||||
},
|
||||
"user_agent": {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$ref": "#/definitions/userAgent.UserAgentHolder",
|
||||
"title": "user agent for the headless request",
|
||||
"description": "User agent for the headless request"
|
||||
},
|
||||
"custom_user_agent": {
|
||||
"type": "string",
|
||||
"title": "custom user agent for the headless request",
|
||||
"description": "Custom user agent for the headless request"
|
||||
},
|
||||
"matchers": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/matchers.Matcher"
|
||||
|
@ -774,6 +796,11 @@
|
|||
"title": "optional cookie reuse enable",
|
||||
"description": "Optional setting that enables cookie reuse"
|
||||
},
|
||||
"read-all": {
|
||||
"type": "boolean",
|
||||
"title": "force read all body",
|
||||
"description": "Enables force reading of entire unsafe http request body"
|
||||
},
|
||||
"redirects": {
|
||||
"type": "boolean",
|
||||
"title": "follow http redirects",
|
||||
|
|
|
@ -3,36 +3,48 @@ before:
|
|||
- go mod tidy
|
||||
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- windows
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm
|
||||
- arm64
|
||||
|
||||
- main: cmd/nuclei/main.go
|
||||
binary: nuclei
|
||||
id: nuclei-cli
|
||||
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
goos: [windows,linux,darwin]
|
||||
goarch: [amd64,386,arm,arm64]
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: '386'
|
||||
goarch: 386
|
||||
- goos: windows
|
||||
goarch: 'arm'
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
goarch: 'arm64'
|
||||
|
||||
binary: '{{ .ProjectName }}'
|
||||
main: cmd/nuclei/main.go
|
||||
goarch: arm64
|
||||
|
||||
flags:
|
||||
- -trimpath
|
||||
|
||||
- main: cmd/cve-annotate/main.go
|
||||
binary: cve-annotate
|
||||
id: annotate
|
||||
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
goos: [linux]
|
||||
goarch: [amd64]
|
||||
|
||||
archives:
|
||||
- format: zip
|
||||
id: nuclei
|
||||
builds: [nuclei-cli]
|
||||
replacements:
|
||||
darwin: macOS
|
||||
|
||||
- format: zip
|
||||
id: annotate
|
||||
builds: [annotate]
|
||||
name_template: "{{ .Binary }}"
|
||||
|
||||
checksum:
|
||||
algorithm: sha256
|
||||
|
|
|
@ -15,6 +15,10 @@ echo "::group::Building Nuclei binary from current branch"
|
|||
go build -o nuclei_dev$extension ../nuclei
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Installing nuclei templates"
|
||||
./nuclei_dev$extension -update-templates
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Building latest release of nuclei"
|
||||
go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei
|
||||
echo "::endgroup::"
|
||||
|
|
|
@ -50,7 +50,7 @@ func main() {
|
|||
nucleiRunner.Close()
|
||||
if options.ShouldSaveResume() {
|
||||
gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
||||
err := nucleiRunner.SaveResumeConfig()
|
||||
err := nucleiRunner.SaveResumeConfig(resumeFileName)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Couldn't create resume file: %s\n", err)
|
||||
}
|
||||
|
@ -60,7 +60,11 @@ func main() {
|
|||
}()
|
||||
|
||||
if err := nucleiRunner.RunEnumeration(); err != nil {
|
||||
gologger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
||||
if options.Validate {
|
||||
gologger.Fatal().Msgf("Could not validate templates: %s\n", err)
|
||||
} else {
|
||||
gologger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
||||
}
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
// on successful execution remove the resume file in case it exists
|
||||
|
@ -84,7 +88,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
|||
createGroup(flagSet, "input", "Target",
|
||||
flagSet.StringSliceVarP(&options.Targets, "target", "u", []string{}, "target URLs/hosts to scan"),
|
||||
flagSet.StringVarP(&options.TargetsFilePath, "list", "l", "", "path to file containing a list of target URLs/hosts to scan (one per line)"),
|
||||
flagSet.BoolVar(&options.Resume, "resume", false, "Resume scan using resume.cfg (clustering will be disabled)"),
|
||||
flagSet.StringVar(&options.Resume, "resume", "", "Resume scan using resume.cfg (clustering will be disabled)"),
|
||||
)
|
||||
|
||||
createGroup(flagSet, "templates", "Templates",
|
||||
|
|
20
v2/go.mod
20
v2/go.mod
|
@ -5,7 +5,7 @@ go 1.17
|
|||
require (
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
|
||||
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725
|
||||
github.com/andygrunwald/go-jira v1.15.0
|
||||
github.com/andygrunwald/go-jira v1.15.1
|
||||
github.com/antchfx/htmlquery v1.2.4
|
||||
github.com/apex/log v1.9.0
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/go-rod/rod v0.102.0
|
||||
github.com/gobwas/ws v1.1.0
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/itchyny/gojq v0.12.6
|
||||
github.com/itchyny/gojq v0.12.7
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/karlseguin/ccache v2.0.3+incompatible
|
||||
|
@ -35,35 +35,34 @@ require (
|
|||
github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa
|
||||
github.com/projectdiscovery/interactsh v1.0.1-0.20220131074403-ca8bb8f87cd0
|
||||
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df
|
||||
github.com/projectdiscovery/rawhttp v0.0.7
|
||||
github.com/projectdiscovery/rawhttp v0.0.8-0.20220225134552-b60c4c126e5b
|
||||
github.com/projectdiscovery/retryabledns v1.0.13-0.20211109182249-43d38df59660
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.2
|
||||
github.com/projectdiscovery/stringsutil v0.0.0-20220119085121-22513a958700
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.3-0.20211126104922-00d2c6bb43b6
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.3.0 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4
|
||||
github.com/shirou/gopsutil/v3 v3.22.1
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
github.com/spf13/cast v1.4.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible
|
||||
github.com/valyala/fasttemplate v1.2.1
|
||||
github.com/weppos/publicsuffix-go v0.15.1-0.20210928183822-5ee35905bd95
|
||||
github.com/xanzy/go-gitlab v0.55.1
|
||||
github.com/xanzy/go-gitlab v0.56.0
|
||||
github.com/ysmood/gson v0.6.4 // indirect
|
||||
github.com/ysmood/leakless v0.7.0 // indirect
|
||||
go.uber.org/atomic v1.9.0
|
||||
go.uber.org/multierr v1.7.0
|
||||
go.uber.org/multierr v1.8.0
|
||||
go.uber.org/ratelimit v0.2.0
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
|
||||
golang.org/x/text v0.3.7
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
moul.io/http2curl v1.0.0
|
||||
)
|
||||
|
||||
require github.com/aws/aws-sdk-go v1.43.4
|
||||
require github.com/aws/aws-sdk-go v1.43.10
|
||||
|
||||
require github.com/projectdiscovery/folderutil v0.0.0-20211206150108-b4e7ea80f36e
|
||||
|
||||
|
@ -71,6 +70,7 @@ require (
|
|||
github.com/Ice3man543/nvd v1.0.8
|
||||
github.com/openrdap/rdap v0.9.1-0.20191017185644-af93e7ef17b7
|
||||
github.com/projectdiscovery/iputil v0.0.0-20210804143329-3a30fcde43f3
|
||||
github.com/rs/xid v1.3.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/zmap/zcrypto v0.0.0-20211005224000-2d0ffdec8a9b
|
||||
)
|
||||
|
@ -148,7 +148,7 @@ require (
|
|||
goftp.io/server/v2 v2.0.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
|
|
40
v2/go.sum
40
v2/go.sum
|
@ -67,8 +67,8 @@ github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgp
|
|||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andygrunwald/go-jira v1.14.0/go.mod h1:KMo2f4DgMZA1C9FdImuLc04x4WQhn5derQpnsuBFgqE=
|
||||
github.com/andygrunwald/go-jira v1.15.0 h1:krX3Ad4i44mOG0u+vIxQLhLkyyQKPbTsOISsDRgBNjU=
|
||||
github.com/andygrunwald/go-jira v1.15.0/go.mod h1:GIYN1sHOIsENWUZ7B4pDeT/nxEtrZpE8l0987O67ZR8=
|
||||
github.com/andygrunwald/go-jira v1.15.1 h1:6J9aYKb9sW8bxv3pBLYBrs0wdsFrmGI5IeTgWSKWKc8=
|
||||
github.com/andygrunwald/go-jira v1.15.1/go.mod h1:GIYN1sHOIsENWUZ7B4pDeT/nxEtrZpE8l0987O67ZR8=
|
||||
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||
github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494=
|
||||
github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc=
|
||||
|
@ -83,8 +83,8 @@ github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3st
|
|||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.43.4 h1:EtsGbtOB+1548T6Nb62XCOofgXtMHwf+WZh5gQc3xTY=
|
||||
github.com/aws/aws-sdk-go v1.43.4/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc=
|
||||
github.com/aws/aws-sdk-go v1.43.10 h1:lFX6gzTBltYBnlJBjd2DWRCmqn2CbTcs6PW99/Dme7k=
|
||||
github.com/aws/aws-sdk-go v1.43.10/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
|
@ -277,8 +277,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
|||
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/go.mod h1:EQUSKgW/YaOxmXpAwGiowFDO4i2Rmtk5+9dFyeiymAg=
|
||||
github.com/itchyny/gojq v0.12.6 h1:VjaFn59Em2wTxDNGcrRkDK9ZHMNa8IksOgL13sLL4d0=
|
||||
github.com/itchyny/gojq v0.12.6/go.mod h1:ZHrkfu7A+RbZLy5J1/JKpS4poEqrzItSTGDItqsfP0A=
|
||||
github.com/itchyny/gojq v0.12.7 h1:hYPTpeWfrJ1OT+2j6cvBScbhl0TkdwGM4bc66onUSOQ=
|
||||
github.com/itchyny/gojq v0.12.7/go.mod h1:ZdvNHVlzPgUf8pgjnuDTmGfHA/21KoutQUJ3An/xNuw=
|
||||
github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU=
|
||||
github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
|
||||
github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=
|
||||
|
@ -428,10 +428,6 @@ github.com/projectdiscovery/fileutil v0.0.0-20210928100737-cab279c5d4b5/go.mod h
|
|||
github.com/projectdiscovery/folderutil v0.0.0-20211206150108-b4e7ea80f36e h1:RJJuYyuwskYtzZi2gziy6SE/b7saWEzyskaA252E0VY=
|
||||
github.com/projectdiscovery/folderutil v0.0.0-20211206150108-b4e7ea80f36e/go.mod h1:BMqXH4jNGByVdE2iLtKvc/6XStaiZRuCIaKv1vw9PnI=
|
||||
github.com/projectdiscovery/goflags v0.0.7/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220208065736-e1d58bce8ce5 h1:IoDOKD+ZWctt0yGMwgGSCjWmSAaaMds7J9Tbxy6zv+A=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220208065736-e1d58bce8ce5/go.mod h1:37KhVbVLllyuIAgpXGqcvE/hsFEwJ+ctEUSHawjhsBY=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220223122339-bb3affd53c37 h1:wqvD7YOYzJsLxgp51saFR6Dr3niEi0e+b9OiOcnAnw8=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220223122339-bb3affd53c37/go.mod h1:37KhVbVLllyuIAgpXGqcvE/hsFEwJ+ctEUSHawjhsBY=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220223132346-fcffa47ead36 h1:7tPZ9Ui9Iyo/bfP+LtOOKJRrXO7ZzunzMjqHClTDZEA=
|
||||
github.com/projectdiscovery/goflags v0.0.8-0.20220223132346-fcffa47ead36/go.mod h1:37KhVbVLllyuIAgpXGqcvE/hsFEwJ+ctEUSHawjhsBY=
|
||||
github.com/projectdiscovery/gologger v1.0.1/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE=
|
||||
|
@ -459,8 +455,9 @@ github.com/projectdiscovery/networkpolicy v0.0.1/go.mod h1:asvdg5wMy3LPVMGALateb
|
|||
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df h1:CvTNAUD5JbLMqpMFoGNgfk2gOcN0NC57ICu0+oK84vs=
|
||||
github.com/projectdiscovery/nuclei-updatecheck-api v0.0.0-20211006155443-c0a8d610a4df/go.mod h1:pxWVDgq88t9dWv4+J2AIaWgY+EqOE1AyfHS0Tn23w4M=
|
||||
github.com/projectdiscovery/nuclei/v2 v2.5.1/go.mod h1:sU2qcY0MQFS0CqP1BgkR8ZnUyFhqK0BdnY6bvTKNjXY=
|
||||
github.com/projectdiscovery/rawhttp v0.0.7 h1:5m4peVgjbl7gqDcRYMTVEuX+Xs/nh76ohTkkvufucLg=
|
||||
github.com/projectdiscovery/rawhttp v0.0.7/go.mod h1:PQERZAhAv7yxI/hR6hdDPgK1WTU56l204BweXrBec+0=
|
||||
github.com/projectdiscovery/rawhttp v0.0.8-0.20220225134552-b60c4c126e5b h1:ODEtmulEsryrOR3z949wxAdwFiRlnqn2HUh+dHcBK6w=
|
||||
github.com/projectdiscovery/rawhttp v0.0.8-0.20220225134552-b60c4c126e5b/go.mod h1:jAoQA4i8iu2v4u50ufmlky1t1WsBKpFP2XKd3BbY2y4=
|
||||
github.com/projectdiscovery/retryabledns v1.0.11/go.mod h1:4sMC8HZyF01HXukRleSQYwz4870bwgb4+hTSXTMrkf4=
|
||||
github.com/projectdiscovery/retryabledns v1.0.12/go.mod h1:4sMC8HZyF01HXukRleSQYwz4870bwgb4+hTSXTMrkf4=
|
||||
github.com/projectdiscovery/retryabledns v1.0.13-0.20210916165024-76c5b76fd59a/go.mod h1:tXaLDs4n3pRZHwfa8mdXpUWe/AYDNK3HlWDjldhRbjI=
|
||||
|
@ -496,8 +493,8 @@ github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c
|
|||
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4=
|
||||
github.com/shirou/gopsutil/v3 v3.22.1 h1:33y31Q8J32+KstqPfscvFwBlNJ6xLaBy4xqBXzlYV5w=
|
||||
github.com/shirou/gopsutil/v3 v3.22.1/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2 h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
|
||||
github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
|
@ -564,8 +561,8 @@ github.com/weppos/publicsuffix-go v0.15.1-0.20210928183822-5ee35905bd95/go.mod h
|
|||
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0 h1:3UeQBvD0TFrlVjOeLOBz+CPAI8dnbqNSVwUwRrkp7vQ=
|
||||
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
|
||||
github.com/xanzy/go-gitlab v0.50.3/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
|
||||
github.com/xanzy/go-gitlab v0.55.1 h1:IgX/DS9buV0AUz8fuJPQkdl0fQGfBiAsAHxpun8sNhg=
|
||||
github.com/xanzy/go-gitlab v0.55.1/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
|
||||
github.com/xanzy/go-gitlab v0.56.0 h1:/QHBvk3IKVNwvXB/UOWVb5J6VCN6r2bg9/WxjUbFY/0=
|
||||
github.com/xanzy/go-gitlab v0.56.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
|
||||
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||
|
@ -616,8 +613,9 @@ go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
|||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
|
||||
go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
|
@ -721,8 +719,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -803,13 +801,15 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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=
|
||||
|
|
|
@ -158,7 +158,7 @@ func New(options *types.Options) (*Runner, error) {
|
|||
resumeCfg := types.NewResumeCfg()
|
||||
if runner.options.ShouldLoadResume() {
|
||||
gologger.Info().Msg("Resuming from save checkpoint")
|
||||
file, err := ioutil.ReadFile(types.DefaultResumeFilePath())
|
||||
file, err := ioutil.ReadFile(runner.options.Resume)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -168,11 +168,11 @@ func New(options *types.Options) (*Runner, error) {
|
|||
}
|
||||
resumeCfg.Compile()
|
||||
}
|
||||
|
||||
runner.resumeCfg = resumeCfg
|
||||
|
||||
opts := interactsh.NewDefaultOptions(runner.output, runner.issuesClient, runner.progress)
|
||||
opts.Debug = runner.options.Debug
|
||||
opts.NoColor = runner.options.NoColor
|
||||
if options.InteractshURL != "" {
|
||||
opts.ServerURL = options.InteractshURL
|
||||
}
|
||||
|
@ -496,10 +496,10 @@ func isTemplate(filename string) bool {
|
|||
}
|
||||
|
||||
// SaveResumeConfig to file
|
||||
func (r *Runner) SaveResumeConfig() error {
|
||||
func (r *Runner) SaveResumeConfig(path string) error {
|
||||
resumeCfg := types.NewResumeCfg()
|
||||
resumeCfg.ResumeFrom = r.resumeCfg.Current
|
||||
data, _ := json.MarshalIndent(resumeCfg, "", "\t")
|
||||
|
||||
return os.WriteFile(types.DefaultResumeFilePath(), data, os.ModePerm)
|
||||
return os.WriteFile(path, data, os.ModePerm)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/google/go-github/github"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/projectdiscovery/folderutil"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
|
@ -223,7 +224,16 @@ func (r *Runner) checkNucleiIgnoreFileUpdates(configDir string) bool {
|
|||
|
||||
// getLatestReleaseFromGithub returns the latest release from GitHub
|
||||
func (r *Runner) getLatestReleaseFromGithub(latestTag string) (*github.RepositoryRelease, error) {
|
||||
gitHubClient := github.NewClient(nil)
|
||||
var tc *http.Client
|
||||
if token, ok := os.LookupEnv("GITHUB_TOKEN"); ok {
|
||||
ctx := context.Background()
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: token},
|
||||
)
|
||||
tc = oauth2.NewClient(ctx, ts)
|
||||
}
|
||||
|
||||
gitHubClient := github.NewClient(tc)
|
||||
|
||||
release, _, err := gitHubClient.Repositories.GetReleaseByTag(context.Background(), userName, repoName, "v"+latestTag)
|
||||
if err != nil {
|
||||
|
|
|
@ -27,7 +27,7 @@ type Config struct {
|
|||
const nucleiConfigFilename = ".templates-config.json"
|
||||
|
||||
// Version is the current version of nuclei
|
||||
const Version = `2.6.2`
|
||||
const Version = `2.6.3`
|
||||
|
||||
func getConfigDetails() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
|
|
|
@ -148,6 +148,12 @@ func (store *Store) Load() {
|
|||
store.workflows = store.LoadWorkflows(store.finalWorkflows)
|
||||
}
|
||||
|
||||
var templateIDPathMap map[string]string
|
||||
|
||||
func init() {
|
||||
templateIDPathMap = make(map[string]string)
|
||||
}
|
||||
|
||||
// ValidateTemplates takes a list of templates and validates them
|
||||
// erroring out on discovering any faulty templates.
|
||||
func (store *Store) ValidateTemplates(templatesList, workflowsList []string) error {
|
||||
|
@ -164,7 +170,7 @@ func (store *Store) ValidateTemplates(templatesList, workflowsList []string) err
|
|||
if areTemplatesValid(store, filteredTemplatePaths) && areWorkflowsValid(store, filteredWorkflowPaths) {
|
||||
return nil
|
||||
}
|
||||
return errors.New("an error occurred during templates validation")
|
||||
return errors.New("errors occured during template validation")
|
||||
}
|
||||
|
||||
func areWorkflowsValid(store *Store, filteredWorkflowPaths map[string]struct{}) bool {
|
||||
|
@ -181,6 +187,7 @@ func areTemplatesValid(store *Store, filteredTemplatePaths map[string]struct{})
|
|||
|
||||
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 {
|
||||
if isParsingError("Error occurred loading template %s: %s\n", templatePath, err) {
|
||||
|
@ -195,8 +202,14 @@ func areWorkflowOrTemplatesValid(store *Store, filteredTemplatePaths map[string]
|
|||
areTemplatesValid = false
|
||||
}
|
||||
} else {
|
||||
if existingTemplatePath, found := templateIDPathMap[template.ID]; !found {
|
||||
templateIDPathMap[template.ID] = templatePath
|
||||
} else {
|
||||
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 {
|
||||
return true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if isWorkflow {
|
||||
|
|
|
@ -57,7 +57,7 @@ type Info struct {
|
|||
// examples:
|
||||
// - value: >
|
||||
// map[string]string{"customField1":"customValue1"}
|
||||
Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty" jsonschema:"title=additional metadata for the template,description=Additional metadata fields for the template"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" jsonschema:"title=additional metadata for the template,description=Additional metadata fields for the template"`
|
||||
|
||||
// description: |
|
||||
// Classification contains classification information about the template.
|
||||
|
|
|
@ -21,12 +21,19 @@ func TestInfoJsonMarshal(t *testing.T) {
|
|||
SeverityHolder: severity.Holder{Severity: severity.High},
|
||||
Tags: stringslice.StringSlice{Value: []string{"cve", "misc"}},
|
||||
Reference: stringslice.StringSlice{Value: "reference1"},
|
||||
Metadata: map[string]interface{}{
|
||||
"string_key": "string_value",
|
||||
"array_key": []string{"array_value1", "array_value2"},
|
||||
"map_key": map[string]string{
|
||||
"key1": "val1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := json.Marshal(&info)
|
||||
assert.Nil(t, err)
|
||||
|
||||
expected := `{"name":"Test Template Name","author":["forgedhallpass","ice3man"],"tags":["cve","misc"],"description":"Test description","reference":"reference1","severity":"high"}`
|
||||
expected := `{"name":"Test Template Name","author":["forgedhallpass","ice3man"],"tags":["cve","misc"],"description":"Test description","reference":"reference1","severity":"high","metadata":{"array_key":["array_value1","array_value2"],"map_key":{"key1":"val1"},"string_key":"string_value"}}`
|
||||
assert.Equal(t, expected, string(result))
|
||||
}
|
||||
|
||||
|
@ -38,6 +45,13 @@ func TestInfoYamlMarshal(t *testing.T) {
|
|||
SeverityHolder: severity.Holder{Severity: severity.High},
|
||||
Tags: stringslice.StringSlice{Value: []string{"cve", "misc"}},
|
||||
Reference: stringslice.StringSlice{Value: "reference1"},
|
||||
Metadata: map[string]interface{}{
|
||||
"string_key": "string_value",
|
||||
"array_key": []string{"array_value1", "array_value2"},
|
||||
"map_key": map[string]string{
|
||||
"key1": "val1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := yaml.Marshal(&info)
|
||||
|
@ -53,6 +67,13 @@ tags:
|
|||
description: Test description
|
||||
reference: reference1
|
||||
severity: high
|
||||
metadata:
|
||||
array_key:
|
||||
- array_value1
|
||||
- array_value2
|
||||
map_key:
|
||||
key1: val1
|
||||
string_key: string_value
|
||||
`
|
||||
assert.Equal(t, expected, string(result))
|
||||
}
|
||||
|
@ -66,7 +87,7 @@ func TestUnmarshal(t *testing.T) {
|
|||
dynamicKey1 := "customDynamicKey1"
|
||||
dynamicKey2 := "customDynamicKey2"
|
||||
|
||||
dynamicKeysMap := map[string]string{
|
||||
dynamicKeysMap := map[string]interface{}{
|
||||
dynamicKey1: "customDynamicValue1",
|
||||
dynamicKey2: "customDynamicValue2",
|
||||
}
|
||||
|
@ -92,8 +113,8 @@ func TestUnmarshal(t *testing.T) {
|
|||
severity: critical
|
||||
reference: ` + strings.Join(references, ", ") + `
|
||||
metadata:
|
||||
` + dynamicKey1 + `: ` + dynamicKeysMap[dynamicKey1] + `
|
||||
` + dynamicKey2 + `: ` + dynamicKeysMap[dynamicKey2] + `
|
||||
` + dynamicKey1 + `: ` + dynamicKeysMap[dynamicKey1].(string) + `
|
||||
` + dynamicKey2 + `: ` + dynamicKeysMap[dynamicKey2].(string) + `
|
||||
`
|
||||
yamlPayload2 := `
|
||||
name: ` + templateName + `
|
||||
|
@ -108,8 +129,8 @@ func TestUnmarshal(t *testing.T) {
|
|||
- ` + references[0] + ` # comments are not unmarshalled
|
||||
- ` + references[1] + `
|
||||
metadata:
|
||||
` + dynamicKey1 + `: ` + dynamicKeysMap[dynamicKey1] + `
|
||||
` + dynamicKey2 + `: ` + dynamicKeysMap[dynamicKey2] + `
|
||||
` + dynamicKey1 + `: ` + dynamicKeysMap[dynamicKey1].(string) + `
|
||||
` + dynamicKey2 + `: ` + dynamicKeysMap[dynamicKey2].(string) + `
|
||||
`
|
||||
|
||||
info1 := assertUnmarshalledTemplateInfo(t, yamlPayload1)
|
||||
|
|
|
@ -24,6 +24,8 @@ const (
|
|||
High
|
||||
// name:critical
|
||||
Critical
|
||||
// name:unknown
|
||||
Unknown
|
||||
limit
|
||||
)
|
||||
|
||||
|
@ -33,6 +35,7 @@ var severityMappings = map[Severity]string{
|
|||
Medium: "medium",
|
||||
High: "high",
|
||||
Critical: "critical",
|
||||
Unknown: "unknown",
|
||||
}
|
||||
|
||||
func GetSupportedSeverities() Severities {
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestYamlUnmarshalFail(t *testing.T) {
|
|||
|
||||
func TestGetSupportedSeverities(t *testing.T) {
|
||||
severities := GetSupportedSeverities()
|
||||
assert.Equal(t, severities, Severities{Info, Low, Medium, High, Critical})
|
||||
assert.Equal(t, severities, Severities{Info, Low, Medium, High, Critical, Unknown})
|
||||
}
|
||||
|
||||
func testUnmarshal(t *testing.T, unmarshaller func(data []byte, v interface{}) error, payloadCreator func(value string) string) {
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package userAgent
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/jsonschema"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type UserAgent int
|
||||
|
||||
// name:UserAgent
|
||||
const (
|
||||
// name:random
|
||||
Random UserAgent = iota
|
||||
// name:off
|
||||
Off
|
||||
// name:default
|
||||
Default
|
||||
// name:custom
|
||||
Custom
|
||||
limit
|
||||
)
|
||||
|
||||
var userAgentMappings = map[UserAgent]string{
|
||||
Random: "random",
|
||||
Off: "off",
|
||||
Default: "default",
|
||||
Custom: "custom",
|
||||
}
|
||||
|
||||
func GetSupportedUserAgentOptions() []UserAgent {
|
||||
var result []UserAgent
|
||||
for index := UserAgent(1); index < limit; index++ {
|
||||
result = append(result, index)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func toUserAgent(valueToMap string) (UserAgent, error) {
|
||||
normalizedValue := normalizeValue(valueToMap)
|
||||
for key, currentValue := range userAgentMappings {
|
||||
if normalizedValue == currentValue {
|
||||
return key, nil
|
||||
}
|
||||
}
|
||||
return -1, errors.New("Invalid userAgent: " + valueToMap)
|
||||
}
|
||||
|
||||
func normalizeValue(value string) string {
|
||||
return strings.TrimSpace(strings.ToLower(value))
|
||||
}
|
||||
|
||||
func (userAgent UserAgent) String() string {
|
||||
return userAgentMappings[userAgent]
|
||||
}
|
||||
|
||||
// UserAgentHolder holds a UserAgent type. Required for un/marshalling purposes
|
||||
type UserAgentHolder struct {
|
||||
Value UserAgent `mapping:"true"`
|
||||
}
|
||||
|
||||
func (userAgentHolder UserAgentHolder) JSONSchemaType() *jsonschema.Type {
|
||||
gotType := &jsonschema.Type{
|
||||
Type: "string",
|
||||
Title: "userAgent for the headless",
|
||||
Description: "userAgent for the headless http request",
|
||||
}
|
||||
for _, userAgent := range GetSupportedUserAgentOptions() {
|
||||
gotType.Enum = append(gotType.Enum, userAgent.String())
|
||||
}
|
||||
return gotType
|
||||
}
|
||||
|
||||
func (userAgentHolder *UserAgentHolder) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var marshalledUserAgent string
|
||||
if err := unmarshal(&marshalledUserAgent); err != nil {
|
||||
return err
|
||||
}
|
||||
computedUserAgent, err := toUserAgent(marshalledUserAgent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userAgentHolder.Value = computedUserAgent
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userAgentHolder *UserAgentHolder) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(userAgentHolder.Value.String())
|
||||
}
|
||||
|
||||
func (userAgentHolder UserAgentHolder) MarshalYAML() (interface{}, error) {
|
||||
return userAgentHolder.Value.String(), nil
|
||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
|
@ -101,12 +102,26 @@ func init() {
|
|||
buffer := &bytes.Buffer{}
|
||||
writer := gzip.NewWriter(buffer)
|
||||
if _, err := writer.Write([]byte(args[0].(string))); err != nil {
|
||||
_ = writer.Close()
|
||||
return "", err
|
||||
}
|
||||
_ = writer.Close()
|
||||
|
||||
return buffer.String(), nil
|
||||
}),
|
||||
"gzip_decode": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
|
||||
reader, err := gzip.NewReader(strings.NewReader(args[0].(string)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
data, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
_ = reader.Close()
|
||||
return "", err
|
||||
}
|
||||
_ = reader.Close()
|
||||
return string(data), nil
|
||||
}),
|
||||
"base64_py": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
|
||||
// python encodes to base64 with lines of 76 bytes terminated by new line "\n"
|
||||
stdBase64 := base64.StdEncoding.EncodeToString([]byte(types.ToString(args[0])))
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package dsl
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -40,15 +37,18 @@ func TestDSLTimeComparison(t *testing.T) {
|
|||
|
||||
func TestDSLGzipSerialize(t *testing.T) {
|
||||
compiled, err := govaluate.NewEvaluableExpressionWithFunctions("gzip(\"hello world\")", HelperFunctions())
|
||||
require.Nil(t, err, "could not compare time")
|
||||
require.Nil(t, err, "could not compile encoder")
|
||||
|
||||
result, err := compiled.Evaluate(make(map[string]interface{}))
|
||||
require.Nil(t, err, "could not evaluate compare time")
|
||||
|
||||
reader, _ := gzip.NewReader(strings.NewReader(types.ToString(result)))
|
||||
data, _ := ioutil.ReadAll(reader)
|
||||
compiled, err = govaluate.NewEvaluableExpressionWithFunctions("gzip_decode(data)", HelperFunctions())
|
||||
require.Nil(t, err, "could not compile decoder")
|
||||
|
||||
require.Equal(t, "hello world", string(data), "could not get gzip encoded data")
|
||||
data, err := compiled.Evaluate(map[string]interface{}{"data": result})
|
||||
require.Nil(t, err, "could not evaluate decoded data")
|
||||
|
||||
require.Equal(t, "hello world", data.(string), "could not get gzip encoded data")
|
||||
}
|
||||
|
||||
func TestDslFunctionSignatures(t *testing.T) {
|
||||
|
@ -102,6 +102,7 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) {
|
|||
[93mcontains[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mgenerate_java_gadget[0m(arg1, arg2, arg3 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mgzip[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mgzip_decode[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mhex_decode[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mhex_encode[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
[93mhtml_escape[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/progress"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/responsehighlighter"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/writer"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/reporting"
|
||||
)
|
||||
|
@ -82,6 +83,8 @@ type Options struct {
|
|||
DisableHttpFallback bool
|
||||
// NoInteractsh disables the engine
|
||||
NoInteractsh bool
|
||||
// NoColor dissbles printing colors for matches
|
||||
NoColor bool
|
||||
|
||||
StopAtFirstMatch bool
|
||||
}
|
||||
|
@ -124,6 +127,7 @@ func NewDefaultOptions(output output.Writer, reporting *reporting.Client, progre
|
|||
IssuesClient: reporting,
|
||||
Progress: progress,
|
||||
DisableHttpFallback: true,
|
||||
NoColor: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,9 +152,6 @@ func (c *Client) firstTimeInitializeClient() error {
|
|||
c.hostname = interactDomain
|
||||
|
||||
interactsh.StartPolling(c.pollDuration, func(interaction *server.Interaction) {
|
||||
if c.options.Debug || c.options.DebugRequest || c.options.DebugResponse {
|
||||
c.debugPrintInteraction(interaction)
|
||||
}
|
||||
item := c.requests.Get(interaction.UniqueID)
|
||||
|
||||
if item == nil {
|
||||
|
@ -189,7 +190,7 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
|
|||
data.Event.InternalEvent["interactsh_response"] = interaction.RawResponse
|
||||
data.Event.InternalEvent["interactsh_ip"] = interaction.RemoteAddress
|
||||
|
||||
result, matched := data.Operators.Execute(data.Event.InternalEvent, data.MatchFunc, data.ExtractFunc, false)
|
||||
result, matched := data.Operators.Execute(data.Event.InternalEvent, data.MatchFunc, data.ExtractFunc, c.options.Debug || c.options.DebugRequest || c.options.DebugResponse)
|
||||
if !matched || result == nil {
|
||||
return false // if we don't match, return
|
||||
}
|
||||
|
@ -205,6 +206,10 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
|
|||
event.Interaction = interaction
|
||||
}
|
||||
|
||||
if c.options.Debug || c.options.DebugRequest || c.options.DebugResponse {
|
||||
c.debugPrintInteraction(interaction, data.Event.OperatorsResult)
|
||||
}
|
||||
|
||||
if writer.WriteResult(data.Event, c.options.Output, c.options.Progress, c.options.IssuesClient) {
|
||||
c.matched = true
|
||||
if _, ok := data.Event.InternalEvent["stop-at-first-match"]; ok || c.options.StopAtFirstMatch {
|
||||
|
@ -350,35 +355,35 @@ func HasMarkers(data string) bool {
|
|||
return strings.Contains(data, interactshURLMarker)
|
||||
}
|
||||
|
||||
func (c *Client) debugPrintInteraction(interaction *server.Interaction) {
|
||||
func (c *Client) debugPrintInteraction(interaction *server.Interaction, event *operators.Result) {
|
||||
builder := &bytes.Buffer{}
|
||||
|
||||
switch interaction.Protocol {
|
||||
case "dns":
|
||||
builder.WriteString(formatInteractionHeader("DNS", interaction.FullId, interaction.RemoteAddress, interaction.Timestamp))
|
||||
if c.options.DebugRequest || c.options.Debug {
|
||||
builder.WriteString(formatInteractionMessage("DNS Request", interaction.RawRequest))
|
||||
builder.WriteString(formatInteractionMessage("DNS Request", interaction.RawRequest, event, c.options.NoColor))
|
||||
}
|
||||
if c.options.DebugResponse || c.options.Debug {
|
||||
builder.WriteString(formatInteractionMessage("DNS Response", interaction.RawResponse))
|
||||
builder.WriteString(formatInteractionMessage("DNS Response", interaction.RawResponse, event, c.options.NoColor))
|
||||
}
|
||||
case "http":
|
||||
builder.WriteString(formatInteractionHeader("HTTP", interaction.FullId, interaction.RemoteAddress, interaction.Timestamp))
|
||||
if c.options.DebugRequest || c.options.Debug {
|
||||
builder.WriteString(formatInteractionMessage("HTTP Request", interaction.RawRequest))
|
||||
builder.WriteString(formatInteractionMessage("HTTP Request", interaction.RawRequest, event, c.options.NoColor))
|
||||
}
|
||||
if c.options.DebugResponse || c.options.Debug {
|
||||
builder.WriteString(formatInteractionMessage("HTTP Response", interaction.RawResponse))
|
||||
builder.WriteString(formatInteractionMessage("HTTP Response", interaction.RawResponse, event, c.options.NoColor))
|
||||
}
|
||||
case "smtp":
|
||||
builder.WriteString(formatInteractionHeader("SMTP", interaction.FullId, interaction.RemoteAddress, interaction.Timestamp))
|
||||
if c.options.DebugRequest || c.options.Debug || c.options.DebugResponse {
|
||||
builder.WriteString(formatInteractionMessage("SMTP Interaction", interaction.RawRequest))
|
||||
builder.WriteString(formatInteractionMessage("SMTP Interaction", interaction.RawRequest, event, c.options.NoColor))
|
||||
}
|
||||
case "ldap":
|
||||
builder.WriteString(formatInteractionHeader("LDAP", interaction.FullId, interaction.RemoteAddress, interaction.Timestamp))
|
||||
if c.options.DebugRequest || c.options.Debug || c.options.DebugResponse {
|
||||
builder.WriteString(formatInteractionMessage("LDAP Interaction", interaction.RawRequest))
|
||||
builder.WriteString(formatInteractionMessage("LDAP Interaction", interaction.RawRequest, event, c.options.NoColor))
|
||||
}
|
||||
}
|
||||
fmt.Fprint(os.Stderr, builder.String())
|
||||
|
@ -388,7 +393,8 @@ func formatInteractionHeader(protocol, ID, address string, at time.Time) string
|
|||
return fmt.Sprintf("[%s] Received %s interaction from %s at %s", ID, protocol, address, at.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
func formatInteractionMessage(key, value string) string {
|
||||
func formatInteractionMessage(key, value string, event *operators.Result, noColor bool) string {
|
||||
value = responsehighlighter.Highlight(event, value, noColor, false)
|
||||
return fmt.Sprintf("\n------------\n%s\n------------\n\n%s\n\n", key, value)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/corpix/uarand"
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/launcher"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -89,9 +88,6 @@ func New(options *types.Options) (*Browser, error) {
|
|||
customAgent = parts[1]
|
||||
}
|
||||
}
|
||||
if customAgent == "" {
|
||||
customAgent = uarand.GetRandom()
|
||||
}
|
||||
|
||||
httpclient, err := newHttpClient(options)
|
||||
if err != nil {
|
||||
|
@ -116,6 +112,16 @@ func MustDisableSandbox() bool {
|
|||
return runtime.GOOS == "linux" && os.Geteuid() == 0
|
||||
}
|
||||
|
||||
// SetUserAgent sets custom user agent to the browser
|
||||
func (b *Browser) SetUserAgent(customUserAgent string) {
|
||||
b.customAgent = customUserAgent
|
||||
}
|
||||
|
||||
// UserAgent fetch the currently set custom user agent
|
||||
func (b *Browser) UserAgent() string {
|
||||
return b.customAgent
|
||||
}
|
||||
|
||||
// Close closes the browser engine
|
||||
func (b *Browser) Close() {
|
||||
b.engine.Close()
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package headless
|
||||
|
||||
import (
|
||||
"github.com/corpix/uarand"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/projectdiscovery/fileutil"
|
||||
useragent "github.com/projectdiscovery/nuclei/v2/pkg/model/types/userAgent"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
||||
|
@ -33,6 +35,15 @@ type Request struct {
|
|||
// Steps is the list of actions to run for headless request
|
||||
Steps []*engine.Action `yaml:"steps,omitempty" jsonschema:"title=list of actions for headless request,description=List of actions to run for headless request"`
|
||||
|
||||
// descriptions: |
|
||||
// User-Agent is the type of user-agent to use for the request.
|
||||
UserAgent useragent.UserAgentHolder `yaml:"user_agent,omitempty" jsonschema:"title=user agent for the headless request,description=User agent for the headless request"`
|
||||
|
||||
// description: |
|
||||
// If UserAgent is set to custom, customUserAgent is the custom user-agent to use for the request.
|
||||
CustomUserAgent string `yaml:"custom_user_agent,omitempty" jsonschema:"title=custom user agent for the headless request,description=Custom user agent for the headless request"`
|
||||
compiledUserAgent string
|
||||
|
||||
// Operators for the current request go here.
|
||||
operators.Operators `yaml:",inline,omitempty"`
|
||||
CompiledOperators *operators.Operators `yaml:"-"`
|
||||
|
@ -90,6 +101,21 @@ func (request *Request) Compile(options *protocols.ExecuterOptions) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Compile User-Agent
|
||||
switch request.UserAgent.Value {
|
||||
case useragent.Off:
|
||||
request.compiledUserAgent = " "
|
||||
case useragent.Default:
|
||||
request.compiledUserAgent = ""
|
||||
case useragent.Custom:
|
||||
if request.CustomUserAgent == "" {
|
||||
return errors.New("please set custom_user_agent in the template")
|
||||
}
|
||||
request.compiledUserAgent = request.CustomUserAgent
|
||||
case useragent.Random:
|
||||
request.compiledUserAgent = uarand.GetRandom()
|
||||
}
|
||||
|
||||
if len(request.Matchers) > 0 || len(request.Extractors) > 0 {
|
||||
compiled := &request.Operators
|
||||
if err := compiled.Compile(); err != nil {
|
||||
|
|
|
@ -26,6 +26,9 @@ func (request *Request) Type() templateTypes.ProtocolType {
|
|||
|
||||
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||
func (request *Request) ExecuteWithResults(inputURL string, metadata, previous output.InternalEvent /*TODO review unused parameter*/, callback protocols.OutputEventCallback) error {
|
||||
if request.options.Browser.UserAgent() == "" {
|
||||
request.options.Browser.SetUserAgent(request.compiledUserAgent)
|
||||
}
|
||||
payloads := generators.BuildPayloadFromOptions(request.options.Options)
|
||||
if request.generator != nil {
|
||||
iterator := request.generator.NewIterator()
|
||||
|
|
|
@ -139,6 +139,10 @@ type Request struct {
|
|||
// all requests defined in raw section.
|
||||
CookieReuse bool `yaml:"cookie-reuse,omitempty" jsonschema:"title=optional cookie reuse enable,description=Optional setting that enables cookie reuse"`
|
||||
// description: |
|
||||
// Enables force reading of the entire raw unsafe request body ignoring
|
||||
// any specified content length headers.
|
||||
ForceReadAllBody bool `yaml:"read-all,omitempty" jsonschema:"title=force read all body,description=Enables force reading of entire unsafe http request body"`
|
||||
// description: |
|
||||
// Redirects specifies whether redirects should be followed by the HTTP Client.
|
||||
//
|
||||
// This can be used in conjunction with `max-redirects` to control the HTTP request redirects.
|
||||
|
|
|
@ -383,6 +383,7 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
|||
options := generatedRequest.original.rawhttpClient.Options
|
||||
options.FollowRedirects = request.Redirects
|
||||
options.CustomRawBytes = generatedRequest.rawRequest.UnsafeRawBytes
|
||||
options.ForceReadAllBody = request.ForceReadAllBody
|
||||
resp, err = generatedRequest.original.rawhttpClient.DoRawWithOptions(generatedRequest.rawRequest.Method, reqURL, generatedRequest.rawRequest.Path, generators.ExpandMapValues(generatedRequest.rawRequest.Headers), ioutil.NopCloser(strings.NewReader(generatedRequest.rawRequest.Data)), options)
|
||||
} else {
|
||||
hostname = generatedRequest.request.URL.Host
|
||||
|
|
|
@ -53,7 +53,7 @@ func (request *Request) ExecuteWithResults(input string, metadata /*TODO review
|
|||
actualAddress := replacer.Replace(kv.address, variables)
|
||||
|
||||
if err := request.executeAddress(variables, actualAddress, address, input, kv.tls, previous, callback); err != nil {
|
||||
gologger.Verbose().Label("ERR").Msgf("Could not make network request for %s: %s\n", actualAddress, err)
|
||||
gologger.Warning().Msgf("Could not make network request for %s: %s\n", actualAddress, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -69,9 +69,8 @@ func (request *Request) executeAddress(variables map[string]interface{}, actualA
|
|||
return err
|
||||
}
|
||||
|
||||
variables = generators.MergeMaps(variables, map[string]interface{}{"Hostname": address})
|
||||
payloads := generators.BuildPayloadFromOptions(request.options.Options)
|
||||
// add Hostname variable to the payload
|
||||
payloads = generators.MergeMaps(payloads, map[string]interface{}{"Hostname": address})
|
||||
|
||||
if request.generator != nil {
|
||||
iterator := request.generator.NewIterator()
|
||||
|
@ -224,7 +223,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
|||
default:
|
||||
buf := make([]byte, bufferSize)
|
||||
nBuf, err := conn.Read(buf)
|
||||
if err != nil && !os.IsTimeout(err) {
|
||||
if err != nil && !os.IsTimeout(err) && err != io.EOF {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
closeTimer(readInterval)
|
||||
return errors.Wrap(err, "could not read from server")
|
||||
|
@ -237,7 +236,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
|||
} else {
|
||||
final = make([]byte, bufferSize)
|
||||
n, err = conn.Read(final)
|
||||
if err != nil && err != io.EOF {
|
||||
if err != nil && !os.IsTimeout(err) && err != io.EOF {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
return errors.Wrap(err, "could not read from server")
|
||||
}
|
||||
|
|
|
@ -181,9 +181,12 @@ func ToMarkdownTableString(templateInfo *model.Info) string {
|
|||
builder := &bytes.Buffer{}
|
||||
|
||||
toMarkDownTable := func(insertionOrderedStringMap *utils.InsertionOrderedStringMap) {
|
||||
insertionOrderedStringMap.ForEach(func(key string, value string) {
|
||||
if utils.IsNotBlank(value) {
|
||||
builder.WriteString(fmt.Sprintf("| %s | %s |\n", key, value))
|
||||
insertionOrderedStringMap.ForEach(func(key string, value interface{}) {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if utils.IsNotBlank(value) {
|
||||
builder.WriteString(fmt.Sprintf("| %s | %s |\n", key, value))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ func TestToMarkdownTableString(t *testing.T) {
|
|||
SeverityHolder: severity.Holder{Severity: severity.High},
|
||||
Tags: stringslice.StringSlice{Value: []string{"cve", "misc"}},
|
||||
Reference: stringslice.StringSlice{Value: "reference1"},
|
||||
Metadata: map[string]string{
|
||||
Metadata: map[string]interface{}{
|
||||
"customDynamicKey1": "customDynamicValue1",
|
||||
"customDynamicKey2": "customDynamicValue2",
|
||||
},
|
||||
|
|
|
@ -31,6 +31,7 @@ var (
|
|||
HEADLESSRequestDoc encoder.Doc
|
||||
ENGINEActionDoc encoder.Doc
|
||||
ActionTypeHolderDoc encoder.Doc
|
||||
USERAGENTUserAgentHolderDoc encoder.Doc
|
||||
SSLRequestDoc encoder.Doc
|
||||
WEBSOCKETRequestDoc encoder.Doc
|
||||
WEBSOCKETInputDoc encoder.Doc
|
||||
|
@ -188,7 +189,7 @@ func init() {
|
|||
MODELInfoDoc.Fields[5].Description = "Severity of the template."
|
||||
MODELInfoDoc.Fields[5].Comments[encoder.LineComment] = "Severity of the template."
|
||||
MODELInfoDoc.Fields[6].Name = "metadata"
|
||||
MODELInfoDoc.Fields[6].Type = "map[string]string"
|
||||
MODELInfoDoc.Fields[6].Type = "map[string]interface{}"
|
||||
MODELInfoDoc.Fields[6].Note = ""
|
||||
MODELInfoDoc.Fields[6].Description = "Metadata of the template."
|
||||
MODELInfoDoc.Fields[6].Comments[encoder.LineComment] = "Metadata of the template."
|
||||
|
@ -270,6 +271,7 @@ func init() {
|
|||
"medium",
|
||||
"high",
|
||||
"critical",
|
||||
"unknown",
|
||||
}
|
||||
|
||||
MODELClassificationDoc.Type = "model.Classification"
|
||||
|
@ -388,7 +390,7 @@ func init() {
|
|||
Value: "HTTP response headers in name:value format",
|
||||
},
|
||||
}
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 28)
|
||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 29)
|
||||
HTTPRequestDoc.Fields[0].Name = "matchers"
|
||||
HTTPRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
||||
HTTPRequestDoc.Fields[0].Note = ""
|
||||
|
@ -521,46 +523,51 @@ func init() {
|
|||
HTTPRequestDoc.Fields[19].Note = ""
|
||||
HTTPRequestDoc.Fields[19].Description = "CookieReuse is an optional setting that enables cookie reuse for\nall requests defined in raw section."
|
||||
HTTPRequestDoc.Fields[19].Comments[encoder.LineComment] = "CookieReuse is an optional setting that enables cookie reuse for"
|
||||
HTTPRequestDoc.Fields[20].Name = "redirects"
|
||||
HTTPRequestDoc.Fields[20].Name = "read-all"
|
||||
HTTPRequestDoc.Fields[20].Type = "bool"
|
||||
HTTPRequestDoc.Fields[20].Note = ""
|
||||
HTTPRequestDoc.Fields[20].Description = "Redirects specifies whether redirects should be followed by the HTTP Client.\n\nThis can be used in conjunction with `max-redirects` to control the HTTP request redirects."
|
||||
HTTPRequestDoc.Fields[20].Comments[encoder.LineComment] = "Redirects specifies whether redirects should be followed by the HTTP Client."
|
||||
HTTPRequestDoc.Fields[21].Name = "pipeline"
|
||||
HTTPRequestDoc.Fields[20].Description = "Enables force reading of the entire raw unsafe request body ignoring\nany specified content length headers."
|
||||
HTTPRequestDoc.Fields[20].Comments[encoder.LineComment] = "Enables force reading of the entire raw unsafe request body ignoring"
|
||||
HTTPRequestDoc.Fields[21].Name = "redirects"
|
||||
HTTPRequestDoc.Fields[21].Type = "bool"
|
||||
HTTPRequestDoc.Fields[21].Note = ""
|
||||
HTTPRequestDoc.Fields[21].Description = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining\n\nAll requests must be idempotent (GET/POST). This can be used for race conditions/billions requests."
|
||||
HTTPRequestDoc.Fields[21].Comments[encoder.LineComment] = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining"
|
||||
HTTPRequestDoc.Fields[22].Name = "unsafe"
|
||||
HTTPRequestDoc.Fields[21].Description = "Redirects specifies whether redirects should be followed by the HTTP Client.\n\nThis can be used in conjunction with `max-redirects` to control the HTTP request redirects."
|
||||
HTTPRequestDoc.Fields[21].Comments[encoder.LineComment] = "Redirects specifies whether redirects should be followed by the HTTP Client."
|
||||
HTTPRequestDoc.Fields[22].Name = "pipeline"
|
||||
HTTPRequestDoc.Fields[22].Type = "bool"
|
||||
HTTPRequestDoc.Fields[22].Note = ""
|
||||
HTTPRequestDoc.Fields[22].Description = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests.\n\nThis uses the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine to achieve complete\ncontrol over the request, with no normalization performed by the client."
|
||||
HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests."
|
||||
HTTPRequestDoc.Fields[23].Name = "race"
|
||||
HTTPRequestDoc.Fields[22].Description = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining\n\nAll requests must be idempotent (GET/POST). This can be used for race conditions/billions requests."
|
||||
HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining"
|
||||
HTTPRequestDoc.Fields[23].Name = "unsafe"
|
||||
HTTPRequestDoc.Fields[23].Type = "bool"
|
||||
HTTPRequestDoc.Fields[23].Note = ""
|
||||
HTTPRequestDoc.Fields[23].Description = "Race determines if all the request have to be attempted at the same time (Race Condition)\n\nThe actual number of requests that will be sent is determined by the `race_count` field."
|
||||
HTTPRequestDoc.Fields[23].Comments[encoder.LineComment] = "Race determines if all the request have to be attempted at the same time (Race Condition)"
|
||||
HTTPRequestDoc.Fields[24].Name = "req-condition"
|
||||
HTTPRequestDoc.Fields[23].Description = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests.\n\nThis uses the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine to achieve complete\ncontrol over the request, with no normalization performed by the client."
|
||||
HTTPRequestDoc.Fields[23].Comments[encoder.LineComment] = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests."
|
||||
HTTPRequestDoc.Fields[24].Name = "race"
|
||||
HTTPRequestDoc.Fields[24].Type = "bool"
|
||||
HTTPRequestDoc.Fields[24].Note = ""
|
||||
HTTPRequestDoc.Fields[24].Description = "ReqCondition automatically assigns numbers to requests and preserves their history.\n\nThis allows matching on them later for multi-request conditions."
|
||||
HTTPRequestDoc.Fields[24].Comments[encoder.LineComment] = "ReqCondition automatically assigns numbers to requests and preserves their history."
|
||||
HTTPRequestDoc.Fields[25].Name = "stop-at-first-match"
|
||||
HTTPRequestDoc.Fields[24].Description = "Race determines if all the request have to be attempted at the same time (Race Condition)\n\nThe actual number of requests that will be sent is determined by the `race_count` field."
|
||||
HTTPRequestDoc.Fields[24].Comments[encoder.LineComment] = "Race determines if all the request have to be attempted at the same time (Race Condition)"
|
||||
HTTPRequestDoc.Fields[25].Name = "req-condition"
|
||||
HTTPRequestDoc.Fields[25].Type = "bool"
|
||||
HTTPRequestDoc.Fields[25].Note = ""
|
||||
HTTPRequestDoc.Fields[25].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
HTTPRequestDoc.Fields[25].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
HTTPRequestDoc.Fields[26].Name = "skip-variables-check"
|
||||
HTTPRequestDoc.Fields[25].Description = "ReqCondition automatically assigns numbers to requests and preserves their history.\n\nThis allows matching on them later for multi-request conditions."
|
||||
HTTPRequestDoc.Fields[25].Comments[encoder.LineComment] = "ReqCondition automatically assigns numbers to requests and preserves their history."
|
||||
HTTPRequestDoc.Fields[26].Name = "stop-at-first-match"
|
||||
HTTPRequestDoc.Fields[26].Type = "bool"
|
||||
HTTPRequestDoc.Fields[26].Note = ""
|
||||
HTTPRequestDoc.Fields[26].Description = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||
HTTPRequestDoc.Fields[26].Comments[encoder.LineComment] = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||
HTTPRequestDoc.Fields[27].Name = "iterate-all"
|
||||
HTTPRequestDoc.Fields[26].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
HTTPRequestDoc.Fields[26].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||
HTTPRequestDoc.Fields[27].Name = "skip-variables-check"
|
||||
HTTPRequestDoc.Fields[27].Type = "bool"
|
||||
HTTPRequestDoc.Fields[27].Note = ""
|
||||
HTTPRequestDoc.Fields[27].Description = "IterateAll iterates all the values extracted from internal extractors"
|
||||
HTTPRequestDoc.Fields[27].Comments[encoder.LineComment] = "IterateAll iterates all the values extracted from internal extractors"
|
||||
HTTPRequestDoc.Fields[27].Description = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||
HTTPRequestDoc.Fields[27].Comments[encoder.LineComment] = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||
HTTPRequestDoc.Fields[28].Name = "iterate-all"
|
||||
HTTPRequestDoc.Fields[28].Type = "bool"
|
||||
HTTPRequestDoc.Fields[28].Note = ""
|
||||
HTTPRequestDoc.Fields[28].Description = "IterateAll iterates all the values extracted from internal extractors"
|
||||
HTTPRequestDoc.Fields[28].Comments[encoder.LineComment] = "IterateAll iterates all the values extracted from internal extractors"
|
||||
|
||||
MATCHERSMatcherDoc.Type = "matchers.Matcher"
|
||||
MATCHERSMatcherDoc.Comments[encoder.LineComment] = " Matcher is used to match a part in the output from a protocol."
|
||||
|
@ -1436,7 +1443,7 @@ func init() {
|
|||
Value: "Headless response received from client (default)",
|
||||
},
|
||||
}
|
||||
HEADLESSRequestDoc.Fields = make([]encoder.Doc, 7)
|
||||
HEADLESSRequestDoc.Fields = make([]encoder.Doc, 9)
|
||||
HEADLESSRequestDoc.Fields[0].Name = "id"
|
||||
HEADLESSRequestDoc.Fields[0].Type = "string"
|
||||
HEADLESSRequestDoc.Fields[0].Note = ""
|
||||
|
@ -1457,22 +1464,32 @@ func init() {
|
|||
HEADLESSRequestDoc.Fields[3].Note = ""
|
||||
HEADLESSRequestDoc.Fields[3].Description = "Steps is the list of actions to run for headless request"
|
||||
HEADLESSRequestDoc.Fields[3].Comments[encoder.LineComment] = "Steps is the list of actions to run for headless request"
|
||||
HEADLESSRequestDoc.Fields[4].Name = "matchers"
|
||||
HEADLESSRequestDoc.Fields[4].Type = "[]matchers.Matcher"
|
||||
HEADLESSRequestDoc.Fields[4].Name = "user_agent"
|
||||
HEADLESSRequestDoc.Fields[4].Type = "userAgent.UserAgentHolder"
|
||||
HEADLESSRequestDoc.Fields[4].Note = ""
|
||||
HEADLESSRequestDoc.Fields[4].Description = "Matchers contains the detection mechanism for the request to identify\nwhether the request was successful by doing pattern matching\non request/responses.\n\nMultiple matchers can be combined with `matcher-condition` flag\nwhich accepts either `and` or `or` as argument."
|
||||
HEADLESSRequestDoc.Fields[4].Comments[encoder.LineComment] = "Matchers contains the detection mechanism for the request to identify"
|
||||
HEADLESSRequestDoc.Fields[5].Name = "extractors"
|
||||
HEADLESSRequestDoc.Fields[5].Type = "[]extractors.Extractor"
|
||||
HEADLESSRequestDoc.Fields[4].Description = "descriptions: |\n User-Agent is the type of user-agent to use for the request."
|
||||
HEADLESSRequestDoc.Fields[4].Comments[encoder.LineComment] = " descriptions: |"
|
||||
HEADLESSRequestDoc.Fields[5].Name = "custom_user_agent"
|
||||
HEADLESSRequestDoc.Fields[5].Type = "string"
|
||||
HEADLESSRequestDoc.Fields[5].Note = ""
|
||||
HEADLESSRequestDoc.Fields[5].Description = "Extractors contains the extraction mechanism for the request to identify\nand extract parts of the response."
|
||||
HEADLESSRequestDoc.Fields[5].Comments[encoder.LineComment] = "Extractors contains the extraction mechanism for the request to identify"
|
||||
HEADLESSRequestDoc.Fields[6].Name = "matchers-condition"
|
||||
HEADLESSRequestDoc.Fields[6].Type = "string"
|
||||
HEADLESSRequestDoc.Fields[5].Description = "description: |\n If UserAgent is set to custom, customUserAgent is the custom user-agent to use for the request."
|
||||
HEADLESSRequestDoc.Fields[5].Comments[encoder.LineComment] = " description: |"
|
||||
HEADLESSRequestDoc.Fields[6].Name = "matchers"
|
||||
HEADLESSRequestDoc.Fields[6].Type = "[]matchers.Matcher"
|
||||
HEADLESSRequestDoc.Fields[6].Note = ""
|
||||
HEADLESSRequestDoc.Fields[6].Description = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||
HEADLESSRequestDoc.Fields[6].Comments[encoder.LineComment] = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||
HEADLESSRequestDoc.Fields[6].Values = []string{
|
||||
HEADLESSRequestDoc.Fields[6].Description = "Matchers contains the detection mechanism for the request to identify\nwhether the request was successful by doing pattern matching\non request/responses.\n\nMultiple matchers can be combined with `matcher-condition` flag\nwhich accepts either `and` or `or` as argument."
|
||||
HEADLESSRequestDoc.Fields[6].Comments[encoder.LineComment] = "Matchers contains the detection mechanism for the request to identify"
|
||||
HEADLESSRequestDoc.Fields[7].Name = "extractors"
|
||||
HEADLESSRequestDoc.Fields[7].Type = "[]extractors.Extractor"
|
||||
HEADLESSRequestDoc.Fields[7].Note = ""
|
||||
HEADLESSRequestDoc.Fields[7].Description = "Extractors contains the extraction mechanism for the request to identify\nand extract parts of the response."
|
||||
HEADLESSRequestDoc.Fields[7].Comments[encoder.LineComment] = "Extractors contains the extraction mechanism for the request to identify"
|
||||
HEADLESSRequestDoc.Fields[8].Name = "matchers-condition"
|
||||
HEADLESSRequestDoc.Fields[8].Type = "string"
|
||||
HEADLESSRequestDoc.Fields[8].Note = ""
|
||||
HEADLESSRequestDoc.Fields[8].Description = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||
HEADLESSRequestDoc.Fields[8].Comments[encoder.LineComment] = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||
HEADLESSRequestDoc.Fields[8].Values = []string{
|
||||
"and",
|
||||
"or",
|
||||
}
|
||||
|
@ -1548,6 +1565,28 @@ func init() {
|
|||
"waitvisible",
|
||||
}
|
||||
|
||||
USERAGENTUserAgentHolderDoc.Type = "userAgent.UserAgentHolder"
|
||||
USERAGENTUserAgentHolderDoc.Comments[encoder.LineComment] = " UserAgentHolder holds a UserAgent type. Required for un/marshalling purposes"
|
||||
USERAGENTUserAgentHolderDoc.Description = "UserAgentHolder holds a UserAgent type. Required for un/marshalling purposes"
|
||||
USERAGENTUserAgentHolderDoc.AppearsIn = []encoder.Appearance{
|
||||
{
|
||||
TypeName: "headless.Request",
|
||||
FieldName: "user_agent",
|
||||
},
|
||||
}
|
||||
USERAGENTUserAgentHolderDoc.Fields = make([]encoder.Doc, 1)
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].Name = ""
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].Type = "UserAgent"
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].Note = ""
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].Description = ""
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].Comments[encoder.LineComment] = ""
|
||||
USERAGENTUserAgentHolderDoc.Fields[0].EnumFields = []string{
|
||||
"random",
|
||||
"off",
|
||||
"default",
|
||||
"custom",
|
||||
}
|
||||
|
||||
SSLRequestDoc.Type = "ssl.Request"
|
||||
SSLRequestDoc.Comments[encoder.LineComment] = " Request is a request for the SSL protocol"
|
||||
SSLRequestDoc.Description = "Request is a request for the SSL protocol"
|
||||
|
@ -1886,6 +1925,7 @@ func GetTemplateDoc() *encoder.FileDoc {
|
|||
&HEADLESSRequestDoc,
|
||||
&ENGINEActionDoc,
|
||||
&ActionTypeHolderDoc,
|
||||
&USERAGENTUserAgentHolderDoc,
|
||||
&SSLRequestDoc,
|
||||
&WEBSOCKETRequestDoc,
|
||||
&WEBSOCKETInputDoc,
|
||||
|
|
|
@ -45,6 +45,7 @@ func RunNucleiAndGetResults(isTemplate bool, template, url string, debug bool, e
|
|||
func RunNucleiBareArgsAndGetResults(debug bool, extra ...string) ([]string, error) {
|
||||
cmd := exec.Command("./nuclei")
|
||||
cmd.Args = append(cmd.Args, extra...)
|
||||
cmd.Args = append(cmd.Args, "-duc") // disable auto updates
|
||||
if debug {
|
||||
cmd.Args = append(cmd.Args, "-debug")
|
||||
cmd.Stderr = os.Stderr
|
||||
|
@ -53,6 +54,9 @@ func RunNucleiBareArgsAndGetResults(debug bool, extra ...string) ([]string, erro
|
|||
cmd.Args = append(cmd.Args, "-silent")
|
||||
}
|
||||
data, err := cmd.Output()
|
||||
if debug {
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -71,11 +75,15 @@ var templateLoaded = regexp.MustCompile(`(?:Templates|Workflows) loaded[^:]*: (\
|
|||
// RunNucleiBinaryAndGetLoadedTemplates returns a list of results for a template
|
||||
func RunNucleiBinaryAndGetLoadedTemplates(nucleiBinary string, debug bool, args []string) (string, error) {
|
||||
cmd := exec.Command(nucleiBinary, args...)
|
||||
cmd.Args = append(cmd.Args, "-duc") // disable auto updates
|
||||
if debug {
|
||||
cmd.Args = append(cmd.Args, "-debug")
|
||||
fmt.Println(cmd.String())
|
||||
}
|
||||
data, err := cmd.CombinedOutput()
|
||||
if debug {
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/rs/xid"
|
||||
)
|
||||
|
||||
// Default resume file
|
||||
const DefaultResumeFileName = "resume.cfg"
|
||||
const DefaultResumeFileName = "resume-%s.cfg"
|
||||
|
||||
func DefaultResumeFilePath() string {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return DefaultResumeFileName
|
||||
return fmt.Sprintf("resume-%s.cfg", xid.New().String())
|
||||
}
|
||||
return filepath.Join(home, ".config", "nuclei", DefaultResumeFileName)
|
||||
resumeFile := filepath.Join(home, ".config", "nuclei", fmt.Sprintf("resume-%s.cfg", xid.New().String()))
|
||||
return resumeFile
|
||||
}
|
||||
|
||||
// ResumeCfg contains the scan progression
|
||||
|
|
|
@ -64,7 +64,7 @@ type Options struct {
|
|||
// TargetsFilePath specifies the targets from a file to scan using templates.
|
||||
TargetsFilePath string
|
||||
// Resume the scan from the state stored in the resume config file
|
||||
Resume bool
|
||||
Resume string
|
||||
// Output is the file to write found results to.
|
||||
Output string
|
||||
// List of HTTP(s)/SOCKS5 proxy to use (comma separated or file input)
|
||||
|
@ -214,7 +214,7 @@ func (options *Options) VarsPayload() map[string]interface{} {
|
|||
|
||||
// ShouldLoadResume resume file
|
||||
func (options *Options) ShouldLoadResume() bool {
|
||||
return options.Resume && fileutil.FileExists(DefaultResumeFilePath())
|
||||
return options.Resume != "" && fileutil.FileExists(options.Resume)
|
||||
}
|
||||
|
||||
// ShouldSaveResume file
|
||||
|
|
|
@ -2,17 +2,17 @@ package utils
|
|||
|
||||
type InsertionOrderedStringMap struct {
|
||||
keys []string `yaml:"-"`
|
||||
values map[string]string
|
||||
values map[string]interface{}
|
||||
}
|
||||
|
||||
func NewEmptyInsertionOrderedStringMap(size int) *InsertionOrderedStringMap {
|
||||
return &InsertionOrderedStringMap{
|
||||
keys: make([]string, 0, size),
|
||||
values: make(map[string]string, size),
|
||||
values: make(map[string]interface{}, size),
|
||||
}
|
||||
}
|
||||
|
||||
func NewInsertionOrderedStringMap(stringMap map[string]string) *InsertionOrderedStringMap {
|
||||
func NewInsertionOrderedStringMap(stringMap map[string]interface{}) *InsertionOrderedStringMap {
|
||||
result := NewEmptyInsertionOrderedStringMap(len(stringMap))
|
||||
|
||||
for k, v := range stringMap {
|
||||
|
@ -22,13 +22,13 @@ func NewInsertionOrderedStringMap(stringMap map[string]string) *InsertionOrdered
|
|||
return result
|
||||
}
|
||||
|
||||
func (insertionOrderedStringMap *InsertionOrderedStringMap) ForEach(fn func(key string, data string)) {
|
||||
func (insertionOrderedStringMap *InsertionOrderedStringMap) ForEach(fn func(key string, data interface{})) {
|
||||
for _, key := range insertionOrderedStringMap.keys {
|
||||
fn(key, insertionOrderedStringMap.values[key])
|
||||
}
|
||||
}
|
||||
|
||||
func (insertionOrderedStringMap *InsertionOrderedStringMap) Set(key string, value string) {
|
||||
func (insertionOrderedStringMap *InsertionOrderedStringMap) Set(key string, value interface{}) {
|
||||
_, present := insertionOrderedStringMap.values[key]
|
||||
insertionOrderedStringMap.values[key] = value
|
||||
if !present {
|
||||
|
|
Loading…
Reference in New Issue