mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-08 02:08:33 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13cb549351 |
No files matched your search
@@ -18,11 +18,6 @@ labels: 'Type: Bug'
|
||||
<!-- We only accept issues that are reproducible on the latest version of nuclei. -->
|
||||
<!-- You can find the latest version of project at https://github.com/projectdiscovery/nuclei/releases/ -->
|
||||
|
||||
## Nuclei command:
|
||||
|
||||
<!-- Provide the exact command you used to run Nuclei. -->
|
||||
<!-- Please redact any literal target hosts/URLs or other sensitive information. -->
|
||||
|
||||
### Current Behavior:
|
||||
<!-- A concise description of what you're experiencing. -->
|
||||
|
||||
|
||||
@@ -12,21 +12,24 @@ jobs:
|
||||
name: Test Builds
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
# required for running python code in py-snippet.yaml integration test
|
||||
- name: Set up Python
|
||||
- name: Set up Python # required for running python code in py-snippet.yaml integration test
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygiene
|
||||
run: |
|
||||
go clean -modcache
|
||||
@@ -62,10 +65,9 @@ jobs:
|
||||
run: go run .
|
||||
working-directory: examples/simple/
|
||||
|
||||
# Temporarily disabled very flaky in github actions
|
||||
# - name: Example SDK Advanced
|
||||
# run: go run .
|
||||
# working-directory: examples/advanced/
|
||||
- name: Example SDK Advanced
|
||||
run: go run .
|
||||
working-directory: examples/advanced/
|
||||
|
||||
- name: Example SDK with speed control
|
||||
run: go run .
|
||||
|
||||
@@ -15,11 +15,13 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Functional Tests
|
||||
env:
|
||||
|
||||
@@ -12,11 +12,16 @@ jobs:
|
||||
name: Lint Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run golangci-lint
|
||||
uses: projectdiscovery/actions/golangci-lint@v1
|
||||
uses: golangci/[email protected]
|
||||
with:
|
||||
version: latest
|
||||
args: --timeout 5m
|
||||
@@ -11,16 +11,19 @@ jobs:
|
||||
name: Test Performance
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.21.x]
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: github.repository == 'projectdiscovery/nuclei'
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Mod hygine
|
||||
run: |
|
||||
|
||||
@@ -11,15 +11,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: "Set up Go"
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- name: "Set up Git"
|
||||
uses: projectdiscovery/actions/setup/git@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Generate YAML Syntax Documentation
|
||||
id: generate-docs
|
||||
@@ -36,6 +35,8 @@ jobs:
|
||||
- name: Commit files
|
||||
if: steps.generate-docs.outputs.CHANGES > 0
|
||||
run: |
|
||||
git config --local user.email "[email protected]"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add SYNTAX-REFERENCE.md nuclei-jsonschema.json
|
||||
git commit -m "Auto Generate Syntax Docs + JSONSchema [$(date)] :robot:" -a
|
||||
|
||||
|
||||
@@ -9,17 +9,20 @@ on:
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
|
||||
- uses: projectdiscovery/actions/goreleaser@v1
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
release: true
|
||||
go-version: 1.21.x
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --clean"
|
||||
version: latest
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"
|
||||
|
||||
@@ -12,12 +12,17 @@ jobs:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- name: "Check out code"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: projectdiscovery/actions/setup/go@v1
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Release snapshot
|
||||
uses: projectdiscovery/actions/goreleaser@v1
|
||||
- name: release test
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
args: "release --clean --snapshot"
|
||||
version: latest
|
||||
@@ -10,9 +10,10 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest-16-cores
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: projectdiscovery/actions/setup/go@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.21.x
|
||||
|
||||
- name: Template Validation
|
||||
run: |
|
||||
|
||||
@@ -203,6 +203,7 @@ CONFIGURATIONS:
|
||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||
-ztls use ztls library with autofallback to standard one for tls13 [Deprecated] autofallback to ztls is enabled by default
|
||||
-sni string tls sni hostname to use (default: input domain name)
|
||||
-dt, -dialer-timeout value timeout for network requests.
|
||||
-dka, -dialer-keep-alive value keep-alive duration for network requests.
|
||||
-lfa, -allow-local-file-access allows file (payload) access anywhere on the system
|
||||
-lna, -restrict-local-network-access blocks connections to the local / private network
|
||||
@@ -211,6 +212,7 @@ CONFIGURATIONS:
|
||||
-sip, -source-ip string source ip address to use for network scan
|
||||
-rsr, -response-size-read int max response size to read in bytes
|
||||
-rss, -response-size-save int max response size to read in bytes (default 1048576)
|
||||
-rrt, -response-read-timeout value response read timeout in seconds (default 5s)
|
||||
-reset reset removes all nuclei configuration and data files (including nuclei-templates)
|
||||
-tlsi, -tls-impersonate enable experimental client hello (ja3) tls randomization
|
||||
-hae, -http-api-endpoint string experimental http api endpoint
|
||||
@@ -236,7 +238,7 @@ FUZZING:
|
||||
UNCOVER:
|
||||
-uc, -uncover enable uncover engine
|
||||
-uq, -uncover-query string[] uncover search query
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow,google) (default shodan)
|
||||
-ue, -uncover-engine string[] uncover search engine (shodan,censys,fofa,shodan-idb,quake,hunter,zoomeye,netlas,criminalip,publicwww,hunterhow) (default shodan)
|
||||
-uf, -uncover-field string uncover fields to return (ip,port,host) (default "ip:port")
|
||||
-ul, -uncover-limit int uncover results to return (default 100)
|
||||
-ur, -uncover-ratelimit int override ratelimit of engines with unknown ratelimit (default 60 req/min) (default 60)
|
||||
@@ -309,10 +311,9 @@ STATISTICS:
|
||||
-mp, -metrics-port int port to expose nuclei metrics on (default 9092)
|
||||
|
||||
CLOUD:
|
||||
-auth configure projectdiscovery cloud (pdcp) api key (default true)
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard
|
||||
-sid, -scan-id string upload scan results to existing scan id (optional)
|
||||
-sname, -scan-name string scan name to set (optional)
|
||||
-auth configure projectdiscovery cloud (pdcp) api key
|
||||
-cup, -cloud-upload upload scan results to pdcp dashboard
|
||||
-sid, -scan-id string upload scan results to given scan id
|
||||
|
||||
AUTHENTICATION:
|
||||
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
|
||||
|
||||
@@ -4339,6 +4339,19 @@ Code contains code to execute for the javascript request.
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>timeout</code> <i>int</i>
|
||||
|
||||
</div>
|
||||
<div class="dt">
|
||||
|
||||
Timeout in seconds is optional timeout for each javascript script execution (i.e init, pre-condition, code)
|
||||
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="dd">
|
||||
|
||||
<code>stop-at-first-match</code> <i>bool</i>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -172,14 +172,7 @@ func (h *nonExistentTemplateList) Execute(nonExistingTemplateList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404", "-config", "test-config.yaml")
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
@@ -195,14 +188,7 @@ func (h *nonExistentWorkflowList) Execute(nonExistingWorkflowList string) error
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
configFileData := `remote-template-domain: [ "` + ts.Listener.Addr().String() + `" ]`
|
||||
err := os.WriteFile("test-config.yaml", []byte(configFileData), permissionutil.ConfigFilePermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove("test-config.yaml")
|
||||
|
||||
_, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404", "-config", "test-config.yaml")
|
||||
_, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404")
|
||||
if err == nil {
|
||||
return fmt.Errorf("expected error for nonexisting workflow url")
|
||||
}
|
||||
|
||||
@@ -297,6 +297,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
|
||||
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13 [Deprecated] autofallback to ztls is enabled by default"), //nolint:all
|
||||
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
|
||||
flagSet.DurationVarP(&options.DialerTimeout, "dialer-timeout", "dt", 0, "timeout for network requests."),
|
||||
flagSet.DurationVarP(&options.DialerKeepAlive, "dialer-keep-alive", "dka", 0, "keep-alive duration for network requests."),
|
||||
flagSet.BoolVarP(&options.AllowLocalFileAccess, "allow-local-file-access", "lfa", false, "allows file (payload) access anywhere on the system"),
|
||||
flagSet.BoolVarP(&options.RestrictLocalNetworkAccess, "restrict-local-network-access", "lna", false, "blocks connections to the local / private network"),
|
||||
@@ -305,6 +306,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
|
||||
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 0, "max response size to read in bytes"),
|
||||
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", unitutils.Mega, "max response size to read in bytes"),
|
||||
flagSet.DurationVarP(&options.ResponseReadTimeout, "response-read-timeout", "rrt", time.Duration(5*time.Second), "response read timeout in seconds"),
|
||||
flagSet.CallbackVar(resetCallback, "reset", "reset removes all nuclei configuration and data files (including nuclei-templates)"),
|
||||
flagSet.BoolVarP(&options.TlsImpersonate, "tls-impersonate", "tlsi", false, "enable experimental client hello (ja3) tls randomization"),
|
||||
flagSet.StringVarP(&options.HttpApiEndpoint, "http-api-endpoint", "hae", "", "experimental http api endpoint"),
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/installer"
|
||||
syncutil "github.com/projectdiscovery/utils/sync"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
// when running nuclei in parallel for first time it is a good practice to make sure
|
||||
// templates exists first
|
||||
tm := installer.TemplateManager{}
|
||||
if err := tm.FreshInstallIfNotExists(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// create nuclei engine with options
|
||||
ne, err := nuclei.NewThreadSafeNucleiEngineCtx(ctx)
|
||||
ne, err := nuclei.NewThreadSafeNucleiEngine()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
|
||||
)
|
||||
import nuclei "github.com/projectdiscovery/nuclei/v3/lib"
|
||||
|
||||
func main() {
|
||||
ne, err := nuclei.NewNucleiEngineCtx(context.Background(),
|
||||
ne, err := nuclei.NewNucleiEngine(
|
||||
nuclei.WithTemplateFilters(nuclei.TemplateFilters{Tags: []string{"oast"}}),
|
||||
nuclei.EnableStatsWithOpts(nuclei.StatsOptions{MetricServerPort: 6064}), // optionally enable metrics server for better observability
|
||||
)
|
||||
|
||||
@@ -20,12 +20,12 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/projectdiscovery/clistats v0.0.20
|
||||
github.com/projectdiscovery/fastdialer v0.2.3
|
||||
github.com/projectdiscovery/hmap v0.0.54
|
||||
github.com/projectdiscovery/fastdialer v0.1.5
|
||||
github.com/projectdiscovery/hmap v0.0.47
|
||||
github.com/projectdiscovery/interactsh v1.2.0
|
||||
github.com/projectdiscovery/rawhttp v0.1.60
|
||||
github.com/projectdiscovery/retryabledns v1.0.69
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.71
|
||||
github.com/projectdiscovery/rawhttp v0.1.51
|
||||
github.com/projectdiscovery/retryabledns v1.0.65
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.66
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@@ -58,9 +58,9 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.27
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0
|
||||
github.com/cespare/xxhash v1.1.0
|
||||
github.com/charmbracelet/glamour v0.6.0
|
||||
github.com/clbanning/mxj/v2 v2.7.0
|
||||
github.com/denisenkom/go-mssqldb v0.12.3
|
||||
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204
|
||||
@@ -76,27 +76,26 @@ require (
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mattn/go-sqlite3 v1.14.22
|
||||
github.com/mholt/archiver v3.1.1+incompatible
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/ory/dockertest/v3 v3.10.0
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9
|
||||
github.com/projectdiscovery/dsl v0.1.8
|
||||
github.com/projectdiscovery/dsl v0.1.3
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
||||
github.com/projectdiscovery/goflags v0.1.62
|
||||
github.com/projectdiscovery/gologger v1.1.18
|
||||
github.com/projectdiscovery/goflags v0.1.56
|
||||
github.com/projectdiscovery/gologger v1.1.12
|
||||
github.com/projectdiscovery/gostruct v0.0.2
|
||||
github.com/projectdiscovery/gozero v0.0.2
|
||||
github.com/projectdiscovery/httpx v1.6.7
|
||||
github.com/projectdiscovery/httpx v1.6.3
|
||||
github.com/projectdiscovery/mapcidr v1.1.34
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/ratelimit v0.0.49
|
||||
github.com/projectdiscovery/ratelimit v0.0.45
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.6
|
||||
github.com/projectdiscovery/uncover v1.0.9
|
||||
github.com/projectdiscovery/useragent v0.0.65
|
||||
github.com/projectdiscovery/utils v0.2.4
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14
|
||||
github.com/projectdiscovery/uncover v1.0.8
|
||||
github.com/projectdiscovery/useragent v0.0.56
|
||||
github.com/projectdiscovery/utils v0.1.4
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.6
|
||||
github.com/redis/go-redis/v9 v9.1.0
|
||||
github.com/seh-msft/burpxml v1.0.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
@@ -130,6 +129,7 @@ require (
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
@@ -158,7 +158,7 @@ require (
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.4 // indirect
|
||||
github.com/google/go-github/v30 v30.1.0 // indirect
|
||||
@@ -200,12 +200,12 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/projectdiscovery/asnmap v1.1.1 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.1.0 // indirect
|
||||
github.com/projectdiscovery/asnmap v1.1.0 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.0.9 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.5 // indirect
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
|
||||
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect
|
||||
github.com/refraction-networking/utls v1.6.7 // indirect
|
||||
github.com/refraction-networking/utls v1.6.6 // indirect
|
||||
github.com/sashabaranov/go-openai v1.15.3 // indirect
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
@@ -293,6 +293,7 @@ require (
|
||||
github.com/trivago/tgo v1.0.7
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/yl2chen/cidranger v1.0.2 // indirect
|
||||
github.com/ysmood/goob v0.4.0 // indirect
|
||||
github.com/ysmood/gson v0.7.3 // indirect
|
||||
github.com/ysmood/leakless v0.8.0 // indirect
|
||||
|
||||
@@ -40,18 +40,17 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8=
|
||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
@@ -261,6 +260,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
@@ -273,6 +274,7 @@ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwu
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc=
|
||||
github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
|
||||
@@ -418,8 +420,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -711,8 +713,6 @@ github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssn
|
||||
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||
github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
|
||||
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||
@@ -741,6 +741,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
@@ -810,6 +811,7 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -824,36 +826,36 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9 h1:zWbG/Fdan0s/dvXkeaHb/CdFTz/yEEzrAF4iCzok3r8=
|
||||
github.com/praetorian-inc/fingerprintx v1.1.9/go.mod h1:k6EJIHe/Da4DH5e4JuoZHe+qSGq/KPUmXGaK+xW74OI=
|
||||
github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kID2iwsDqI=
|
||||
github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60=
|
||||
github.com/projectdiscovery/asnmap v1.1.0 h1:ynvbLB5cNpyQ2+k9IP0Rpla+0JmCJpd3mw6KLAW13m0=
|
||||
github.com/projectdiscovery/asnmap v1.1.0/go.mod h1:QNjBnGLxUBEZAgaYk/Av5cjKKWFY3i/FOfoIWCUApoY=
|
||||
github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
|
||||
github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
|
||||
github.com/projectdiscovery/cdncheck v1.1.0 h1:qDITidmJsejzpk3rMkauCh6sjI2GH9hW/snk0cQ3kXE=
|
||||
github.com/projectdiscovery/cdncheck v1.1.0/go.mod h1:sZ8U4MjHSsyaTVjBbYWHT1cwUVvUYwDX1W+WvWRicIc=
|
||||
github.com/projectdiscovery/cdncheck v1.0.9 h1:BS15gzj9gb5AVSKqTDzPamfSgStu7nJQOocUvrssFlg=
|
||||
github.com/projectdiscovery/cdncheck v1.0.9/go.mod h1:18SSl1w7rMj53CGeRIZTbDoa286a6xZIxGbaiEo4Fxs=
|
||||
github.com/projectdiscovery/clistats v0.0.20 h1:5jO5SLiRJ7f0nDV0ndBNmBeesbROouPooH+DGMgoWq4=
|
||||
github.com/projectdiscovery/clistats v0.0.20/go.mod h1:GJ2av0KnOvK0AISQnP8hyDclYIji1LVkx2l0pwnzAu4=
|
||||
github.com/projectdiscovery/dsl v0.1.8 h1:ulz+o097XsYgqP4QXaAQhVSkoeD2ZPWd29wX3CTodUA=
|
||||
github.com/projectdiscovery/dsl v0.1.8/go.mod h1:AYJS2WQ/q0smr2v4pEJTg4DPe6k56KFKR7UFXvzNz/4=
|
||||
github.com/projectdiscovery/fastdialer v0.2.3 h1:K03x5XEXGyVWxS2rtSR104E9kHF0aphN7kOCzbh8zv0=
|
||||
github.com/projectdiscovery/fastdialer v0.2.3/go.mod h1:a0BKvETrO1EAohUYp9gwtbbce0hKD1qGrTegyAUqyRo=
|
||||
github.com/projectdiscovery/dsl v0.1.3 h1:Lxlgpx8lwq/CaBjVUmwF6KmkMDnYf9IVKlMsWCF72OE=
|
||||
github.com/projectdiscovery/dsl v0.1.3/go.mod h1:WAuQLD4KQ/94RASotE7cvk7X6kY7JQG9Fcqc3lRQfpI=
|
||||
github.com/projectdiscovery/fastdialer v0.1.5 h1:5rNJ8I+GVzDsUqRSVLUqGTm7LsshfNYmCh20lLn1aaI=
|
||||
github.com/projectdiscovery/fastdialer v0.1.5/go.mod h1:oVoMl9Y6da2timhszy0okyBvhbKDSk+zqFazGV4y6pU=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
|
||||
github.com/projectdiscovery/freeport v0.0.5 h1:jnd3Oqsl4S8n0KuFkE5Hm8WGDP24ITBvmyw5pFTHS8Q=
|
||||
github.com/projectdiscovery/freeport v0.0.5/go.mod h1:PY0bxSJ34HVy67LHIeF3uIutiCSDwOqKD8ruBkdiCwE=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG906Drtbpz4DwU5mhGIeOhRcktDH4cGQitGUMAsg=
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY=
|
||||
github.com/projectdiscovery/goflags v0.1.62 h1:UmzKJQT+1UyqT1cZDmb3vZ8/IGhQ7LTsWfdqVcAGoJc=
|
||||
github.com/projectdiscovery/goflags v0.1.62/go.mod h1:d1/D8GaTDoV332ABwceUcY1ffKODaYFlGP0Oriq3wfk=
|
||||
github.com/projectdiscovery/gologger v1.1.18 h1:fux2S/LXYe18/w4PylAFpEFg+EApNCuyS85x25nDE98=
|
||||
github.com/projectdiscovery/gologger v1.1.18/go.mod h1:IgjKgVLfVGUovxlC6WJcXK0qvo/tNZ1P0+r6miQqyRk=
|
||||
github.com/projectdiscovery/goflags v0.1.56 h1:tJYiZN7s9Jk9DxfYOUiqOoybaIDlXyX4ZgT4B/06SyU=
|
||||
github.com/projectdiscovery/goflags v0.1.56/go.mod h1:DsGF0NPpM5hGg75N3MTSvWJ4MIT7HFEAOEeWZ074+Fg=
|
||||
github.com/projectdiscovery/gologger v1.1.12 h1:uX/QkQdip4PubJjjG0+uk5DtyAi1ANPJUvpmimXqv4A=
|
||||
github.com/projectdiscovery/gologger v1.1.12/go.mod h1:DI8nywPLERS5mo8QEA9E7gd5HZ3Je14SjJBH3F5/kLw=
|
||||
github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
|
||||
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
|
||||
github.com/projectdiscovery/gozero v0.0.2 h1:8fJeaCjxL9tpm33uG/RsCQs6HGM/NE6eA3cjkilRQ+E=
|
||||
github.com/projectdiscovery/gozero v0.0.2/go.mod h1:d8bZvDWW07LWNYWrwjZ4OO1I0cpkfqaysyDfSs9ibK8=
|
||||
github.com/projectdiscovery/hmap v0.0.54 h1:b3pdQZwCw4is3xiL2jBx7SJZcYaf/7vtozY7bjUzO/s=
|
||||
github.com/projectdiscovery/hmap v0.0.54/go.mod h1:j0oakxYOWEfk29wRq5gQgrCv1JnfAfzGaMsRWwEas80=
|
||||
github.com/projectdiscovery/httpx v1.6.7 h1:luJAtQ+iKpiyKKDpcWw1/fF1MaRX6JZ4R3P+ol5Uikk=
|
||||
github.com/projectdiscovery/httpx v1.6.7/go.mod h1:rqcuexBrb4v36ZyX0BHcHaovTurOJn2P65Tdt9cYdfE=
|
||||
github.com/projectdiscovery/hmap v0.0.47 h1:NdakfvlFruevnOvehdllofg/hc0CQn2WQaLHaRcsGAk=
|
||||
github.com/projectdiscovery/hmap v0.0.47/go.mod h1:/9V6EnyTY33hAy71Quox6Ggu9ZkKp36tgepBh/NzNSg=
|
||||
github.com/projectdiscovery/httpx v1.6.3 h1:TSu3zEKOHGFfMsGeB0lZEFRl6Tq4nPuIgKDXi9NnYpg=
|
||||
github.com/projectdiscovery/httpx v1.6.3/go.mod h1:9FmsmkT71aTa4WnOyBIPzB8I9c0QAJ9PSVUqs2NkHRQ=
|
||||
github.com/projectdiscovery/interactsh v1.2.0 h1:Al6jHiR+Usl9egYJDLJaWNHOcH8Rugk8gWMasc8Cmw8=
|
||||
github.com/projectdiscovery/interactsh v1.2.0/go.mod h1:Wxt0fnzxsfrAZQQlpVrf3xMatP4OXZaZbjuDkIQKdYY=
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8=
|
||||
@@ -866,30 +868,30 @@ github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9 h1:IrlDoYZagNNO8y+7iZeHT8k5izE+nek7TdtvEBwCxqk=
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9/go.mod h1:XFJ2Lnv8BE/ziQCFjBHMsH1w6VmkPiQtk+NlBpdMU7M=
|
||||
github.com/projectdiscovery/ratelimit v0.0.49 h1:PYatMp8g5OuoFsZOA90e48nLd2vB6a4Tw0FZ8h9zqkQ=
|
||||
github.com/projectdiscovery/ratelimit v0.0.49/go.mod h1:Xi0LTMHg4HQlmCZFzRBIhRW6N+QW5RxQ8V/Qs+Vta4k=
|
||||
github.com/projectdiscovery/rawhttp v0.1.60 h1:L57kAATGRuCfOp8Fs0ly3j2wlip7R5pco2RVfwqh/II=
|
||||
github.com/projectdiscovery/rawhttp v0.1.60/go.mod h1:M97w6lsphTHKeqLSio4Lw9K4KLO2riJMYAOqVMIZ3ck=
|
||||
github.com/projectdiscovery/ratelimit v0.0.45 h1:h28oF+hJ0CHcdBZozT1Go7ppWmzTxSXDKNNh2G1Ot9Q=
|
||||
github.com/projectdiscovery/ratelimit v0.0.45/go.mod h1:1vSJUseDS7SjNwIBi9wNRcgsMKNTLxy/GfdlLFVbgI4=
|
||||
github.com/projectdiscovery/rawhttp v0.1.51 h1:T4sskU2fsX9zNR7nyae0tD/0fliIs73KwBzyoJwBs10=
|
||||
github.com/projectdiscovery/rawhttp v0.1.51/go.mod h1:ejBaw3dCfJSfbtFv0ib6YfFSjQzt7ZdRVpQWJASxIUs=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk=
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
|
||||
github.com/projectdiscovery/retryabledns v1.0.69 h1:6vhhlfxPQoJI0j1enYSzyagyAZJNfGSg9TNloVsxEBQ=
|
||||
github.com/projectdiscovery/retryabledns v1.0.69/go.mod h1:5SDuGtXgL4W1z/9V+xnmHFYg03Fi1Ud/F2kqlPlAgfE=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.71 h1:yXPNShCOwoTz7dBSJsBhBh4g4ujX62XS/BrH/fL1VyE=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.71/go.mod h1:wY3T89EwcCKAw6iyMDvwzGPyL3d8TaBU80hnDErEKgM=
|
||||
github.com/projectdiscovery/retryabledns v1.0.65 h1:wOtMuVkrcrGkzaT8Jixb3BtUcJODXLRz+z9EjftmFsQ=
|
||||
github.com/projectdiscovery/retryabledns v1.0.65/go.mod h1:lf3xRdFhGh55fWVlzK1oAaDPrsKliqH3gGvsFNAOkCk=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.66 h1:dY+sGVf/O8CvKcSdTx0rxJoKG+HyOScz5T89TijZohU=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.66/go.mod h1:3QJt06j4hEZVpJOr31u49I3mDnqbAzhcjJX8Yvn/xnY=
|
||||
github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
|
||||
github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
|
||||
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
|
||||
github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0=
|
||||
github.com/projectdiscovery/tlsx v1.1.6 h1:iw2zwKbd2+kRQ8J1G4dLmS0CLyemd/tKz1UzcNsC77A=
|
||||
github.com/projectdiscovery/tlsx v1.1.6/go.mod h1:s7SRRFdrwIZBK/RXXZi4CR/CubqFSvp8h5Bk1srEZIo=
|
||||
github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0JprejqLSopN9Y=
|
||||
github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U=
|
||||
github.com/projectdiscovery/useragent v0.0.65 h1:x78ZwWdqpzokOHxLITUXvq+ljkTKc19z3ILGtoV1N70=
|
||||
github.com/projectdiscovery/useragent v0.0.65/go.mod h1:deOP8YLJU6SCzM8k+K8PjkcOF4Ux0spqyO4ODZGIT4A=
|
||||
github.com/projectdiscovery/utils v0.2.4 h1:CHnlt2la4jr8TeL7ZK7UhQItHY7DDXqIuLnnxyAJLDY=
|
||||
github.com/projectdiscovery/utils v0.2.4/go.mod h1:2Vx7geSrBfCPqknZywqbChQm8SE30mcyrlB5YsxEnhA=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14 h1:nt1IM4RUmqeymsXk4h6BsZbKDoS2hjFvPkT2GaI1rz4=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14/go.mod h1:/hzgxkBFTMe2wDbA93nFfoMjULw7/vIZ9QPSAnCgUa8=
|
||||
github.com/projectdiscovery/uncover v1.0.8 h1:nE8bYJuwhqk0BEMRQRhNbjPGMy40A9gkiMk5xq6U4u0=
|
||||
github.com/projectdiscovery/uncover v1.0.8/go.mod h1:1SwsNqjwMkJEzJQ7lQr5AHIdYd+BQlyqhO5IwIYmIAM=
|
||||
github.com/projectdiscovery/useragent v0.0.56 h1:KpUtOgq1vUerPrgRFZAIr1hF0lDxA2RF6YkT2PLwSoQ=
|
||||
github.com/projectdiscovery/useragent v0.0.56/go.mod h1:LAh9vudxXPA5JfNN3+1g/Unqvulq0BDkjxK7IrE+e/s=
|
||||
github.com/projectdiscovery/utils v0.1.4 h1:VSULN/RBEXbkgWuhrDey84ZDnSXtYMSev9p+QHXXDeI=
|
||||
github.com/projectdiscovery/utils v0.1.4/go.mod h1:mXs6OOeG9l/dVchjB2PGvQO3+wuMiE14Y/kmHeKogoM=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.6 h1:4iZDEnytsnAqjQgD5K6lmAzVx++KSQeMCDfomDtQM1M=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.6/go.mod h1:wBYGKmA5BQp/NWsAy1q/jSH8N1LHWQ/LV26DuR+KzPM=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4/go.mod h1:8PIPRcUD55UbtQdcfFR1hpIGRWG0P7alClXNGt1TBik=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -927,8 +929,8 @@ github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
|
||||
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
|
||||
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
|
||||
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
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.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -1172,6 +1174,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
@@ -1265,6 +1268,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
|
||||
@@ -23,4 +23,4 @@ code:
|
||||
- type: dsl
|
||||
dsl:
|
||||
- true
|
||||
# digest: 4a0a0047304502200307590191cb7c766b6c21e5777d345bdddf7adf9d6da8f7d336d585d9ac4a8b022100fd30fb0c7722778eb3d861d60e721d805925b8d8df2b979ef2104c35ec57d5cb:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 490a004630440220192fb8f704b078c2885047b85ac1a0491be86485c033a976d201599683a35aab0220604b1c3781e9d97079d0e5c23c18e6a2d87493c8e2b930536e692ee7d06e9247:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -20,4 +20,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input baz"
|
||||
# digest: 4a0a0047304502203fe1d7d52bc2a41886d576a90c82c3be42078baaa4b46e1f3d8519665d6f88b202210081feb82c41150c5b218e226fc4f299ded19f42ba01ef34ba60b0634b4ea6ee12:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4a0a00473045022033f72f1b9d5143f58a2dc79c2597000f34080251ac3702c36c3fad00917dfeeb0221009ba05c715c9e2e36dba471be6c0106a09ae3822d8a3e9e4bcf377e9f4a395a01:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -18,4 +18,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4b0a00483046022100afb5ebff14a40e7f9b679ffc4d93ce7849e33eb398ebb47f2e757cd24831f9dd02210089ffa21b2763e99ebce95dfc5b91e1e62da4ccdc9d2ad5c48584fa350ba335af:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4a0a004730450220377128cb11d9f6f0fee1f4dbd841e46783de26e90a216fa55a7609ee2bc823c60221009166ee0f85e3a1811588ab19e73ea96ab3d582dc8180dbcbbad0ea9ab7e9025d:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -26,4 +26,4 @@ code:
|
||||
part: interactsh_protocol
|
||||
words:
|
||||
- "http"
|
||||
# digest: 4b0a00483046022100939f83e74d43932a5bd792b1fd2c100eec2df60f2b2a8dd56b5c8ef5faa92b17022100f93031b0de373af7d78e623968ea5a2d67c4561ef70e3e6da15aef7e5c853115:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4b0a00483046022100d472d50bd83117d334f5217c7a40dcdf34138e90029eaace51697d902296bf37022100a393b49420a96f60d6d89b79b5135ee2233b2468d374851890eea114b08195d1:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -21,4 +21,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from input"
|
||||
# digest: 4a0a00473045022100b8e676ce0c57b60c233a0203539dec20457bbb5f1790d351a5d45405b6668b2602204b1f2fa18e7db099f05329009597ceb2d9b7337562c1a676e8d50ea2f1c6fcbe:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 4b0a004830460221008886054bb5dd6345e434e30f31c8fddce3c484a4f33aa6321b5185675866029d022100d188a83d0fde029f8b586061c65ab72b43755c3fb10fdd59501bb9bbadbb1ff7:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -19,4 +19,4 @@ code:
|
||||
regex:
|
||||
- 'hello from (.*)'
|
||||
group: 1
|
||||
# digest: 490a00463044022050da011362cf08c2cb81e812c7f86d7282afe0562d4bf00d390f1300d19bc910022029e9d305da69e941ac18797645aecb217abde6557f891e141301b48e89a3c0cd:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 490a0046304402202c63d47bb0acdd40b3b852d95490d492ff5741b84071b2a8a40371be7797c13602202b6b977e157edf2ef70a402a2e57d4eb5a67c5ca91f0a2f9a10a966e8485ebaf:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -18,4 +18,4 @@ code:
|
||||
- type: word
|
||||
words:
|
||||
- "hello from first"
|
||||
# digest: 4b0a00483046022100b3b8759c0df028455eb59b1433ac240e5d4604b011bb0c63680bd3cc159ac6f0022100f44aa11b640d11ad0e2902897f4eb51666ab3cd83c31dfd2590f6e43391e39b0:4a3eb6b4988d95847d4203be25ed1d46
|
||||
# digest: 490a00463044022025661eab353b7f359c0d428a86b6287545d7f759375e8025cc8c9c77b616ca6502200bc2c019059622df3c88e7caa6dd7d1fb9b956010aa0de2ee2b9f7dd0a3c4954:4a3eb6b4988d95847d4203be25ed1d46
|
||||
@@ -142,7 +142,7 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) {
|
||||
// temporary buffer to store the results
|
||||
buff := &bytes.Buffer{}
|
||||
ticker := time.NewTicker(flushTimer)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolinit"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/headless/engine"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
|
||||
@@ -114,7 +115,12 @@ func ParseOptions(options *types.Options) {
|
||||
// Load the resolvers if user asked for them
|
||||
loadResolvers(options)
|
||||
|
||||
err := protocolinit.Init(options)
|
||||
err := protocolstate.Init(options)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocol state: %s\n", err)
|
||||
}
|
||||
|
||||
err = protocolinit.Init(options)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err)
|
||||
}
|
||||
|
||||
@@ -396,7 +396,6 @@ func WithHeaders(headers []string) NucleiSDKOptions {
|
||||
func EnablePassiveMode() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
e.opts.OfflineHTTP = true
|
||||
e.opts.DisableHTTPProbe = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -441,11 +440,3 @@ func WithCatalog(cat catalog.Catalog) NucleiSDKOptions {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DisableUpdateCheck disables nuclei update check
|
||||
func DisableUpdateCheck() NucleiSDKOptions {
|
||||
return func(e *NucleiEngine) error {
|
||||
DefaultConfig.DisableUpdateCheck()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -243,12 +243,7 @@ func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...f
|
||||
}
|
||||
e.resultCallbacks = append(e.resultCallbacks, filtered...)
|
||||
|
||||
templatesAndWorkflows := append(e.store.Templates(), e.store.Workflows()...)
|
||||
if len(templatesAndWorkflows) == 0 {
|
||||
return ErrNoTemplatesAvailable
|
||||
}
|
||||
|
||||
_ = e.engine.ExecuteScanWithOpts(ctx, templatesAndWorkflows, e.inputProvider, false)
|
||||
_ = e.engine.ExecuteScanWithOpts(ctx, e.store.Templates(), e.inputProvider, false)
|
||||
defer e.engine.WorkPool().Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
+8
-8
@@ -108,14 +108,6 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.opts.ProxyInternal && types.ProxyURL != "" || types.ProxySocksURL != "" {
|
||||
httpclient, err := httpclientpool.Get(e.opts, &httpclientpool.Configuration{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.httpClient = httpclient
|
||||
}
|
||||
|
||||
e.parser = templates.NewParser()
|
||||
|
||||
if sharedInit == nil || protocolstate.ShouldInit() {
|
||||
@@ -129,6 +121,14 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
e.applyRequiredDefaults(ctx)
|
||||
var err error
|
||||
|
||||
if e.opts.ProxyInternal && types.ProxyURL != "" || types.ProxySocksURL != "" {
|
||||
httpclient, err := httpclientpool.Get(e.opts, &httpclientpool.Configuration{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.httpClient = httpclient
|
||||
}
|
||||
|
||||
// setup progressbar
|
||||
if e.enableStats {
|
||||
progressInstance, progressErr := progress.NewStatsTicker(e.opts.StatsInterval, e.enableStats, e.opts.StatsJSON, false, e.opts.MetricsPort)
|
||||
|
||||
@@ -941,6 +941,11 @@
|
||||
"title": "code to execute in javascript",
|
||||
"description": "Executes inline javascript code for the request"
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer",
|
||||
"title": "timeout for javascript execution",
|
||||
"description": "Timeout in seconds is optional timeout for entire javascript script execution"
|
||||
},
|
||||
"stop-at-first-match": {
|
||||
"type": "boolean",
|
||||
"title": "stop at first match",
|
||||
|
||||
@@ -51,8 +51,7 @@ func NewFileAuthProvider(path string, callback authx.LazyFetchSecret) (AuthProvi
|
||||
|
||||
// init initializes the file auth provider
|
||||
func (f *FileAuthProvider) init() {
|
||||
for _, _secret := range f.store.Secrets {
|
||||
secret := _secret // allocate copy of pointer
|
||||
for _, secret := range f.store.Secrets {
|
||||
if len(secret.DomainsRegex) > 0 {
|
||||
for _, domain := range secret.DomainsRegex {
|
||||
if f.compiled == nil {
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
CLIConfigFileName = "config.yaml"
|
||||
ReportingConfigFilename = "reporting-config.yaml"
|
||||
// Version is the current version of nuclei
|
||||
Version = `v3.3.0`
|
||||
Version = `v3.2.9`
|
||||
// Directory Names of custom templates
|
||||
CustomS3TemplatesDirName = "s3"
|
||||
CustomGitHubTemplatesDirName = "github"
|
||||
|
||||
@@ -27,7 +27,7 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te
|
||||
var match bool
|
||||
ctx := scan.NewScanContext(ctx, contextargs.New(ctx))
|
||||
if e.Callback != nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err == nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err != nil {
|
||||
for _, result := range results {
|
||||
e.Callback(result)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
match = e.executeWorkflow(ctx, template.CompiledWorkflow)
|
||||
default:
|
||||
if e.Callback != nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err == nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err != nil {
|
||||
for _, result := range results {
|
||||
e.Callback(result)
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t
|
||||
match = e.executeWorkflow(ctx, template.CompiledWorkflow)
|
||||
default:
|
||||
if e.Callback != nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err == nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err != nil {
|
||||
for _, result := range results {
|
||||
e.Callback(result)
|
||||
}
|
||||
|
||||
+2
-5
@@ -167,12 +167,9 @@ func (rule *Rule) evaluateVarsWithInteractsh(data map[string]interface{}, intera
|
||||
if rule.options.Interactsh != nil {
|
||||
// Iterate through the data to replace and evaluate variables with Interactsh URLs
|
||||
for k, v := range data {
|
||||
value := fmt.Sprint(v)
|
||||
// Replace variables with Interactsh URLs and collect new URLs
|
||||
got, oastUrls := rule.options.Interactsh.Replace(value, interactshUrls)
|
||||
if got != value {
|
||||
data[k] = got
|
||||
}
|
||||
got, oastUrls := rule.options.Interactsh.Replace(fmt.Sprint(v), interactshUrls)
|
||||
|
||||
// Append new OAST URLs if any
|
||||
if len(oastUrls) > 0 {
|
||||
interactshUrls = append(interactshUrls, oastUrls...)
|
||||
|
||||
+2
-2
@@ -181,9 +181,9 @@ func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp.
|
||||
// for fuzzing.
|
||||
func (rule *Rule) executeEvaluate(input *ExecuteRuleInput, _, value, payload string, interactshURLs []string) (string, []string) {
|
||||
// TODO: Handle errors
|
||||
values := generators.MergeMaps(rule.options.Variables.GetAll(), map[string]interface{}{
|
||||
values := generators.MergeMaps(input.Values, map[string]interface{}{
|
||||
"value": value,
|
||||
}, rule.options.Options.Vars.AsMap(), input.Values)
|
||||
}, rule.options.Options.Vars.AsMap(), rule.options.Variables.GetAll())
|
||||
firstpass, _ := expressions.Evaluate(payload, values)
|
||||
interactData, interactshURLs := rule.options.Interactsh.Replace(firstpass, interactshURLs)
|
||||
evaluated, _ := expressions.Evaluate(interactData, values)
|
||||
|
||||
@@ -66,10 +66,9 @@ func (i *HttpInputProvider) Count() int64 {
|
||||
// Iterate over all inputs in order
|
||||
func (i *HttpInputProvider) Iterate(callback func(value *contextargs.MetaInput) bool) {
|
||||
err := i.format.Parse(i.inputFile, func(request *types.RequestResponse) bool {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.ReqResp = request
|
||||
metaInput.Input = request.URL.String()
|
||||
return callback(metaInput)
|
||||
return callback(&contextargs.MetaInput{
|
||||
ReqResp: request,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
gologger.Warning().Msgf("Could not parse input file while iterating: %s\n", err)
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
configTypes "github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -33,7 +32,7 @@ func IsErrNotImplemented(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if stringsutil.ContainsAll(err.Error(), "provider", "does not implement") {
|
||||
if strings.Contains(err.Error(), "provider") && strings.Contains(err.Error(), "does not implement") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -122,7 +122,7 @@ func (i *ListInputProvider) Iterate(callback func(value *contextargs.MetaInput)
|
||||
})
|
||||
}
|
||||
callbackFunc := func(k, _ []byte) error {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput := &contextargs.MetaInput{}
|
||||
if err := metaInput.Unmarshal(string(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -153,16 +153,14 @@ func (i *ListInputProvider) Set(value string) {
|
||||
}
|
||||
return fmt.Sprintf("got empty hostname for %v skipping ip selection", URL)
|
||||
})
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.setItem(metaInput)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if input is ip or hostname
|
||||
if iputil.IsIP(urlx.Hostname()) {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.setItem(metaInput)
|
||||
return
|
||||
}
|
||||
@@ -183,9 +181,7 @@ func (i *ListInputProvider) Set(value string) {
|
||||
if ip == "" {
|
||||
continue
|
||||
}
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = value
|
||||
metaInput.CustomIP = ip
|
||||
metaInput := &contextargs.MetaInput{Input: value, CustomIP: ip}
|
||||
i.setItem(metaInput)
|
||||
}
|
||||
return
|
||||
@@ -215,13 +211,11 @@ func (i *ListInputProvider) Set(value string) {
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
if ip != "" {
|
||||
metaInput.Input = URL
|
||||
metaInput.CustomIP = ip
|
||||
metaInput := &contextargs.MetaInput{Input: URL, CustomIP: ip}
|
||||
i.setItem(metaInput)
|
||||
} else {
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.setItem(metaInput)
|
||||
}
|
||||
}
|
||||
@@ -359,8 +353,7 @@ func (i *ListInputProvider) scanInputFromReader(reader io.Reader) {
|
||||
|
||||
// isExcluded checks if a URL is in the exclusion list
|
||||
func (i *ListInputProvider) isExcluded(URL string) bool {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
key, err := metaInput.MarshalString()
|
||||
if err != nil {
|
||||
gologger.Warning().Msgf("%s\n", err)
|
||||
@@ -385,16 +378,14 @@ func (i *ListInputProvider) Del(value string) {
|
||||
}
|
||||
return fmt.Sprintf("got empty hostname for %v skipping ip selection", URL)
|
||||
})
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.delItem(metaInput)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if input is ip or hostname
|
||||
if iputil.IsIP(urlx.Hostname()) {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.delItem(metaInput)
|
||||
return
|
||||
}
|
||||
@@ -415,9 +406,7 @@ func (i *ListInputProvider) Del(value string) {
|
||||
if ip == "" {
|
||||
continue
|
||||
}
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = value
|
||||
metaInput.CustomIP = ip
|
||||
metaInput := &contextargs.MetaInput{Input: value, CustomIP: ip}
|
||||
i.delItem(metaInput)
|
||||
}
|
||||
return
|
||||
@@ -447,13 +436,11 @@ func (i *ListInputProvider) Del(value string) {
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
if ip != "" {
|
||||
metaInput.Input = URL
|
||||
metaInput.CustomIP = ip
|
||||
metaInput := &contextargs.MetaInput{Input: URL, CustomIP: ip}
|
||||
i.delItem(metaInput)
|
||||
} else {
|
||||
metaInput.Input = URL
|
||||
metaInput := &contextargs.MetaInput{Input: URL}
|
||||
i.delItem(metaInput)
|
||||
}
|
||||
}
|
||||
@@ -527,8 +514,7 @@ func (i *ListInputProvider) addTargets(targets []string) {
|
||||
|
||||
func (i *ListInputProvider) removeTargets(targets []string) {
|
||||
for _, target := range targets {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = target
|
||||
metaInput := &contextargs.MetaInput{Input: target}
|
||||
i.delItem(metaInput)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func Test_expandCIDR(t *testing.T) {
|
||||
// scan
|
||||
got := []string{}
|
||||
input.hostMap.Scan(func(k, _ []byte) error {
|
||||
metainput := contextargs.NewMetaInput()
|
||||
var metainput contextargs.MetaInput
|
||||
if err := metainput.Unmarshal(string(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func Test_scanallips_normalizeStoreInputValue(t *testing.T) {
|
||||
// scan
|
||||
got := []string{}
|
||||
input.hostMap.Scan(func(k, v []byte) error {
|
||||
metainput := contextargs.NewMetaInput()
|
||||
var metainput contextargs.MetaInput
|
||||
if err := metainput.Unmarshal(string(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func Test_expandASNInputValue(t *testing.T) {
|
||||
// scan the hmap
|
||||
got := []string{}
|
||||
input.hostMap.Scan(func(k, v []byte) error {
|
||||
metainput := contextargs.NewMetaInput()
|
||||
var metainput contextargs.MetaInput
|
||||
if err := metainput.Unmarshal(string(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -43,9 +43,7 @@ func (s *SimpleInputProvider) Iterate(callback func(value *contextargs.MetaInput
|
||||
|
||||
// Set adds an item to the input provider
|
||||
func (s *SimpleInputProvider) Set(value string) {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = value
|
||||
s.Inputs = append(s.Inputs, metaInput)
|
||||
s.Inputs = append(s.Inputs, &contextargs.MetaInput{Input: value})
|
||||
}
|
||||
|
||||
// SetWithProbe adds an item to the input provider with HTTP probing
|
||||
@@ -54,17 +52,13 @@ func (s *SimpleInputProvider) SetWithProbe(value string, probe types.InputLivene
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = probedValue
|
||||
s.Inputs = append(s.Inputs, metaInput)
|
||||
s.Inputs = append(s.Inputs, &contextargs.MetaInput{Input: probedValue})
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWithExclusions adds an item to the input provider if it doesn't match any of the exclusions
|
||||
func (s *SimpleInputProvider) SetWithExclusions(value string) error {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = value
|
||||
s.Inputs = append(s.Inputs, metaInput)
|
||||
s.Inputs = append(s.Inputs, &contextargs.MetaInput{Input: value})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+1
-12
@@ -47,8 +47,6 @@ func (h *Helper) Transform(input string, protocol templateTypes.ProtocolType) st
|
||||
return h.convertInputToType(input, typeHostWithOptionalPort, "")
|
||||
case templateTypes.WebsocketProtocol:
|
||||
return h.convertInputToType(input, typeWebsocket, "")
|
||||
case templateTypes.SSLProtocol:
|
||||
return h.convertInputToType(input, typeHostWithPort, "443")
|
||||
}
|
||||
return input
|
||||
}
|
||||
@@ -96,8 +94,6 @@ func (h *Helper) convertInputToType(input string, inputType inputType, defaultPo
|
||||
if _, err := filepath.Match(input, ""); err != filepath.ErrBadPattern && !isURL {
|
||||
return input
|
||||
}
|
||||
// if none of these satisfy the condition return empty
|
||||
return ""
|
||||
case typeHostOnly:
|
||||
if hasHost {
|
||||
return host
|
||||
@@ -115,10 +111,6 @@ func (h *Helper) convertInputToType(input string, inputType inputType, defaultPo
|
||||
return string(probed)
|
||||
}
|
||||
}
|
||||
// try to parse it as absolute url and return
|
||||
if absUrl, err := urlutil.ParseAbsoluteURL(input, false); err == nil {
|
||||
return absUrl.String()
|
||||
}
|
||||
case typeHostWithPort, typeHostWithOptionalPort:
|
||||
if hasHost && hasPort {
|
||||
return net.JoinHostPort(host, port)
|
||||
@@ -136,9 +128,6 @@ func (h *Helper) convertInputToType(input string, inputType inputType, defaultPo
|
||||
if uri != nil && stringsutil.EqualFoldAny(uri.Scheme, "ws", "wss") {
|
||||
return input
|
||||
}
|
||||
// empty if prefix is not given
|
||||
return ""
|
||||
}
|
||||
// do not return empty
|
||||
return input
|
||||
return ""
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func TestConvertInputToType(t *testing.T) {
|
||||
{"https://google.com:443", typeHostOnly, "google.com", ""},
|
||||
|
||||
// url
|
||||
{"test.com", typeURL, "test.com", ""},
|
||||
{"test.com", typeURL, "", ""},
|
||||
{"google.com", typeURL, "https://google.com", ""},
|
||||
{"https://google.com", typeURL, "https://google.com", ""},
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestConvertInputToType(t *testing.T) {
|
||||
{"input_test.*", typeFilepath, "input_test.*", ""},
|
||||
|
||||
// host-port
|
||||
{"google.com", typeHostWithPort, "google.com", ""},
|
||||
{"google.com", typeHostWithPort, "", ""},
|
||||
{"google.com:443", typeHostWithPort, "google.com:443", ""},
|
||||
{"https://google.com", typeHostWithPort, "google.com:443", ""},
|
||||
{"https://google.com:443", typeHostWithPort, "google.com:443", ""},
|
||||
|
||||
+21
-28
@@ -4,11 +4,11 @@ package compiler
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
contextutil "github.com/projectdiscovery/utils/context"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
@@ -38,13 +38,13 @@ type ExecuteOptions struct {
|
||||
// Cleanup is extra cleanup function to be called after execution
|
||||
Cleanup func(runtime *goja.Runtime)
|
||||
|
||||
/// Timeout for this script execution
|
||||
Timeout int
|
||||
// Source is original source of the script
|
||||
Source *string
|
||||
|
||||
Context context.Context
|
||||
|
||||
TimeoutVariants *types.Timeouts
|
||||
|
||||
// Manually exported objects
|
||||
exports map[string]interface{}
|
||||
}
|
||||
@@ -55,11 +55,6 @@ type ExecuteArgs struct {
|
||||
TemplateCtx map[string]interface{} // templateCtx contains template scoped variables
|
||||
}
|
||||
|
||||
// Map returns a merged map of the TemplateCtx and Args fields.
|
||||
func (e *ExecuteArgs) Map() map[string]interface{} {
|
||||
return generators.MergeMaps(e.TemplateCtx, e.Args)
|
||||
}
|
||||
|
||||
// NewExecuteArgs returns a new execute arguments.
|
||||
func NewExecuteArgs() *ExecuteArgs {
|
||||
return &ExecuteArgs{
|
||||
@@ -71,24 +66,12 @@ func NewExecuteArgs() *ExecuteArgs {
|
||||
// ExecuteResult is the result of executing a script.
|
||||
type ExecuteResult map[string]interface{}
|
||||
|
||||
// Map returns the map representation of the ExecuteResult
|
||||
func (e ExecuteResult) Map() map[string]interface{} {
|
||||
if e == nil {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// NewExecuteResult returns a new execute result instance
|
||||
func NewExecuteResult() ExecuteResult {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
|
||||
// GetSuccess returns whether the script was successful or not.
|
||||
func (e ExecuteResult) GetSuccess() bool {
|
||||
if e == nil {
|
||||
return false
|
||||
}
|
||||
val, ok := e["success"].(bool)
|
||||
if !ok {
|
||||
return false
|
||||
@@ -96,6 +79,15 @@ func (e ExecuteResult) GetSuccess() bool {
|
||||
return val
|
||||
}
|
||||
|
||||
// Execute executes a script with the default options.
|
||||
func (c *Compiler) Execute(code string, args *ExecuteArgs) (ExecuteResult, error) {
|
||||
p, err := WrapScriptNCompile(code, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.ExecuteWithOptions(p, args, &ExecuteOptions{Context: context.Background()})
|
||||
}
|
||||
|
||||
// ExecuteWithOptions executes a script with the provided options.
|
||||
func (c *Compiler) ExecuteWithOptions(program *goja.Program, args *ExecuteArgs, opts *ExecuteOptions) (ExecuteResult, error) {
|
||||
if opts == nil {
|
||||
@@ -114,9 +106,14 @@ func (c *Compiler) ExecuteWithOptions(program *goja.Program, args *ExecuteArgs,
|
||||
// merge all args into templatectx
|
||||
args.TemplateCtx = generators.MergeMaps(args.TemplateCtx, args.Args)
|
||||
|
||||
// execute with context and timeout
|
||||
if opts.Timeout <= 0 || opts.Timeout > 180 {
|
||||
// some js scripts can take longer time so allow configuring timeout
|
||||
// from template but keep it within sane limits (180s)
|
||||
opts.Timeout = JsProtocolTimeout
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeoutCause(opts.Context, opts.TimeoutVariants.JsCompilerExecutionTimeout, ErrJSExecDeadline)
|
||||
// execute with context and timeout
|
||||
ctx, cancel := context.WithTimeoutCause(opts.Context, time.Duration(opts.Timeout)*time.Second, ErrJSExecDeadline)
|
||||
defer cancel()
|
||||
// execute the script
|
||||
results, err := contextutil.ExecFuncWithTwoReturns(ctx, func() (val goja.Value, err error) {
|
||||
@@ -129,13 +126,9 @@ func (c *Compiler) ExecuteWithOptions(program *goja.Program, args *ExecuteArgs,
|
||||
})
|
||||
if err != nil {
|
||||
if val, ok := err.(*goja.Exception); ok {
|
||||
if x := val.Unwrap(); x != nil {
|
||||
err = x
|
||||
}
|
||||
err = val.Unwrap()
|
||||
}
|
||||
e := NewExecuteResult()
|
||||
e["error"] = err.Error()
|
||||
return e, err
|
||||
return nil, err
|
||||
}
|
||||
var res ExecuteResult
|
||||
if opts.exports != nil {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/gologger/levels"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
)
|
||||
|
||||
func TestNewCompilerConsoleDebug(t *testing.T) {
|
||||
@@ -21,14 +18,7 @@ func TestNewCompilerConsoleDebug(t *testing.T) {
|
||||
})
|
||||
|
||||
compiler := New()
|
||||
p, err := WrapScriptNCompile("console.log('hello world');", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = compiler.ExecuteWithOptions(p, NewExecuteArgs(), &ExecuteOptions{Context: context.Background(),
|
||||
TimeoutVariants: &types.Timeouts{JsCompilerExecutionTimeout: time.Duration(20) * time.Second}},
|
||||
)
|
||||
_, err := compiler.Execute("console.log('hello world');", NewExecuteArgs())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -37,6 +27,17 @@ func TestNewCompilerConsoleDebug(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteResultGetSuccess(t *testing.T) {
|
||||
compiler := New()
|
||||
result, err := compiler.Execute("1+1 == 2", NewExecuteArgs())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.GetSuccess() != true {
|
||||
t.Fatalf("expected true, got=%v", result.GetSuccess())
|
||||
}
|
||||
}
|
||||
|
||||
type noopWriter struct {
|
||||
Callback func(data []byte, level levels.Level)
|
||||
}
|
||||
|
||||
+10
-1
@@ -7,17 +7,26 @@ import (
|
||||
// jsprotocolInit
|
||||
|
||||
var (
|
||||
// Per Execution Javascript timeout in seconds
|
||||
JsProtocolTimeout = 10
|
||||
PoolingJsVmConcurrency = 100
|
||||
NonPoolingVMConcurrency = 20
|
||||
JsTimeoutMultiplier = 1.5
|
||||
)
|
||||
|
||||
// Init initializes the javascript protocol
|
||||
func Init(opts *types.Options) error {
|
||||
|
||||
if opts.Timeout < 10 {
|
||||
// keep existing 10s timeout
|
||||
return nil
|
||||
}
|
||||
if opts.JsConcurrency < 100 {
|
||||
// 100 is reasonable default
|
||||
opts.JsConcurrency = 100
|
||||
}
|
||||
// we have dialer timeout set to 10s so js needs to be at least
|
||||
// 15s to return the actual error if not it will be a dialer timeout
|
||||
JsProtocolTimeout = int(float64(opts.Timeout) * JsTimeoutMultiplier)
|
||||
PoolingJsVmConcurrency = opts.JsConcurrency
|
||||
PoolingJsVmConcurrency -= NonPoolingVMConcurrency
|
||||
return nil
|
||||
|
||||
@@ -241,5 +241,5 @@ func stringify(gojaValue goja.Value, runtime *goja.Runtime) string {
|
||||
}
|
||||
}
|
||||
// for everything else stringify
|
||||
return fmt.Sprintf("%+v", value)
|
||||
return fmt.Sprintf("%v", value)
|
||||
}
|
||||
@@ -42,11 +42,7 @@ Description: getNetworkPort registers defaultPort and returns defaultPort if it
|
||||
|
||||
Name: isPortOpen
|
||||
Signatures: "isPortOpen(host string, port string, [timeout int]) bool"
|
||||
Description: isPortOpen checks if given TCP port is open on host. timeout is optional and defaults to 5 seconds
|
||||
|
||||
Name: isUDPPortOpen
|
||||
Signatures: "isUDPPortOpen(host string, port string, [timeout int]) bool"
|
||||
Description: isUDPPortOpen checks if the given UDP port is open on the host. Timeout is optional and defaults to 5 seconds.
|
||||
Description: isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds
|
||||
|
||||
Name: ToBytes
|
||||
Signatures: "ToBytes(...interface{}) []byte"
|
||||
|
||||
@@ -53,12 +53,10 @@ func init() {
|
||||
"FilterWorkstationTrustAccount": lib_ldap.FilterWorkstationTrustAccount,
|
||||
|
||||
// Objects / Classes
|
||||
"Client": lib_ldap.NewClient,
|
||||
"Config": gojs.GetClassConstructor[lib_ldap.Config](&lib_ldap.Config{}),
|
||||
"LdapAttributes": gojs.GetClassConstructor[lib_ldap.LdapAttributes](&lib_ldap.LdapAttributes{}),
|
||||
"LdapEntry": gojs.GetClassConstructor[lib_ldap.LdapEntry](&lib_ldap.LdapEntry{}),
|
||||
"Metadata": gojs.GetClassConstructor[lib_ldap.Metadata](&lib_ldap.Metadata{}),
|
||||
"SearchResult": gojs.GetClassConstructor[lib_ldap.SearchResult](&lib_ldap.SearchResult{}),
|
||||
"ADObject": gojs.GetClassConstructor[lib_ldap.ADObject](&lib_ldap.ADObject{}),
|
||||
"Client": lib_ldap.NewClient,
|
||||
"Config": gojs.GetClassConstructor[lib_ldap.Config](&lib_ldap.Config{}),
|
||||
"Metadata": gojs.GetClassConstructor[lib_ldap.Metadata](&lib_ldap.Metadata{}),
|
||||
},
|
||||
).Register()
|
||||
}
|
||||
|
||||
@@ -188,9 +188,9 @@ export class Config {
|
||||
*/
|
||||
export interface AuthorizationDataEntry {
|
||||
|
||||
ADData?: Uint8Array,
|
||||
|
||||
ADType?: number,
|
||||
|
||||
ADData?: Uint8Array,
|
||||
}
|
||||
|
||||
|
||||
@@ -200,9 +200,9 @@ export interface AuthorizationDataEntry {
|
||||
*/
|
||||
export interface BitString {
|
||||
|
||||
Bytes?: Uint8Array,
|
||||
|
||||
BitLength?: number,
|
||||
|
||||
Bytes?: Uint8Array,
|
||||
}
|
||||
|
||||
|
||||
@@ -212,9 +212,9 @@ export interface BitString {
|
||||
*/
|
||||
export interface BitString {
|
||||
|
||||
Bytes?: Uint8Array,
|
||||
|
||||
BitLength?: number,
|
||||
|
||||
Bytes?: Uint8Array,
|
||||
}
|
||||
|
||||
|
||||
@@ -236,15 +236,19 @@ export interface Config {
|
||||
*/
|
||||
export interface EncTicketPart {
|
||||
|
||||
AuthTime?: Date,
|
||||
|
||||
StartTime?: Date,
|
||||
|
||||
EndTime?: Date,
|
||||
|
||||
RenewTill?: Date,
|
||||
|
||||
CRealm?: string,
|
||||
|
||||
AuthTime?: Date,
|
||||
CAddr?: HostAddress,
|
||||
|
||||
StartTime?: Date,
|
||||
AuthorizationData?: AuthorizationDataEntry,
|
||||
|
||||
Flags?: BitString,
|
||||
|
||||
@@ -253,10 +257,6 @@ export interface EncTicketPart {
|
||||
CName?: PrincipalName,
|
||||
|
||||
Transited?: TransitedEncoding,
|
||||
|
||||
CAddr?: HostAddress,
|
||||
|
||||
AuthorizationData?: AuthorizationDataEntry,
|
||||
}
|
||||
|
||||
|
||||
@@ -266,11 +266,11 @@ export interface EncTicketPart {
|
||||
*/
|
||||
export interface EncryptedData {
|
||||
|
||||
EType?: number,
|
||||
|
||||
KVNO?: number,
|
||||
|
||||
Cipher?: Uint8Array,
|
||||
|
||||
EType?: number,
|
||||
}
|
||||
|
||||
|
||||
@@ -318,33 +318,41 @@ export interface HostAddress {
|
||||
*/
|
||||
export interface LibDefaults {
|
||||
|
||||
CCacheType?: number,
|
||||
NoAddresses?: boolean,
|
||||
|
||||
K5LoginAuthoritative?: boolean,
|
||||
RealmTryDomains?: number,
|
||||
|
||||
Proxiable?: boolean,
|
||||
DNSLookupKDC?: boolean,
|
||||
|
||||
RDNS?: boolean,
|
||||
DefaultRealm?: string,
|
||||
|
||||
K5LoginDirectory?: string,
|
||||
|
||||
KDCTimeSync?: number,
|
||||
SafeChecksumType?: number,
|
||||
|
||||
VerifyAPReqNofail?: boolean,
|
||||
|
||||
AllowWeakCrypto?: boolean,
|
||||
|
||||
DefaultTGSEnctypes?: string[],
|
||||
|
||||
DefaultTGSEnctypeIDs?: number[],
|
||||
DefaultTktEnctypeIDs?: number[],
|
||||
|
||||
DNSCanonicalizeHostname?: boolean,
|
||||
IgnoreAcceptorHostname?: boolean,
|
||||
|
||||
Forwardable?: boolean,
|
||||
K5LoginAuthoritative?: boolean,
|
||||
|
||||
PermittedEnctypes?: string[],
|
||||
|
||||
/**
|
||||
* time in nanoseconds
|
||||
*/
|
||||
|
||||
RenewLifetime?: number,
|
||||
Clockskew?: number,
|
||||
|
||||
DNSCanonicalizeHostname?: boolean,
|
||||
|
||||
Proxiable?: boolean,
|
||||
|
||||
RDNS?: boolean,
|
||||
|
||||
/**
|
||||
* time in nanoseconds
|
||||
@@ -354,45 +362,37 @@ export interface LibDefaults {
|
||||
|
||||
DefaultClientKeytabName?: string,
|
||||
|
||||
DefaultTktEnctypeIDs?: number[],
|
||||
PermittedEnctypeIDs?: number[],
|
||||
|
||||
UDPPreferenceLimit?: number,
|
||||
|
||||
DefaultTGSEnctypeIDs?: number[],
|
||||
|
||||
DefaultTktEnctypes?: string[],
|
||||
|
||||
CCacheType?: number,
|
||||
|
||||
DNSLookupRealm?: boolean,
|
||||
|
||||
ExtraAddresses?: Uint8Array,
|
||||
|
||||
DefaultRealm?: string,
|
||||
|
||||
NoAddresses?: boolean,
|
||||
|
||||
PreferredPreauthTypes?: number[],
|
||||
|
||||
PermittedEnctypeIDs?: number[],
|
||||
|
||||
RealmTryDomains?: number,
|
||||
|
||||
DefaultKeytabName?: string,
|
||||
|
||||
DefaultTktEnctypes?: string[],
|
||||
|
||||
DNSLookupKDC?: boolean,
|
||||
|
||||
IgnoreAcceptorHostname?: boolean,
|
||||
|
||||
AllowWeakCrypto?: boolean,
|
||||
|
||||
Canonicalize?: boolean,
|
||||
|
||||
SafeChecksumType?: number,
|
||||
Forwardable?: boolean,
|
||||
|
||||
UDPPreferenceLimit?: number,
|
||||
K5LoginDirectory?: string,
|
||||
|
||||
KDCTimeSync?: number,
|
||||
|
||||
/**
|
||||
* time in nanoseconds
|
||||
*/
|
||||
|
||||
Clockskew?: number,
|
||||
RenewLifetime?: number,
|
||||
|
||||
PermittedEnctypes?: string[],
|
||||
DefaultKeytabName?: string,
|
||||
|
||||
KDCDefaultOptions?: BitString,
|
||||
}
|
||||
@@ -416,8 +416,6 @@ export interface PrincipalName {
|
||||
*/
|
||||
export interface Realm {
|
||||
|
||||
Realm?: string,
|
||||
|
||||
AdminServer?: string[],
|
||||
|
||||
DefaultDomain?: string,
|
||||
@@ -427,6 +425,8 @@ export interface Realm {
|
||||
KPasswdServer?: string[],
|
||||
|
||||
MasterKDC?: string[],
|
||||
|
||||
Realm?: string,
|
||||
}
|
||||
|
||||
|
||||
|
||||
+62
-214
@@ -209,8 +209,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public FindADObjects(filter: string): SearchResult | null {
|
||||
return null;
|
||||
public FindADObjects(filter: string): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -225,8 +225,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public GetADUsers(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUsers(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -241,8 +241,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public GetADActiveUsers(): SearchResult | null {
|
||||
return null;
|
||||
public GetADActiveUsers(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -257,8 +257,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public GetADUserWithNeverExpiringPasswords(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUserWithNeverExpiringPasswords(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -273,8 +273,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public GetADUserTrustedForDelegation(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUserTrustedForDelegation(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -289,8 +289,8 @@ export class Client {
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
public GetADUserWithPasswordNotRequired(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUserWithPasswordNotRequired(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -305,8 +305,8 @@ export class Client {
|
||||
* log(to_json(groups));
|
||||
* ```
|
||||
*/
|
||||
public GetADGroups(): SearchResult | null {
|
||||
return null;
|
||||
public GetADGroups(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -321,8 +321,8 @@ export class Client {
|
||||
* log(to_json(dcs));
|
||||
* ```
|
||||
*/
|
||||
public GetADDCList(): SearchResult | null {
|
||||
return null;
|
||||
public GetADDCList(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -337,8 +337,8 @@ export class Client {
|
||||
* log(to_json(admins));
|
||||
* ```
|
||||
*/
|
||||
public GetADAdmins(): SearchResult | null {
|
||||
return null;
|
||||
public GetADAdmins(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -353,8 +353,8 @@ export class Client {
|
||||
* log(to_json(kerberoastable));
|
||||
* ```
|
||||
*/
|
||||
public GetADUserKerberoastable(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUserKerberoastable(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -369,8 +369,8 @@ export class Client {
|
||||
* log(to_json(AsRepRoastable));
|
||||
* ```
|
||||
*/
|
||||
public GetADUserAsRepRoastable(): SearchResult | null {
|
||||
return null;
|
||||
public GetADUserAsRepRoastable(): ADObject[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -428,8 +428,8 @@ export class Client {
|
||||
* const results = client.Search('(objectClass=*)', 'cn', 'mail');
|
||||
* ```
|
||||
*/
|
||||
public Search(filter: string, attributes: any): SearchResult | null {
|
||||
return null;
|
||||
public Search(filter: string, attributes: any): Record<string, string[]>[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -481,6 +481,33 @@ export class Client {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ADObject represents an Active Directory object
|
||||
* @example
|
||||
* ```javascript
|
||||
* const ldap = require('nuclei/ldap');
|
||||
* const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
* const users = client.GetADUsers();
|
||||
* log(to_json(users));
|
||||
* ```
|
||||
*/
|
||||
export interface ADObject {
|
||||
|
||||
DistinguishedName?: string,
|
||||
|
||||
SAMAccountName?: string,
|
||||
|
||||
PWDLastSet?: string,
|
||||
|
||||
LastLogon?: string,
|
||||
|
||||
MemberOf?: string[],
|
||||
|
||||
ServicePrincipalName?: string[],
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Config is extra configuration for the ldap client
|
||||
* @example
|
||||
@@ -508,186 +535,27 @@ export interface Config {
|
||||
|
||||
|
||||
/**
|
||||
* LdapAttributes represents all LDAP attributes of a particular
|
||||
* ldap entry
|
||||
* Entry Interface
|
||||
*/
|
||||
export interface LdapAttributes {
|
||||
export interface Entry {
|
||||
|
||||
/**
|
||||
* CurrentTime contains current time
|
||||
*/
|
||||
DN?: string,
|
||||
|
||||
CurrentTime?: string[],
|
||||
|
||||
/**
|
||||
* SubschemaSubentry contains subschema subentry
|
||||
*/
|
||||
|
||||
SubschemaSubentry?: string[],
|
||||
|
||||
/**
|
||||
* DsServiceName contains ds service name
|
||||
*/
|
||||
|
||||
DsServiceName?: string[],
|
||||
|
||||
/**
|
||||
* NamingContexts contains naming contexts
|
||||
*/
|
||||
|
||||
NamingContexts?: string[],
|
||||
|
||||
/**
|
||||
* DefaultNamingContext contains default naming context
|
||||
*/
|
||||
|
||||
DefaultNamingContext?: string[],
|
||||
|
||||
/**
|
||||
* SchemaNamingContext contains schema naming context
|
||||
*/
|
||||
|
||||
SchemaNamingContext?: string[],
|
||||
|
||||
/**
|
||||
* ConfigurationNamingContext contains configuration naming context
|
||||
*/
|
||||
|
||||
ConfigurationNamingContext?: string[],
|
||||
|
||||
/**
|
||||
* RootDomainNamingContext contains root domain naming context
|
||||
*/
|
||||
|
||||
RootDomainNamingContext?: string[],
|
||||
|
||||
/**
|
||||
* SupportedLDAPVersion contains supported LDAP version
|
||||
*/
|
||||
|
||||
SupportedLDAPVersion?: string[],
|
||||
|
||||
/**
|
||||
* HighestCommittedUSN contains highest committed USN
|
||||
*/
|
||||
|
||||
HighestCommittedUSN?: string[],
|
||||
|
||||
/**
|
||||
* SupportedSASLMechanisms contains supported SASL mechanisms
|
||||
*/
|
||||
|
||||
SupportedSASLMechanisms?: string[],
|
||||
|
||||
/**
|
||||
* DnsHostName contains DNS host name
|
||||
*/
|
||||
|
||||
DnsHostName?: string[],
|
||||
|
||||
/**
|
||||
* LdapServiceName contains LDAP service name
|
||||
*/
|
||||
|
||||
LdapServiceName?: string[],
|
||||
|
||||
/**
|
||||
* ServerName contains server name
|
||||
*/
|
||||
|
||||
ServerName?: string[],
|
||||
|
||||
/**
|
||||
* IsSynchronized contains is synchronized
|
||||
*/
|
||||
|
||||
IsSynchronized?: string[],
|
||||
|
||||
/**
|
||||
* IsGlobalCatalogReady contains is global catalog ready
|
||||
*/
|
||||
|
||||
IsGlobalCatalogReady?: string[],
|
||||
|
||||
/**
|
||||
* DomainFunctionality contains domain functionality
|
||||
*/
|
||||
|
||||
DomainFunctionality?: string[],
|
||||
|
||||
/**
|
||||
* ForestFunctionality contains forest functionality
|
||||
*/
|
||||
|
||||
ForestFunctionality?: string[],
|
||||
|
||||
/**
|
||||
* DomainControllerFunctionality contains domain controller functionality
|
||||
*/
|
||||
|
||||
DomainControllerFunctionality?: string[],
|
||||
|
||||
/**
|
||||
* DistinguishedName contains the distinguished name
|
||||
*/
|
||||
|
||||
DistinguishedName?: string[],
|
||||
|
||||
/**
|
||||
* SAMAccountName contains the SAM account name
|
||||
*/
|
||||
|
||||
SAMAccountName?: string[],
|
||||
|
||||
/**
|
||||
* PWDLastSet contains the password last set time
|
||||
*/
|
||||
|
||||
PWDLastSet?: string[],
|
||||
|
||||
/**
|
||||
* LastLogon contains the last logon time
|
||||
*/
|
||||
|
||||
LastLogon?: string[],
|
||||
|
||||
/**
|
||||
* MemberOf contains the groups the entry is a member of
|
||||
*/
|
||||
|
||||
MemberOf?: string[],
|
||||
|
||||
/**
|
||||
* ServicePrincipalName contains the service principal names
|
||||
*/
|
||||
|
||||
ServicePrincipalName?: string[],
|
||||
|
||||
/**
|
||||
* Extra contains other extra fields which might be present
|
||||
*/
|
||||
|
||||
Extra?: Record<string, any>,
|
||||
Attributes?: EntryAttribute,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* LdapEntry represents a single LDAP entry
|
||||
* EntryAttribute Interface
|
||||
*/
|
||||
export interface LdapEntry {
|
||||
export interface EntryAttribute {
|
||||
|
||||
/**
|
||||
* DN contains distinguished name
|
||||
*/
|
||||
Name?: string,
|
||||
|
||||
DN?: string,
|
||||
Values?: string[],
|
||||
|
||||
/**
|
||||
* Attributes contains list of attributes
|
||||
*/
|
||||
|
||||
Attributes?: LdapAttributes,
|
||||
ByteValues?: Uint8Array,
|
||||
}
|
||||
|
||||
|
||||
@@ -716,32 +584,12 @@ export interface Metadata {
|
||||
|
||||
|
||||
/**
|
||||
* SearchResult contains search result of any / all ldap search request
|
||||
* @example
|
||||
* ```javascript
|
||||
* const ldap = require('nuclei/ldap');
|
||||
* const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
* const results = client.Search('(objectinterface=*)', 'cn', 'mail');
|
||||
* ```
|
||||
* SearchResult Interface
|
||||
*/
|
||||
export interface SearchResult {
|
||||
|
||||
/**
|
||||
* Referrals contains list of referrals
|
||||
*/
|
||||
|
||||
Referrals?: string[],
|
||||
|
||||
/**
|
||||
* Controls contains list of controls
|
||||
*/
|
||||
|
||||
Controls?: string[],
|
||||
|
||||
/**
|
||||
* Entries contains list of entries
|
||||
*/
|
||||
|
||||
Entries?: LdapEntry[],
|
||||
Entries?: Entry,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* Client is a client for MS SQL database.
|
||||
* Internally client uses microsoft/go-mssqldb driver.
|
||||
* Internally client uses denisenkom/go-mssqldb driver.
|
||||
* @example
|
||||
* ```javascript
|
||||
* const mssql = require('nuclei/mssql');
|
||||
|
||||
@@ -78,6 +78,8 @@ export interface IsRDPResponse {
|
||||
*/
|
||||
export interface ServiceRDP {
|
||||
|
||||
DNSDomainName?: string,
|
||||
|
||||
ForestName?: string,
|
||||
|
||||
OSFingerprint?: string,
|
||||
@@ -91,7 +93,5 @@ export interface ServiceRDP {
|
||||
NetBIOSDomainName?: string,
|
||||
|
||||
DNSComputerName?: string,
|
||||
|
||||
DNSDomainName?: string,
|
||||
}
|
||||
|
||||
+12
-12
@@ -137,10 +137,6 @@ export interface NegotiationLog {
|
||||
*/
|
||||
export interface SMBCapabilities {
|
||||
|
||||
DFSSupport?: boolean,
|
||||
|
||||
Leasing?: boolean,
|
||||
|
||||
LargeMTU?: boolean,
|
||||
|
||||
MultiChan?: boolean,
|
||||
@@ -150,6 +146,10 @@ export interface SMBCapabilities {
|
||||
DirLeasing?: boolean,
|
||||
|
||||
Encryption?: boolean,
|
||||
|
||||
DFSSupport?: boolean,
|
||||
|
||||
Leasing?: boolean,
|
||||
}
|
||||
|
||||
|
||||
@@ -159,16 +159,16 @@ export interface SMBCapabilities {
|
||||
*/
|
||||
export interface SMBLog {
|
||||
|
||||
SupportV1?: boolean,
|
||||
|
||||
NativeOs?: string,
|
||||
|
||||
NTLM?: string,
|
||||
|
||||
GroupName?: string,
|
||||
|
||||
HasNTLM?: boolean,
|
||||
|
||||
SupportV1?: boolean,
|
||||
|
||||
NativeOs?: string,
|
||||
|
||||
Version?: SMBVersions,
|
||||
|
||||
Capabilities?: SMBCapabilities,
|
||||
@@ -185,13 +185,13 @@ export interface SMBLog {
|
||||
*/
|
||||
export interface SMBVersions {
|
||||
|
||||
VerString?: string,
|
||||
|
||||
Major?: number,
|
||||
|
||||
Minor?: number,
|
||||
|
||||
Revision?: number,
|
||||
|
||||
VerString?: string,
|
||||
}
|
||||
|
||||
|
||||
@@ -225,12 +225,12 @@ export interface ServiceSMB {
|
||||
*/
|
||||
export interface SessionSetupLog {
|
||||
|
||||
NegotiateFlags?: number,
|
||||
|
||||
SetupFlags?: number,
|
||||
|
||||
TargetName?: string,
|
||||
|
||||
NegotiateFlags?: number,
|
||||
|
||||
HeaderLog?: HeaderLog,
|
||||
}
|
||||
|
||||
+22
-22
@@ -133,9 +133,9 @@ export interface Algorithms {
|
||||
|
||||
HostKey?: string,
|
||||
|
||||
W?: DirectionAlgorithms,
|
||||
|
||||
R?: DirectionAlgorithms,
|
||||
|
||||
W?: DirectionAlgorithms,
|
||||
}
|
||||
|
||||
|
||||
@@ -159,13 +159,13 @@ export interface DirectionAlgorithms {
|
||||
*/
|
||||
export interface EndpointId {
|
||||
|
||||
SoftwareVersion?: string,
|
||||
|
||||
Comment?: string,
|
||||
|
||||
Raw?: string,
|
||||
|
||||
ProtoVersion?: string,
|
||||
|
||||
SoftwareVersion?: string,
|
||||
|
||||
Comment?: string,
|
||||
}
|
||||
|
||||
|
||||
@@ -197,34 +197,34 @@ export interface HandshakeLog {
|
||||
*/
|
||||
export interface KexInitMsg {
|
||||
|
||||
KexAlgos?: string[],
|
||||
|
||||
CiphersClientServer?: string[],
|
||||
|
||||
MACsServerClient?: string[],
|
||||
|
||||
LanguagesClientServer?: string[],
|
||||
|
||||
CompressionClientServer?: string[],
|
||||
|
||||
CompressionServerClient?: string[],
|
||||
|
||||
Reserved?: number,
|
||||
|
||||
MACsClientServer?: string[],
|
||||
|
||||
/**
|
||||
* fixed size array of length: [16]
|
||||
*/
|
||||
|
||||
Cookie?: Uint8Array,
|
||||
|
||||
ServerHostKeyAlgos?: string[],
|
||||
CiphersClientServer?: string[],
|
||||
|
||||
MACsClientServer?: string[],
|
||||
|
||||
MACsServerClient?: string[],
|
||||
|
||||
CompressionServerClient?: string[],
|
||||
|
||||
LanguagesClientServer?: string[],
|
||||
|
||||
FirstKexFollows?: boolean,
|
||||
|
||||
KexAlgos?: string[],
|
||||
|
||||
CiphersServerClient?: string[],
|
||||
|
||||
CompressionClientServer?: string[],
|
||||
|
||||
LanguagesServerClient?: string[],
|
||||
|
||||
FirstKexFollows?: boolean,
|
||||
ServerHostKeyAlgos?: string[],
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package global
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -13,10 +12,8 @@ import (
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
@@ -112,43 +109,13 @@ func initBuiltInFunc(runtime *goja.Runtime) {
|
||||
Signatures: []string{
|
||||
"isPortOpen(host string, port string, [timeout int]) bool",
|
||||
},
|
||||
Description: "isPortOpen checks if given TCP port is open on host. timeout is optional and defaults to 5 seconds",
|
||||
Description: "isPortOpen checks if given port is open on host. timeout is optional and defaults to 5 seconds",
|
||||
FuncDecl: func(host string, port string, timeout ...int) (bool, error) {
|
||||
ctx := context.Background()
|
||||
timeoutInSec := 5
|
||||
if len(timeout) > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second)
|
||||
defer cancel()
|
||||
timeoutInSec = timeout[0]
|
||||
}
|
||||
if host == "" || port == "" {
|
||||
return false, errkit.New("isPortOpen: host or port is empty")
|
||||
}
|
||||
conn, err := protocolstate.Dialer.Dial(ctx, "tcp", net.JoinHostPort(host, port))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_ = conn.Close()
|
||||
return true, nil
|
||||
},
|
||||
})
|
||||
|
||||
_ = gojs.RegisterFuncWithSignature(runtime, gojs.FuncOpts{
|
||||
Name: "isUDPPortOpen",
|
||||
Signatures: []string{
|
||||
"isUDPPortOpen(host string, port string, [timeout int]) bool",
|
||||
},
|
||||
Description: "isUDPPortOpen checks if the given UDP port is open on the host. Timeout is optional and defaults to 5 seconds.",
|
||||
FuncDecl: func(host string, port string, timeout ...int) (bool, error) {
|
||||
ctx := context.Background()
|
||||
if len(timeout) > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second)
|
||||
defer cancel()
|
||||
}
|
||||
if host == "" || port == "" {
|
||||
return false, errkit.New("isPortOpen: host or port is empty")
|
||||
}
|
||||
conn, err := protocolstate.Dialer.Dial(ctx, "udp", net.JoinHostPort(host, port))
|
||||
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), time.Duration(timeoutInSec)*time.Second)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
+46
-24
@@ -74,6 +74,25 @@ func NegativeFilter(filter string) string {
|
||||
return fmt.Sprintf("(!%s)", filter)
|
||||
}
|
||||
|
||||
type (
|
||||
// ADObject represents an Active Directory object
|
||||
// @example
|
||||
// ```javascript
|
||||
// const ldap = require('nuclei/ldap');
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// const users = client.GetADUsers();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
ADObject struct {
|
||||
DistinguishedName string
|
||||
SAMAccountName string
|
||||
PWDLastSet string
|
||||
LastLogon string
|
||||
MemberOf []string
|
||||
ServicePrincipalName []string
|
||||
}
|
||||
)
|
||||
|
||||
// FindADObjects finds AD objects based on a filter
|
||||
// and returns them as a list of ADObject
|
||||
// @example
|
||||
@@ -83,7 +102,7 @@ func NegativeFilter(filter string) string {
|
||||
// const users = client.FindADObjects(ldap.FilterIsPerson);
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) FindADObjects(filter string) SearchResult {
|
||||
func (c *Client) FindADObjects(filter string) []ADObject {
|
||||
c.nj.Require(c.conn != nil, "no existing connection")
|
||||
sr := ldap.NewSearchRequest(
|
||||
c.BaseDN, ldap.ScopeWholeSubtree,
|
||||
@@ -102,7 +121,19 @@ func (c *Client) FindADObjects(filter string) SearchResult {
|
||||
|
||||
res, err := c.conn.Search(sr)
|
||||
c.nj.HandleError(err, "ldap search request failed")
|
||||
return *getSearchResult(res)
|
||||
|
||||
var objects []ADObject
|
||||
for _, obj := range res.Entries {
|
||||
objects = append(objects, ADObject{
|
||||
DistinguishedName: obj.GetAttributeValue("distinguishedName"),
|
||||
SAMAccountName: obj.GetAttributeValue("sAMAccountName"),
|
||||
PWDLastSet: DecodeADTimestamp(obj.GetAttributeValue("pwdLastSet")),
|
||||
LastLogon: DecodeADTimestamp(obj.GetAttributeValue("lastLogon")),
|
||||
MemberOf: obj.GetAttributeValues("memberOf"),
|
||||
ServicePrincipalName: obj.GetAttributeValues("servicePrincipalName"),
|
||||
})
|
||||
}
|
||||
return objects
|
||||
}
|
||||
|
||||
// GetADUsers returns all AD users
|
||||
@@ -114,7 +145,7 @@ func (c *Client) FindADObjects(filter string) SearchResult {
|
||||
// const users = client.GetADUsers();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) GetADUsers() SearchResult {
|
||||
func (c *Client) GetADUsers() []ADObject {
|
||||
return c.FindADObjects(FilterIsPerson)
|
||||
}
|
||||
|
||||
@@ -127,7 +158,7 @@ func (c *Client) GetADUsers() SearchResult {
|
||||
// const users = client.GetADActiveUsers();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) GetADActiveUsers() SearchResult {
|
||||
func (c *Client) GetADActiveUsers() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled))
|
||||
}
|
||||
|
||||
@@ -140,7 +171,7 @@ func (c *Client) GetADActiveUsers() SearchResult {
|
||||
// const users = client.GetADUserWithNeverExpiringPasswords();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) GetADUserWithNeverExpiringPasswords() SearchResult {
|
||||
func (c *Client) GetADUserWithNeverExpiringPasswords() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterDontExpirePassword))
|
||||
}
|
||||
|
||||
@@ -153,7 +184,7 @@ func (c *Client) GetADUserWithNeverExpiringPasswords() SearchResult {
|
||||
// const users = client.GetADUserTrustedForDelegation();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) GetADUserTrustedForDelegation() SearchResult {
|
||||
func (c *Client) GetADUserTrustedForDelegation() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterTrustedForDelegation))
|
||||
}
|
||||
|
||||
@@ -166,7 +197,7 @@ func (c *Client) GetADUserTrustedForDelegation() SearchResult {
|
||||
// const users = client.GetADUserWithPasswordNotRequired();
|
||||
// log(to_json(users));
|
||||
// ```
|
||||
func (c *Client) GetADUserWithPasswordNotRequired() SearchResult {
|
||||
func (c *Client) GetADUserWithPasswordNotRequired() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterPasswordNotRequired))
|
||||
}
|
||||
|
||||
@@ -179,7 +210,7 @@ func (c *Client) GetADUserWithPasswordNotRequired() SearchResult {
|
||||
// const groups = client.GetADGroups();
|
||||
// log(to_json(groups));
|
||||
// ```
|
||||
func (c *Client) GetADGroups() SearchResult {
|
||||
func (c *Client) GetADGroups() []ADObject {
|
||||
return c.FindADObjects(FilterIsGroup)
|
||||
}
|
||||
|
||||
@@ -192,7 +223,7 @@ func (c *Client) GetADGroups() SearchResult {
|
||||
// const dcs = client.GetADDCList();
|
||||
// log(to_json(dcs));
|
||||
// ```
|
||||
func (c *Client) GetADDCList() SearchResult {
|
||||
func (c *Client) GetADDCList() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsComputer, FilterAccountEnabled, FilterServerTrustAccount))
|
||||
}
|
||||
|
||||
@@ -205,7 +236,7 @@ func (c *Client) GetADDCList() SearchResult {
|
||||
// const admins = client.GetADAdmins();
|
||||
// log(to_json(admins));
|
||||
// ```
|
||||
func (c *Client) GetADAdmins() SearchResult {
|
||||
func (c *Client) GetADAdmins() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled, FilterIsAdmin))
|
||||
}
|
||||
|
||||
@@ -218,7 +249,7 @@ func (c *Client) GetADAdmins() SearchResult {
|
||||
// const kerberoastable = client.GetADUserKerberoastable();
|
||||
// log(to_json(kerberoastable));
|
||||
// ```
|
||||
func (c *Client) GetADUserKerberoastable() SearchResult {
|
||||
func (c *Client) GetADUserKerberoastable() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled, FilterHasServicePrincipalName))
|
||||
}
|
||||
|
||||
@@ -231,7 +262,7 @@ func (c *Client) GetADUserKerberoastable() SearchResult {
|
||||
// const AsRepRoastable = client.GetADUserAsRepRoastable();
|
||||
// log(to_json(AsRepRoastable));
|
||||
// ```
|
||||
func (c *Client) GetADUserAsRepRoastable() SearchResult {
|
||||
func (c *Client) GetADUserAsRepRoastable() []ADObject {
|
||||
return c.FindADObjects(JoinFilters(FilterIsPerson, FilterDontRequirePreauth))
|
||||
}
|
||||
|
||||
@@ -245,16 +276,7 @@ func (c *Client) GetADUserAsRepRoastable() SearchResult {
|
||||
// ```
|
||||
func (c *Client) GetADDomainSID() string {
|
||||
r := c.Search(FilterServerTrustAccount, "objectSid")
|
||||
c.nj.Require(len(r.Entries) > 0, "no result from GetADDomainSID query")
|
||||
for _, entry := range r.Entries {
|
||||
if sid, ok := entry.Attributes.Extra["objectSid"]; ok {
|
||||
if sid, ok := sid.([]string); ok {
|
||||
return DecodeSID(sid[0])
|
||||
} else {
|
||||
c.nj.HandleError(fmt.Errorf("invalid objectSid type: %T", entry.Attributes.Extra["objectSid"]), "invalid objectSid type")
|
||||
}
|
||||
}
|
||||
}
|
||||
c.nj.HandleError(fmt.Errorf("no objectSid found"), "no objectSid found")
|
||||
return ""
|
||||
c.nj.Require(len(r) > 0, "no result from GetADDomainSID query")
|
||||
c.nj.Require(len(r[0]["objectSid"]) > 0, "could not grab DomainSID")
|
||||
return DecodeSID(r[0]["objectSid"][0])
|
||||
}
|
||||
+28
-14
@@ -203,24 +203,38 @@ func (c *Client) AuthenticateWithNTLMHash(username, hash string) {
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// const results = client.Search('(objectClass=*)', 'cn', 'mail');
|
||||
// ```
|
||||
func (c *Client) Search(filter string, attributes ...string) SearchResult {
|
||||
func (c *Client) Search(filter string, attributes ...string) []map[string][]string {
|
||||
c.nj.Require(c.conn != nil, "no existing connection")
|
||||
c.nj.Require(c.BaseDN != "", "base dn cannot be empty")
|
||||
c.nj.Require(len(attributes) > 0, "attributes cannot be empty")
|
||||
|
||||
res, err := c.conn.Search(
|
||||
ldap.NewSearchRequest(
|
||||
"",
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.NeverDerefAliases,
|
||||
0, 0, false,
|
||||
filter,
|
||||
attributes,
|
||||
nil,
|
||||
c.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
|
||||
0, 0, false, filter, attributes, nil,
|
||||
),
|
||||
)
|
||||
c.nj.HandleError(err, "ldap search request failed")
|
||||
return *getSearchResult(res)
|
||||
if len(res.Entries) == 0 {
|
||||
// return empty list
|
||||
return nil
|
||||
}
|
||||
|
||||
// convert ldap.Entry to []map[string][]string
|
||||
var out []map[string][]string
|
||||
for _, r := range res.Entries {
|
||||
app := make(map[string][]string)
|
||||
empty := true
|
||||
for _, a := range attributes {
|
||||
v := r.GetAttributeValues(a)
|
||||
if len(v) > 0 {
|
||||
app[a] = v
|
||||
empty = false
|
||||
}
|
||||
}
|
||||
if !empty {
|
||||
out = append(out, app)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// AdvancedSearch accepts all values of search request type and return Ldap Entry
|
||||
@@ -236,7 +250,7 @@ func (c *Client) AdvancedSearch(
|
||||
TypesOnly bool,
|
||||
Filter string,
|
||||
Attributes []string,
|
||||
Controls []ldap.Control) SearchResult {
|
||||
Controls []ldap.Control) ldap.SearchResult {
|
||||
c.nj.Require(c.conn != nil, "no existing connection")
|
||||
if c.BaseDN == "" {
|
||||
c.BaseDN = fmt.Sprintf("dc=%s", strings.Join(strings.Split(c.Realm, "."), ",dc="))
|
||||
@@ -245,7 +259,7 @@ func (c *Client) AdvancedSearch(
|
||||
res, err := c.conn.Search(req)
|
||||
c.nj.HandleError(err, "ldap search request failed")
|
||||
c.nj.Require(res != nil, "ldap search request failed got nil response")
|
||||
return *getSearchResult(res)
|
||||
return *res
|
||||
}
|
||||
|
||||
type (
|
||||
@@ -281,7 +295,7 @@ func (c *Client) CollectMetadata() Metadata {
|
||||
|
||||
srMetadata := ldap.NewSearchRequest(
|
||||
"",
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.ScopeBaseObject,
|
||||
ldap.NeverDerefAliases,
|
||||
0, 0, false,
|
||||
"(objectClass=*)",
|
||||
|
||||
@@ -5,189 +5,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
)
|
||||
|
||||
type (
|
||||
// SearchResult contains search result of any / all ldap search request
|
||||
// @example
|
||||
// ```javascript
|
||||
// const ldap = require('nuclei/ldap');
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// const results = client.Search('(objectClass=*)', 'cn', 'mail');
|
||||
// ```
|
||||
SearchResult struct {
|
||||
// Referrals contains list of referrals
|
||||
Referrals []string `json:"referrals"`
|
||||
// Controls contains list of controls
|
||||
Controls []string `json:"controls"`
|
||||
// Entries contains list of entries
|
||||
Entries []LdapEntry `json:"entries"`
|
||||
}
|
||||
|
||||
// LdapEntry represents a single LDAP entry
|
||||
LdapEntry struct {
|
||||
// DN contains distinguished name
|
||||
DN string `json:"dn"`
|
||||
// Attributes contains list of attributes
|
||||
Attributes LdapAttributes `json:"attributes"`
|
||||
}
|
||||
|
||||
// LdapAttributes represents all LDAP attributes of a particular
|
||||
// ldap entry
|
||||
LdapAttributes struct {
|
||||
// CurrentTime contains current time
|
||||
CurrentTime []string `json:"currentTime,omitempty"`
|
||||
// SubschemaSubentry contains subschema subentry
|
||||
SubschemaSubentry []string `json:"subschemaSubentry,omitempty"`
|
||||
// DsServiceName contains ds service name
|
||||
DsServiceName []string `json:"dsServiceName,omitempty"`
|
||||
// NamingContexts contains naming contexts
|
||||
NamingContexts []string `json:"namingContexts,omitempty"`
|
||||
// DefaultNamingContext contains default naming context
|
||||
DefaultNamingContext []string `json:"defaultNamingContext,omitempty"`
|
||||
// SchemaNamingContext contains schema naming context
|
||||
SchemaNamingContext []string `json:"schemaNamingContext,omitempty"`
|
||||
// ConfigurationNamingContext contains configuration naming context
|
||||
ConfigurationNamingContext []string `json:"configurationNamingContext,omitempty"`
|
||||
// RootDomainNamingContext contains root domain naming context
|
||||
RootDomainNamingContext []string `json:"rootDomainNamingContext,omitempty"`
|
||||
// SupportedLDAPVersion contains supported LDAP version
|
||||
SupportedLDAPVersion []string `json:"supportedLDAPVersion,omitempty"`
|
||||
// HighestCommittedUSN contains highest committed USN
|
||||
HighestCommittedUSN []string `json:"highestCommittedUSN,omitempty"`
|
||||
// SupportedSASLMechanisms contains supported SASL mechanisms
|
||||
SupportedSASLMechanisms []string `json:"supportedSASLMechanisms,omitempty"`
|
||||
// DnsHostName contains DNS host name
|
||||
DnsHostName []string `json:"dnsHostName,omitempty"`
|
||||
// LdapServiceName contains LDAP service name
|
||||
LdapServiceName []string `json:"ldapServiceName,omitempty"`
|
||||
// ServerName contains server name
|
||||
ServerName []string `json:"serverName,omitempty"`
|
||||
// IsSynchronized contains is synchronized
|
||||
IsSynchronized []string `json:"isSynchronized,omitempty"`
|
||||
// IsGlobalCatalogReady contains is global catalog ready
|
||||
IsGlobalCatalogReady []string `json:"isGlobalCatalogReady,omitempty"`
|
||||
// DomainFunctionality contains domain functionality
|
||||
DomainFunctionality []string `json:"domainFunctionality,omitempty"`
|
||||
// ForestFunctionality contains forest functionality
|
||||
ForestFunctionality []string `json:"forestFunctionality,omitempty"`
|
||||
// DomainControllerFunctionality contains domain controller functionality
|
||||
DomainControllerFunctionality []string `json:"domainControllerFunctionality,omitempty"`
|
||||
// DistinguishedName contains the distinguished name
|
||||
DistinguishedName []string `json:"distinguishedName,omitempty"`
|
||||
// SAMAccountName contains the SAM account name
|
||||
SAMAccountName []string `json:"sAMAccountName,omitempty"`
|
||||
// PWDLastSet contains the password last set time
|
||||
PWDLastSet []string `json:"pwdLastSet,omitempty"`
|
||||
// LastLogon contains the last logon time
|
||||
LastLogon []string `json:"lastLogon,omitempty"`
|
||||
// MemberOf contains the groups the entry is a member of
|
||||
MemberOf []string `json:"memberOf,omitempty"`
|
||||
// ServicePrincipalName contains the service principal names
|
||||
ServicePrincipalName []string `json:"servicePrincipalName,omitempty"`
|
||||
// Extra contains other extra fields which might be present
|
||||
Extra map[string]any `json:"extra,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// getSearchResult converts a ldap.SearchResult to a SearchResult
|
||||
func getSearchResult(sr *ldap.SearchResult) *SearchResult {
|
||||
t := &SearchResult{
|
||||
Referrals: []string{},
|
||||
Controls: []string{},
|
||||
Entries: []LdapEntry{},
|
||||
}
|
||||
// add referrals
|
||||
t.Referrals = append(t.Referrals, sr.Referrals...)
|
||||
// add controls
|
||||
for _, ctrl := range sr.Controls {
|
||||
t.Controls = append(t.Controls, ctrl.String())
|
||||
}
|
||||
// add entries
|
||||
for _, entry := range sr.Entries {
|
||||
t.Entries = append(t.Entries, parseLdapEntry(entry))
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func parseLdapEntry(entry *ldap.Entry) LdapEntry {
|
||||
e := LdapEntry{
|
||||
DN: entry.DN,
|
||||
}
|
||||
attrs := LdapAttributes{
|
||||
Extra: make(map[string]any),
|
||||
}
|
||||
for _, attr := range entry.Attributes {
|
||||
switch attr.Name {
|
||||
case "currentTime":
|
||||
attrs.CurrentTime = decodeTimestamps(attr.Values)
|
||||
case "subschemaSubentry":
|
||||
attrs.SubschemaSubentry = attr.Values
|
||||
case "dsServiceName":
|
||||
attrs.DsServiceName = attr.Values
|
||||
case "namingContexts":
|
||||
attrs.NamingContexts = attr.Values
|
||||
case "defaultNamingContext":
|
||||
attrs.DefaultNamingContext = attr.Values
|
||||
case "schemaNamingContext":
|
||||
attrs.SchemaNamingContext = attr.Values
|
||||
case "configurationNamingContext":
|
||||
attrs.ConfigurationNamingContext = attr.Values
|
||||
case "rootDomainNamingContext":
|
||||
attrs.RootDomainNamingContext = attr.Values
|
||||
case "supportedLDAPVersion":
|
||||
attrs.SupportedLDAPVersion = attr.Values
|
||||
case "highestCommittedUSN":
|
||||
attrs.HighestCommittedUSN = attr.Values
|
||||
case "supportedSASLMechanisms":
|
||||
attrs.SupportedSASLMechanisms = attr.Values
|
||||
case "dnsHostName":
|
||||
attrs.DnsHostName = attr.Values
|
||||
case "ldapServiceName":
|
||||
attrs.LdapServiceName = attr.Values
|
||||
case "serverName":
|
||||
attrs.ServerName = attr.Values
|
||||
case "isSynchronized":
|
||||
attrs.IsSynchronized = attr.Values
|
||||
case "isGlobalCatalogReady":
|
||||
attrs.IsGlobalCatalogReady = attr.Values
|
||||
case "domainFunctionality":
|
||||
attrs.DomainFunctionality = attr.Values
|
||||
case "forestFunctionality":
|
||||
attrs.ForestFunctionality = attr.Values
|
||||
case "domainControllerFunctionality":
|
||||
attrs.DomainControllerFunctionality = attr.Values
|
||||
case "distinguishedName":
|
||||
attrs.DistinguishedName = attr.Values
|
||||
case "sAMAccountName":
|
||||
attrs.SAMAccountName = attr.Values
|
||||
case "pwdLastSet":
|
||||
attrs.PWDLastSet = decodeTimestamps(attr.Values)
|
||||
case "lastLogon":
|
||||
attrs.LastLogon = decodeTimestamps(attr.Values)
|
||||
case "memberOf":
|
||||
attrs.MemberOf = attr.Values
|
||||
case "servicePrincipalName":
|
||||
attrs.ServicePrincipalName = attr.Values
|
||||
default:
|
||||
attrs.Extra[attr.Name] = attr.Values
|
||||
}
|
||||
}
|
||||
e.Attributes = attrs
|
||||
return e
|
||||
}
|
||||
|
||||
// decodeTimestamps decodes multiple timestamps
|
||||
func decodeTimestamps(timestamps []string) []string {
|
||||
res := []string{}
|
||||
for _, timestamp := range timestamps {
|
||||
res = append(res, DecodeADTimestamp(timestamp))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// DecodeSID decodes a SID string
|
||||
// @example
|
||||
// ```javascript
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/microsoft/go-mssqldb"
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
@@ -9,14 +9,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/microsoft/go-mssqldb"
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"github.com/praetorian-inc/fingerprintx/pkg/plugins/services/mssql"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
type (
|
||||
// Client is a client for MS SQL database.
|
||||
// Internally client uses microsoft/go-mssqldb driver.
|
||||
// Internally client uses denisenkom/go-mssqldb driver.
|
||||
// @example
|
||||
// ```javascript
|
||||
// const mssql = require('nuclei/mssql');
|
||||
|
||||
@@ -36,7 +36,6 @@ type (
|
||||
// const isMySQL = mysql.IsMySQL('acme.com', 3306);
|
||||
// ```
|
||||
func (c *MySQLClient) IsMySQL(host string, port int) (bool, error) {
|
||||
// todo: why this is exposed? Service fingerprint should be automatic
|
||||
return memoizedisMySQL(host, port)
|
||||
}
|
||||
|
||||
@@ -78,16 +77,6 @@ func (c *MySQLClient) Connect(host string, port int, username, password string)
|
||||
// host is not valid according to network policy
|
||||
return false, protocolstate.ErrHostDenied.Msgf(host)
|
||||
}
|
||||
|
||||
// executing queries implies the remote mysql service
|
||||
ok, err := c.IsMySQL(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, fmt.Errorf("not a mysql service")
|
||||
}
|
||||
|
||||
dsn, err := BuildDSN(MySQLOptions{
|
||||
Host: host,
|
||||
Port: port,
|
||||
@@ -193,16 +182,6 @@ func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*ut
|
||||
// host is not valid according to network policy
|
||||
return nil, protocolstate.ErrHostDenied.Msgf(opts.Host)
|
||||
}
|
||||
|
||||
// executing queries implies the remote mysql service
|
||||
ok, err := c.IsMySQL(opts.Host, opts.Port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a mysql service")
|
||||
}
|
||||
|
||||
dsn, err := BuildDSN(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -241,15 +220,6 @@ func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*ut
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, query string) (*utils.SQLResult, error) {
|
||||
// executing queries implies the remote mysql service
|
||||
ok, err := c.IsMySQL(host, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a mysql service")
|
||||
}
|
||||
|
||||
return c.ExecuteQueryWithOpts(MySQLOptions{
|
||||
Host: host,
|
||||
Port: port,
|
||||
|
||||
@@ -37,7 +37,6 @@ type (
|
||||
// const isPostgres = postgres.IsPostgres('acme.com', 5432);
|
||||
// ```
|
||||
func (c *PGClient) IsPostgres(host string, port int) (bool, error) {
|
||||
// todo: why this is exposed? Service fingerprint should be automatic
|
||||
return memoizedisPostgres(host, port)
|
||||
}
|
||||
|
||||
@@ -75,13 +74,6 @@ func isPostgres(host string, port int) (bool, error) {
|
||||
// const connected = client.Connect('acme.com', 5432, 'username', 'password');
|
||||
// ```
|
||||
func (c *PGClient) Connect(host string, port int, username, password string) (bool, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
return memoizedconnect(host, port, username, password, "postgres")
|
||||
}
|
||||
|
||||
@@ -96,14 +88,6 @@ func (c *PGClient) Connect(host string, port int, username, password string) (bo
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
func (c *PGClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
|
||||
return memoizedexecuteQuery(host, port, username, password, dbName, query)
|
||||
}
|
||||
|
||||
@@ -145,14 +129,6 @@ func executeQuery(host string, port int, username string, password string, dbNam
|
||||
// const connected = client.ConnectWithDB('acme.com', 5432, 'username', 'password', 'dbname');
|
||||
// ```
|
||||
func (c *PGClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
|
||||
return memoizedconnect(host, port, username, password, dbName)
|
||||
}
|
||||
|
||||
@@ -173,10 +149,10 @@ func connect(host string, port int, username string, password string, dbName str
|
||||
defer cancel()
|
||||
|
||||
db := pg.Connect(&pg.Options{
|
||||
Addr: target,
|
||||
User: username,
|
||||
Password: password,
|
||||
Database: dbName,
|
||||
Addr: target,
|
||||
User: username,
|
||||
Password: password,
|
||||
Database: dbName,
|
||||
Dialer: func(network, addr string) (net.Conn, error) {
|
||||
return protocolstate.Dialer.Dial(context.Background(), network, addr)
|
||||
},
|
||||
|
||||
@@ -37,7 +37,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
pythonEnvRegex = `os\.getenv\(['"]([^'"]+)['"]\)`
|
||||
pythonEnvRegex = `os\.getenv\(['"]([^'"]+)['"]\)`
|
||||
TimeoutMultiplier = 6 // timeout multiplier for code protocol
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -178,6 +179,9 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
metaSrc.AddVariable(gozerotypes.Variable{Name: name, Value: v})
|
||||
}
|
||||
|
||||
// set timeout using multiplier
|
||||
timeout := TimeoutMultiplier * request.options.Options.Timeout
|
||||
|
||||
if request.PreCondition != "" {
|
||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||
gologger.Debug().Msgf("[%s] Executing Precondition for Code request\n", request.TemplateID)
|
||||
@@ -195,11 +199,11 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
|
||||
result, err := request.options.JsCompiler.ExecuteWithOptions(request.preConditionCompiled, args,
|
||||
&compiler.ExecuteOptions{
|
||||
TimeoutVariants: request.options.Options.GetTimeouts(),
|
||||
Source: &request.PreCondition,
|
||||
Callback: registerPreConditionFunctions,
|
||||
Cleanup: cleanUpPreConditionFunctions,
|
||||
Context: input.Context(),
|
||||
Timeout: timeout,
|
||||
Source: &request.PreCondition,
|
||||
Callback: registerPreConditionFunctions,
|
||||
Cleanup: cleanUpPreConditionFunctions,
|
||||
Context: input.Context(),
|
||||
})
|
||||
if err != nil {
|
||||
return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err)
|
||||
@@ -214,7 +218,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeoutCause(input.Context(), request.options.Options.GetTimeouts().CodeExecutionTimeout, ErrCodeExecutionDeadline)
|
||||
ctx, cancel := context.WithTimeoutCause(input.Context(), time.Duration(timeout)*time.Second, ErrCodeExecutionDeadline)
|
||||
defer cancel()
|
||||
// Note: we use contextutil despite the fact that gozero accepts context as argument
|
||||
gOutput, err := contextutil.ExecFuncWithTwoReturns(ctx, func() (*gozerotypes.Result, error) {
|
||||
|
||||
@@ -50,11 +50,9 @@ func NewWithInput(ctx context.Context, input string) *Context {
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("contextargs: could not create cookie jar: %s\n", err)
|
||||
}
|
||||
metaInput := NewMetaInput()
|
||||
metaInput.Input = input
|
||||
return &Context{
|
||||
ctx: ctx,
|
||||
MetaInput: metaInput,
|
||||
MetaInput: &MetaInput{Input: input},
|
||||
CookieJar: jar,
|
||||
args: &mapsutil.SyncLockMap[string, interface{}]{
|
||||
Map: make(map[string]interface{}),
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
|
||||
@@ -25,12 +24,6 @@ type MetaInput struct {
|
||||
|
||||
// ReqResp is the raw request for the input
|
||||
ReqResp *types.RequestResponse `json:"raw-request,omitempty"`
|
||||
|
||||
mu *sync.Mutex
|
||||
}
|
||||
|
||||
func NewMetaInput() *MetaInput {
|
||||
return &MetaInput{mu: &sync.Mutex{}}
|
||||
}
|
||||
|
||||
func (metaInput *MetaInput) marshalToBuffer() (bytes.Buffer, error) {
|
||||
@@ -142,10 +135,10 @@ func (metaInput *MetaInput) Unmarshal(data string) error {
|
||||
}
|
||||
|
||||
func (metaInput *MetaInput) Clone() *MetaInput {
|
||||
input := NewMetaInput()
|
||||
input.Input = metaInput.Input
|
||||
input.CustomIP = metaInput.CustomIP
|
||||
input.hash = metaInput.hash
|
||||
input := &MetaInput{
|
||||
Input: metaInput.Input,
|
||||
CustomIP: metaInput.CustomIP,
|
||||
}
|
||||
if metaInput.ReqResp != nil {
|
||||
input.ReqResp = metaInput.ReqResp.Clone()
|
||||
}
|
||||
@@ -167,9 +160,6 @@ func (metaInput *MetaInput) GetScanHash(templateId string) string {
|
||||
// there may be some cases where metainput is changed ex: while executing self-contained template etc
|
||||
// but that totally changes the scanID/hash so to avoid that we compute hash only once
|
||||
// and reuse it for all subsequent calls
|
||||
metaInput.mu.Lock()
|
||||
defer metaInput.mu.Unlock()
|
||||
|
||||
if metaInput.hash == "" {
|
||||
var rawRequest string
|
||||
if metaInput.ReqResp != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types/nucleierr"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
)
|
||||
|
||||
// CacheInterface defines the signature of the hosterrorscache so that
|
||||
@@ -201,7 +200,7 @@ func (c *Cache) checkError(err error) bool {
|
||||
errX := errkit.FromError(err)
|
||||
tmp := errX.Cause()
|
||||
cause := tmp.Error()
|
||||
if stringsutil.ContainsAll(cause, "ReadStatusLine:", "read: connection reset by peer") {
|
||||
if strings.Contains(cause, "ReadStatusLine:") && strings.Contains(cause, "read: connection reset by peer") {
|
||||
// this is a FP and should not be counted as a host error
|
||||
// because server closes connection when it reads corrupted bytes which we send via rawhttp
|
||||
return false
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
var (
|
||||
defaultInteractionDuration = 60 * time.Second
|
||||
interactshURLMarkerRegex = regexp.MustCompile(`(%7[B|b]|\{){2}(interactsh-url(?:_[0-9]+){0,3})(%7[D|d]|\}){2}`)
|
||||
interactshURLMarkerRegex = regexp.MustCompile(`{{interactsh-url(?:_[0-9]+){0,3}}}`)
|
||||
|
||||
ErrInteractshClientNotInitialized = errors.New("interactsh client not initialized")
|
||||
)
|
||||
|
||||
@@ -34,7 +34,9 @@ func Init(options *types.Options) error {
|
||||
|
||||
lfaAllowed = options.AllowLocalFileAccess
|
||||
opts := fastdialer.DefaultOptions
|
||||
opts.DialerTimeout = options.GetTimeouts().DialTimeout
|
||||
if options.DialerTimeout > 0 {
|
||||
opts.DialerTimeout = options.DialerTimeout
|
||||
}
|
||||
if options.DialerKeepAlive > 0 {
|
||||
opts.DialerKeepAlive = options.DialerKeepAlive
|
||||
}
|
||||
|
||||
@@ -141,6 +141,12 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
recursion := true
|
||||
request.Recursion = &recursion
|
||||
}
|
||||
dnsClientOptions := &dnsclientpool.Configuration{
|
||||
Retries: request.Retries,
|
||||
}
|
||||
if len(request.Resolvers) > 0 {
|
||||
dnsClientOptions.Resolvers = request.Resolvers
|
||||
}
|
||||
// Create a dns client for the class
|
||||
client, err := request.getDnsClient(options, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@ package dns
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
|
||||
protocolutils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
|
||||
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
|
||||
"github.com/projectdiscovery/retryabledns"
|
||||
iputil "github.com/projectdiscovery/utils/ip"
|
||||
syncutil "github.com/projectdiscovery/utils/sync"
|
||||
@@ -36,8 +38,16 @@ func (request *Request) Type() templateTypes.ProtocolType {
|
||||
|
||||
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||
func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
||||
// Parse the URL and return domain if URL.
|
||||
var domain string
|
||||
if utils.IsURL(input.MetaInput.Input) {
|
||||
domain = extractDomain(input.MetaInput.Input)
|
||||
} else {
|
||||
domain = input.MetaInput.Input
|
||||
}
|
||||
|
||||
var err error
|
||||
domain, err := request.parseDNSInput(input.MetaInput.Input)
|
||||
domain, err = request.parseDNSInput(domain)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not build request")
|
||||
}
|
||||
@@ -220,7 +230,7 @@ func (request *Request) parseDNSInput(host string) (string, error) {
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func dumpResponse(event *output.InternalWrappedEvent, request *Request, _ *protocols.ExecutorOptions, response, domain string) {
|
||||
func dumpResponse(event *output.InternalWrappedEvent, request *Request, requestOptions *protocols.ExecutorOptions, response, domain string) {
|
||||
cliOptions := request.options.Options
|
||||
if cliOptions.Debug || cliOptions.DebugResponse || cliOptions.StoreResponse {
|
||||
hexDump := false
|
||||
@@ -251,3 +261,12 @@ func dumpTraceData(event *output.InternalWrappedEvent, requestOptions *protocols
|
||||
gologger.Debug().Msgf("[%s] Dumped DNS Trace data for %s\n\n%s", requestOptions.TemplateID, domain, highlightedResponse)
|
||||
}
|
||||
}
|
||||
|
||||
// extractDomain extracts the domain name of a URL
|
||||
func extractDomain(theURL string) string {
|
||||
u, err := url.Parse(theURL)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return u.Hostname()
|
||||
}
|
||||
@@ -67,5 +67,19 @@ func TestDNSExecuteWithResults(t *testing.T) {
|
||||
require.Equal(t, 1, len(finalEvent.Results[0].ExtractedResults), "could not get correct number of extracted results")
|
||||
require.Equal(t, "93.184.215.14", finalEvent.Results[0].ExtractedResults[0], "could not get correct extracted results")
|
||||
finalEvent = nil
|
||||
// Note: changing url to domain is responsible at tmplexec package and is implemented there
|
||||
|
||||
t.Run("url-to-domain", func(t *testing.T) {
|
||||
metadata := make(output.InternalEvent)
|
||||
previous := make(output.InternalEvent)
|
||||
err := request.ExecuteWithResults(contextargs.NewWithInput(context.Background(), "https://example.com"), metadata, previous, func(event *output.InternalWrappedEvent) {
|
||||
finalEvent = event
|
||||
})
|
||||
require.Nil(t, err, "could not execute dns request")
|
||||
})
|
||||
require.NotNil(t, finalEvent, "could not get event output from request")
|
||||
require.Equal(t, 1, len(finalEvent.Results), "could not get correct number of results")
|
||||
require.Equal(t, "test", finalEvent.Results[0].MatcherName, "could not get correct matcher name of results")
|
||||
require.Equal(t, 1, len(finalEvent.Results[0].ExtractedResults), "could not get correct number of extracted results")
|
||||
require.Equal(t, "93.184.215.14", finalEvent.Results[0].ExtractedResults[0], "could not get correct extracted results")
|
||||
finalEvent = nil
|
||||
}
|
||||
@@ -51,9 +51,6 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if input.MetaInput.Input == "" {
|
||||
return errors.New("input cannot be empty file or folder expected")
|
||||
}
|
||||
err = request.getInputPaths(input.MetaInput.Input, func(filePath string) {
|
||||
wg.Add()
|
||||
func(filePath string) {
|
||||
@@ -253,8 +250,6 @@ func (request *Request) findMatchesWithReader(reader io.Reader, input *contextar
|
||||
for k, v := range previous {
|
||||
dslMap[k] = v
|
||||
}
|
||||
// add vars to template context
|
||||
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, dslMap)
|
||||
// add template context variables to DSL map
|
||||
if request.options.HasTemplateCtx(input.MetaInput) {
|
||||
dslMap = generators.MergeMaps(dslMap, request.options.GetTemplateCtx(input.MetaInput).GetAll())
|
||||
@@ -328,6 +323,7 @@ func (request *Request) buildEvent(input, filePath string, fileMatches []FileMat
|
||||
exprLines[fileMatch.Expr] = append(exprLines[fileMatch.Expr], fileMatch.Line)
|
||||
exprBytes[fileMatch.Expr] = append(exprBytes[fileMatch.Expr], fileMatch.ByteIndex)
|
||||
}
|
||||
|
||||
event := eventcreator.CreateEventWithOperatorResults(request, internalEvent, operatorResult)
|
||||
// Annotate with line numbers if asked by the user
|
||||
if request.options.Options.ShowMatchLine {
|
||||
|
||||
@@ -215,10 +215,6 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
||||
}
|
||||
|
||||
dumpResponse(event, request.options, responseBody, input.MetaInput.Input)
|
||||
shouldStopAtFirstMatch := request.StopAtFirstMatch || request.options.StopAtFirstMatch || request.options.Options.StopAtFirstMatch
|
||||
if shouldStopAtFirstMatch && event.HasOperatorResult() {
|
||||
return types.ErrNoMoreRequests
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
request.Raw[i] = strings.ReplaceAll(raw, "\n", "\r\n")
|
||||
}
|
||||
}
|
||||
request.rawhttpClient = httpclientpool.GetRawHTTP(options)
|
||||
request.rawhttpClient = httpclientpool.GetRawHTTP(options.Options)
|
||||
}
|
||||
if len(request.Matchers) > 0 || len(request.Extractors) > 0 {
|
||||
compiled := &request.Operators
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"golang.org/x/net/publicsuffix"
|
||||
|
||||
"github.com/projectdiscovery/fastdialer/fastdialer/ja3/impersonate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
@@ -32,14 +31,28 @@ var (
|
||||
forceMaxRedirects int
|
||||
normalClient *retryablehttp.Client
|
||||
clientPool *mapsutil.SyncLockMap[string, *retryablehttp.Client]
|
||||
// MaxResponseHeaderTimeout is the timeout for response headers
|
||||
// to be read from the server (this prevents infinite hang started by server if any)
|
||||
// Note: this will be overridden temporarily when using @timeout request annotation
|
||||
MaxResponseHeaderTimeout = time.Duration(10) * time.Second
|
||||
// HttpTimeoutMultiplier is the multiplier for the http timeout
|
||||
HttpTimeoutMultiplier = 3
|
||||
)
|
||||
|
||||
// GetHttpTimeout returns the http timeout for the client
|
||||
func GetHttpTimeout(opts *types.Options) time.Duration {
|
||||
return time.Duration(opts.Timeout*HttpTimeoutMultiplier) * time.Second
|
||||
}
|
||||
|
||||
// Init initializes the clientpool implementation
|
||||
func Init(options *types.Options) error {
|
||||
// Don't create clients if already created in the past.
|
||||
if normalClient != nil {
|
||||
return nil
|
||||
}
|
||||
if options.Timeout > 10 {
|
||||
MaxResponseHeaderTimeout = time.Duration(options.Timeout) * time.Second
|
||||
}
|
||||
if options.ShouldFollowHTTPRedirects() {
|
||||
forceMaxRedirects = options.MaxRedirects
|
||||
}
|
||||
@@ -130,7 +143,7 @@ func (c *Configuration) HasStandardOptions() bool {
|
||||
}
|
||||
|
||||
// GetRawHTTP returns the rawhttp request client
|
||||
func GetRawHTTP(options *protocols.ExecutorOptions) *rawhttp.Client {
|
||||
func GetRawHTTP(options *types.Options) *rawhttp.Client {
|
||||
if rawHttpClient == nil {
|
||||
rawHttpOptions := rawhttp.DefaultOptions
|
||||
if types.ProxyURL != "" {
|
||||
@@ -140,7 +153,7 @@ func GetRawHTTP(options *protocols.ExecutorOptions) *rawhttp.Client {
|
||||
} else if protocolstate.Dialer != nil {
|
||||
rawHttpOptions.FastDialer = protocolstate.Dialer
|
||||
}
|
||||
rawHttpOptions.Timeout = options.Options.GetTimeouts().HttpTimeout
|
||||
rawHttpOptions.Timeout = GetHttpTimeout(options)
|
||||
rawHttpClient = rawhttp.NewClient(rawHttpOptions)
|
||||
}
|
||||
return rawHttpClient
|
||||
@@ -226,7 +239,7 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
}
|
||||
|
||||
// responseHeaderTimeout is max timeout for response headers to be read
|
||||
responseHeaderTimeout := options.GetTimeouts().HttpResponseHeaderTimeout
|
||||
responseHeaderTimeout := MaxResponseHeaderTimeout
|
||||
if configuration.ResponseHeaderTimeout != 0 {
|
||||
responseHeaderTimeout = configuration.ResponseHeaderTimeout
|
||||
}
|
||||
@@ -295,7 +308,7 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
||||
CheckRedirect: makeCheckRedirectFunc(redirectFlow, maxRedirects),
|
||||
}
|
||||
if !configuration.NoTimeout {
|
||||
httpclient.Timeout = options.GetTimeouts().HttpTimeout
|
||||
httpclient.Timeout = GetHttpTimeout(options)
|
||||
}
|
||||
client := retryablehttp.NewWithHTTPClient(httpclient, retryableHttpOptions)
|
||||
if jar != nil {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/rawhttp"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
@@ -37,7 +36,7 @@ func SendRawRequest(client *rawhttp.Client, opts *RawHttpRequestOpts) (*http.Res
|
||||
resp, err := client.DoRawWithOptions(opts.Method, opts.URL, opts.Path, opts.Headers, opts.Body, opts.Options)
|
||||
if err != nil {
|
||||
cause := err.Error()
|
||||
if stringsutil.ContainsAll(cause, "ReadStatusLine: ", "read: connection reset by peer") {
|
||||
if strings.Contains(cause, "ReadStatusLine: ") && strings.Contains(cause, "read: connection reset by peer") {
|
||||
// this error is caused when rawhttp client sends a corrupted or malformed request packet to server
|
||||
// some servers may attempt gracefully shutdown but most will just abruptly close the connection which results
|
||||
// in a connection reset by peer error and this can be safely assumed as 400 Bad Request in terms of normal http flow
|
||||
|
||||
@@ -483,7 +483,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
request.options.RateLimitTake()
|
||||
|
||||
ctx := request.newContext(input)
|
||||
ctxWithTimeout, cancel := context.WithTimeoutCause(ctx, request.options.Options.GetTimeouts().HttpTimeout, ErrHttpEngineRequestDeadline)
|
||||
ctxWithTimeout, cancel := context.WithTimeoutCause(ctx, httpclientpool.GetHttpTimeout(request.options.Options), ErrHttpEngineRequestDeadline)
|
||||
defer cancel()
|
||||
|
||||
generatedHttpRequest, err := generator.Make(ctxWithTimeout, input, data, payloads, dynamicValue)
|
||||
@@ -844,8 +844,6 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
|
||||
outputEvent["ip"] = input.MetaInput.CustomIP
|
||||
} else {
|
||||
outputEvent["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
|
||||
// try getting cname
|
||||
request.addCNameIfAvailable(hostname, outputEvent)
|
||||
}
|
||||
|
||||
if len(generatedRequest.interactshURLs) > 0 {
|
||||
@@ -942,8 +940,6 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
|
||||
outputEvent["ip"] = input.MetaInput.CustomIP
|
||||
} else {
|
||||
outputEvent["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
|
||||
// try getting cname
|
||||
request.addCNameIfAvailable(hostname, outputEvent)
|
||||
}
|
||||
if request.options.Interactsh != nil {
|
||||
request.options.Interactsh.MakePlaceholders(generatedRequest.interactshURLs, outputEvent)
|
||||
@@ -1035,23 +1031,6 @@ func (request *Request) validateNFixEvent(input *contextargs.Context, gr *genera
|
||||
}
|
||||
}
|
||||
|
||||
// addCNameIfAvailable adds the cname to the event if available
|
||||
func (request *Request) addCNameIfAvailable(hostname string, outputEvent map[string]interface{}) {
|
||||
data, err := protocolstate.Dialer.GetDNSData(hostname)
|
||||
if err == nil {
|
||||
switch len(data.CNAME) {
|
||||
case 0:
|
||||
return
|
||||
case 1:
|
||||
outputEvent["cname"] = data.CNAME[0]
|
||||
default:
|
||||
// add 1st and put others in cname_all
|
||||
outputEvent["cname"] = data.CNAME[0]
|
||||
outputEvent["cname_all"] = data.CNAME
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleSignature of the http request
|
||||
func (request *Request) handleSignature(generatedRequest *generatedRequest) error {
|
||||
switch request.Signature.Value {
|
||||
@@ -1083,15 +1062,10 @@ func (request *Request) setCustomHeaders(req *generatedRequest) {
|
||||
req.rawRequest.Headers[k] = v
|
||||
} else {
|
||||
kk, vv := strings.TrimSpace(k), strings.TrimSpace(v)
|
||||
// NOTE(dwisiswant0): Do we really not need to convert it first into
|
||||
// lowercase?
|
||||
req.request.Header.Set(kk, vv)
|
||||
if kk == "Host" {
|
||||
req.request.Host = vv
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
req.request.Header[kk] = []string{vv}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +130,6 @@ func (r *Request) parseAnnotations(rawRequest string, request *retryablehttp.Req
|
||||
if duration := reTimeoutAnnotation.FindStringSubmatch(rawRequest); len(duration) > 0 {
|
||||
value := strings.TrimSpace(duration[1])
|
||||
if parsed, err := time.ParseDuration(value); err == nil {
|
||||
// to avoid dos via timeout request annotation in http template we set it to maximum of 2 minutes
|
||||
if parsed > 2*time.Minute {
|
||||
parsed = 2 * time.Minute
|
||||
}
|
||||
//nolint:govet // cancelled automatically by withTimeout
|
||||
// global timeout is overridden by annotation by replacing context
|
||||
ctx, overrides.cancelFunc = context.WithTimeoutCause(context.TODO(), parsed, ErrTimeoutAnnotationDeadline)
|
||||
@@ -144,7 +140,7 @@ func (r *Request) parseAnnotations(rawRequest string, request *retryablehttp.Req
|
||||
} else {
|
||||
//nolint:govet // cancelled automatically by withTimeout
|
||||
// global timeout is overridden by annotation by replacing context
|
||||
ctx, overrides.cancelFunc = context.WithTimeoutCause(context.TODO(), r.options.Options.GetTimeouts().HttpTimeout, ErrRequestTimeoutDeadline)
|
||||
ctx, overrides.cancelFunc = context.WithTimeoutCause(context.TODO(), httpclientpool.GetHttpTimeout(r.options.Options), ErrRequestTimeoutDeadline)
|
||||
request = request.Clone(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
+76
-102
@@ -35,7 +35,6 @@ import (
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
iputil "github.com/projectdiscovery/utils/ip"
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
syncutil "github.com/projectdiscovery/utils/sync"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
@@ -66,6 +65,9 @@ type Request struct {
|
||||
// Code contains code to execute for the javascript request.
|
||||
Code string `yaml:"code,omitempty" json:"code,omitempty" jsonschema:"title=code to execute in javascript,description=Executes inline javascript code for the request"`
|
||||
// description: |
|
||||
// Timeout in seconds is optional timeout for each javascript script execution (i.e init, pre-condition, code)
|
||||
Timeout int `yaml:"timeout,omitempty" json:"timeout,omitempty" jsonschema:"title=timeout for javascript execution,description=Timeout in seconds is optional timeout for entire javascript script execution"`
|
||||
// description: |
|
||||
// StopAtFirstMatch stops processing the request at first match.
|
||||
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" json:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop the execution after a match is found"`
|
||||
// description: |
|
||||
@@ -151,9 +153,9 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||
}
|
||||
|
||||
opts := &compiler.ExecuteOptions{
|
||||
TimeoutVariants: request.options.Options.GetTimeouts(),
|
||||
Source: &request.Init,
|
||||
Context: context.Background(),
|
||||
Timeout: request.Timeout,
|
||||
Source: &request.Init,
|
||||
Context: context.Background(),
|
||||
}
|
||||
// register 'export' function to export variables from init code
|
||||
// these are saved in args and are available in pre-condition and request code
|
||||
@@ -343,37 +345,18 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
|
||||
argsCopy.TemplateCtx = templateCtx.GetAll()
|
||||
|
||||
result, err := request.options.JsCompiler.ExecuteWithOptions(request.preConditionCompiled, argsCopy,
|
||||
&compiler.ExecuteOptions{
|
||||
TimeoutVariants: requestOptions.Options.GetTimeouts(),
|
||||
Source: &request.PreCondition, Context: target.Context(),
|
||||
})
|
||||
// if precondition was successful
|
||||
if err == nil && result.GetSuccess() {
|
||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||
request.options.Progress.IncrementRequests()
|
||||
gologger.Debug().Msgf("[%s] Precondition for request was satisfied\n", request.TemplateID)
|
||||
}
|
||||
} else {
|
||||
var outError error
|
||||
// if js code failed to execute
|
||||
if err != nil {
|
||||
outError = errkit.Append(errkit.New("pre-condition not satisfied skipping template execution"), err)
|
||||
} else {
|
||||
// execution successful but pre-condition returned false
|
||||
outError = errkit.New("pre-condition not satisfied skipping template execution")
|
||||
}
|
||||
results := map[string]interface{}(result)
|
||||
results["error"] = outError.Error()
|
||||
// generate and return failed event
|
||||
data := request.generateEventData(input, results, hostPort)
|
||||
data = generators.MergeMaps(data, payloadValues)
|
||||
event := eventcreator.CreateEventWithAdditionalOptions(request, data, request.options.Options.Debug || request.options.Options.DebugResponse, func(wrappedEvent *output.InternalWrappedEvent) {
|
||||
allVars := argsCopy.Map()
|
||||
allVars = generators.MergeMaps(allVars, data)
|
||||
wrappedEvent.OperatorsResult.PayloadValues = allVars
|
||||
})
|
||||
callback(event)
|
||||
return err
|
||||
&compiler.ExecuteOptions{Timeout: request.Timeout, Source: &request.PreCondition, Context: target.Context()})
|
||||
if err != nil {
|
||||
return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err)
|
||||
}
|
||||
if !result.GetSuccess() || types.ToString(result["error"]) != "" {
|
||||
gologger.Warning().Msgf("[%s] Precondition for request %s was not satisfied\n", request.TemplateID, request.PreCondition)
|
||||
request.options.Progress.IncrementFailedRequestsBy(1)
|
||||
return nil
|
||||
}
|
||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||
request.options.Progress.IncrementRequests()
|
||||
gologger.Debug().Msgf("[%s] Precondition for request was satisfied\n", request.TemplateID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,11 +500,7 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
|
||||
}
|
||||
|
||||
results, err := request.options.JsCompiler.ExecuteWithOptions(request.scriptCompiled, argsCopy,
|
||||
&compiler.ExecuteOptions{
|
||||
TimeoutVariants: requestOptions.Options.GetTimeouts(),
|
||||
Source: &request.Code,
|
||||
Context: input.Context(),
|
||||
})
|
||||
&compiler.ExecuteOptions{Timeout: request.Timeout, Source: &request.Code, Context: input.Context()})
|
||||
if err != nil {
|
||||
// shouldn't fail even if it returned error instead create a failure event
|
||||
results = compiler.ExecuteResult{"success": false, "error": err.Error()}
|
||||
@@ -548,9 +527,63 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
|
||||
}
|
||||
}
|
||||
|
||||
values := mapsutil.Merge(payloadValues, results)
|
||||
// generate event data
|
||||
data := request.generateEventData(input, values, hostPort)
|
||||
data := make(map[string]interface{})
|
||||
for k, v := range payloadValues {
|
||||
data[k] = v
|
||||
}
|
||||
data["type"] = request.Type().String()
|
||||
for k, v := range results {
|
||||
data[k] = v
|
||||
}
|
||||
data["request"] = beautifyJavascript(request.Code)
|
||||
data["host"] = input.MetaInput.Input
|
||||
data["matched"] = hostPort
|
||||
data["template-path"] = requestOptions.TemplatePath
|
||||
data["template-id"] = requestOptions.TemplateID
|
||||
data["template-info"] = requestOptions.TemplateInfo
|
||||
if request.StopAtFirstMatch || request.options.StopAtFirstMatch {
|
||||
data["stop-at-first-match"] = true
|
||||
}
|
||||
|
||||
// add ip address to data
|
||||
if input.MetaInput.CustomIP != "" {
|
||||
data["ip"] = input.MetaInput.CustomIP
|
||||
} else {
|
||||
// context: https://github.com/projectdiscovery/nuclei/issues/5021
|
||||
hostname := input.MetaInput.Input
|
||||
if strings.Contains(hostname, ":") {
|
||||
host, _, err := net.SplitHostPort(hostname)
|
||||
if err == nil {
|
||||
hostname = host
|
||||
} else {
|
||||
// naive way
|
||||
if !strings.Contains(hostname, "]") {
|
||||
hostname = hostname[:strings.LastIndex(hostname, ":")]
|
||||
}
|
||||
}
|
||||
}
|
||||
data["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
|
||||
// if input itself was an ip, use it
|
||||
if iputil.IsIP(hostname) {
|
||||
data["ip"] = hostname
|
||||
}
|
||||
|
||||
// if ip is not found,this is because ssh and other protocols do not use fastdialer
|
||||
// although its not perfect due to its use case dial and get ip
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(hostname)
|
||||
if err == nil {
|
||||
for _, v := range dnsData.A {
|
||||
data["ip"] = v
|
||||
break
|
||||
}
|
||||
if data["ip"] == "" {
|
||||
for _, v := range dnsData.AAAA {
|
||||
data["ip"] = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add and get values from templatectx
|
||||
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.GetID(), data)
|
||||
@@ -597,65 +630,6 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateEventData generates event data for the request
|
||||
func (request *Request) generateEventData(input *contextargs.Context, values map[string]interface{}, matched string) map[string]interface{} {
|
||||
data := make(map[string]interface{})
|
||||
for k, v := range values {
|
||||
data[k] = v
|
||||
}
|
||||
data["type"] = request.Type().String()
|
||||
data["request-pre-condition"] = beautifyJavascript(request.PreCondition)
|
||||
data["request"] = beautifyJavascript(request.Code)
|
||||
data["host"] = input.MetaInput.Input
|
||||
data["matched"] = matched
|
||||
data["template-path"] = request.options.TemplatePath
|
||||
data["template-id"] = request.options.TemplateID
|
||||
data["template-info"] = request.options.TemplateInfo
|
||||
if request.StopAtFirstMatch || request.options.StopAtFirstMatch {
|
||||
data["stop-at-first-match"] = true
|
||||
}
|
||||
// add ip address to data
|
||||
if input.MetaInput.CustomIP != "" {
|
||||
data["ip"] = input.MetaInput.CustomIP
|
||||
} else {
|
||||
// context: https://github.com/projectdiscovery/nuclei/issues/5021
|
||||
hostname := input.MetaInput.Input
|
||||
if strings.Contains(hostname, ":") {
|
||||
host, _, err := net.SplitHostPort(hostname)
|
||||
if err == nil {
|
||||
hostname = host
|
||||
} else {
|
||||
// naive way
|
||||
if !strings.Contains(hostname, "]") {
|
||||
hostname = hostname[:strings.LastIndex(hostname, ":")]
|
||||
}
|
||||
}
|
||||
}
|
||||
data["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
|
||||
// if input itself was an ip, use it
|
||||
if iputil.IsIP(hostname) {
|
||||
data["ip"] = hostname
|
||||
}
|
||||
|
||||
// if ip is not found,this is because ssh and other protocols do not use fastdialer
|
||||
// although its not perfect due to its use case dial and get ip
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(hostname)
|
||||
if err == nil {
|
||||
for _, v := range dnsData.A {
|
||||
data["ip"] = v
|
||||
break
|
||||
}
|
||||
if data["ip"] == "" {
|
||||
for _, v := range dnsData.AAAA {
|
||||
data["ip"] = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (request *Request) getArgsCopy(input *contextargs.Context, payloadValues map[string]interface{}, requestOptions *protocols.ExecutorOptions, ignoreErrors bool) (*compiler.ExecuteArgs, error) {
|
||||
// Template args from payloads
|
||||
argsCopy, err := request.evaluateArgs(payloadValues, requestOptions, ignoreErrors)
|
||||
|
||||
@@ -327,7 +327,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
||||
}
|
||||
|
||||
if input.Read > 0 {
|
||||
buffer, err := ConnReadNWithTimeout(conn, int64(input.Read), request.options.Options.GetTimeouts().TcpReadTimeout)
|
||||
buffer, err := ConnReadNWithTimeout(conn, int64(input.Read), request.options.Options.ResponseReadTimeout)
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("could not read response from connection")
|
||||
}
|
||||
@@ -377,7 +377,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
||||
bufferSize = -1
|
||||
}
|
||||
|
||||
final, err := ConnReadNWithTimeout(conn, int64(bufferSize), request.options.Options.GetTimeouts().TcpReadTimeout)
|
||||
final, err := ConnReadNWithTimeout(conn, int64(bufferSize), request.options.Options.ResponseReadTimeout)
|
||||
if err != nil {
|
||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||
gologger.Verbose().Msgf("could not read more data from %s: %s", actualAddress, err)
|
||||
|
||||
@@ -197,11 +197,6 @@ func (e *ExecutorOptions) AddTemplateVars(input *contextargs.MetaInput, reqType
|
||||
}
|
||||
templateCtx := e.GetTemplateCtx(input)
|
||||
for k, v := range vars {
|
||||
if stringsutil.HasPrefixAny(k, templateTypes.SupportedProtocolsStrings()...) {
|
||||
// this was inherited from previous protocols no need to modify it we can directly set it or omit
|
||||
templateCtx.Set(k, v)
|
||||
continue
|
||||
}
|
||||
if !stringsutil.EqualFoldAny(k, "template-id", "template-info", "template-path") {
|
||||
if reqID != "" {
|
||||
k = reqID + "_" + k
|
||||
@@ -221,11 +216,6 @@ func (e *ExecutorOptions) AddTemplateVar(input *contextargs.MetaInput, templateT
|
||||
return
|
||||
}
|
||||
templateCtx := e.GetTemplateCtx(input)
|
||||
if stringsutil.HasPrefixAny(key, templateTypes.SupportedProtocolsStrings()...) {
|
||||
// this was inherited from previous protocols no need to modify it we can directly set it or omit
|
||||
templateCtx.Set(key, value)
|
||||
return
|
||||
}
|
||||
if reqID != "" {
|
||||
key = reqID + "_" + key
|
||||
} else if templateType < templateTypes.InvalidProtocol {
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/projectdiscovery/tlsx/pkg/tlsx/openssl"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
// Request is a request for the SSL protocol
|
||||
@@ -198,7 +199,10 @@ func (request *Request) GetID() string {
|
||||
|
||||
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||
func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
||||
hostPort := input.MetaInput.Input
|
||||
hostPort, err := getAddress(input.MetaInput.Input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hostname, port, _ := net.SplitHostPort(hostPort)
|
||||
|
||||
requestOptions := request.options
|
||||
@@ -354,6 +358,19 @@ var RequestPartDefinitions = map[string]string{
|
||||
"matched": "Matched is the input which was matched upon",
|
||||
}
|
||||
|
||||
// getAddress returns the address of the host to make request to
|
||||
func getAddress(toTest string) (string, error) {
|
||||
urlx, err := urlutil.Parse(toTest)
|
||||
if err != nil {
|
||||
// use given input instead of url parsing failure
|
||||
return toTest, nil
|
||||
}
|
||||
if urlx.Port() == "" {
|
||||
urlx.UpdatePort("443")
|
||||
}
|
||||
return urlx.Host, nil
|
||||
}
|
||||
|
||||
// Match performs matching operation for a matcher on model and returns:
|
||||
// true and a list of matched snippets if the matcher type is supports it
|
||||
// otherwise false and an empty string slice
|
||||
|
||||
@@ -36,3 +36,8 @@ func TestSSLProtocol(t *testing.T) {
|
||||
require.Nil(t, err, "could not run ssl request")
|
||||
require.NotEmpty(t, gotEvent, "could not get event items")
|
||||
}
|
||||
|
||||
func TestGetAddress(t *testing.T) {
|
||||
address, _ := getAddress("https://scanme.sh")
|
||||
require.Equal(t, "scanme.sh:443", address, "could not get correct address")
|
||||
}
|
||||
@@ -30,7 +30,6 @@ func (s *ScanEventsCharts) GenerateHTML(filePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer output.Close()
|
||||
return page.Render(output)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ func (s *ScanStatsWorker) initEventsFile() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
s.enc = json.NewEncoder(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -77,9 +77,6 @@ func (s *ScanContext) LogEvent(e *output.InternalWrappedEvent) {
|
||||
s.events = append(s.events, e)
|
||||
}
|
||||
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
|
||||
s.results = append(s.results, e.Results...)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ func Cluster(list []*Template) [][]*Template {
|
||||
dns[hash] = []*Template{}
|
||||
}
|
||||
dns[hash] = append(dns[hash], template)
|
||||
gologger.Error().Msgf("Clustered DNS template: %s with hash: %d", template.ID, hash)
|
||||
} else {
|
||||
final = append(final, []*Template{template})
|
||||
}
|
||||
@@ -75,7 +74,6 @@ func Cluster(list []*Template) [][]*Template {
|
||||
http[hash] = []*Template{}
|
||||
}
|
||||
http[hash] = append(http[hash], template)
|
||||
gologger.Error().Msgf("Clustered HTTP template: %s with hash: %d", template.ID, hash)
|
||||
} else {
|
||||
final = append(final, []*Template{template})
|
||||
}
|
||||
@@ -86,7 +84,6 @@ func Cluster(list []*Template) [][]*Template {
|
||||
ssl[hash] = []*Template{}
|
||||
}
|
||||
ssl[hash] = append(ssl[hash], template)
|
||||
gologger.Error().Msgf("Clustered SSL template: %s with hash: %d", template.ID, hash)
|
||||
} else {
|
||||
final = append(final, []*Template{template})
|
||||
}
|
||||
@@ -95,7 +92,7 @@ func Cluster(list []*Template) [][]*Template {
|
||||
}
|
||||
}
|
||||
|
||||
// add all clustered templates
|
||||
// add all clusterd templates
|
||||
for _, templates := range http {
|
||||
final = append(final, templates)
|
||||
}
|
||||
@@ -106,7 +103,6 @@ func Cluster(list []*Template) [][]*Template {
|
||||
final = append(final, templates)
|
||||
}
|
||||
|
||||
gologger.Error().Msgf("Total clusters formed: %d", len(final))
|
||||
return final
|
||||
}
|
||||
|
||||
@@ -154,12 +150,10 @@ func ClusterTemplates(templatesList []*Template, options protocols.ExecutorOptio
|
||||
TotalRequests: len(cluster[0].RequestsHTTP) + len(cluster[0].RequestsDNS),
|
||||
})
|
||||
clusterCount += len(cluster)
|
||||
gologger.Error().Msgf("Created cluster with ID: %s containing %d templates", clusterID, len(cluster))
|
||||
} else {
|
||||
finalTemplatesList = append(finalTemplatesList, cluster...)
|
||||
}
|
||||
}
|
||||
gologger.Error().Msgf("Total templates after clustering: %d", len(finalTemplatesList))
|
||||
return finalTemplatesList, clusterCount
|
||||
}
|
||||
|
||||
|
||||
@@ -39,15 +39,15 @@ func setup() {
|
||||
progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0)
|
||||
|
||||
executerOpts = protocols.ExecutorOptions{
|
||||
Output: testutils.NewMockOutputWriter(options.OmitTemplate),
|
||||
Options: options,
|
||||
Progress: progressImpl,
|
||||
ProjectFile: nil,
|
||||
IssuesClient: nil,
|
||||
Browser: nil,
|
||||
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
|
||||
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
|
||||
Parser: templates.NewParser(),
|
||||
Output: testutils.NewMockOutputWriter(options.OmitTemplate),
|
||||
Options: options,
|
||||
Progress: progressImpl,
|
||||
ProjectFile: nil,
|
||||
IssuesClient: nil,
|
||||
Browser: nil,
|
||||
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
|
||||
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
|
||||
Parser: templates.NewParser(),
|
||||
}
|
||||
workflowLoader, err := workflow.NewLoader(&executerOpts)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||
"github.com/segmentio/ksuid"
|
||||
)
|
||||
|
||||
@@ -49,7 +48,7 @@ func (r *randStrPreprocessor) ProcessNReturnData(data []byte) ([]byte, map[strin
|
||||
continue
|
||||
}
|
||||
value := expression[1]
|
||||
if stringsutil.ContainsAny(value, "(", ")") {
|
||||
if strings.Contains(value, "(") || strings.Contains(value, ")") {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -1929,7 +1929,7 @@ func init() {
|
||||
Value: "Matched is the input which was matched upon",
|
||||
},
|
||||
}
|
||||
JAVASCRIPTRequestDoc.Fields = make([]encoder.Doc, 9)
|
||||
JAVASCRIPTRequestDoc.Fields = make([]encoder.Doc, 10)
|
||||
JAVASCRIPTRequestDoc.Fields[0].Name = "id"
|
||||
JAVASCRIPTRequestDoc.Fields[0].Type = "string"
|
||||
JAVASCRIPTRequestDoc.Fields[0].Note = ""
|
||||
@@ -1955,28 +1955,33 @@ func init() {
|
||||
JAVASCRIPTRequestDoc.Fields[4].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[4].Description = "Code contains code to execute for the javascript request."
|
||||
JAVASCRIPTRequestDoc.Fields[4].Comments[encoder.LineComment] = "Code contains code to execute for the javascript request."
|
||||
JAVASCRIPTRequestDoc.Fields[5].Name = "stop-at-first-match"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Type = "bool"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Name = "timeout"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Type = "int"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[5].Description = "StopAtFirstMatch stops processing the request at first match."
|
||||
JAVASCRIPTRequestDoc.Fields[5].Comments[encoder.LineComment] = "StopAtFirstMatch stops processing the request at first match."
|
||||
JAVASCRIPTRequestDoc.Fields[6].Name = "attack"
|
||||
JAVASCRIPTRequestDoc.Fields[6].Type = "generators.AttackTypeHolder"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Description = "Timeout in seconds is optional timeout for each javascript script execution (i.e init, pre-condition, code)"
|
||||
JAVASCRIPTRequestDoc.Fields[5].Comments[encoder.LineComment] = "Timeout in seconds is optional timeout for each javascript script execution (i.e init, pre-condition, code)"
|
||||
JAVASCRIPTRequestDoc.Fields[6].Name = "stop-at-first-match"
|
||||
JAVASCRIPTRequestDoc.Fields[6].Type = "bool"
|
||||
JAVASCRIPTRequestDoc.Fields[6].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[6].Description = "Attack is the type of payload combinations to perform.\n\nSniper is each payload once, pitchfork combines multiple payload sets and clusterbomb generates\npermutations and combinations for all payloads."
|
||||
JAVASCRIPTRequestDoc.Fields[6].Comments[encoder.LineComment] = "Attack is the type of payload combinations to perform."
|
||||
JAVASCRIPTRequestDoc.Fields[7].Name = "threads"
|
||||
JAVASCRIPTRequestDoc.Fields[7].Type = "int"
|
||||
JAVASCRIPTRequestDoc.Fields[6].Description = "StopAtFirstMatch stops processing the request at first match."
|
||||
JAVASCRIPTRequestDoc.Fields[6].Comments[encoder.LineComment] = "StopAtFirstMatch stops processing the request at first match."
|
||||
JAVASCRIPTRequestDoc.Fields[7].Name = "attack"
|
||||
JAVASCRIPTRequestDoc.Fields[7].Type = "generators.AttackTypeHolder"
|
||||
JAVASCRIPTRequestDoc.Fields[7].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[7].Description = "Payload concurreny i.e threads for sending requests."
|
||||
JAVASCRIPTRequestDoc.Fields[7].Comments[encoder.LineComment] = "Payload concurreny i.e threads for sending requests."
|
||||
|
||||
JAVASCRIPTRequestDoc.Fields[7].AddExample("Send requests using 10 concurrent threads", 10)
|
||||
JAVASCRIPTRequestDoc.Fields[8].Name = "payloads"
|
||||
JAVASCRIPTRequestDoc.Fields[8].Type = "map[string]interface{}"
|
||||
JAVASCRIPTRequestDoc.Fields[7].Description = "Attack is the type of payload combinations to perform.\n\nSniper is each payload once, pitchfork combines multiple payload sets and clusterbomb generates\npermutations and combinations for all payloads."
|
||||
JAVASCRIPTRequestDoc.Fields[7].Comments[encoder.LineComment] = "Attack is the type of payload combinations to perform."
|
||||
JAVASCRIPTRequestDoc.Fields[8].Name = "threads"
|
||||
JAVASCRIPTRequestDoc.Fields[8].Type = "int"
|
||||
JAVASCRIPTRequestDoc.Fields[8].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[8].Description = "Payloads contains any payloads for the current request.\n\nPayloads support both key-values combinations where a list\nof payloads is provided, or optionally a single file can also\nbe provided as payload which will be read on run-time."
|
||||
JAVASCRIPTRequestDoc.Fields[8].Comments[encoder.LineComment] = "Payloads contains any payloads for the current request."
|
||||
JAVASCRIPTRequestDoc.Fields[8].Description = "Payload concurreny i.e threads for sending requests."
|
||||
JAVASCRIPTRequestDoc.Fields[8].Comments[encoder.LineComment] = "Payload concurreny i.e threads for sending requests."
|
||||
|
||||
JAVASCRIPTRequestDoc.Fields[8].AddExample("Send requests using 10 concurrent threads", 10)
|
||||
JAVASCRIPTRequestDoc.Fields[9].Name = "payloads"
|
||||
JAVASCRIPTRequestDoc.Fields[9].Type = "map[string]interface{}"
|
||||
JAVASCRIPTRequestDoc.Fields[9].Note = ""
|
||||
JAVASCRIPTRequestDoc.Fields[9].Description = "Payloads contains any payloads for the current request.\n\nPayloads support both key-values combinations where a list\nof payloads is provided, or optionally a single file can also\nbe provided as payload which will be read on run-time."
|
||||
JAVASCRIPTRequestDoc.Fields[9].Comments[encoder.LineComment] = "Payloads contains any payloads for the current request."
|
||||
|
||||
HTTPSignatureTypeHolderDoc.Type = "http.SignatureTypeHolder"
|
||||
HTTPSignatureTypeHolderDoc.Comments[encoder.LineComment] = " SignatureTypeHolder is used to hold internal type of the signature"
|
||||
|
||||
@@ -69,18 +69,6 @@ func GetSupportedProtocolTypes() ProtocolTypes {
|
||||
return result
|
||||
}
|
||||
|
||||
// SupportedProtocolsStrings returns a slice of strings of supported protocols
|
||||
func SupportedProtocolsStrings() []string {
|
||||
var result []string
|
||||
for _, protocol := range GetSupportedProtocolTypes() {
|
||||
if protocol.String() == "" {
|
||||
continue
|
||||
}
|
||||
result = append(result, protocol.String())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func toProtocolType(valueToMap string) (ProtocolType, error) {
|
||||
normalizedValue := normalizeValue(valueToMap)
|
||||
for key, currentValue := range protocolMappings {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
"github.com/gobwas/ws"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/projectdiscovery/utils/conversion"
|
||||
)
|
||||
|
||||
// ExtraArgs
|
||||
@@ -71,26 +70,20 @@ func RunNucleiBareArgsAndGetResults(debug bool, env []string, extra ...string) (
|
||||
} else {
|
||||
cmd.Args = append(cmd.Args, "-silent")
|
||||
}
|
||||
output, err := cmd.Output()
|
||||
var data string
|
||||
if len(output) > 0 {
|
||||
data = strings.TrimSpace(conversion.String(output))
|
||||
}
|
||||
data, err := cmd.Output()
|
||||
if debug {
|
||||
fmt.Println(data)
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
if len(data) < 1 && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), string(data))
|
||||
}
|
||||
var parts []string
|
||||
items := strings.Split(data, "\n")
|
||||
items := strings.Split(string(data), "\n")
|
||||
for _, i := range items {
|
||||
if i != "" {
|
||||
parts = append(parts, i)
|
||||
}
|
||||
}
|
||||
|
||||
if (data == "" || len(parts) == 0) && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), data)
|
||||
}
|
||||
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
@@ -105,25 +98,20 @@ func RunNucleiWithArgsAndGetResults(debug bool, args ...string) ([]string, error
|
||||
} else {
|
||||
cmd.Args = append(cmd.Args, "-silent")
|
||||
}
|
||||
output, err := cmd.Output()
|
||||
var data string
|
||||
if len(output) > 0 {
|
||||
data = strings.TrimSpace(conversion.String(output))
|
||||
}
|
||||
data, err := cmd.Output()
|
||||
if debug {
|
||||
fmt.Println(data)
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
if len(data) < 1 && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), string(data))
|
||||
}
|
||||
var parts []string
|
||||
items := strings.Split(data, "\n")
|
||||
items := strings.Split(string(data), "\n")
|
||||
for _, i := range items {
|
||||
if i != "" {
|
||||
parts = append(parts, i)
|
||||
}
|
||||
}
|
||||
|
||||
if (data == "" || len(parts) == 0) && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), data)
|
||||
}
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
@@ -139,16 +127,12 @@ func RunNucleiArgsAndGetErrors(debug bool, env []string, extra ...string) ([]str
|
||||
cmd.Args = append(cmd.Args, "-allow-local-file-access")
|
||||
cmd.Args = append(cmd.Args, "-nc") // disable color
|
||||
cmd.Env = append(cmd.Env, ExtraEnvVars...)
|
||||
dataOutput, err := cmd.CombinedOutput()
|
||||
data, err := cmd.CombinedOutput()
|
||||
if debug {
|
||||
fmt.Println(string(dataOutput))
|
||||
}
|
||||
var data string
|
||||
if len(dataOutput) > 0 {
|
||||
data = strings.TrimSpace(conversion.String(dataOutput))
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
results := []string{}
|
||||
for _, v := range strings.Split(data, "\n") {
|
||||
for _, v := range strings.Split(string(data), "\n") {
|
||||
line := strings.TrimSpace(v)
|
||||
switch {
|
||||
case strings.HasPrefix(line, "[ERR]"):
|
||||
@@ -162,7 +146,7 @@ func RunNucleiArgsAndGetErrors(debug bool, env []string, extra ...string) ([]str
|
||||
return results, err
|
||||
}
|
||||
|
||||
// RunNucleiArgsWithEnvAndGetResults returns a list of results in nuclei output (ERR,WRN,FTL)
|
||||
// RunNucleiArgsWithEnvAndGetErrors returns a list of errors in nuclei output (ERR,WRN,FTL)
|
||||
func RunNucleiArgsWithEnvAndGetResults(debug bool, env []string, extra ...string) ([]string, error) {
|
||||
cmd := exec.Command("./nuclei")
|
||||
extra = append(extra, ExtraDebugArgs...)
|
||||
@@ -180,24 +164,20 @@ func RunNucleiArgsWithEnvAndGetResults(debug bool, env []string, extra ...string
|
||||
} else {
|
||||
cmd.Args = append(cmd.Args, "-silent")
|
||||
}
|
||||
dataOutput, err := cmd.Output()
|
||||
var data string
|
||||
if len(dataOutput) > 0 {
|
||||
data = strings.TrimSpace(conversion.String(dataOutput))
|
||||
}
|
||||
data, err := cmd.Output()
|
||||
if debug {
|
||||
fmt.Println(data)
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
if len(data) < 1 && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), string(data))
|
||||
}
|
||||
var parts []string
|
||||
items := strings.Split(data, "\n")
|
||||
items := strings.Split(string(data), "\n")
|
||||
for _, i := range items {
|
||||
if i != "" {
|
||||
parts = append(parts, i)
|
||||
}
|
||||
}
|
||||
if (data == "" || len(parts) == 0) && err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", err.Error(), data)
|
||||
}
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -76,6 +76,7 @@ var DefaultOptions = &types.Options{
|
||||
InteractionsPollDuration: 5,
|
||||
GitHubTemplateRepo: []string{},
|
||||
GitHubToken: "",
|
||||
ResponseReadTimeout: time.Second * 5,
|
||||
}
|
||||
|
||||
// TemplateInfo contains info for a mock executed template.
|
||||
@@ -89,17 +90,17 @@ type TemplateInfo struct {
|
||||
func NewMockExecuterOptions(options *types.Options, info *TemplateInfo) *protocols.ExecutorOptions {
|
||||
progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0)
|
||||
executerOpts := &protocols.ExecutorOptions{
|
||||
TemplateID: info.ID,
|
||||
TemplateInfo: info.Info,
|
||||
TemplatePath: info.Path,
|
||||
Output: NewMockOutputWriter(options.OmitTemplate),
|
||||
Options: options,
|
||||
Progress: progressImpl,
|
||||
ProjectFile: nil,
|
||||
IssuesClient: nil,
|
||||
Browser: nil,
|
||||
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
|
||||
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
|
||||
TemplateID: info.ID,
|
||||
TemplateInfo: info.Info,
|
||||
TemplatePath: info.Path,
|
||||
Output: NewMockOutputWriter(options.OmitTemplate),
|
||||
Options: options,
|
||||
Progress: progressImpl,
|
||||
ProjectFile: nil,
|
||||
IssuesClient: nil,
|
||||
Browser: nil,
|
||||
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
|
||||
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
|
||||
}
|
||||
executerOpts.CreateTemplateCtxStore()
|
||||
return executerOpts
|
||||
|
||||
@@ -146,7 +146,6 @@ func TestFlowWithConditionPositive(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFlowWithNoMatchers(t *testing.T) {
|
||||
setup()
|
||||
// when using conditional flow with no matchers at all
|
||||
// we implicitly assume that request was successful and internally changed the result to true (for scope of condition only)
|
||||
|
||||
|
||||
@@ -29,15 +29,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
|
||||
// execution logic for http()/dns() etc
|
||||
for index := range f.allProtocols[opts.protoName] {
|
||||
req := f.allProtocols[opts.protoName][index]
|
||||
// transform input if required
|
||||
inputItem := f.ctx.Input.Clone()
|
||||
if f.options.InputHelper != nil && f.ctx.Input.MetaInput.Input != "" {
|
||||
if inputItem.MetaInput.Input = f.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
|
||||
f.ctx.LogError(fmt.Errorf("failed to transform input for protocol %s", req.Type()))
|
||||
return false
|
||||
}
|
||||
}
|
||||
err := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), nil, f.protocolResultCallback(req, matcherStatus, opts))
|
||||
err := req.ExecuteWithResults(f.ctx.Input, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), nil, f.protocolResultCallback(req, matcherStatus, opts))
|
||||
if err != nil {
|
||||
// save all errors in a map with id as key
|
||||
// its less likely that there will be race condition but just in case
|
||||
@@ -66,15 +58,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
|
||||
}
|
||||
return matcherStatus.Load()
|
||||
}
|
||||
// transform input if required
|
||||
inputItem := f.ctx.Input.Clone()
|
||||
if f.options.InputHelper != nil && f.ctx.Input.MetaInput.Input != "" {
|
||||
if inputItem.MetaInput.Input = f.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
|
||||
f.ctx.LogError(fmt.Errorf("failed to transform input for protocol %s", req.Type()))
|
||||
return false
|
||||
}
|
||||
}
|
||||
err := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), nil, f.protocolResultCallback(req, matcherStatus, opts))
|
||||
err := req.ExecuteWithResults(f.ctx.Input, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), nil, f.protocolResultCallback(req, matcherStatus, opts))
|
||||
if err != nil {
|
||||
index := id
|
||||
err = f.allErrs.Set(opts.protoName+":"+index, err)
|
||||
@@ -88,7 +72,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
|
||||
|
||||
// protocolResultCallback returns a callback that is executed
|
||||
// after execution of each protocol request
|
||||
func (f *FlowExecutor) protocolResultCallback(req protocols.Request, matcherStatus *atomic.Bool, _ *ProtoOptions) func(result *output.InternalWrappedEvent) {
|
||||
func (f *FlowExecutor) protocolResultCallback(req protocols.Request, matcherStatus *atomic.Bool, opts *ProtoOptions) func(result *output.InternalWrappedEvent) {
|
||||
return func(result *output.InternalWrappedEvent) {
|
||||
if result != nil {
|
||||
// Note: flow specific implicit behaviours should be handled here
|
||||
|
||||
@@ -109,19 +109,14 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
|
||||
return ctx.Context().Err()
|
||||
default:
|
||||
}
|
||||
inputItem := ctx.Input.Clone()
|
||||
if m.options.InputHelper != nil && ctx.Input.MetaInput.Input != "" {
|
||||
if inputItem.MetaInput.Input = m.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// FIXME: this hack of using hash to get templateCtx has known issues scan context based approach should be adopted ASAP
|
||||
values := m.options.GetTemplateCtx(inputItem.MetaInput).GetAll()
|
||||
err := req.ExecuteWithResults(inputItem, output.InternalEvent(values), nil, multiProtoCallback)
|
||||
|
||||
values := m.options.GetTemplateCtx(ctx.Input.MetaInput).GetAll()
|
||||
err := req.ExecuteWithResults(ctx.Input, output.InternalEvent(values), nil, multiProtoCallback)
|
||||
// in case of fatal error skip execution of next protocols
|
||||
if err != nil {
|
||||
// always log errors
|
||||
ctx.LogError(err)
|
||||
|
||||
// for some classes of protocols (i.e ssl) errors like tls handshake are a legitimate behavior so we don't stop execution
|
||||
// connection failures are already tracked by the internal host error cache
|
||||
// we use strings comparison as the error is not formalized into instance within the standard library
|
||||
@@ -129,6 +124,7 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
|
||||
if req.Type() == types.SSLProtocol && stringsutil.ContainsAnyI(err.Error(), "protocol version not supported", "could not do tls handshake") {
|
||||
continue
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ package multiproto_test
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/loader/workflow"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/progress"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
@@ -38,7 +36,6 @@ func setup() {
|
||||
Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory),
|
||||
RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second),
|
||||
Parser: templates.NewParser(),
|
||||
InputHelper: input.NewHelper(),
|
||||
}
|
||||
workflowLoader, err := workflow.NewLoader(&executerOpts)
|
||||
if err != nil {
|
||||
@@ -48,6 +45,7 @@ func setup() {
|
||||
}
|
||||
|
||||
func TestMultiProtoWithDynamicExtractor(t *testing.T) {
|
||||
setup()
|
||||
Template, err := templates.Parse("testcases/multiprotodynamic.yaml", nil, executerOpts)
|
||||
require.Nil(t, err, "could not parse template")
|
||||
|
||||
@@ -64,6 +62,7 @@ func TestMultiProtoWithDynamicExtractor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMultiProtoWithProtoPrefix(t *testing.T) {
|
||||
setup()
|
||||
Template, err := templates.Parse("testcases/multiprotowithprefix.yaml", nil, executerOpts)
|
||||
require.Nil(t, err, "could not parse template")
|
||||
|
||||
@@ -78,8 +77,3 @@ func TestMultiProtoWithProtoPrefix(t *testing.T) {
|
||||
require.Nil(t, err, "could not execute template")
|
||||
require.True(t, gotresults)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
setup()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
+6
-74
@@ -278,6 +278,8 @@ type Options struct {
|
||||
SNI string
|
||||
// InputFileMode specifies the mode of input file (jsonl, burp, openapi, swagger, etc)
|
||||
InputFileMode string
|
||||
// DialerTimeout sets the timeout for network requests.
|
||||
DialerTimeout time.Duration
|
||||
// DialerKeepAlive sets the keep alive duration for network requests.
|
||||
DialerKeepAlive time.Duration
|
||||
// Interface to use for network scan
|
||||
@@ -290,6 +292,8 @@ type Options struct {
|
||||
ResponseReadSize int
|
||||
// ResponseSaveSize is the maximum size of response to save
|
||||
ResponseSaveSize int
|
||||
// ResponseReadTimeout is response read timeout in seconds
|
||||
ResponseReadTimeout time.Duration
|
||||
// Health Check
|
||||
HealthCheck bool
|
||||
// Time to wait between each input read operation before closing the stream
|
||||
@@ -402,79 +406,6 @@ type Options struct {
|
||||
HttpApiEndpoint string
|
||||
// ListTemplateProfiles lists all available template profiles
|
||||
ListTemplateProfiles bool
|
||||
// timeouts contains various types of timeouts used in nuclei
|
||||
// these timeouts are derived from dial-timeout (-timeout) with known multipliers
|
||||
// This is internally managed and does not need to be set by user by explicitly setting
|
||||
// this overrides the default/derived one
|
||||
timeouts *Timeouts
|
||||
}
|
||||
|
||||
// SetTimeouts sets the timeout variants to use for the executor
|
||||
func (opts *Options) SetTimeouts(t *Timeouts) {
|
||||
opts.timeouts = t
|
||||
}
|
||||
|
||||
// GetTimeouts returns the timeout variants to use for the executor
|
||||
func (eo *Options) GetTimeouts() *Timeouts {
|
||||
if eo.timeouts != nil {
|
||||
// redundant but apply to avoid any potential issues
|
||||
eo.timeouts.ApplyDefaults()
|
||||
return eo.timeouts
|
||||
}
|
||||
// set timeout variant value
|
||||
eo.timeouts = NewTimeoutVariant(eo.Timeout)
|
||||
eo.timeouts.ApplyDefaults()
|
||||
return eo.timeouts
|
||||
}
|
||||
|
||||
// Timeouts is a struct that contains all the timeout variants for nuclei
|
||||
// dialer timeout is used to derive other timeouts
|
||||
type Timeouts struct {
|
||||
// DialTimeout for fastdialer (default 10s)
|
||||
DialTimeout time.Duration
|
||||
// Tcp(Network Protocol) Read From Connection Timeout (default 5s)
|
||||
TcpReadTimeout time.Duration
|
||||
// Http Response Header Timeout (default 10s)
|
||||
// this timeout prevents infinite hangs started by server if any
|
||||
// this is temporarily overridden when using @timeout request annotation
|
||||
HttpResponseHeaderTimeout time.Duration
|
||||
// HttpTimeout for http client (default -> 3 x dial-timeout = 30s)
|
||||
HttpTimeout time.Duration
|
||||
// JsCompilerExec timeout/deadline (default -> 2 x dial-timeout = 20s)
|
||||
JsCompilerExecutionTimeout time.Duration
|
||||
// CodeExecutionTimeout for code execution (default -> 3 x dial-timeout = 30s)
|
||||
CodeExecutionTimeout time.Duration
|
||||
}
|
||||
|
||||
// NewTimeoutVariant creates a new timeout variant with the given dial timeout in seconds
|
||||
func NewTimeoutVariant(dialTimeoutSec int) *Timeouts {
|
||||
tv := &Timeouts{
|
||||
DialTimeout: time.Duration(dialTimeoutSec) * time.Second,
|
||||
}
|
||||
tv.ApplyDefaults()
|
||||
return tv
|
||||
}
|
||||
|
||||
// ApplyDefaults applies default values to timeout variants when missing
|
||||
func (tv *Timeouts) ApplyDefaults() {
|
||||
if tv.DialTimeout == 0 {
|
||||
tv.DialTimeout = 10 * time.Second
|
||||
}
|
||||
if tv.TcpReadTimeout == 0 {
|
||||
tv.TcpReadTimeout = 5 * time.Second
|
||||
}
|
||||
if tv.HttpResponseHeaderTimeout == 0 {
|
||||
tv.HttpResponseHeaderTimeout = 10 * time.Second
|
||||
}
|
||||
if tv.HttpTimeout == 0 {
|
||||
tv.HttpTimeout = 3 * tv.DialTimeout
|
||||
}
|
||||
if tv.JsCompilerExecutionTimeout == 0 {
|
||||
tv.JsCompilerExecutionTimeout = 2 * tv.DialTimeout
|
||||
}
|
||||
if tv.CodeExecutionTimeout == 0 {
|
||||
tv.CodeExecutionTimeout = 3 * tv.DialTimeout
|
||||
}
|
||||
}
|
||||
|
||||
// ShouldLoadResume resume file
|
||||
@@ -513,6 +444,7 @@ func DefaultOptions() *Options {
|
||||
MaxHostError: 30,
|
||||
ResponseReadSize: 10 * unitutils.Mega,
|
||||
ResponseSaveSize: unitutils.Mega,
|
||||
ResponseReadTimeout: 5 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,7 +524,7 @@ func (o *Options) GetValidAbsPath(helperFilePath, templatePath string) (string,
|
||||
return "", errorutil.New("access to helper file %v denied", helperFilePath)
|
||||
}
|
||||
|
||||
// isHomeDir checks if given is home directory
|
||||
// isRootDir checks if given is root directory
|
||||
func isHomeDir(path string) bool {
|
||||
homeDir := folderutil.HomeDirOrDefault("")
|
||||
return strings.HasPrefix(path, homeDir)
|
||||
|
||||
@@ -54,11 +54,6 @@ func (s *Agent) Start(interval time.Duration) context.CancelFunc {
|
||||
ticker := time.NewTicker(interval)
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
gologger.Error().Msgf("Recovered in Start: %v", r)
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -75,12 +70,6 @@ func (s *Agent) Start(interval time.Duration) context.CancelFunc {
|
||||
|
||||
// monitorWorker is a worker for monitoring running goroutines
|
||||
func (s *Agent) monitorWorker(cancel context.CancelFunc) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
gologger.Error().Msgf("Recovered in monitorWorker: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
current := runtime.NumGoroutine()
|
||||
if current != s.goroutineCount {
|
||||
s.goroutineCount = current
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ func IsURL(input string) bool {
|
||||
return err == nil && u.Scheme != "" && u.Host != ""
|
||||
}
|
||||
|
||||
// ReaderFromPathOrURL reads and returns the contents of a file or url.
|
||||
// ReadFromPathOrURL reads and returns the contents of a file or url.
|
||||
func ReaderFromPathOrURL(templatePath string, catalog catalog.Catalog) (io.ReadCloser, error) {
|
||||
if IsURL(templatePath) {
|
||||
resp, err := retryablehttp.DefaultClient().Get(templatePath)
|
||||
|
||||
Reference in new issue
Block a user