mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-08 10:10:18 -10:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4626b56dd0 | ||
|
|
d946a7890a | ||
|
|
e941b685e0 | ||
|
|
55639e32c8 |
No files matched your search
@@ -1,7 +1,6 @@
|
||||
addReviewers: true
|
||||
reviewers:
|
||||
- dogancanbakir
|
||||
- dwisiswant0
|
||||
|
||||
numberOfReviewers: 1
|
||||
skipKeywords:
|
||||
|
||||
+1
-9
@@ -39,12 +39,4 @@ dist
|
||||
pkg/protocols/common/helpers/deserialization/testdata/Deserialize.class
|
||||
pkg/protocols/common/helpers/deserialization/testdata/ValueObject.class
|
||||
pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
|
||||
vendor
|
||||
|
||||
# Headless `screenshot` action
|
||||
*.png
|
||||
|
||||
# Profiling & tracing
|
||||
*.prof
|
||||
*.pprof
|
||||
*.trace
|
||||
vendor
|
||||
@@ -457,49 +457,26 @@ func (template *Template) compileProtocolRequests(options protocols.ExecuterOpti
|
||||
That's it, you've added a new protocol to Nuclei. The next good step would be to write integration tests which are described in `integration-tests` and `cmd/integration-tests` directories.
|
||||
|
||||
|
||||
## Profiling and Tracing
|
||||
## Profiling Instructions
|
||||
|
||||
To analyze Nuclei's performance and resource usage, you can generate memory profiles and trace files using the `-profile-mem` flag:
|
||||
To enable dumping of Memory profiling data, `-profile-mem` flag can be used along with path to a file. This writes a pprof formatted file which can be used for investigate resource usage with `pprof` tool.
|
||||
|
||||
```bash
|
||||
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
|
||||
```console
|
||||
$ nuclei -t nuclei-templates/ -u https://example.com -profile-mem mem.pprof
|
||||
```
|
||||
|
||||
This command creates two files:
|
||||
To view profile data in pprof, first install pprof. Then run the below command -
|
||||
|
||||
* `nuclei.prof`: Memory (heap) profile
|
||||
* `nuclei.trace`: Execution trace
|
||||
|
||||
### Analyzing the Memory Profile
|
||||
|
||||
1. View the profile in the terminal:
|
||||
|
||||
```bash
|
||||
go tool pprof nuclei.prof
|
||||
```console
|
||||
$ go tool pprof mem.pprof
|
||||
```
|
||||
|
||||
2. Display top memory consumers:
|
||||
To open a web UI on a port to visualize debug data, the below command can be used.
|
||||
|
||||
```bash
|
||||
go tool pprof -top nuclei.prof | grep "$(go list -m)" | head -10
|
||||
```console
|
||||
$ go tool pprof -http=:8081 mem.pprof
|
||||
```
|
||||
|
||||
3. Visualize the profile in a web browser:
|
||||
|
||||
```bash
|
||||
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.prof
|
||||
```
|
||||
|
||||
### Analyzing the Trace File
|
||||
|
||||
To examine the execution trace:
|
||||
|
||||
```bash
|
||||
go tool trace nuclei.trace
|
||||
```
|
||||
|
||||
These tools help identify performance bottlenecks and memory leaks, allowing for targeted optimizations of Nuclei's codebase.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- [pkg/reporting](./pkg/reporting) - Reporting modules for nuclei.
|
||||
|
||||
@@ -3,6 +3,7 @@ FROM golang:1.21-alpine AS build-env
|
||||
RUN apk add build-base
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
RUN go mod download
|
||||
RUN go build ./cmd/nuclei
|
||||
|
||||
|
||||
+2
-34
@@ -3664,18 +3664,8 @@ Enum Values:
|
||||
|
||||
- <code>files</code>
|
||||
|
||||
- <code>waitdom</code>
|
||||
|
||||
- <code>waitfcp</code>
|
||||
|
||||
- <code>waitfmp</code>
|
||||
|
||||
- <code>waitidle</code>
|
||||
|
||||
- <code>waitload</code>
|
||||
|
||||
- <code>waitstable</code>
|
||||
|
||||
- <code>getresource</code>
|
||||
|
||||
- <code>extract</code>
|
||||
@@ -3764,33 +3754,11 @@ Appears in:
|
||||
Part Definitions:
|
||||
|
||||
|
||||
- <code>template-id</code> - ID of the template executed
|
||||
- <code>template-info</code> - Info Block of the template executed
|
||||
- <code>template-path</code> - Path of the template executed
|
||||
- <code>host</code> - Host is the input to the template
|
||||
- <code>port</code> - Port is the port of the host
|
||||
- <code>matched</code> - Matched is the input which was matched upon
|
||||
- <code>type</code> - Type is the type of request made
|
||||
- <code>timestamp</code> - Timestamp is the time when the request was made
|
||||
- <code>response</code> - JSON SSL protocol handshake details
|
||||
- <code>cipher</code> - Cipher is the encryption algorithm used
|
||||
- <code>domains</code> - Domains are the list of domain names in the certificate
|
||||
- <code>fingerprint_hash</code> - Fingerprint hash is the unique identifier of the certificate
|
||||
- <code>ip</code> - IP is the IP address of the server
|
||||
- <code>issuer_cn</code> - Issuer CN is the common name of the certificate issuer
|
||||
- <code>issuer_dn</code> - Issuer DN is the distinguished name of the certificate issuer
|
||||
- <code>issuer_org</code> - Issuer organization is the organization of the certificate issuer
|
||||
- <code>not_after</code> - Timestamp after which the remote cert expires
|
||||
- <code>not_before</code> - Timestamp before which the certificate is not valid
|
||||
- <code>probe_status</code> - Probe status indicates if the probe was successful
|
||||
- <code>serial</code> - Serial is the serial number of the certificate
|
||||
- <code>sni</code> - SNI is the server name indication used in the handshake
|
||||
- <code>subject_an</code> - Subject AN is the list of subject alternative names
|
||||
- <code>subject_cn</code> - Subject CN is the common name of the certificate subject
|
||||
- <code>subject_dn</code> - Subject DN is the distinguished name of the certificate subject
|
||||
- <code>subject_org</code> - Subject organization is the organization of the certificate subject
|
||||
- <code>tls_connection</code> - TLS connection is the type of TLS connection used
|
||||
- <code>tls_version</code> - TLS version is the version of the TLS protocol used
|
||||
- <code>host</code> - Host is the input to the template
|
||||
- <code>matched</code> - Matched is the input which was matched upon
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
@@ -27,9 +26,9 @@ func (h *httpNoAccess) Execute(filePath string) error {
|
||||
}
|
||||
event := &output.ResultEvent{}
|
||||
_ = json.Unmarshal([]byte(results[0]), event)
|
||||
expectedError := "no address found for host"
|
||||
if !strings.Contains(event.Error, expectedError) {
|
||||
return fmt.Errorf("unexpected result: expecting \"%s\" error but got \"%s\"", expectedError, event.Error)
|
||||
|
||||
if event.Error != "no address found for host" {
|
||||
return fmt.Errorf("unexpected result: expecting \"no address found for host\" error but got none")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||
sliceutil "github.com/projectdiscovery/utils/slice"
|
||||
)
|
||||
|
||||
var workflowTestcases = []TestCaseInfo{
|
||||
@@ -26,7 +25,6 @@ var workflowTestcases = []TestCaseInfo{
|
||||
{Path: "workflow/dns-value-share-workflow.yaml", TestCase: &workflowDnsKeyValueShare{}},
|
||||
{Path: "workflow/code-value-share-workflow.yaml", TestCase: &workflowCodeKeyValueShare{}, DisableOn: isCodeDisabled}, // isCodeDisabled declared in code.go
|
||||
{Path: "workflow/multiprotocol-value-share-workflow.yaml", TestCase: &workflowMultiProtocolKeyValueShare{}},
|
||||
{Path: "workflow/multimatch-value-share-workflow.yaml", TestCase: &workflowMultiMatchKeyValueShare{}},
|
||||
{Path: "workflow/shared-cookie.yaml", TestCase: &workflowSharedCookies{}},
|
||||
}
|
||||
|
||||
@@ -231,44 +229,6 @@ func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error {
|
||||
return expectResultsCount(results, 2)
|
||||
}
|
||||
|
||||
type workflowMultiMatchKeyValueShare struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
func (h *workflowMultiMatchKeyValueShare) Execute(filePath string) error {
|
||||
var receivedData []string
|
||||
router := httprouter.New()
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "This is test matcher text")
|
||||
})
|
||||
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
fmt.Fprintf(w, "href=\"test-value-%s\"", r.URL.Query().Get("v"))
|
||||
})
|
||||
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
receivedData = append(receivedData, string(body))
|
||||
fmt.Fprintf(w, "test-value")
|
||||
})
|
||||
ts := httptest.NewServer(router)
|
||||
defer ts.Close()
|
||||
|
||||
results, err := testutils.RunNucleiWorkflowAndGetResults(filePath, ts.URL, debug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we received the data from both request to /path1 and it is not overwritten by the later one.
|
||||
// They will appear in brackets because of another bug: https://github.com/orgs/projectdiscovery/discussions/3766
|
||||
if !sliceutil.Contains(receivedData, "[test-value-1]") || !sliceutil.Contains(receivedData, "[test-value-2]") {
|
||||
return fmt.Errorf(
|
||||
"incorrect data: did not receive both extracted data from the first request!\nReceived Data:\n\t%s\nResults:\n\t%s",
|
||||
strings.Join(receivedData, "\n\t"),
|
||||
strings.Join(results, "\n\t"),
|
||||
)
|
||||
}
|
||||
// The number of expected results is 3: the workflow's Matcher Name based condition check forwards both match, and the other branch with simple subtemplates goes with one
|
||||
return expectResultsCount(results, 3)
|
||||
}
|
||||
|
||||
type workflowSharedCookies struct{}
|
||||
|
||||
// Execute executes a test case and returns an error if occurred
|
||||
|
||||
@@ -142,34 +142,4 @@
|
||||
# # Username for the elasticsearch instance
|
||||
# username: test
|
||||
# # Password is the password for elasticsearch instance
|
||||
# password: test
|
||||
#linear:
|
||||
# # api-key is the API key for the linear account
|
||||
# api-key: ""
|
||||
# # allow-list sets a tracker level filter to only create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: critical
|
||||
# # deny-list sets a tracker level filter to never create issues for templates with
|
||||
# # these severity labels or tags (does not affect exporters. set those globally)
|
||||
# deny-list:
|
||||
# severity: low
|
||||
# # team-id is the ID of the team in Linear
|
||||
# team-id: ""
|
||||
# # project-id is the ID of the project in Linear
|
||||
# project-id: ""
|
||||
# # duplicate-issue-check flag to enable duplicate tracking issue check
|
||||
# duplicate-issue-check: false
|
||||
# # open-state-id is the ID of the open state in Linear
|
||||
# open-state-id: ""
|
||||
#mongodb:
|
||||
# # the connection string to the MongoDB database
|
||||
# # (e.g., mongodb://root:example@localhost:27017/nuclei?ssl=false&authSource=admin)
|
||||
# connection-string: ""
|
||||
# # the name of the collection to store the issues
|
||||
# collection-name: ""
|
||||
# # excludes the Request and Response from the results (helps with filesize)
|
||||
# omit-raw: false
|
||||
# # determines the number of results to be kept in memory before writing it to the database or 0 to
|
||||
# # persist all in memory and write all results at the end (default)
|
||||
# batch-size: 0
|
||||
# password: test
|
||||
+11
-41
@@ -9,7 +9,6 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -104,52 +103,26 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Profiling & tracing related code
|
||||
// Profiling related code
|
||||
if memProfile != "" {
|
||||
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".prof"
|
||||
memProfileFile, err := os.Create(memProfile)
|
||||
f, err := os.Create(memProfile)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q file: %v", memProfile, err)
|
||||
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
|
||||
}
|
||||
|
||||
traceFilepath := strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".trace"
|
||||
traceFile, err := os.Create(traceFilepath)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not create trace %q file: %v", traceFilepath, err)
|
||||
}
|
||||
|
||||
oldMemProfileRate := runtime.MemProfileRate
|
||||
old := runtime.MemProfileRate
|
||||
runtime.MemProfileRate = 4096
|
||||
|
||||
// Start tracing
|
||||
if err := trace.Start(traceFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
|
||||
}
|
||||
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
|
||||
|
||||
defer func() {
|
||||
// Start CPU profiling
|
||||
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
|
||||
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
|
||||
}
|
||||
memProfileFile.Close()
|
||||
traceFile.Close()
|
||||
trace.Stop()
|
||||
runtime.MemProfileRate = oldMemProfileRate
|
||||
|
||||
gologger.Info().Msgf("Memory profile saved at %q", memProfile)
|
||||
gologger.Info().Msgf("Traced at %q", traceFilepath)
|
||||
_ = pprof.Lookup("heap").WriteTo(f, 0)
|
||||
f.Close()
|
||||
runtime.MemProfileRate = old
|
||||
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
|
||||
}()
|
||||
}
|
||||
|
||||
runner.ParseOptions(options)
|
||||
|
||||
if options.ScanUploadFile != "" {
|
||||
if err := runner.UploadResultsToCloud(options); err != nil {
|
||||
gologger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
nucleiRunner, err := runner.New(options)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
|
||||
@@ -316,7 +289,6 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.RuntimeMapVarP(&options.Vars, "var", "V", nil, "custom vars in key=value format"),
|
||||
flagSet.StringVarP(&options.ResolversFile, "resolvers", "r", "", "file containing resolver list for nuclei"),
|
||||
flagSet.BoolVarP(&options.SystemResolvers, "system-resolvers", "sr", false, "use system DNS resolving as error fallback"),
|
||||
flagSet.BoolVarP(&options.DisableDefaultResolvers, "disable-default-resolvers", "dfr", false, "disable default resolvers"),
|
||||
flagSet.BoolVarP(&options.DisableClustering, "disable-clustering", "dc", false, "disable clustering of requests"),
|
||||
flagSet.BoolVar(&options.OfflineHTTP, "passive", false, "enable passive HTTP response processing mode"),
|
||||
flagSet.BoolVarP(&options.ForceAttemptHTTP2, "force-http2", "fh2", false, "force http2 connection on requests"),
|
||||
@@ -423,7 +395,7 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CallbackVar(printVersion, "version", "show nuclei version"),
|
||||
flagSet.BoolVarP(&options.HangMonitor, "hang-monitor", "hm", false, "enable nuclei hang monitoring"),
|
||||
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "generate memory (heap) profile & trace files"),
|
||||
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
|
||||
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
|
||||
flagSet.BoolVarP(&options.ShowVarDump, "show-var-dump", "svd", false, "show variables dump for debugging"),
|
||||
flagSet.BoolVarP(&options.EnablePprof, "enable-pprof", "ep", false, "enable pprof debugging server"),
|
||||
@@ -448,11 +420,9 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||
flagSet.CreateGroup("cloud", "Cloud",
|
||||
flagSet.DynamicVar(&pdcpauth, "auth", "true", "configure projectdiscovery cloud (pdcp) api key"),
|
||||
flagSet.StringVarP(&options.TeamID, "team-id", "tid", _pdcp.TeamIDEnv, "upload scan results to given team id (optional)"),
|
||||
flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard [DEPRECATED use -dashboard]"),
|
||||
flagSet.BoolVarP(&options.EnableCloudUpload, "cloud-upload", "cup", false, "upload scan results to pdcp dashboard"),
|
||||
flagSet.StringVarP(&options.ScanID, "scan-id", "sid", "", "upload scan results to existing scan id (optional)"),
|
||||
flagSet.StringVarP(&options.ScanName, "scan-name", "sname", "", "scan name to set (optional)"),
|
||||
flagSet.BoolVarP(&options.EnableCloudUpload, "dashboard", "pd", false, "upload / view nuclei results in projectdiscovery cloud (pdcp) UI dashboard"),
|
||||
flagSet.StringVarP(&options.ScanUploadFile, "dashboard-upload", "pdu", "", "upload / view nuclei results file (jsonl) in projectdiscovery cloud (pdcp) UI dashboard"),
|
||||
)
|
||||
|
||||
flagSet.CreateGroup("Authentication", "Authentication",
|
||||
|
||||
+4
-4
@@ -21,9 +21,9 @@ WORKFLOW="Build Test"
|
||||
GREP_ERROR_PATTERN='Test "http/interactsh.yaml" failed'
|
||||
|
||||
#Set fonts for Help.
|
||||
NORM=$(tput sgr0)
|
||||
BOLD=$(tput bold)
|
||||
REV=$(tput smso)
|
||||
NORM=`tput sgr0`
|
||||
BOLD=`tput bold`
|
||||
REV=`tput smso`
|
||||
|
||||
HELP()
|
||||
{
|
||||
@@ -73,7 +73,7 @@ function print_bold() {
|
||||
function retry_failed_jobs() {
|
||||
print_bold "Checking failed workflows for branch $BRANCH before $BEFORE"
|
||||
|
||||
date=$(date +%Y-%m-%d'T'%H:%M'Z' -d "$BEFORE")
|
||||
date=`date +%Y-%m-%d'T'%H:%M'Z' -d "$BEFORE"`
|
||||
|
||||
workflowIds=$(gh run list --limit "$LIMIT" --json headBranch,status,name,conclusion,databaseId,updatedAt | jq -c '.[] |
|
||||
select ( .headBranch==$branch ) |
|
||||
|
||||
@@ -19,13 +19,13 @@ require (
|
||||
github.com/miekg/dns v1.1.59
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/projectdiscovery/clistats v0.1.1
|
||||
github.com/projectdiscovery/fastdialer v0.2.9
|
||||
github.com/projectdiscovery/hmap v0.0.59
|
||||
github.com/projectdiscovery/clistats v0.1.0
|
||||
github.com/projectdiscovery/fastdialer v0.2.7
|
||||
github.com/projectdiscovery/hmap v0.0.56
|
||||
github.com/projectdiscovery/interactsh v1.2.0
|
||||
github.com/projectdiscovery/rawhttp v0.1.67
|
||||
github.com/projectdiscovery/retryabledns v1.0.77
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78
|
||||
github.com/projectdiscovery/rawhttp v0.1.61
|
||||
github.com/projectdiscovery/retryabledns v1.0.73
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.76
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.4
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/rs/xid v1.5.0
|
||||
@@ -38,9 +38,9 @@ require (
|
||||
github.com/weppos/publicsuffix-go v0.30.2
|
||||
github.com/xanzy/go-gitlab v0.107.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/oauth2 v0.22.0
|
||||
golang.org/x/text v0.18.0
|
||||
golang.org/x/text v0.16.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@@ -59,7 +59,7 @@ require (
|
||||
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.8.0
|
||||
github.com/charmbracelet/glamour v0.6.0
|
||||
github.com/clbanning/mxj/v2 v2.7.0
|
||||
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c
|
||||
github.com/docker/go-units v0.5.0
|
||||
@@ -72,7 +72,7 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/h2non/filetype v1.1.3
|
||||
github.com/invopop/yaml v0.3.1
|
||||
github.com/kitabisa/go-ci v1.0.3
|
||||
github.com/kitabisa/go-ci v1.0.2
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa
|
||||
github.com/lib/pq v1.10.9
|
||||
@@ -85,28 +85,27 @@ require (
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
||||
github.com/projectdiscovery/goflags v0.1.64
|
||||
github.com/projectdiscovery/gologger v1.1.24
|
||||
github.com/projectdiscovery/gologger v1.1.21
|
||||
github.com/projectdiscovery/gostruct v0.0.2
|
||||
github.com/projectdiscovery/gozero v0.0.2
|
||||
github.com/projectdiscovery/httpx v1.6.8
|
||||
github.com/projectdiscovery/mapcidr v1.1.34
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/ratelimit v0.0.56
|
||||
github.com/projectdiscovery/ratelimit v0.0.53
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.1.7
|
||||
github.com/projectdiscovery/uncover v1.0.9
|
||||
github.com/projectdiscovery/useragent v0.0.71
|
||||
github.com/projectdiscovery/utils v0.2.11
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18
|
||||
github.com/projectdiscovery/useragent v0.0.65
|
||||
github.com/projectdiscovery/utils v0.2.7
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14
|
||||
github.com/redis/go-redis/v9 v9.1.0
|
||||
github.com/seh-msft/burpxml v1.0.1
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9
|
||||
github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706
|
||||
go.mongodb.org/mongo-driver v1.17.0
|
||||
golang.org/x/term v0.24.0
|
||||
golang.org/x/term v0.21.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
moul.io/http2curl v1.0.0
|
||||
)
|
||||
@@ -121,7 +120,6 @@ require (
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27 // indirect
|
||||
@@ -136,8 +134,6 @@ require (
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.13.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.3.2 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/cloudflare/cfssl v1.6.4 // indirect
|
||||
@@ -146,7 +142,7 @@ require (
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||
github.com/docker/cli v24.0.5+incompatible // indirect
|
||||
github.com/docker/docker v24.0.9+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
@@ -196,12 +192,11 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
|
||||
github.com/muesli/termenv v0.15.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.14 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
@@ -209,7 +204,7 @@ require (
|
||||
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/freeport v0.0.6 // 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
|
||||
@@ -230,22 +225,18 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/ysmood/fetchup v0.2.3 // indirect
|
||||
github.com/ysmood/got v0.34.1 // indirect
|
||||
github.com/yuin/goldmark v1.7.4 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.3 // indirect
|
||||
github.com/yuin/goldmark v1.5.4 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.1 // indirect
|
||||
github.com/zcalusic/sysinfo v1.0.2 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/goleak v1.3.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
|
||||
mellium.im/sasl v0.3.1 // indirect
|
||||
)
|
||||
@@ -287,16 +278,16 @@ require (
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mholt/acmez v1.2.0 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/projectdiscovery/blackrock v0.0.1 // indirect
|
||||
github.com/projectdiscovery/networkpolicy v0.0.9
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rivo/uniseg v0.4.6 // indirect
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
@@ -312,10 +303,10 @@ require (
|
||||
go.etcd.io/bbolt v1.3.10 // indirect
|
||||
go.uber.org/zap v1.25.0 // indirect
|
||||
goftp.io/server/v2 v2.0.1 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
|
||||
@@ -93,15 +93,9 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/akrylysov/pogreb v0.10.2 h1:e6PxmeyEhWyi2AKOBIJzAEi4HkiC+lKyCocRGlnDi78=
|
||||
github.com/akrylysov/pogreb v0.10.2/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -180,10 +174,9 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY=
|
||||
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
|
||||
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
@@ -224,14 +217,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs=
|
||||
github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
|
||||
github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY=
|
||||
github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
|
||||
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
@@ -284,8 +271,8 @@ github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c/go.mod h1:
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/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/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=
|
||||
@@ -521,6 +508,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
@@ -571,8 +559,6 @@ github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf h1:umfGUaWdFP2s6
|
||||
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf/go.mod h1:V99KdStnMHZsvVOwIvhfcUzYgYkRZeQWUtumtL+SKxA=
|
||||
github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A=
|
||||
github.com/hdm/jarm-go v0.0.7/go.mod h1:kinGoS0+Sdn1Rr54OtanET5E5n7AlD6T6CrJAKDjJSQ=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -639,8 +625,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kitabisa/go-ci v1.0.3 h1:JmIUIvcercRQc/9x/v02ydCCqU4MadSHaNaOF8T2pGA=
|
||||
github.com/kitabisa/go-ci v1.0.3/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U=
|
||||
github.com/kitabisa/go-ci v1.0.2 h1:rqHf8KEbQOxVb998TbqGRo70Z7ol44io7/jLYJUvKp8=
|
||||
github.com/kitabisa/go-ci v1.0.2/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
@@ -709,8 +695,9 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -721,8 +708,9 @@ github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1w
|
||||
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
|
||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
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=
|
||||
@@ -755,14 +743,13 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
|
||||
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
|
||||
github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
|
||||
github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs=
|
||||
github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
@@ -794,8 +781,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w=
|
||||
github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA=
|
||||
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
|
||||
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
@@ -843,28 +830,28 @@ github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k
|
||||
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/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE=
|
||||
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
|
||||
github.com/projectdiscovery/clistats v0.1.0 h1:b+LF1w0xhNd7cneKWMXb+/yUmF1n5szawxP4XGpmbxs=
|
||||
github.com/projectdiscovery/clistats v0.1.0/go.mod h1:GJ2av0KnOvK0AISQnP8hyDclYIji1LVkx2l0pwnzAu4=
|
||||
github.com/projectdiscovery/dsl v0.2.1 h1:TK3KD4jsg4YbvY7WJqnz1QyH4AOvAwezeBFOX97Evgk=
|
||||
github.com/projectdiscovery/dsl v0.2.1/go.mod h1:IRQXsmi5/g1dDZ79//A9t2vrRtxm4frRSd5t8CZVSbI=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9 h1:vDCqxVMCyUu3oVEizEK1K8K+CCcLkVDW3X2HfiWaVFA=
|
||||
github.com/projectdiscovery/fastdialer v0.2.9/go.mod h1:mYv5QaNBDDSHlZO9DI0niRMw+G5hUzwIhs8QixSElUI=
|
||||
github.com/projectdiscovery/fastdialer v0.2.7 h1:x7bEf/kDyVOuG9kHfJLMhWO3h7J+6fMDgLWkGYL8EFg=
|
||||
github.com/projectdiscovery/fastdialer v0.2.7/go.mod h1:7/BGdaw7sCekuBh6lLZqPuoO5N0Qaizwvex/PjO+V8o=
|
||||
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.6 h1:ROqzuXN8JPqkGdBueb3ah691nS2g2p7r3/3x2E33GbI=
|
||||
github.com/projectdiscovery/freeport v0.0.6/go.mod h1:T2kIy+WrbyxBIhI8V3Y9aeNGnuhnM8tEUSK/cm9GjAg=
|
||||
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.64 h1:FDfwdt9N97Hi8OuhbkDlKtVttpc/CRMIWQVa08VsHsI=
|
||||
github.com/projectdiscovery/goflags v0.1.64/go.mod h1:3FyHIVQtnycNOc1LE3O1jj/XR5XuMdF9QfHd0ujhnX4=
|
||||
github.com/projectdiscovery/gologger v1.1.24 h1:TmA4k9sA6ZvfyRnprZKQ0Uq34g//u5R9yTDPL9IzTOQ=
|
||||
github.com/projectdiscovery/gologger v1.1.24/go.mod h1:JA0JMJ+ply+J2wD062TN4h85thm6/28jAlrntwccKVU=
|
||||
github.com/projectdiscovery/gologger v1.1.21 h1:FD9MGE9adY/y2IxDpQgPZIvZAkQIx3bvcuY+d1FLQUo=
|
||||
github.com/projectdiscovery/gologger v1.1.21/go.mod h1:eyvlcHiSuzJQtwmh+fcfwZVaqVgSGtEP1oL1gJFgP3c=
|
||||
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.59 h1:xWCr/GY2QJanFzwKydh/EkGdOKM4iAcN9hQvvCMgO6A=
|
||||
github.com/projectdiscovery/hmap v0.0.59/go.mod h1:uHhhnPmvq9qXvCjBSQXCBAlmA1r8JGufP775IkBSbgs=
|
||||
github.com/projectdiscovery/hmap v0.0.56 h1:QLIuFhCc7jrBH9WYpxNBDooSoH+/S8cCm7VO5rMt3lU=
|
||||
github.com/projectdiscovery/hmap v0.0.56/go.mod h1:XyGKMO93nLOzpaTTCDBSKEGx/XWXjSpoyZJxT92Qd/Q=
|
||||
github.com/projectdiscovery/httpx v1.6.8 h1:k0Y5g3ue/7QbDP0+LykIxp/VhPDLfau3UEUyuxtP7qE=
|
||||
github.com/projectdiscovery/httpx v1.6.8/go.mod h1:7BIsDxyRwkBjthqFmEajXrA5f3yb4tlVfLmpNdf0ZXA=
|
||||
github.com/projectdiscovery/interactsh v1.2.0 h1:Al6jHiR+Usl9egYJDLJaWNHOcH8Rugk8gWMasc8Cmw8=
|
||||
@@ -879,16 +866,16 @@ 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.56 h1:WliU7NvfMb5hK/IJjOFlWIXU1G7+QRylMhSybaSCTI8=
|
||||
github.com/projectdiscovery/ratelimit v0.0.56/go.mod h1:GbnAo+MbB4R/4jiOI1mH4KAJfovmrPnq4NElcI99fvs=
|
||||
github.com/projectdiscovery/rawhttp v0.1.67 h1:HYzathMk3c8Y83hYjHM4GCBFbz/G+vABe0Lz6ajaowY=
|
||||
github.com/projectdiscovery/rawhttp v0.1.67/go.mod h1:5viJ6odzc9ZuEFppj/E7HdX+u99FoYlvXnhHyTNc7N0=
|
||||
github.com/projectdiscovery/ratelimit v0.0.53 h1:1ci2zaVCtJ9daDi9IXjNwpDxl2InYq375role/xqUR4=
|
||||
github.com/projectdiscovery/ratelimit v0.0.53/go.mod h1:4kNYTL7xKLo1qMYHTREUCBqHyvykFF+XBWutTh9fkwg=
|
||||
github.com/projectdiscovery/rawhttp v0.1.61 h1:EbskCj6kkDSG31sO5zEUFTqHp9ltccG1DdcI+MCdahQ=
|
||||
github.com/projectdiscovery/rawhttp v0.1.61/go.mod h1:5XmDAKph9pLVnh87zjL+vXDpfG5W8Gz5N2BAtYTkuVU=
|
||||
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.77 h1:rCFSiTPNI7h9PP1uUvrmcq/6XVZVdxpha2H1ioArKpk=
|
||||
github.com/projectdiscovery/retryabledns v1.0.77/go.mod h1:ce1JTjAOxLujqITtA5VLlbhLRVubx+GETYasivapai4=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78 h1:If7/XjCWk893YrnTMaW69TNMsfE1Er3i1SWOkWbEk4E=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.78/go.mod h1:NqzTdnGihSRkF9c/aXo+3qTJXEeNwnOuza6GrlPo9qw=
|
||||
github.com/projectdiscovery/retryabledns v1.0.73 h1:CLqtgoI6+YVcUE2jnZPFVvwj59CHDE4HNImLf62sSuw=
|
||||
github.com/projectdiscovery/retryabledns v1.0.73/go.mod h1:Wo5tQHKtx6XcYYhMypRg8dr0GGnqIb4CzoTSEw2lo7I=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.76 h1:2+4QpWnXUZFBkoeCEBXtUjSeBTdgKtaGwP8LRtKAC3g=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.76/go.mod h1:0qIv7Ld8WWSKWYXMsNAWRYU5gsxnxpBza3SjDgt6nVc=
|
||||
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=
|
||||
@@ -897,12 +884,12 @@ github.com/projectdiscovery/tlsx v1.1.7 h1:eSsl/SmTDL/z2CMeSrbssk4f/9oOotMP1SgXl
|
||||
github.com/projectdiscovery/tlsx v1.1.7/go.mod h1:g66QQ4/y4tLVjoGbzWIv+Q6xwFzxfJbEDx86Y1dYHDM=
|
||||
github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0JprejqLSopN9Y=
|
||||
github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U=
|
||||
github.com/projectdiscovery/useragent v0.0.71 h1:Q02L3LV15ztOQ6FfmVSqVmOd5QhvzI+yAgYOc/32Nvg=
|
||||
github.com/projectdiscovery/useragent v0.0.71/go.mod h1:DHPruFLCvCvkd2qqPwwQZrP9sziv0lxQJ0R1rE1fa8E=
|
||||
github.com/projectdiscovery/utils v0.2.11 h1:TO7fBG5QI256sn1YuTD87yn4+4OjGJ2wT1772uEnp4Q=
|
||||
github.com/projectdiscovery/utils v0.2.11/go.mod h1:W0E74DWkKxlcyKS5XwcAwiob7+smoszPPi1NgX3vZyk=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18 h1:fFgETis0HcsNE7wREaUPYP45JqIyHgGorJaVp1RH7g4=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.18/go.mod h1:/hzgxkBFTMe2wDbA93nFfoMjULw7/vIZ9QPSAnCgUa8=
|
||||
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.7 h1:XWdz7SscL++jqsnQ9ecHzSZE0RK33tyPcnqcXw+vmKs=
|
||||
github.com/projectdiscovery/utils v0.2.7/go.mod h1:N0N7tbdNFPegd9NpJ3onCPClaBrERcOIB88yww6UCF8=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14 h1:nt1IM4RUmqeymsXk4h6BsZbKDoS2hjFvPkT2GaI1rz4=
|
||||
github.com/projectdiscovery/wappalyzergo v0.1.14/go.mod h1:/hzgxkBFTMe2wDbA93nFfoMjULw7/vIZ9QPSAnCgUa8=
|
||||
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=
|
||||
@@ -946,8 +933,8 @@ github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7
|
||||
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=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg=
|
||||
github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
@@ -1087,12 +1074,6 @@ github.com/xanzy/go-gitlab v0.107.0 h1:P2CT9Uy9yN9lJo3FLxpMZ4xj6uWcpnigXsjvqJ6nd
|
||||
github.com/xanzy/go-gitlab v0.107.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -1106,8 +1087,6 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMx
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
|
||||
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
|
||||
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
|
||||
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
|
||||
@@ -1127,11 +1106,11 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
||||
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4=
|
||||
github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
||||
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
|
||||
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
|
||||
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc=
|
||||
@@ -1160,8 +1139,6 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k=
|
||||
go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
@@ -1210,8 +1187,8 @@ golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1295,6 +1272,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
@@ -1304,8 +1282,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1330,8 +1308,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1394,6 +1372,7 @@ golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1406,8 +1385,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -1420,8 +1399,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1438,8 +1417,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
id: multimatch-value-share-template
|
||||
|
||||
info:
|
||||
name: MultiMatch Value Share Template
|
||||
author: tovask
|
||||
severity: info
|
||||
|
||||
http:
|
||||
- path:
|
||||
- "{{BaseURL}}/path1?v=1"
|
||||
- "{{BaseURL}}/path1?v=2"
|
||||
matchers:
|
||||
- type: word
|
||||
name: test-matcher
|
||||
words:
|
||||
- "href"
|
||||
extractors:
|
||||
- type: regex
|
||||
part: body
|
||||
name: extracted
|
||||
regex:
|
||||
- 'href="(.*)"'
|
||||
group: 1
|
||||
@@ -1,21 +0,0 @@
|
||||
id: multimatch-value-share-workflow
|
||||
|
||||
info:
|
||||
name: MultiMatch Value Share Workflow
|
||||
author: tovask
|
||||
severity: info
|
||||
description: Workflow to test value sharing when multiple matches occur in the extractor template
|
||||
|
||||
workflows:
|
||||
- template: workflow/multimatch-value-share-template.yaml
|
||||
subtemplates:
|
||||
- template: workflow/match-1.yaml
|
||||
subtemplates:
|
||||
- template: workflow/http-value-share-template-2.yaml
|
||||
- template: workflow/multimatch-value-share-template.yaml
|
||||
matchers:
|
||||
- name: test-matcher
|
||||
subtemplates:
|
||||
- template: workflow/match-1.yaml
|
||||
subtemplates:
|
||||
- template: workflow/http-value-share-template-2.yaml
|
||||
@@ -51,7 +51,6 @@ func GetAuthTmplStore(opts types.Options, catalog catalog.Catalog, execOpts prot
|
||||
opts.ExcludeProtocols = nil
|
||||
opts.IncludeConditions = nil
|
||||
cfg := loader.NewConfig(&opts, catalog, execOpts)
|
||||
cfg.StoreId = loader.AuthStoreId
|
||||
store, err := loader.New(cfg)
|
||||
if err != nil {
|
||||
return nil, errorutil.NewWithErr(err).Msgf("failed to initialize dynamic auth templates store")
|
||||
|
||||
@@ -501,17 +501,8 @@ func (r *Runner) RunEnumeration() error {
|
||||
}
|
||||
|
||||
if r.options.ShouldUseHostError() {
|
||||
maxHostError := r.options.MaxHostError
|
||||
if r.options.TemplateThreads > maxHostError {
|
||||
gologger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", r.colorizer.BrightYellow("WRN"))
|
||||
gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", r.options.TemplateThreads)
|
||||
|
||||
maxHostError = r.options.TemplateThreads
|
||||
}
|
||||
|
||||
cache := hosterrorscache.New(maxHostError, hosterrorscache.DefaultMaxHostsCount, r.options.TrackError)
|
||||
cache := hosterrorscache.New(r.options.MaxHostError, hosterrorscache.DefaultMaxHostsCount, r.options.TrackError)
|
||||
cache.SetVerbose(r.options.Verbose)
|
||||
|
||||
r.hostErrors = cache
|
||||
executorOpts.HostErrorsCache = cache
|
||||
}
|
||||
@@ -793,52 +784,6 @@ func (r *Runner) SaveResumeConfig(path string) error {
|
||||
return os.WriteFile(path, data, permissionutil.ConfigFilePermission)
|
||||
}
|
||||
|
||||
// upload existing scan results to cloud with progress
|
||||
func UploadResultsToCloud(options *types.Options) error {
|
||||
h := &pdcpauth.PDCPCredHandler{}
|
||||
creds, err := h.GetCreds()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get credentials for cloud upload")
|
||||
}
|
||||
ctx := context.TODO()
|
||||
uploadWriter, err := pdcp.NewUploadWriter(ctx, creds)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not create upload writer")
|
||||
}
|
||||
if options.ScanID != "" {
|
||||
_ = uploadWriter.SetScanID(options.ScanID)
|
||||
}
|
||||
if options.ScanName != "" {
|
||||
uploadWriter.SetScanName(options.ScanName)
|
||||
}
|
||||
if options.TeamID != "" {
|
||||
uploadWriter.SetTeamID(options.TeamID)
|
||||
}
|
||||
|
||||
// Open file to count the number of results first
|
||||
file, err := os.Open(options.ScanUploadFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open scan upload file")
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
gologger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile)
|
||||
dec := json.NewDecoder(file)
|
||||
for dec.More() {
|
||||
var r output.ResultEvent
|
||||
err := dec.Decode(&r)
|
||||
if err != nil {
|
||||
gologger.Warning().Msgf("Could not decode jsonl: %s\n", err)
|
||||
continue
|
||||
}
|
||||
if err = uploadWriter.Write(&r); err != nil {
|
||||
gologger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err)
|
||||
}
|
||||
}
|
||||
uploadWriter.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
type WalkFunc func(reflect.Value, reflect.StructField)
|
||||
|
||||
// Walk traverses a struct and executes a callback function on each value in the struct.
|
||||
|
||||
+8
-8
@@ -108,6 +108,14 @@ 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() {
|
||||
@@ -118,14 +126,6 @@ func (e *NucleiEngine) init(ctx context.Context) error {
|
||||
_ = protocolinit.Init(e.opts)
|
||||
})
|
||||
|
||||
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.applyRequiredDefaults(ctx)
|
||||
var err error
|
||||
|
||||
|
||||
@@ -247,12 +247,7 @@
|
||||
"time",
|
||||
"select",
|
||||
"files",
|
||||
"waitdom",
|
||||
"waitfcp",
|
||||
"waitfmp",
|
||||
"waitidle",
|
||||
"waitload",
|
||||
"waitstable",
|
||||
"getresource",
|
||||
"extract",
|
||||
"setmethod",
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
CLIConfigFileName = "config.yaml"
|
||||
ReportingConfigFilename = "reporting-config.yaml"
|
||||
// Version is the current version of nuclei
|
||||
Version = `v3.3.4`
|
||||
Version = `v3.3.2`
|
||||
// Directory Names of custom templates
|
||||
CustomS3TemplatesDirName = "s3"
|
||||
CustomGitHubTemplatesDirName = "github"
|
||||
|
||||
@@ -216,17 +216,12 @@ func (c *DiskCatalog) findGlobPathMatches(absPath string, processed map[string]s
|
||||
// is a file, it returns true otherwise false with no errors.
|
||||
func (c *DiskCatalog) findFileMatches(absPath string, processed map[string]struct{}) (match string, matched bool, err error) {
|
||||
if c.templatesFS != nil {
|
||||
absPath = strings.Trim(absPath, "/")
|
||||
absPath = strings.TrimPrefix(absPath, "/")
|
||||
}
|
||||
var info fs.File
|
||||
if c.templatesFS == nil {
|
||||
info, err = os.Open(absPath)
|
||||
} else {
|
||||
// If we were given no path, then it's not a file, it's the root, and we can quietly return.
|
||||
if absPath == "" {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
info, err = c.templatesFS.Open(absPath)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -268,12 +263,6 @@ func (c *DiskCatalog) findDirectoryMatches(absPath string, processed map[string]
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// For the special case of the root directory, we need to pass "." to `fs.WalkDir`.
|
||||
if absPath == "" {
|
||||
absPath = "."
|
||||
}
|
||||
absPath = strings.TrimSuffix(absPath, "/")
|
||||
|
||||
err = fs.WalkDir(
|
||||
c.templatesFS,
|
||||
absPath,
|
||||
|
||||
+11
-25
@@ -2,7 +2,6 @@ package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -22,11 +21,6 @@ func (c *DiskCatalog) ResolvePath(templateName, second string) (string, error) {
|
||||
if filepath.IsAbs(templateName) {
|
||||
return templateName, nil
|
||||
}
|
||||
if c.templatesFS != nil {
|
||||
if potentialPath, err := c.tryResolve(templateName); err != errNoValidCombination {
|
||||
return potentialPath, nil
|
||||
}
|
||||
}
|
||||
if second != "" {
|
||||
secondBasePath := filepath.Join(filepath.Dir(second), templateName)
|
||||
if potentialPath, err := c.tryResolve(secondBasePath); err != errNoValidCombination {
|
||||
@@ -34,19 +28,17 @@ func (c *DiskCatalog) ResolvePath(templateName, second string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if c.templatesFS == nil {
|
||||
curDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
templatePath := filepath.Join(curDirectory, templateName)
|
||||
if potentialPath, err := c.tryResolve(templatePath); err != errNoValidCombination {
|
||||
return potentialPath, nil
|
||||
}
|
||||
curDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
templatePath := filepath.Join(config.DefaultConfig.GetTemplateDir(), templateName)
|
||||
templatePath := filepath.Join(curDirectory, templateName)
|
||||
if potentialPath, err := c.tryResolve(templatePath); err != errNoValidCombination {
|
||||
return potentialPath, nil
|
||||
}
|
||||
|
||||
templatePath = filepath.Join(config.DefaultConfig.GetTemplateDir(), templateName)
|
||||
if potentialPath, err := c.tryResolve(templatePath); err != errNoValidCombination {
|
||||
return potentialPath, nil
|
||||
}
|
||||
@@ -58,14 +50,8 @@ var errNoValidCombination = errors.New("no valid combination found")
|
||||
|
||||
// tryResolve attempts to load locate the target by iterating across all the folders tree
|
||||
func (c *DiskCatalog) tryResolve(fullPath string) (string, error) {
|
||||
if c.templatesFS == nil {
|
||||
if fileutil.FileOrFolderExists(fullPath) {
|
||||
return fullPath, nil
|
||||
}
|
||||
} else {
|
||||
if _, err := fs.Stat(c.templatesFS, fullPath); err == nil {
|
||||
return fullPath, nil
|
||||
}
|
||||
if fileutil.FileOrFolderExists(fullPath) {
|
||||
return fullPath, nil
|
||||
}
|
||||
return "", errNoValidCombination
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader/filter"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/keys"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
|
||||
@@ -33,7 +32,6 @@ import (
|
||||
const (
|
||||
httpPrefix = "http://"
|
||||
httpsPrefix = "https://"
|
||||
AuthStoreId = "auth_store"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -42,7 +40,6 @@ var (
|
||||
|
||||
// Config contains the configuration options for the loader
|
||||
type Config struct {
|
||||
StoreId string // used to set store id (optional)
|
||||
Templates []string
|
||||
TemplateURLs []string
|
||||
Workflows []string
|
||||
@@ -69,7 +66,6 @@ type Config struct {
|
||||
|
||||
// Store is a storage for loaded nuclei templates
|
||||
type Store struct {
|
||||
id string // id of the store (optional)
|
||||
tagFilter *templates.TagFilter
|
||||
pathFilter *filter.PathFilter
|
||||
config *Config
|
||||
@@ -135,7 +131,6 @@ func New(cfg *Config) (*Store, error) {
|
||||
|
||||
// Create a tag filter based on provided configuration
|
||||
store := &Store{
|
||||
id: cfg.StoreId,
|
||||
config: cfg,
|
||||
tagFilter: tagFilter,
|
||||
pathFilter: filter.NewPathFilter(&filter.PathFilterConfig{
|
||||
@@ -234,10 +229,6 @@ func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error)
|
||||
}
|
||||
}
|
||||
|
||||
func (store *Store) ID() string {
|
||||
return store.id
|
||||
}
|
||||
|
||||
// Templates returns all the templates in the store
|
||||
func (store *Store) Templates() []*templates.Template {
|
||||
return store.templates
|
||||
@@ -443,7 +434,7 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
// increment signed/unsigned counters
|
||||
if tmpl.Verified {
|
||||
if tmpl.TemplateVerifier == "" {
|
||||
templates.SignatureStats[keys.PDVerifier].Add(1)
|
||||
templates.SignatureStats[templates.PDVerifier].Add(1)
|
||||
} else {
|
||||
templates.SignatureStats[tmpl.TemplateVerifier].Add(1)
|
||||
}
|
||||
@@ -480,8 +471,7 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
return
|
||||
}
|
||||
// DAST only templates
|
||||
// Skip DAST filter when loading auth templates
|
||||
if store.ID() != AuthStoreId && store.config.ExecutorOptions.Options.DAST {
|
||||
if store.config.ExecutorOptions.Options.DAST {
|
||||
// check if the template is a DAST template
|
||||
if parsed.IsFuzzing() {
|
||||
loadTemplate(parsed)
|
||||
|
||||
@@ -107,7 +107,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
currentInfo.Unlock()
|
||||
|
||||
// Skip if the host has had errors
|
||||
if e.executerOpts.HostErrorsCache != nil && e.executerOpts.HostErrorsCache.Check(e.executerOpts.ProtocolType.String(), contextargs.NewWithMetaInput(ctx, scannedValue)) {
|
||||
if e.executerOpts.HostErrorsCache != nil && e.executerOpts.HostErrorsCache.Check(contextargs.NewWithMetaInput(ctx, scannedValue)) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ func (e *Engine) runWorkflowStep(template *workflows.WorkflowTemplate, ctx *scan
|
||||
}
|
||||
if err != nil {
|
||||
if w.Options.HostErrorsCache != nil {
|
||||
w.Options.HostErrorsCache.MarkFailed(w.Options.ProtocolType.String(), ctx.Input, err)
|
||||
w.Options.HostErrorsCache.MarkFailed(ctx.Input, err)
|
||||
}
|
||||
if len(template.Executers) == 1 {
|
||||
mainErr = err
|
||||
@@ -139,8 +139,7 @@ func (e *Engine) runWorkflowStep(template *workflows.WorkflowTemplate, ctx *scan
|
||||
defer swg.Done()
|
||||
|
||||
// create a new context with the same input but with unset callbacks
|
||||
// clone the Input so that other parallel executions won't overwrite the shared variables when subsequent templates are running
|
||||
subCtx := scan.NewScanContext(ctx.Context(), ctx.Input.Clone())
|
||||
subCtx := scan.NewScanContext(ctx.Context(), ctx.Input)
|
||||
if err := e.runWorkflowStep(subtemplate, subCtx, results, swg, w); err != nil {
|
||||
gologger.Warning().Msgf(workflowStepExecutionError, subtemplate.Template, err)
|
||||
}
|
||||
|
||||
@@ -6,19 +6,12 @@ import (
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
|
||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||
)
|
||||
|
||||
type MultiPartForm struct {
|
||||
boundary string
|
||||
filesMetadata map[string]FileMetadata
|
||||
}
|
||||
|
||||
type FileMetadata struct {
|
||||
ContentType string
|
||||
Filename string
|
||||
boundary string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -48,40 +41,11 @@ func (m *MultiPartForm) Encode(data KV) (string, error) {
|
||||
data.Iterate(func(key string, value any) bool {
|
||||
var fw io.Writer
|
||||
var err error
|
||||
|
||||
if filesArray, ok := value.([]interface{}); ok {
|
||||
fileMetadata, ok := m.filesMetadata[key]
|
||||
if !ok {
|
||||
Itererr = fmt.Errorf("file metadata not found for key %s", key)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, file := range filesArray {
|
||||
h := make(textproto.MIMEHeader)
|
||||
h.Set("Content-Disposition",
|
||||
fmt.Sprintf(`form-data; name=%q; filename=%q`,
|
||||
key, fileMetadata.Filename))
|
||||
h.Set("Content-Type", fileMetadata.ContentType)
|
||||
|
||||
if fw, err = w.CreatePart(h); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(file.(string))); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Add field
|
||||
if fw, err = w.CreateFormField(key); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err = fw.Write([]byte(value.(string))); err != nil {
|
||||
Itererr = err
|
||||
return false
|
||||
@@ -134,7 +98,6 @@ func (m *MultiPartForm) Decode(data string) (KV, error) {
|
||||
result.Set(key, values[0])
|
||||
}
|
||||
}
|
||||
m.filesMetadata = make(map[string]FileMetadata)
|
||||
for key, files := range form.File {
|
||||
fileContents := []interface{}{}
|
||||
for _, fileHeader := range files {
|
||||
@@ -149,11 +112,6 @@ func (m *MultiPartForm) Decode(data string) (KV, error) {
|
||||
return KV{}, err
|
||||
}
|
||||
fileContents = append(fileContents, buffer.String())
|
||||
|
||||
m.filesMetadata[key] = FileMetadata{
|
||||
ContentType: fileHeader.Header.Get("Content-Type"),
|
||||
Filename: fileHeader.Filename,
|
||||
}
|
||||
}
|
||||
result.Set(key, fileContents)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
globalAuth = "globalAuth"
|
||||
DEFAULT_HTTP_SCHEME_HEADER = "Authorization"
|
||||
globalAuth = "globalAuth"
|
||||
)
|
||||
|
||||
// GenerateRequestsFromSchema generates http requests from an OpenAPI 3.0 document object
|
||||
@@ -427,20 +426,18 @@ func GenerateParameterFromSecurityScheme(scheme *openapi3.SecuritySchemeRef) (*o
|
||||
if !generic.EqualsAny(scheme.Value.Scheme, "basic", "bearer") {
|
||||
return nil, errorutil.NewWithTag("openapi", "unsupported security scheme (%s) found in openapi file", scheme.Value.Scheme)
|
||||
}
|
||||
// HTTP authentication schemes basic or bearer use the Authorization header
|
||||
headerName := scheme.Value.Name
|
||||
if headerName == "" {
|
||||
headerName = DEFAULT_HTTP_SCHEME_HEADER
|
||||
if scheme.Value.Name == "" {
|
||||
return nil, errorutil.NewWithTag("openapi", "security scheme (%s) name is empty", scheme.Value.Scheme)
|
||||
}
|
||||
// create parameters using the scheme
|
||||
switch scheme.Value.Scheme {
|
||||
case "basic":
|
||||
h := openapi3.NewHeaderParameter(headerName)
|
||||
h := openapi3.NewHeaderParameter(scheme.Value.Name)
|
||||
h.Required = true
|
||||
h.Description = globalAuth // differentiator for normal variables and global auth
|
||||
return h, nil
|
||||
case "bearer":
|
||||
h := openapi3.NewHeaderParameter(headerName)
|
||||
h := openapi3.NewHeaderParameter(scheme.Value.Name)
|
||||
h.Required = true
|
||||
h.Description = globalAuth // differentiator for normal variables and global auth
|
||||
return h, nil
|
||||
|
||||
@@ -155,7 +155,7 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object {
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// client.Authenticate('user', 'password');
|
||||
// ```
|
||||
func (c *Client) Authenticate(username, password string) bool {
|
||||
func (c *Client) Authenticate(username, password string) {
|
||||
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="))
|
||||
@@ -163,21 +163,19 @@ func (c *Client) Authenticate(username, password string) bool {
|
||||
if err := c.conn.NTLMBind(c.Realm, username, password); err == nil {
|
||||
// if bind with NTLMBind(), there is nothing
|
||||
// else to do, you are authenticated
|
||||
return true
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
switch password {
|
||||
case "":
|
||||
if err = c.conn.UnauthenticatedBind(username); err != nil {
|
||||
if err := c.conn.UnauthenticatedBind(username); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
default:
|
||||
if err = c.conn.Bind(username, password); err != nil {
|
||||
if err := c.conn.Bind(username, password); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// AuthenticateWithNTLMHash authenticates with the ldap server using the given username and NTLM hash
|
||||
@@ -187,16 +185,14 @@ func (c *Client) Authenticate(username, password string) bool {
|
||||
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
|
||||
// client.AuthenticateWithNTLMHash('pdtm', 'hash');
|
||||
// ```
|
||||
func (c *Client) AuthenticateWithNTLMHash(username, hash string) bool {
|
||||
func (c *Client) AuthenticateWithNTLMHash(username, hash string) {
|
||||
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="))
|
||||
}
|
||||
var err error
|
||||
if err = c.conn.NTLMBindWithHash(c.Realm, username, hash); err != nil {
|
||||
if err := c.conn.NTLMBindWithHash(c.Realm, username, hash); err != nil {
|
||||
c.nj.ThrowError(err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Search accepts whatever filter and returns a list of maps having provided attributes
|
||||
@@ -283,10 +279,9 @@ func (c *Client) CollectMetadata() Metadata {
|
||||
}
|
||||
metadata.BaseDN = c.BaseDN
|
||||
|
||||
// Use scope as Base since Root DSE doesn't have subentries
|
||||
srMetadata := ldap.NewSearchRequest(
|
||||
"",
|
||||
ldap.ScopeBaseObject,
|
||||
ldap.ScopeWholeSubtree,
|
||||
ldap.NeverDerefAliases,
|
||||
0, 0, false,
|
||||
"(objectClass=*)",
|
||||
|
||||
@@ -53,7 +53,7 @@ func BuildDSN(opts MySQLOptions) (string, error) {
|
||||
}
|
||||
target := net.JoinHostPort(opts.Host, fmt.Sprintf("%d", opts.Port))
|
||||
var dsn strings.Builder
|
||||
dsn.WriteString(fmt.Sprintf("%v:%v", url.QueryEscape(opts.Username), opts.Password))
|
||||
dsn.WriteString(fmt.Sprintf("%v:%v", url.QueryEscape(opts.Username), url.QueryEscape(opts.Password)))
|
||||
dsn.WriteString("@")
|
||||
dsn.WriteString(fmt.Sprintf("%v(%v)", opts.Protocol, target))
|
||||
if opts.DbName != "" {
|
||||
|
||||
@@ -3,7 +3,5 @@ package keys
|
||||
|
||||
import _ "embed"
|
||||
|
||||
const PDVerifier = "projectdiscovery/nuclei-templates"
|
||||
|
||||
//go:embed nuclei.crt
|
||||
var NucleiCert []byte // public key for verifying digital signature of templates
|
||||
+13
-56
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -72,10 +71,7 @@ type StandardWriter struct {
|
||||
omitTemplate bool
|
||||
DisableStdout bool
|
||||
AddNewLinesOutputFile bool // by default this is only done for stdout
|
||||
keysToRedact []*regexp.Regexp
|
||||
|
||||
RequestCallback func(templateID, url, requestType string, err error)
|
||||
WriteCallback func(o *ResultEvent)
|
||||
KeysToRedact []string
|
||||
}
|
||||
|
||||
var decolorizerRegex = regexp.MustCompile(`\x1B\[[0-9;]*[a-zA-Z]`)
|
||||
@@ -103,15 +99,6 @@ type InternalWrappedEvent struct {
|
||||
InteractshMatched atomic.Bool
|
||||
}
|
||||
|
||||
func (iwe *InternalWrappedEvent) CloneShallow() *InternalWrappedEvent {
|
||||
return &InternalWrappedEvent{
|
||||
InternalEvent: maps.Clone(iwe.InternalEvent),
|
||||
Results: nil,
|
||||
OperatorsResult: nil,
|
||||
UsesInteractsh: iwe.UsesInteractsh,
|
||||
}
|
||||
}
|
||||
|
||||
func (iwe *InternalWrappedEvent) HasOperatorResult() bool {
|
||||
iwe.RLock()
|
||||
defer iwe.RUnlock()
|
||||
@@ -203,7 +190,6 @@ type ResultEvent struct {
|
||||
FuzzingPosition string `json:"fuzzing_position,omitempty"`
|
||||
|
||||
FileToIndexPosition map[string]int `json:"-"`
|
||||
TemplateVerifier string `json:"-"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
@@ -268,27 +254,8 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
|
||||
storeResponse: options.StoreResponse,
|
||||
storeResponseDir: options.StoreResponseDir,
|
||||
omitTemplate: options.OmitTemplate,
|
||||
KeysToRedact: options.Redact,
|
||||
}
|
||||
for _, key := range options.Redact {
|
||||
keyPattern := regexp.MustCompile(fmt.Sprintf(`(?i)(%s\s*[:=]\s*["']?)[^"'\r\n&]+(["'\r\n]?)`, regexp.QuoteMeta(key)))
|
||||
writer.keysToRedact = append(writer.keysToRedact, keyPattern)
|
||||
}
|
||||
|
||||
return writer, nil
|
||||
}
|
||||
|
||||
func NewStandardWriterWithHooks(
|
||||
options *types.Options,
|
||||
requestCallback func(templateID, url, requestType string, err error),
|
||||
writeCallback func(o *ResultEvent),
|
||||
) (*StandardWriter, error) {
|
||||
writer, err := NewStandardWriter(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writer.RequestCallback = requestCallback
|
||||
writer.WriteCallback = writeCallback
|
||||
|
||||
return writer, nil
|
||||
}
|
||||
|
||||
@@ -296,15 +263,14 @@ func NewStandardWriterWithHooks(
|
||||
func (w *StandardWriter) Write(event *ResultEvent) error {
|
||||
// Enrich the result event with extra metadata on the template-path and url.
|
||||
if event.TemplatePath != "" {
|
||||
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID), event.TemplateVerifier)
|
||||
event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID))
|
||||
}
|
||||
|
||||
if len(w.keysToRedact) > 0 {
|
||||
event.URL = w.redactKeys(event.URL)
|
||||
event.Request = w.redactKeys(event.Request)
|
||||
event.Response = w.redactKeys(event.Response)
|
||||
event.CURLCommand = w.redactKeys(event.CURLCommand)
|
||||
event.Matched = w.redactKeys(event.Matched)
|
||||
if len(w.KeysToRedact) > 0 {
|
||||
event.Request = redactKeys(event.Request, w.KeysToRedact)
|
||||
event.Response = redactKeys(event.Response, w.KeysToRedact)
|
||||
event.CURLCommand = redactKeys(event.CURLCommand, w.KeysToRedact)
|
||||
event.Matched = redactKeys(event.Matched, w.KeysToRedact)
|
||||
}
|
||||
|
||||
event.Timestamp = time.Now()
|
||||
@@ -342,15 +308,12 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
|
||||
_, _ = w.outputFile.Write([]byte("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
if w.WriteCallback != nil {
|
||||
w.WriteCallback(event)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *StandardWriter) redactKeys(data string) string {
|
||||
for _, keyPattern := range w.keysToRedact {
|
||||
func redactKeys(data string, keysToRedact []string) string {
|
||||
for _, key := range keysToRedact {
|
||||
keyPattern := regexp.MustCompile(fmt.Sprintf(`(?i)(%s\s*[:=]\s*["']?)[^"'\r\n&]+(["'\r\n]?)`, regexp.QuoteMeta(key)))
|
||||
data = keyPattern.ReplaceAllString(data, `$1***$2`)
|
||||
}
|
||||
return data
|
||||
@@ -370,11 +333,7 @@ type JSONLogRequest struct {
|
||||
|
||||
// Request writes a log the requests trace log
|
||||
func (w *StandardWriter) Request(templatePath, input, requestType string, requestErr error) {
|
||||
if w.traceFile == nil && w.errorFile == nil && w.RequestCallback == nil {
|
||||
return
|
||||
}
|
||||
if w.RequestCallback != nil {
|
||||
w.RequestCallback(templatePath, input, requestType, requestErr)
|
||||
if w.traceFile == nil && w.errorFile == nil {
|
||||
return
|
||||
}
|
||||
request := &JSONLogRequest{
|
||||
@@ -423,7 +382,6 @@ func (w *StandardWriter) Request(templatePath, input, requestType string, reques
|
||||
if val := errkit.GetAttrValue(requestErr, "address"); val.Any() != nil {
|
||||
request.Address = val.String()
|
||||
}
|
||||
|
||||
data, err := jsoniter.Marshal(request)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -436,7 +394,6 @@ func (w *StandardWriter) Request(templatePath, input, requestType string, reques
|
||||
if requestErr != nil && w.errorFile != nil {
|
||||
_, _ = w.errorFile.Write(data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Colorizer returns the colorizer instance for writer
|
||||
@@ -478,7 +435,7 @@ func (w *StandardWriter) WriteFailure(wrappedEvent *InternalWrappedEvent) error
|
||||
// if no results were found, manually create a failure event
|
||||
event := wrappedEvent.InternalEvent
|
||||
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]), types.ToString(event["template-id"]), types.ToString(event["template-verifier"]))
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]), types.ToString(event["template-id"]))
|
||||
var templateInfo model.Info
|
||||
if event["template-info"] != nil {
|
||||
templateInfo = event["template-info"].(model.Info)
|
||||
|
||||
@@ -348,7 +348,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(request.options.TemplateID),
|
||||
TemplatePath: types.ToString(request.options.TemplatePath),
|
||||
Info: request.options.TemplateInfo,
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Matched: types.ToString(wrapped.InternalEvent["input"]),
|
||||
Host: fields.Host,
|
||||
|
||||
@@ -22,13 +22,6 @@ func (g *PayloadGenerator) validate(payloads map[string]interface{}, templatePat
|
||||
return errors.New("invalid number of lines in payload")
|
||||
}
|
||||
|
||||
// For historical reasons, "validate" checks to see if the payload file exist.
|
||||
// If we're using a custom helper function, then we need to skip any validation beyond just checking the string syntax.
|
||||
// Actually attempting to load the file will determine whether or not it exists.
|
||||
if g.options.LoadHelperFileFunction != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if it's a file and try to load it
|
||||
if fileutil.FileExists(payloadType) {
|
||||
continue
|
||||
|
||||
@@ -20,10 +20,10 @@ import (
|
||||
// CacheInterface defines the signature of the hosterrorscache so that
|
||||
// users of Nuclei as embedded lib may implement their own cache
|
||||
type CacheInterface interface {
|
||||
SetVerbose(verbose bool) // log verbosely
|
||||
Close() // close the cache
|
||||
Check(protoType string, ctx *contextargs.Context) bool // return true if the host should be skipped
|
||||
MarkFailed(protoType string, ctx *contextargs.Context, err error) // record a failure (and cause) for the host
|
||||
SetVerbose(verbose bool) // log verbosely
|
||||
Close() // close the cache
|
||||
Check(ctx *contextargs.Context) bool // return true if the host should be skipped
|
||||
MarkFailed(ctx *contextargs.Context, err error) // record a failure (and cause) for the host
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -75,34 +75,24 @@ func (c *Cache) Close() {
|
||||
c.failedTargets.Purge()
|
||||
}
|
||||
|
||||
// NormalizeCacheValue processes the input value and returns a normalized cache
|
||||
// value.
|
||||
func (c *Cache) NormalizeCacheValue(value string) string {
|
||||
var normalizedValue string = value
|
||||
|
||||
u, err := url.ParseRequestURI(value)
|
||||
if err != nil || u.Host == "" {
|
||||
u, err2 := url.ParseRequestURI("https://" + value)
|
||||
if err2 != nil {
|
||||
return normalizedValue
|
||||
}
|
||||
|
||||
normalizedValue = u.Host
|
||||
} else {
|
||||
port := u.Port()
|
||||
if port == "" {
|
||||
switch u.Scheme {
|
||||
case "https":
|
||||
normalizedValue = net.JoinHostPort(u.Host, "443")
|
||||
case "http":
|
||||
normalizedValue = net.JoinHostPort(u.Host, "80")
|
||||
func (c *Cache) normalizeCacheValue(value string) string {
|
||||
finalValue := value
|
||||
if strings.HasPrefix(value, "http") {
|
||||
if parsed, err := url.Parse(value); err == nil {
|
||||
hostname := parsed.Host
|
||||
finalPort := parsed.Port()
|
||||
if finalPort == "" {
|
||||
if parsed.Scheme == "https" {
|
||||
finalPort = "443"
|
||||
} else {
|
||||
finalPort = "80"
|
||||
}
|
||||
hostname = net.JoinHostPort(parsed.Host, finalPort)
|
||||
}
|
||||
} else {
|
||||
normalizedValue = u.Host
|
||||
finalValue = hostname
|
||||
}
|
||||
}
|
||||
|
||||
return normalizedValue
|
||||
return finalValue
|
||||
}
|
||||
|
||||
// ErrUnresponsiveHost is returned when a host is unresponsive
|
||||
@@ -115,7 +105,7 @@ func (c *Cache) NormalizeCacheValue(value string) string {
|
||||
// - URL: https?:// type
|
||||
// - Host:port type
|
||||
// - host type
|
||||
func (c *Cache) Check(protoType string, ctx *contextargs.Context) bool {
|
||||
func (c *Cache) Check(ctx *contextargs.Context) bool {
|
||||
finalValue := c.GetKeyFromContext(ctx, nil)
|
||||
|
||||
existingCacheItem, err := c.failedTargets.GetIFPresent(finalValue)
|
||||
@@ -138,8 +128,8 @@ func (c *Cache) Check(protoType string, ctx *contextargs.Context) bool {
|
||||
}
|
||||
|
||||
// MarkFailed marks a host as failed previously
|
||||
func (c *Cache) MarkFailed(protoType string, ctx *contextargs.Context, err error) {
|
||||
if !c.checkError(protoType, err) {
|
||||
func (c *Cache) MarkFailed(ctx *contextargs.Context, err error) {
|
||||
if !c.checkError(err) {
|
||||
return
|
||||
}
|
||||
finalValue := c.GetKeyFromContext(ctx, err)
|
||||
@@ -176,7 +166,7 @@ func (c *Cache) GetKeyFromContext(ctx *contextargs.Context, err error) string {
|
||||
address = tmp.String()
|
||||
}
|
||||
}
|
||||
finalValue := c.NormalizeCacheValue(address)
|
||||
finalValue := c.normalizeCacheValue(address)
|
||||
return finalValue
|
||||
}
|
||||
|
||||
@@ -186,13 +176,11 @@ var reCheckError = regexp.MustCompile(`(no address found for host|could not reso
|
||||
// added to the host skipping table.
|
||||
// it first parses error and extracts the cause and checks for blacklisted
|
||||
// or common errors that should be skipped
|
||||
func (c *Cache) checkError(protoType string, err error) bool {
|
||||
func (c *Cache) checkError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if protoType != "http" {
|
||||
return false
|
||||
}
|
||||
|
||||
kind := errkit.GetErrorKind(err, nucleierr.ErrTemplateLogic)
|
||||
switch kind {
|
||||
case nucleierr.ErrTemplateLogic:
|
||||
|
||||
@@ -11,16 +11,12 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
protoType = "http"
|
||||
)
|
||||
|
||||
func TestCacheCheck(t *testing.T) {
|
||||
cache := New(3, DefaultMaxHostsCount, nil)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
cache.MarkFailed(protoType, newCtxArgs("test"), fmt.Errorf("could not resolve host"))
|
||||
got := cache.Check(protoType, newCtxArgs("test"))
|
||||
cache.MarkFailed(newCtxArgs("test"), fmt.Errorf("could not resolve host"))
|
||||
got := cache.Check(newCtxArgs("test"))
|
||||
if i < 2 {
|
||||
// till 3 the host is not flagged to skip
|
||||
require.False(t, got)
|
||||
@@ -30,7 +26,7 @@ func TestCacheCheck(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
value := cache.Check(protoType, newCtxArgs("test"))
|
||||
value := cache.Check(newCtxArgs("test"))
|
||||
require.Equal(t, true, value, "could not get checked value")
|
||||
}
|
||||
|
||||
@@ -38,8 +34,8 @@ func TestTrackErrors(t *testing.T) {
|
||||
cache := New(3, DefaultMaxHostsCount, []string{"custom error"})
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
cache.MarkFailed(protoType, newCtxArgs("custom"), fmt.Errorf("got: nested: custom error"))
|
||||
got := cache.Check(protoType, newCtxArgs("custom"))
|
||||
cache.MarkFailed(newCtxArgs("custom"), fmt.Errorf("got: nested: custom error"))
|
||||
got := cache.Check(newCtxArgs("custom"))
|
||||
if i < 2 {
|
||||
// till 3 the host is not flagged to skip
|
||||
require.False(t, got)
|
||||
@@ -48,7 +44,7 @@ func TestTrackErrors(t *testing.T) {
|
||||
require.True(t, got)
|
||||
}
|
||||
}
|
||||
value := cache.Check(protoType, newCtxArgs("custom"))
|
||||
value := cache.Check(newCtxArgs("custom"))
|
||||
require.Equal(t, true, value, "could not get checked value")
|
||||
}
|
||||
|
||||
@@ -90,7 +86,7 @@ func TestCacheMarkFailed(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
normalizedCacheValue := cache.GetKeyFromContext(newCtxArgs(test.host), nil)
|
||||
cache.MarkFailed(protoType, newCtxArgs(test.host), fmt.Errorf("no address found for host"))
|
||||
cache.MarkFailed(newCtxArgs(test.host), fmt.Errorf("no address found for host"))
|
||||
failedTarget, err := cache.failedTargets.Get(normalizedCacheValue)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, failedTarget)
|
||||
@@ -113,7 +109,7 @@ func TestCacheMarkFailedConcurrent(t *testing.T) {
|
||||
|
||||
// the cache is not atomic during items creation, so we pre-create them with counter to zero
|
||||
for _, test := range tests {
|
||||
normalizedValue := cache.NormalizeCacheValue(test.host)
|
||||
normalizedValue := cache.normalizeCacheValue(test.host)
|
||||
newItem := &cacheItem{errors: atomic.Int32{}}
|
||||
newItem.errors.Store(0)
|
||||
_ = cache.failedTargets.Set(normalizedValue, newItem)
|
||||
@@ -126,16 +122,16 @@ func TestCacheMarkFailedConcurrent(t *testing.T) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
cache.MarkFailed(protoType, newCtxArgs(currentTest.host), fmt.Errorf("could not resolve host"))
|
||||
cache.MarkFailed(newCtxArgs(currentTest.host), fmt.Errorf("could not resolve host"))
|
||||
}()
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for _, test := range tests {
|
||||
require.True(t, cache.Check(protoType, newCtxArgs(test.host)))
|
||||
require.True(t, cache.Check(newCtxArgs(test.host)))
|
||||
|
||||
normalizedCacheValue := cache.NormalizeCacheValue(test.host)
|
||||
normalizedCacheValue := cache.normalizeCacheValue(test.host)
|
||||
failedTarget, err := cache.failedTargets.Get(normalizedCacheValue)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, failedTarget)
|
||||
|
||||
@@ -77,8 +77,9 @@ var muGlobalChange sync.Mutex
|
||||
|
||||
// Global setting
|
||||
func GlobalGuardBytesBufferAlloc() error {
|
||||
if !muGlobalChange.TryLock() {
|
||||
if muGlobalChange.TryLock() {
|
||||
return nil
|
||||
|
||||
}
|
||||
defer muGlobalChange.Unlock()
|
||||
|
||||
@@ -94,8 +95,9 @@ func GlobalGuardBytesBufferAlloc() error {
|
||||
|
||||
// Global setting
|
||||
func GlobalRestoreBytesBufferAlloc() {
|
||||
if !muGlobalChange.TryLock() {
|
||||
if muGlobalChange.TryLock() {
|
||||
return
|
||||
|
||||
}
|
||||
defer muGlobalChange.Unlock()
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ func Init(options *types.Options) error {
|
||||
|
||||
lfaAllowed = options.AllowLocalFileAccess
|
||||
opts := fastdialer.DefaultOptions
|
||||
if options.DisableDefaultResolvers {
|
||||
opts.HostsFile = false
|
||||
opts.ResolversFile = false
|
||||
}
|
||||
opts.DialerTimeout = options.GetTimeouts().DialTimeout
|
||||
if options.DialerKeepAlive > 0 {
|
||||
opts.DialerKeepAlive = options.DialerKeepAlive
|
||||
@@ -138,7 +134,6 @@ func Init(options *types.Options) error {
|
||||
if options.SystemResolvers {
|
||||
opts.ResolversFile = true
|
||||
opts.EnableFallback = true
|
||||
opts.HostsFile = true
|
||||
}
|
||||
if len(options.InternalResolversList) > 0 {
|
||||
opts.BaseResolvers = options.InternalResolversList
|
||||
|
||||
@@ -114,7 +114,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: types.ToString(wrapped.InternalEvent["host"]),
|
||||
Matched: types.ToString(wrapped.InternalEvent["matched"]),
|
||||
|
||||
@@ -104,7 +104,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Path: types.ToString(wrapped.InternalEvent["path"]),
|
||||
Matched: types.ToString(wrapped.InternalEvent["matched"]),
|
||||
|
||||
@@ -45,24 +45,9 @@ const (
|
||||
// ActionFilesInput performs an action on a file input.
|
||||
// name:files
|
||||
ActionFilesInput
|
||||
// ActionWaitDOM waits for the HTML document has been completely loaded & parsed.
|
||||
// name:waitdom
|
||||
ActionWaitDOM
|
||||
// ActionWaitFCP waits for the first piece of content (text, image, etc.) is painted on the screen.
|
||||
// name:waitfcp
|
||||
ActionWaitFCP
|
||||
// ActionWaitFMP waits for page has rendered enough meaningful content to be useful to the user.
|
||||
// name:waitfmp
|
||||
ActionWaitFMP
|
||||
// ActionWaitIdle waits for the network is completely idle (no ongoing network requests).
|
||||
// name:waitidle
|
||||
ActionWaitIdle
|
||||
// ActionWaitLoad waits for the page and all its resources (like stylesheets and images) have finished loading.
|
||||
// ActionWaitLoad waits for the page to stop loading.
|
||||
// name:waitload
|
||||
ActionWaitLoad
|
||||
// ActionWaitStable waits until the page is stable.
|
||||
// name:waitstable
|
||||
ActionWaitStable
|
||||
// ActionGetResource performs a get resource action on an element
|
||||
// name:getresource
|
||||
ActionGetResource
|
||||
@@ -117,12 +102,7 @@ var ActionStringToAction = map[string]ActionType{
|
||||
"time": ActionTimeInput,
|
||||
"select": ActionSelectInput,
|
||||
"files": ActionFilesInput,
|
||||
"waitdom": ActionWaitDOM,
|
||||
"waitfcp": ActionWaitFCP,
|
||||
"waitfmp": ActionWaitFMP,
|
||||
"waitidle": ActionWaitIdle,
|
||||
"waitload": ActionWaitLoad,
|
||||
"waitstable": ActionWaitStable,
|
||||
"getresource": ActionGetResource,
|
||||
"extract": ActionExtract,
|
||||
"setmethod": ActionSetMethod,
|
||||
@@ -149,12 +129,7 @@ var ActionToActionString = map[ActionType]string{
|
||||
ActionTimeInput: "time",
|
||||
ActionSelectInput: "select",
|
||||
ActionFilesInput: "files",
|
||||
ActionWaitDOM: "waitdom",
|
||||
ActionWaitFCP: "waitfcp",
|
||||
ActionWaitFMP: "waitfmp",
|
||||
ActionWaitIdle: "waitidle",
|
||||
ActionWaitLoad: "waitload",
|
||||
ActionWaitStable: "waitstable",
|
||||
ActionGetResource: "getresource",
|
||||
ActionExtract: "extract",
|
||||
ActionSetMethod: "setmethod",
|
||||
|
||||
@@ -94,28 +94,8 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action, var
|
||||
err = p.TimeInputElement(act, outData)
|
||||
case ActionSelectInput:
|
||||
err = p.SelectInputElement(act, outData)
|
||||
case ActionWaitDOM:
|
||||
event := proto.PageLifecycleEventNameDOMContentLoaded
|
||||
err = p.WaitPageLifecycleEvent(act, outData, event)
|
||||
case ActionWaitFCP:
|
||||
event := proto.PageLifecycleEventNameFirstContentfulPaint
|
||||
err = p.WaitPageLifecycleEvent(act, outData, event)
|
||||
case ActionWaitFMP:
|
||||
event := proto.PageLifecycleEventNameFirstMeaningfulPaint
|
||||
err = p.WaitPageLifecycleEvent(act, outData, event)
|
||||
case ActionWaitIdle:
|
||||
event := proto.PageLifecycleEventNameNetworkIdle
|
||||
err = p.WaitPageLifecycleEvent(act, outData, event)
|
||||
case ActionWaitLoad:
|
||||
event := proto.PageLifecycleEventNameLoad
|
||||
err = p.WaitPageLifecycleEvent(act, outData, event)
|
||||
case ActionWaitStable:
|
||||
err = p.WaitStable(act, outData)
|
||||
// NOTE(dwisiswant0): Mapping `ActionWaitLoad` to `Page.WaitStable`,
|
||||
// just in case waiting for the `proto.PageLifecycleEventNameLoad` event
|
||||
// doesn't meet expectations.
|
||||
// case ActionWaitLoad, ActionWaitStable:
|
||||
// err = p.WaitStable(act, outData)
|
||||
err = p.WaitLoad(act, outData)
|
||||
case ActionGetResource:
|
||||
err = p.GetResource(act, outData)
|
||||
case ActionExtract:
|
||||
@@ -224,17 +204,6 @@ func createBackOffSleeper(pollTimeout, timeout time.Duration) utils.Sleeper {
|
||||
}
|
||||
}
|
||||
|
||||
func getNavigationFunc(p *Page, act *Action, event proto.PageLifecycleEventName) (func(), error) {
|
||||
dur, err := getTimeout(p, act)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Wrong timeout given")
|
||||
}
|
||||
|
||||
fn := p.page.Timeout(dur).WaitNavigation(event)
|
||||
|
||||
return fn, nil
|
||||
}
|
||||
|
||||
func getTimeout(p *Page, act *Action) (time.Duration, error) {
|
||||
return geTimeParameter(p, act, "timeout", 3, time.Second)
|
||||
}
|
||||
@@ -549,38 +518,20 @@ func (p *Page) SelectInputElement(act *Action, out ActionData) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitPageLifecycleEvent waits for specified page lifecycle event name
|
||||
func (p *Page) WaitPageLifecycleEvent(act *Action, out ActionData, event proto.PageLifecycleEventName) error {
|
||||
fn, err := getNavigationFunc(p, act, event)
|
||||
if err != nil {
|
||||
return err
|
||||
// WaitLoad waits for the page to load
|
||||
func (p *Page) WaitLoad(act *Action, out ActionData) error {
|
||||
p.page.Timeout(2 * time.Second).WaitNavigation(proto.PageLifecycleEventNameFirstMeaningfulPaint)()
|
||||
|
||||
// Wait for the window.onload event and also wait for the network requests
|
||||
// to become idle for a maximum duration of 3 seconds. If the requests
|
||||
// do not finish,
|
||||
if err := p.page.WaitLoad(); err != nil {
|
||||
return errors.Wrap(err, "could not wait load event")
|
||||
}
|
||||
|
||||
fn()
|
||||
|
||||
_ = p.page.WaitIdle(1 * time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitStable waits until the page is stable
|
||||
func (p *Page) WaitStable(act *Action, out ActionData) error {
|
||||
var dur time.Duration = time.Second // default stable page duration: 1s
|
||||
|
||||
timeout, err := getTimeout(p, act)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Wrong timeout given")
|
||||
}
|
||||
|
||||
argDur := act.Data["duration"]
|
||||
if argDur != "" {
|
||||
dur, err = time.ParseDuration(argDur)
|
||||
if err != nil {
|
||||
dur = time.Second
|
||||
}
|
||||
}
|
||||
|
||||
return p.page.Timeout(timeout).WaitStable(dur)
|
||||
}
|
||||
|
||||
// GetResource gets a resource from an element from page.
|
||||
func (p *Page) GetResource(act *Action, out ActionData) error {
|
||||
element, err := p.pageElementBy(act.Data)
|
||||
|
||||
@@ -201,7 +201,7 @@ func TestActionScreenshot(t *testing.T) {
|
||||
filePath := filepath.Join(os.TempDir(), "test.png")
|
||||
actions := []*Action{
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionNavigate}, Data: map[string]string{"url": "{{BaseURL}}"}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionWaitFMP}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionWaitLoad}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionScreenshot}, Data: map[string]string{"to": filePath}},
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ func TestActionScreenshotToDir(t *testing.T) {
|
||||
|
||||
actions := []*Action{
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionNavigate}, Data: map[string]string{"url": "{{BaseURL}}"}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionWaitFMP}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionWaitLoad}},
|
||||
{ActionType: ActionTypeHolder{ActionType: ActionScreenshot}, Data: map[string]string{"to": filePath, "mkdir": "true"}},
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Path: fields.Path,
|
||||
|
||||
@@ -170,7 +170,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
|
||||
@@ -1042,10 +1042,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{}) {
|
||||
if protocolstate.Dialer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := protocolstate.Dialer.GetDNSData(hostname)
|
||||
if err == nil {
|
||||
switch len(data.CNAME) {
|
||||
@@ -1177,14 +1173,14 @@ func (request *Request) markUnresponsiveAddress(input *contextargs.Context, err
|
||||
return
|
||||
}
|
||||
if request.options.HostErrorsCache != nil {
|
||||
request.options.HostErrorsCache.MarkFailed(request.options.ProtocolType.String(), input, err)
|
||||
request.options.HostErrorsCache.MarkFailed(input, err)
|
||||
}
|
||||
}
|
||||
|
||||
// isUnresponsiveAddress checks if the error is a unreponsive based on its execution history
|
||||
func (request *Request) isUnresponsiveAddress(input *contextargs.Context) bool {
|
||||
if request.options.HostErrorsCache != nil {
|
||||
return request.options.HostErrorsCache.Check(request.options.ProtocolType.String(), input)
|
||||
return request.options.HostErrorsCache.Check(input)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value
|
||||
func (request *Request) executeGeneratedFuzzingRequest(gr fuzz.GeneratedRequest, input *contextargs.Context, callback protocols.OutputEventCallback) bool {
|
||||
hasInteractMatchers := interactsh.HasMatchers(request.CompiledOperators)
|
||||
hasInteractMarkers := len(gr.InteractURLs) > 0
|
||||
if request.options.HostErrorsCache != nil && request.options.HostErrorsCache.Check(request.options.ProtocolType.String(), input) {
|
||||
if request.options.HostErrorsCache != nil && request.options.HostErrorsCache.Check(input) {
|
||||
return false
|
||||
}
|
||||
request.options.RateLimitTake()
|
||||
@@ -215,7 +215,7 @@ func (request *Request) executeGeneratedFuzzingRequest(gr fuzz.GeneratedRequest,
|
||||
}
|
||||
if requestErr != nil {
|
||||
if request.options.HostErrorsCache != nil {
|
||||
request.options.HostErrorsCache.MarkFailed(request.options.ProtocolType.String(), input, requestErr)
|
||||
request.options.HostErrorsCache.MarkFailed(input, requestErr)
|
||||
}
|
||||
gologger.Verbose().Msgf("[%s] Error occurred in request: %s\n", request.options.TemplateID, requestErr)
|
||||
}
|
||||
|
||||
@@ -766,7 +766,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
|
||||
@@ -100,14 +100,13 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
fields.Ip = types.ToString(wrapped.InternalEvent["ip"])
|
||||
}
|
||||
data := &output.ResultEvent{
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
URL: fields.URL,
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
URL: fields.URL,
|
||||
Matched: types.ToString(wrapped.InternalEvent["matched"]),
|
||||
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
|
||||
Metadata: wrapped.OperatorsResult.PayloadValues,
|
||||
|
||||
@@ -504,14 +504,14 @@ func (request *Request) markUnresponsiveAddress(input *contextargs.Context, err
|
||||
return
|
||||
}
|
||||
if request.options.HostErrorsCache != nil {
|
||||
request.options.HostErrorsCache.MarkFailed(request.options.ProtocolType.String(), input, err)
|
||||
request.options.HostErrorsCache.MarkFailed(input, err)
|
||||
}
|
||||
}
|
||||
|
||||
// isUnresponsiveAddress checks if the error is a unreponsive based on its execution history
|
||||
func (request *Request) isUnresponsiveAddress(input *contextargs.Context) bool {
|
||||
if request.options.HostErrorsCache != nil {
|
||||
return request.options.HostErrorsCache.Check(request.options.ProtocolType.String(), input)
|
||||
return request.options.HostErrorsCache.Check(input)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -142,7 +142,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Path: types.ToString(wrapped.InternalEvent["path"]),
|
||||
Matched: types.ToString(wrapped.InternalEvent["matched"]),
|
||||
|
||||
@@ -61,8 +61,6 @@ type ExecutorOptions struct {
|
||||
TemplatePath string
|
||||
// TemplateInfo contains information block of the template request
|
||||
TemplateInfo model.Info
|
||||
// TemplateVerifier is the verifier for the template
|
||||
TemplateVerifier string
|
||||
// RawTemplate is the raw template for the request
|
||||
RawTemplate []byte
|
||||
// Output is a writer interface for writing output events from executer.
|
||||
|
||||
@@ -347,33 +347,11 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
|
||||
// description. Multiple definitions are separated by commas.
|
||||
// Definitions not having a name (generated on runtime) are prefixed & suffixed by <>.
|
||||
var RequestPartDefinitions = map[string]string{
|
||||
"template-id": "ID of the template executed",
|
||||
"template-info": "Info Block of the template executed",
|
||||
"template-path": "Path of the template executed",
|
||||
"host": "Host is the input to the template",
|
||||
"port": "Port is the port of the host",
|
||||
"matched": "Matched is the input which was matched upon",
|
||||
"type": "Type is the type of request made",
|
||||
"timestamp": "Timestamp is the time when the request was made",
|
||||
"response": "JSON SSL protocol handshake details",
|
||||
"cipher": "Cipher is the encryption algorithm used",
|
||||
"domains": "Domains are the list of domain names in the certificate",
|
||||
"fingerprint_hash": "Fingerprint hash is the unique identifier of the certificate",
|
||||
"ip": "IP is the IP address of the server",
|
||||
"issuer_cn": "Issuer CN is the common name of the certificate issuer",
|
||||
"issuer_dn": "Issuer DN is the distinguished name of the certificate issuer",
|
||||
"issuer_org": "Issuer organization is the organization of the certificate issuer",
|
||||
"not_after": "Timestamp after which the remote cert expires",
|
||||
"not_before": "Timestamp before which the certificate is not valid",
|
||||
"probe_status": "Probe status indicates if the probe was successful",
|
||||
"serial": "Serial is the serial number of the certificate",
|
||||
"sni": "SNI is the server name indication used in the handshake",
|
||||
"subject_an": "Subject AN is the list of subject alternative names",
|
||||
"subject_cn": "Subject CN is the common name of the certificate subject",
|
||||
"subject_dn": "Subject DN is the distinguished name of the certificate subject",
|
||||
"subject_org": "Subject organization is the organization of the certificate subject",
|
||||
"tls_connection": "TLS connection is the type of TLS connection used",
|
||||
"tls_version": "TLS version is the version of the TLS protocol used",
|
||||
"type": "Type is the type of request made",
|
||||
"response": "JSON SSL protocol handshake details",
|
||||
"not_after": "Timestamp after which the remote cert expires",
|
||||
"host": "Host is the input to the template",
|
||||
"matched": "Matched is the input which was matched upon",
|
||||
}
|
||||
|
||||
// Match performs matching operation for a matcher on model and returns:
|
||||
@@ -420,7 +398,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(wrapped.InternalEvent["template-id"]),
|
||||
TemplatePath: types.ToString(wrapped.InternalEvent["template-path"]),
|
||||
Info: wrapped.InternalEvent["template-info"].(model.Info),
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
|
||||
@@ -402,7 +402,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(request.options.TemplateID),
|
||||
TemplatePath: types.ToString(request.options.TemplatePath),
|
||||
Info: request.options.TemplateInfo,
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: fields.Host,
|
||||
Port: fields.Port,
|
||||
|
||||
@@ -177,7 +177,6 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent
|
||||
TemplateID: types.ToString(request.options.TemplateID),
|
||||
TemplatePath: types.ToString(request.options.TemplatePath),
|
||||
Info: request.options.TemplateInfo,
|
||||
TemplateVerifier: request.options.TemplateVerifier,
|
||||
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||
Host: types.ToString(wrapped.InternalEvent["host"]),
|
||||
Metadata: wrapped.OperatorsResult.PayloadValues,
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
package mongo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
mongooptions "go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Exporter struct {
|
||||
options *Options
|
||||
mutex *sync.Mutex
|
||||
rows []output.ResultEvent
|
||||
collection *mongo.Collection
|
||||
connection *mongo.Client
|
||||
}
|
||||
|
||||
// Options contains the configuration options for MongoDB exporter client
|
||||
type Options struct {
|
||||
// ConnectionString is the connection string to the MongoDB database
|
||||
ConnectionString string `yaml:"connection-string"`
|
||||
// CollectionName is the name of the MongoDB collection in which to store the results
|
||||
CollectionName string `yaml:"collection-name"`
|
||||
// OmitRaw excludes the Request and Response from the results (helps with filesize)
|
||||
OmitRaw bool `yaml:"omit-raw"`
|
||||
// BatchSize determines the number of results to be kept in memory before writing it to the database or 0 to
|
||||
// persist all in memory and write all results at the end (default)
|
||||
BatchSize int `yaml:"batch-size"`
|
||||
}
|
||||
|
||||
// New creates a new MongoDB exporter integration client based on options.
|
||||
func New(options *Options) (*Exporter, error) {
|
||||
exporter := &Exporter{
|
||||
mutex: &sync.Mutex{},
|
||||
options: options,
|
||||
rows: []output.ResultEvent{},
|
||||
}
|
||||
|
||||
// If the environment variable for the connection string is set, then use that instead. This allows for easier
|
||||
// management of sensitive items such as credentials
|
||||
envConnectionString := os.Getenv("MONGO_CONNECTION_STRING")
|
||||
if envConnectionString != "" {
|
||||
options.ConnectionString = envConnectionString
|
||||
gologger.Info().Msgf("Using connection string from environment variable MONGO_CONNECTION_STRING")
|
||||
}
|
||||
|
||||
// Create the connection to the database
|
||||
clientOptions := mongooptions.Client().ApplyURI(options.ConnectionString)
|
||||
|
||||
// Create a new client and connect to the MongoDB server
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error creating MongoDB client: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the connection is valid
|
||||
err = client.Ping(context.Background(), nil)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error connecting to MongoDB: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the database from the connection string to set the database and collection
|
||||
parsed, err := url.Parse(options.ConnectionString)
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error parsing connection string: %s", options.ConnectionString)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
databaseName := strings.TrimPrefix(parsed.Path, "/")
|
||||
|
||||
if databaseName == "" {
|
||||
return nil, errors.New("error getting database name from connection string")
|
||||
}
|
||||
|
||||
exporter.connection = client
|
||||
exporter.collection = client.Database(databaseName).Collection(options.CollectionName)
|
||||
|
||||
return exporter, nil
|
||||
}
|
||||
|
||||
// Export writes a result document to the configured MongoDB collection
|
||||
// in the database configured by the connection string
|
||||
func (exporter *Exporter) Export(event *output.ResultEvent) error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
if exporter.options.OmitRaw {
|
||||
event.Request = ""
|
||||
event.Response = ""
|
||||
}
|
||||
|
||||
// Add the row to the queue to be processed
|
||||
exporter.rows = append(exporter.rows, *event)
|
||||
|
||||
// If the batch size is greater than 0 and the number of rows has reached the batch, flush it to the database
|
||||
if exporter.options.BatchSize > 0 && len(exporter.rows) >= exporter.options.BatchSize {
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteRows writes all rows from the rows list to the MongoDB collection and removes them from the list
|
||||
func (exporter *Exporter) WriteRows() error {
|
||||
// Loop through the rows and write them, removing them as they're entered
|
||||
for len(exporter.rows) > 0 {
|
||||
data := exporter.rows[0]
|
||||
|
||||
// Write the data to the database
|
||||
_, err := exporter.collection.InsertOne(context.TODO(), data)
|
||||
if err != nil {
|
||||
gologger.Fatal().Msgf("Error inserting record into MongoDB collection: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove the item from the list
|
||||
exporter.rows = exporter.rows[1:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (exporter *Exporter) Close() error {
|
||||
exporter.mutex.Lock()
|
||||
defer exporter.mutex.Unlock()
|
||||
|
||||
// Write all pending rows
|
||||
err := exporter.WriteRows()
|
||||
if err != nil {
|
||||
// The error is already logged, return it to bubble up to the caller
|
||||
return err
|
||||
}
|
||||
|
||||
// Close the database connection
|
||||
err = exporter.connection.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
gologger.Error().Msgf("Error disconnecting from MongoDB: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonexporter"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonl"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/sarif"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/splunk"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters"
|
||||
@@ -45,8 +44,6 @@ type Options struct {
|
||||
JSONExporter *jsonexporter.Options `yaml:"json"`
|
||||
// JSONLExporter contains configuration options for JSONL Exporter Module
|
||||
JSONLExporter *jsonl.Options `yaml:"jsonl"`
|
||||
// MongoDBExporter containers the configuration options for the MongoDB Exporter Module
|
||||
MongoDBExporter *mongo.Options `yaml:"mongodb"`
|
||||
|
||||
HttpClient *retryablehttp.Client `yaml:"-"`
|
||||
OmitRaw bool `yaml:"-"`
|
||||
|
||||
@@ -2,7 +2,6 @@ package reporting
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
|
||||
"os"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@@ -167,13 +166,6 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
|
||||
}
|
||||
client.exporters = append(client.exporters, exporter)
|
||||
}
|
||||
if options.MongoDBExporter != nil {
|
||||
exporter, err := mongo.New(options.MongoDBExporter)
|
||||
if err != nil {
|
||||
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
|
||||
}
|
||||
client.exporters = append(client.exporters, exporter)
|
||||
}
|
||||
|
||||
if doNotDedupe {
|
||||
return client, nil
|
||||
@@ -220,7 +212,6 @@ func CreateConfigIfNotExists() error {
|
||||
SplunkExporter: &splunk.Options{},
|
||||
JSONExporter: &json_exporter.Options{},
|
||||
JSONLExporter: &jsonl.Options{},
|
||||
MongoDBExporter: &mongo.Options{},
|
||||
}
|
||||
reportingFile, err := os.Create(reportingConfig)
|
||||
if err != nil {
|
||||
|
||||
+17
-10
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
)
|
||||
|
||||
type ScanContextOption func(*ScanContext)
|
||||
@@ -31,7 +30,7 @@ type ScanContext struct {
|
||||
OnWarning func(string)
|
||||
|
||||
// unexported state fields
|
||||
error error
|
||||
errors []error
|
||||
warnings []string
|
||||
events []*output.InternalWrappedEvent
|
||||
results []*output.ResultEvent
|
||||
@@ -53,8 +52,8 @@ func (s *ScanContext) Context() context.Context {
|
||||
return s.ctx
|
||||
}
|
||||
|
||||
func (s *ScanContext) GenerateErrorMessage() error {
|
||||
return s.error
|
||||
func (s *ScanContext) GenerateErrorMessage() string {
|
||||
return joinErrors(s.errors)
|
||||
}
|
||||
|
||||
// GenerateResult returns final results slice from all events
|
||||
@@ -95,16 +94,13 @@ func (s *ScanContext) LogError(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if s.OnError != nil {
|
||||
s.OnError(err)
|
||||
}
|
||||
if s.error == nil {
|
||||
s.error = err
|
||||
} else {
|
||||
s.error = errkit.Append(s.error, err)
|
||||
}
|
||||
s.errors = append(s.errors, err)
|
||||
|
||||
errorMessage := s.GenerateErrorMessage().Error()
|
||||
errorMessage := s.GenerateErrorMessage()
|
||||
|
||||
for _, result := range s.results {
|
||||
result.Error = errorMessage
|
||||
@@ -133,3 +129,14 @@ func (s *ScanContext) LogWarning(format string, args ...any) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// joinErrors joins multiple errors and returns a single error string
|
||||
func joinErrors(errors []error) string {
|
||||
var errorMessages []string
|
||||
for _, e := range errors {
|
||||
if e != nil {
|
||||
errorMessages = append(errorMessages, e.Error())
|
||||
}
|
||||
}
|
||||
return strings.Join(errorMessages, "; ")
|
||||
}
|
||||
+17
-21
@@ -251,30 +251,28 @@ func (e *ClusterExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
event.InternalEvent = make(map[string]interface{})
|
||||
}
|
||||
for _, operator := range e.operators {
|
||||
clonedEvent := event.CloneShallow()
|
||||
|
||||
result, matched := operator.operator.Execute(clonedEvent.InternalEvent, e.requests.Match, e.requests.Extract, e.options.Options.Debug || e.options.Options.DebugResponse)
|
||||
clonedEvent.InternalEvent["template-id"] = operator.templateID
|
||||
clonedEvent.InternalEvent["template-path"] = operator.templatePath
|
||||
clonedEvent.InternalEvent["template-info"] = operator.templateInfo
|
||||
result, matched := operator.operator.Execute(event.InternalEvent, e.requests.Match, e.requests.Extract, e.options.Options.Debug || e.options.Options.DebugResponse)
|
||||
event.InternalEvent["template-id"] = operator.templateID
|
||||
event.InternalEvent["template-path"] = operator.templatePath
|
||||
event.InternalEvent["template-info"] = operator.templateInfo
|
||||
|
||||
if result == nil && !matched && e.options.Options.MatcherStatus {
|
||||
if err := e.options.Output.WriteFailure(clonedEvent); err != nil {
|
||||
if err := e.options.Output.WriteFailure(event); err != nil {
|
||||
gologger.Warning().Msgf("Could not write failure event to output: %s\n", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if matched && result != nil {
|
||||
clonedEvent.OperatorsResult = result
|
||||
clonedEvent.Results = e.requests.MakeResultEvent(clonedEvent)
|
||||
event.OperatorsResult = result
|
||||
event.Results = e.requests.MakeResultEvent(event)
|
||||
results = true
|
||||
|
||||
_ = writer.WriteResult(clonedEvent, e.options.Output, e.options.Progress, e.options.IssuesClient)
|
||||
_ = writer.WriteResult(event, e.options.Output, e.options.Progress, e.options.IssuesClient)
|
||||
}
|
||||
}
|
||||
})
|
||||
if err != nil && e.options.HostErrorsCache != nil {
|
||||
e.options.HostErrorsCache.MarkFailed(e.options.ProtocolType.String(), ctx.Input, err)
|
||||
e.options.HostErrorsCache.MarkFailed(ctx.Input, err)
|
||||
}
|
||||
return results, err
|
||||
}
|
||||
@@ -292,16 +290,14 @@ func (e *ClusterExecuter) ExecuteWithResults(ctx *scan.ScanContext) ([]*output.R
|
||||
}
|
||||
err := e.requests.ExecuteWithResults(inputItem, dynamicValues, nil, func(event *output.InternalWrappedEvent) {
|
||||
for _, operator := range e.operators {
|
||||
clonedEvent := event.CloneShallow()
|
||||
|
||||
result, matched := operator.operator.Execute(clonedEvent.InternalEvent, e.requests.Match, e.requests.Extract, e.options.Options.Debug || e.options.Options.DebugResponse)
|
||||
result, matched := operator.operator.Execute(event.InternalEvent, e.requests.Match, e.requests.Extract, e.options.Options.Debug || e.options.Options.DebugResponse)
|
||||
if matched && result != nil {
|
||||
clonedEvent.OperatorsResult = result
|
||||
clonedEvent.InternalEvent["template-id"] = operator.templateID
|
||||
clonedEvent.InternalEvent["template-path"] = operator.templatePath
|
||||
clonedEvent.InternalEvent["template-info"] = operator.templateInfo
|
||||
clonedEvent.Results = e.requests.MakeResultEvent(clonedEvent)
|
||||
scanCtx.LogEvent(clonedEvent)
|
||||
event.OperatorsResult = result
|
||||
event.InternalEvent["template-id"] = operator.templateID
|
||||
event.InternalEvent["template-path"] = operator.templatePath
|
||||
event.InternalEvent["template-info"] = operator.templateInfo
|
||||
event.Results = e.requests.MakeResultEvent(event)
|
||||
scanCtx.LogEvent(event)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -310,7 +306,7 @@ func (e *ClusterExecuter) ExecuteWithResults(ctx *scan.ScanContext) ([]*output.R
|
||||
}
|
||||
|
||||
if err != nil && e.options.HostErrorsCache != nil {
|
||||
e.options.HostErrorsCache.MarkFailed(e.options.ProtocolType.String(), ctx.Input, err)
|
||||
e.options.HostErrorsCache.MarkFailed(ctx.Input, err)
|
||||
}
|
||||
return scanCtx.GenerateResult(), err
|
||||
}
|
||||
@@ -36,7 +36,8 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
Unsigned = "unsigned"
|
||||
Unsigned = "unsigned"
|
||||
PDVerifier = "projectdiscovery/nuclei-templates"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -419,7 +420,7 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e
|
||||
break
|
||||
}
|
||||
}
|
||||
options.TemplateVerifier = template.TemplateVerifier
|
||||
|
||||
if !(template.Verified && verifier.Identifier() == "projectdiscovery/nuclei-templates") {
|
||||
template.Options.RawTemplate = data
|
||||
}
|
||||
|
||||
@@ -1603,12 +1603,7 @@ func init() {
|
||||
"time",
|
||||
"select",
|
||||
"files",
|
||||
"waitdom",
|
||||
"waitfcp",
|
||||
"waitfmp",
|
||||
"waitidle",
|
||||
"waitload",
|
||||
"waitstable",
|
||||
"getresource",
|
||||
"extract",
|
||||
"setmethod",
|
||||
@@ -1656,113 +1651,25 @@ func init() {
|
||||
},
|
||||
}
|
||||
SSLRequestDoc.PartDefinitions = []encoder.KeyValue{
|
||||
{
|
||||
Key: "template-id",
|
||||
Value: "ID of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "template-info",
|
||||
Value: "Info Block of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "template-path",
|
||||
Value: "Path of the template executed",
|
||||
},
|
||||
{
|
||||
Key: "host",
|
||||
Value: "Host is the input to the template",
|
||||
},
|
||||
{
|
||||
Key: "port",
|
||||
Value: "Port is the port of the host",
|
||||
},
|
||||
{
|
||||
Key: "matched",
|
||||
Value: "Matched is the input which was matched upon",
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Value: "Type is the type of request made",
|
||||
},
|
||||
{
|
||||
Key: "timestamp",
|
||||
Value: "Timestamp is the time when the request was made",
|
||||
},
|
||||
{
|
||||
Key: "response",
|
||||
Value: "JSON SSL protocol handshake details",
|
||||
},
|
||||
{
|
||||
Key: "cipher",
|
||||
Value: "Cipher is the encryption algorithm used",
|
||||
},
|
||||
{
|
||||
Key: "domains",
|
||||
Value: "Domains are the list of domain names in the certificate",
|
||||
},
|
||||
{
|
||||
Key: "fingerprint_hash",
|
||||
Value: "Fingerprint hash is the unique identifier of the certificate",
|
||||
},
|
||||
{
|
||||
Key: "ip",
|
||||
Value: "IP is the IP address of the server",
|
||||
},
|
||||
{
|
||||
Key: "issuer_cn",
|
||||
Value: "Issuer CN is the common name of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "issuer_dn",
|
||||
Value: "Issuer DN is the distinguished name of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "issuer_org",
|
||||
Value: "Issuer organization is the organization of the certificate issuer",
|
||||
},
|
||||
{
|
||||
Key: "not_after",
|
||||
Value: "Timestamp after which the remote cert expires",
|
||||
},
|
||||
{
|
||||
Key: "not_before",
|
||||
Value: "Timestamp before which the certificate is not valid",
|
||||
Key: "host",
|
||||
Value: "Host is the input to the template",
|
||||
},
|
||||
{
|
||||
Key: "probe_status",
|
||||
Value: "Probe status indicates if the probe was successful",
|
||||
},
|
||||
{
|
||||
Key: "serial",
|
||||
Value: "Serial is the serial number of the certificate",
|
||||
},
|
||||
{
|
||||
Key: "sni",
|
||||
Value: "SNI is the server name indication used in the handshake",
|
||||
},
|
||||
{
|
||||
Key: "subject_an",
|
||||
Value: "Subject AN is the list of subject alternative names",
|
||||
},
|
||||
{
|
||||
Key: "subject_cn",
|
||||
Value: "Subject CN is the common name of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "subject_dn",
|
||||
Value: "Subject DN is the distinguished name of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "subject_org",
|
||||
Value: "Subject organization is the organization of the certificate subject",
|
||||
},
|
||||
{
|
||||
Key: "tls_connection",
|
||||
Value: "TLS connection is the type of TLS connection used",
|
||||
},
|
||||
{
|
||||
Key: "tls_version",
|
||||
Value: "TLS version is the version of the TLS protocol used",
|
||||
Key: "matched",
|
||||
Value: "Matched is the input which was matched upon",
|
||||
},
|
||||
}
|
||||
SSLRequestDoc.Fields = make([]encoder.Doc, 9)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/keys"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/model"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
|
||||
@@ -106,7 +105,7 @@ func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, preprocessor Pr
|
||||
// increment signed/unsigned counters
|
||||
if template.Verified {
|
||||
if template.TemplateVerifier == "" {
|
||||
SignatureStats[keys.PDVerifier].Add(1)
|
||||
SignatureStats[PDVerifier].Add(1)
|
||||
} else {
|
||||
SignatureStats[template.TemplateVerifier].Add(1)
|
||||
}
|
||||
|
||||
+13
-12
@@ -89,17 +89,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
|
||||
@@ -116,6 +116,7 @@ type MockOutputWriter struct {
|
||||
aurora aurora.Aurora
|
||||
omitTemplate bool
|
||||
RequestCallback func(templateID, url, requestType string, err error)
|
||||
FailureCallback func(result *output.InternalEvent)
|
||||
WriteCallback func(o *output.ResultEvent)
|
||||
}
|
||||
|
||||
@@ -166,7 +167,7 @@ func (m *MockOutputWriter) WriteFailure(wrappedEvent *output.InternalWrappedEven
|
||||
|
||||
// create event
|
||||
event := wrappedEvent.InternalEvent
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]), types.ToString(event["template-id"]), types.ToString(event["template-verifier"]))
|
||||
templatePath, templateURL := utils.TemplatePathURL(types.ToString(event["template-path"]), types.ToString(event["template-id"]))
|
||||
var templateInfo model.Info
|
||||
if ti, ok := event["template-info"].(model.Info); ok {
|
||||
templateInfo = ti
|
||||
|
||||
+24
-21
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/flow"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/generic"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/multiproto"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types/nucleierr"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
)
|
||||
|
||||
@@ -206,9 +207,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
ctx.LogError(errx)
|
||||
|
||||
if lastMatcherEvent != nil {
|
||||
lastMatcherEvent.Lock()
|
||||
lastMatcherEvent.InternalEvent["error"] = getErrorCause(ctx.GenerateErrorMessage())
|
||||
lastMatcherEvent.Unlock()
|
||||
lastMatcherEvent.InternalEvent["error"] = tryParseCause(fmt.Errorf("%s", ctx.GenerateErrorMessage()))
|
||||
writeFailureCallback(lastMatcherEvent, e.options.Options.MatcherStatus)
|
||||
}
|
||||
|
||||
@@ -223,7 +222,7 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
Info: e.options.TemplateInfo,
|
||||
Type: e.getTemplateType(),
|
||||
Host: ctx.Input.MetaInput.Input,
|
||||
Error: getErrorCause(ctx.GenerateErrorMessage()),
|
||||
Error: tryParseCause(fmt.Errorf("%s", ctx.GenerateErrorMessage())),
|
||||
},
|
||||
},
|
||||
OperatorsResult: &operators.Result{
|
||||
@@ -236,27 +235,31 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
|
||||
return executed.Load() || matched.Load(), errx
|
||||
}
|
||||
|
||||
// getErrorCause tries to parse the cause of given error
|
||||
// tryParseCause tries to parse the cause of given error
|
||||
// this is legacy support due to use of errorutil in existing libraries
|
||||
// but this should not be required once all libraries are updated
|
||||
func getErrorCause(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
errx := errkit.FromError(err)
|
||||
var cause error
|
||||
for _, e := range errx.Errors() {
|
||||
if e != nil && strings.Contains(e.Error(), "context deadline exceeded") {
|
||||
continue
|
||||
func tryParseCause(err error) string {
|
||||
errStr := ""
|
||||
errX := errkit.FromError(err)
|
||||
if errX != nil {
|
||||
var errCause error
|
||||
|
||||
if len(errX.Errors()) > 1 {
|
||||
errCause = errX.Errors()[0]
|
||||
}
|
||||
cause = e
|
||||
break
|
||||
if errCause == nil {
|
||||
errCause = errX
|
||||
}
|
||||
|
||||
msg := strings.Trim(errCause.Error(), "{} ")
|
||||
parts := strings.Split(msg, ":")
|
||||
errCause = errkit.New("%s", parts[len(parts)-1])
|
||||
errKind := errkit.GetErrorKind(err, nucleierr.ErrTemplateLogic).String()
|
||||
errStr = errCause.Error()
|
||||
errStr = strings.TrimSpace(strings.Replace(errStr, "errKind="+errKind, "", -1))
|
||||
}
|
||||
if cause == nil {
|
||||
cause = errkit.Append(errkit.New("could not get error cause"), errx)
|
||||
}
|
||||
// parseScanError prettifies the error message and removes everything except the cause
|
||||
return parseScanError(cause.Error())
|
||||
|
||||
return errStr
|
||||
}
|
||||
|
||||
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||
|
||||
@@ -85,7 +85,7 @@ func (g *Generic) ExecuteWithResults(ctx *scan.ScanContext) error {
|
||||
if err != nil {
|
||||
ctx.LogError(err)
|
||||
if g.options.HostErrorsCache != nil {
|
||||
g.options.HostErrorsCache.MarkFailed(g.options.ProtocolType.String(), ctx.Input, err)
|
||||
g.options.HostErrorsCache.MarkFailed(ctx.Input, err)
|
||||
}
|
||||
gologger.Warning().Msgf("[%s] Could not execute request for %s: %s\n", g.options.TemplateID, ctx.Input.MetaInput.PrettyPrint(), err)
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
package tmplexec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/flow"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/generic"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/multiproto"
|
||||
"github.com/projectdiscovery/utils/errkit"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -35,37 +30,3 @@ type TemplateEngine interface {
|
||||
// Name returns name of template engine
|
||||
Name() string
|
||||
}
|
||||
|
||||
var (
|
||||
// A temporary fix to remove errKind from error message
|
||||
// this is because errkit is not used everywhere yet
|
||||
reNoKind = regexp.MustCompile(`([\[][^][]+[\]]|errKind=[^ ]+) `)
|
||||
)
|
||||
|
||||
// parseScanError parses given scan error and only returning the cause
|
||||
// instead of inefficient one
|
||||
func parseScanError(msg string) string {
|
||||
if msg == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.HasPrefix(msg, "ReadStatusLine:") {
|
||||
// last index is actual error (from rawhttp)
|
||||
parts := strings.Split(msg, ":")
|
||||
msg = strings.TrimSpace(parts[len(parts)-1])
|
||||
}
|
||||
if strings.Contains(msg, "read ") {
|
||||
// same here
|
||||
parts := strings.Split(msg, ":")
|
||||
msg = strings.TrimSpace(parts[len(parts)-1])
|
||||
}
|
||||
e := errkit.FromError(errors.New(msg))
|
||||
for _, err := range e.Errors() {
|
||||
if err != nil && strings.Contains(err.Error(), "context deadline exceeded") {
|
||||
continue
|
||||
}
|
||||
msg = reNoKind.ReplaceAllString(err.Error(), "")
|
||||
return msg
|
||||
}
|
||||
wrapped := errkit.Append(errkit.New("failed to get error cause"), e).Error()
|
||||
return reNoKind.ReplaceAllString(wrapped, "")
|
||||
}
|
||||
+2
-23
@@ -23,9 +23,6 @@ var (
|
||||
ErrNoMoreRequests = io.EOF
|
||||
)
|
||||
|
||||
// LoadHelperFileFunction can be used to load a helper file.
|
||||
type LoadHelperFileFunction func(helperFile, templatePath string, catalog catalog.Catalog) (io.ReadCloser, error)
|
||||
|
||||
// Options contains the configuration options for nuclei scanner.
|
||||
type Options struct {
|
||||
// Tags contains a list of tags to execute templates for. Multiple paths
|
||||
@@ -179,8 +176,6 @@ type Options struct {
|
||||
UseInstalledChrome bool
|
||||
// SystemResolvers enables override of nuclei's DNS client opting to use system resolver stack.
|
||||
SystemResolvers bool
|
||||
// DisableDNSResolvers disables default DNS resolvers for nuclei
|
||||
DisableDefaultResolvers bool
|
||||
// ShowActions displays a list of all headless actions
|
||||
ShowActions bool
|
||||
// Deprecated: Enabled by default through clistats . Metrics enables display of metrics via an http endpoint
|
||||
@@ -389,8 +384,6 @@ type Options struct {
|
||||
ScanID string
|
||||
// ScanName is the name of the scan to be uploaded
|
||||
ScanName string
|
||||
// ScanUploadFile is the jsonl file to upload scan results to cloud
|
||||
ScanUploadFile string
|
||||
// TeamID is the team ID to use for cloud upload
|
||||
TeamID string
|
||||
// JsConcurrency is the number of concurrent js routines to run
|
||||
@@ -413,9 +406,6 @@ type Options struct {
|
||||
HttpApiEndpoint string
|
||||
// ListTemplateProfiles lists all available template profiles
|
||||
ListTemplateProfiles bool
|
||||
// LoadHelperFileFunction is a function that will be used to execute LoadHelperFile.
|
||||
// If none is provided, then the default implementation will be used.
|
||||
LoadHelperFileFunction LoadHelperFileFunction
|
||||
// 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
|
||||
@@ -548,21 +538,10 @@ func (options *Options) ParseHeadlessOptionalArguments() map[string]string {
|
||||
return optionalArguments
|
||||
}
|
||||
|
||||
// LoadHelperFile loads a helper file needed for the template.
|
||||
//
|
||||
// If LoadHelperFileFunction is set, then that function will be used.
|
||||
// Otherwise, the default implementation will be used, which respects the sandbox rules and only loads files from allowed directories.
|
||||
func (options *Options) LoadHelperFile(helperFile, templatePath string, catalog catalog.Catalog) (io.ReadCloser, error) {
|
||||
if options.LoadHelperFileFunction != nil {
|
||||
return options.LoadHelperFileFunction(helperFile, templatePath, catalog)
|
||||
}
|
||||
return options.defaultLoadHelperFile(helperFile, templatePath, catalog)
|
||||
}
|
||||
|
||||
// defaultLoadHelperFile loads a helper file needed for the template
|
||||
// LoadHelperFile loads a helper file needed for the template
|
||||
// this respects the sandbox rules and only loads files from
|
||||
// allowed directories
|
||||
func (options *Options) defaultLoadHelperFile(helperFile, templatePath string, catalog catalog.Catalog) (io.ReadCloser, error) {
|
||||
func (options *Options) LoadHelperFile(helperFile, templatePath string, catalog catalog.Catalog) (io.ReadCloser, error) {
|
||||
if !options.AllowLocalFileAccess {
|
||||
// if global file access is disabled try loading with restrictions
|
||||
absPath, err := options.GetValidAbsPath(helperFile, templatePath)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/keys"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -13,13 +12,16 @@ const (
|
||||
)
|
||||
|
||||
// TemplatePathURL returns the Path and URL for the provided template
|
||||
func TemplatePathURL(fullPath, templateId, templateVerifier string) (path string, url string) {
|
||||
func TemplatePathURL(fullPath, templateId string) (string, string) {
|
||||
var templateDirectory string
|
||||
configData := config.DefaultConfig
|
||||
if configData.TemplatesDirectory != "" && strings.HasPrefix(fullPath, configData.TemplatesDirectory) {
|
||||
path = strings.TrimPrefix(strings.TrimPrefix(fullPath, configData.TemplatesDirectory), "/")
|
||||
templateDirectory = configData.TemplatesDirectory
|
||||
} else {
|
||||
return "", ""
|
||||
}
|
||||
if templateVerifier == keys.PDVerifier {
|
||||
url = TemplatesRepoURL + templateId
|
||||
}
|
||||
return
|
||||
|
||||
finalPath := strings.TrimPrefix(strings.TrimPrefix(fullPath, templateDirectory), "/")
|
||||
templateURL := TemplatesRepoURL + templateId
|
||||
return finalPath, templateURL
|
||||
}
|
||||
Reference in new issue
Block a user