mirror of https://github.com/daffainfo/nuclei.git
Merge branch 'dev' into feature-ldap
commit
8fbe451d54
|
@ -7,7 +7,10 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Test Builds
|
name: Test Builds
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
|
|
|
@ -8,7 +8,10 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
functional:
|
functional:
|
||||||
name: Functional Test
|
name: Functional Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
|
@ -23,5 +26,5 @@ jobs:
|
||||||
GH_ACTION: true
|
GH_ACTION: true
|
||||||
run: |
|
run: |
|
||||||
chmod +x run.sh
|
chmod +x run.sh
|
||||||
bash run.sh
|
bash run.sh ${{ matrix.os }}
|
||||||
working-directory: v2/cmd/functional-test
|
working-directory: v2/cmd/functional-test
|
||||||
|
|
|
@ -247,6 +247,19 @@ Websocket contains the Websocket request to make in the template.
|
||||||
|
|
||||||
<div class="dd">
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>whois</code> <i>[]<a href="#whoisrequest">whois.Request</a></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
WHOIS contains the WHOIS request to make in the template.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
<code>workflows</code> <i>[]<a href="#workflowsworkflowtemplate">workflows.WorkflowTemplate</a></i>
|
<code>workflows</code> <i>[]<a href="#workflowsworkflowtemplate">workflows.WorkflowTemplate</a></i>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -284,6 +297,24 @@ Stop execution once first match is found
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>signature</code> <i><a href="#httpsignaturetypeholder">http.SignatureTypeHolder</a></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
Signature is the request signature method
|
||||||
|
|
||||||
|
|
||||||
|
Valid values:
|
||||||
|
|
||||||
|
|
||||||
|
- <code>AWS</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1169,6 +1200,24 @@ max-size: 2048
|
||||||
|
|
||||||
<div class="dd">
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>signature</code> <i><a href="#signaturetypeholder">SignatureTypeHolder</a></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
Signature is the request signature method
|
||||||
|
|
||||||
|
|
||||||
|
Valid values:
|
||||||
|
|
||||||
|
|
||||||
|
- <code>AWS</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
<code>cookie-reuse</code> <i>bool</i>
|
<code>cookie-reuse</code> <i>bool</i>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1320,6 +1369,8 @@ Appears in:
|
||||||
|
|
||||||
- <code><a href="#websocketrequest">websocket.Request</a>.matchers</code>
|
- <code><a href="#websocketrequest">websocket.Request</a>.matchers</code>
|
||||||
|
|
||||||
|
- <code><a href="#whoisrequest">whois.Request</a>.matchers</code>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1713,6 +1764,8 @@ Appears in:
|
||||||
|
|
||||||
- <code><a href="#websocketrequest">websocket.Request</a>.extractors</code>
|
- <code><a href="#websocketrequest">websocket.Request</a>.extractors</code>
|
||||||
|
|
||||||
|
- <code><a href="#whoisrequest">whois.Request</a>.extractors</code>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2127,6 +2180,20 @@ Enum Values:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## SignatureTypeHolder
|
||||||
|
SignatureTypeHolder is used to hold internal type of the signature
|
||||||
|
|
||||||
|
Appears in:
|
||||||
|
|
||||||
|
|
||||||
|
- <code><a href="#httprequest">http.Request</a>.signature</code>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## dns.Request
|
## dns.Request
|
||||||
Request contains a DNS protocol request to be made from a template
|
Request contains a DNS protocol request to be made from a template
|
||||||
|
|
||||||
|
@ -2561,7 +2628,7 @@ extensions:
|
||||||
</div>
|
</div>
|
||||||
<div class="dt">
|
<div class="dt">
|
||||||
|
|
||||||
ExtensionDenylist is the list of file extensions to deny during matching.
|
DenyList is the list of file, directories or extensions to deny during matching.
|
||||||
|
|
||||||
By default, it contains some non-interesting extensions that are hardcoded
|
By default, it contains some non-interesting extensions that are hardcoded
|
||||||
in nuclei.
|
in nuclei.
|
||||||
|
@ -3599,6 +3666,106 @@ name: prefix
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## whois.Request
|
||||||
|
Request is a request for the WHOIS protocol
|
||||||
|
|
||||||
|
Appears in:
|
||||||
|
|
||||||
|
|
||||||
|
- <code><a href="#template">Template</a>.whois</code>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>matchers</code> <i>[]<a href="#matchersmatcher">matchers.Matcher</a></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
Matchers contains the detection mechanism for the request to identify
|
||||||
|
whether the request was successful by doing pattern matching
|
||||||
|
on request/responses.
|
||||||
|
|
||||||
|
Multiple matchers can be combined with `matcher-condition` flag
|
||||||
|
which accepts either `and` or `or` as argument.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>extractors</code> <i>[]<a href="#extractorsextractor">extractors.Extractor</a></i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
Extractors contains the extraction mechanism for the request to identify
|
||||||
|
and extract parts of the response.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>matchers-condition</code> <i>string</i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
MatchersCondition is the condition between the matchers. Default is OR.
|
||||||
|
|
||||||
|
|
||||||
|
Valid values:
|
||||||
|
|
||||||
|
|
||||||
|
- <code>and</code>
|
||||||
|
|
||||||
|
- <code>or</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>query</code> <i>string</i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
Query contains query for the request
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="dd">
|
||||||
|
|
||||||
|
<code>server</code> <i>string</i>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="dt">
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Optional WHOIS server URL.
|
||||||
|
|
||||||
|
If present, specifies the WHOIS server to execute the Request on.
|
||||||
|
Otherwise, nil enables bootstrapping
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## workflows.WorkflowTemplate
|
## workflows.WorkflowTemplate
|
||||||
|
|
||||||
Appears in:
|
Appears in:
|
||||||
|
@ -3730,3 +3897,17 @@ Subtemplates are run if the name of matcher matches.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## http.SignatureTypeHolder
|
||||||
|
SignatureTypeHolder is used to hold internal type of the signature
|
||||||
|
|
||||||
|
Appears in:
|
||||||
|
|
||||||
|
|
||||||
|
- <code><a href="#template">Template</a>.signature</code>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ self-contained: true
|
||||||
requests:
|
requests:
|
||||||
- raw:
|
- raw:
|
||||||
- |
|
- |
|
||||||
GET http://localhost:5431/ HTTP/1.1
|
GET http://127.0.0.1:5431/ HTTP/1.1
|
||||||
Host: {{Hostname}}
|
Host: {{Hostname}}
|
||||||
|
|
||||||
matchers:
|
matchers:
|
||||||
|
|
|
@ -8,7 +8,7 @@ info:
|
||||||
self-contained: true
|
self-contained: true
|
||||||
network:
|
network:
|
||||||
- host:
|
- host:
|
||||||
- "localhost:5431"
|
- "127.0.0.1:5431"
|
||||||
|
|
||||||
matchers:
|
matchers:
|
||||||
- type: word
|
- type: word
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
id: basic-whois-example
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: test template for WHOIS
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
|
||||||
|
whois:
|
||||||
|
- query: "{{Host}}"
|
||||||
|
extractors:
|
||||||
|
- type: kval
|
||||||
|
kval:
|
||||||
|
- "expiration date"
|
||||||
|
- "registrar"
|
|
@ -472,8 +472,8 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"title": "extensions to deny match",
|
"title": "denylist",
|
||||||
"description": "List of file extensions to deny during matching"
|
"description": "List of files"
|
||||||
},
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -741,6 +741,12 @@
|
||||||
"title": "maximum http response body size",
|
"title": "maximum http response body size",
|
||||||
"description": "Maximum size of http response body to read in bytes"
|
"description": "Maximum size of http response body to read in bytes"
|
||||||
},
|
},
|
||||||
|
"signature": {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"$ref": "#/definitions/http.SignatureTypeHolder",
|
||||||
|
"title": "signature is the http request signature method",
|
||||||
|
"description": "Signature is the HTTP Request signature Method"
|
||||||
|
},
|
||||||
"cookie-reuse": {
|
"cookie-reuse": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"title": "optional cookie reuse enable",
|
"title": "optional cookie reuse enable",
|
||||||
|
@ -790,6 +796,14 @@
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"http.SignatureTypeHolder": {
|
||||||
|
"enum": [
|
||||||
|
"AWS"
|
||||||
|
],
|
||||||
|
"type": "string",
|
||||||
|
"title": "type of the signature",
|
||||||
|
"description": "Type of the signature"
|
||||||
|
},
|
||||||
"network.Input": {
|
"network.Input": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -1026,6 +1040,47 @@
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"whois.Request": {
|
||||||
|
"properties": {
|
||||||
|
"matchers": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/matchers.Matcher"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"title": "matchers to run on response",
|
||||||
|
"description": "Detection mechanism to identify whether the request was successful by doing pattern matching"
|
||||||
|
},
|
||||||
|
"extractors": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/extractors.Extractor"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"title": "extractors to run on response",
|
||||||
|
"description": "Extractors contains the extraction mechanism for the request to identify and extract parts of the response"
|
||||||
|
},
|
||||||
|
"matchers-condition": {
|
||||||
|
"enum": [
|
||||||
|
"and",
|
||||||
|
"or"
|
||||||
|
],
|
||||||
|
"type": "string",
|
||||||
|
"title": "condition between the matchers",
|
||||||
|
"description": "Conditions between the matchers"
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "query for the WHOIS request",
|
||||||
|
"description": "Query contains query for the request"
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "server url to execute the WHOIS request on",
|
||||||
|
"description": "Server contains the server url to execute the WHOIS request on"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"templates.Template": {
|
"templates.Template": {
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
|
@ -1110,6 +1165,15 @@
|
||||||
"title": "websocket requests to make",
|
"title": "websocket requests to make",
|
||||||
"description": "Websocket requests to make for the template"
|
"description": "Websocket requests to make for the template"
|
||||||
},
|
},
|
||||||
|
"whois": {
|
||||||
|
"items": {
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"$ref": "#/definitions/whois.Request"
|
||||||
|
},
|
||||||
|
"type": "array",
|
||||||
|
"title": "whois requests to make",
|
||||||
|
"description": "WHOIS requests to make for the template"
|
||||||
|
},
|
||||||
"workflows": {
|
"workflows": {
|
||||||
"items": {
|
"items": {
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
@ -1128,6 +1192,11 @@
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"title": "stop at first match",
|
"title": "stop at first match",
|
||||||
"description": "Stop at first match for the template"
|
"description": "Stop at first match for the template"
|
||||||
|
},
|
||||||
|
"signature": {
|
||||||
|
"$ref": "#/definitions/http.SignatureTypeHolder",
|
||||||
|
"title": "signature is the http request signature method",
|
||||||
|
"description": "Signature is the HTTP Request signature Method"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
|
@ -71,7 +71,7 @@ func getCVEData(client *nvd.Client, filePath, data string) {
|
||||||
cveName := matches[0][1]
|
cveName := matches[0][1]
|
||||||
|
|
||||||
severityMatches := severityRegex.FindAllStringSubmatch(data, 1)
|
severityMatches := severityRegex.FindAllStringSubmatch(data, 1)
|
||||||
if len(matches) == 0 {
|
if len(severityMatches) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
severityValue := severityMatches[0][1]
|
severityValue := severityMatches[0][1]
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# reading os type from arguments
|
||||||
|
CURRENT_OS=$1
|
||||||
|
|
||||||
|
if [ "${CURRENT_OS}" == "windows-latest" ];then
|
||||||
|
extension=.exe
|
||||||
|
fi
|
||||||
|
|
||||||
echo "::group::Building functional-test binary"
|
echo "::group::Building functional-test binary"
|
||||||
go build
|
go build -o functional-test$extension
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Building Nuclei binary from current branch"
|
echo "::group::Building Nuclei binary from current branch"
|
||||||
go build -o nuclei_dev ../nuclei
|
go build -o nuclei_dev$extension ../nuclei
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Installing latest release of nuclei"
|
echo "::group::Building latest release of nuclei"
|
||||||
GO111MODULE=on go install -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei
|
go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo 'Starting Nuclei functional test'
|
echo 'Starting Nuclei functional test'
|
||||||
./functional-test -main nuclei -dev ./nuclei_dev -testcases testcases.txt
|
./functional-test$extension -main ./nuclei$extension -dev ./nuclei_dev$extension -testcases testcases.txt
|
||||||
|
|
|
@ -26,6 +26,7 @@ var (
|
||||||
"loader": loaderTestcases,
|
"loader": loaderTestcases,
|
||||||
"websocket": websocketTestCases,
|
"websocket": websocketTestCases,
|
||||||
"headless": headlessTestcases,
|
"headless": headlessTestcases,
|
||||||
|
"whois": whoisTestCases,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var whoisTestCases = map[string]testutils.TestCase{
|
||||||
|
"whois/basic.yaml": &whoisBasic{},
|
||||||
|
}
|
||||||
|
|
||||||
|
type whoisBasic struct{}
|
||||||
|
|
||||||
|
// Execute executes a test case and returns an error if occurred
|
||||||
|
func (h *whoisBasic) Execute(filePath string) error {
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://example.com", debug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return expectResultsCount(results, 1)
|
||||||
|
}
|
|
@ -1,61 +1,55 @@
|
||||||
# to specify which severities should be reported
|
|
||||||
#allow-list:
|
#allow-list:
|
||||||
# severity: critical, high
|
# severity: high, critical
|
||||||
# to specify which severities should be excluded from reporting
|
|
||||||
#deny-list:
|
#deny-list:
|
||||||
# severity: info, low, medium
|
# severity: low
|
||||||
|
#
|
||||||
# GitHub contains configuration options for GitHub issue tracker
|
# GitHub contains configuration options for GitHub issue tracker
|
||||||
#GitHub:
|
#github:
|
||||||
# # base-url (optional) is the self-hosted GitHub application url
|
# # base-url is the optional self-hosted GitHub application url
|
||||||
# base-url: ""
|
# base-url: https://localhost:8443/github
|
||||||
# # username is the username of the GitHub user
|
# # username is the username of the GitHub user
|
||||||
# username: ""
|
# username: test-username
|
||||||
# # owner is the owner name of the repository for issues.
|
# # owner is the owner name of the repository for issues
|
||||||
# owner: ""
|
# owner: test-owner
|
||||||
# # token is the token for GitHub account.
|
# # token is the token for GitHub account
|
||||||
# token: ""
|
# token: test-token
|
||||||
# # project-name is the name of the repository.
|
# # project-name is the name of the repository
|
||||||
# project-name: ""
|
# project-name: test-project
|
||||||
# # issue-label (optional) is the label of the created issue type
|
# # issue-label is the label of the created issue type
|
||||||
# issue-label: ""
|
# issue-label: bug
|
||||||
# # severity-as-label (optional) sets the severity as the label of the created issue type
|
#
|
||||||
# severity-as-label: false
|
# GitLab contains configuration options for gitlab issue tracker
|
||||||
|
#gitlab:
|
||||||
# GitLab contains configuration options for GitLab issue tracker
|
# # base-url is the optional self-hosted GitLab application url
|
||||||
#GitLab:
|
# base-url: https://localhost:8443/gitlab
|
||||||
# # base-url (optional) is the self-hosted GitLab application url
|
|
||||||
# base-url: ""
|
|
||||||
# # username is the username of the GitLab user
|
# # username is the username of the GitLab user
|
||||||
# username: ""
|
# username: test-username
|
||||||
# # token is the token for GitLab account.
|
# # token is the token for GitLab account
|
||||||
# token: ""
|
# token: test-token
|
||||||
# # project-id is the ID of the repository.
|
# # project-name is the name/id of the project(repository)
|
||||||
# project-id: ""
|
# project-name: "1234"
|
||||||
# # issue-label (optional) is the label of the created issue type
|
# # issue-label is the label of the created issue type
|
||||||
# issue-label: ""
|
# issue-label: bug
|
||||||
# # severity-as-label (optional) sets the severity as the label of the created issue type
|
#
|
||||||
# severity-as-label: false
|
|
||||||
|
|
||||||
# Jira contains configuration options for Jira issue tracker
|
# Jira contains configuration options for Jira issue tracker
|
||||||
#Jira:
|
#jira:
|
||||||
# # cloud (optional) is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
# # cloud is the boolean which tells if Jira instance is running in the cloud or on-prem version is used
|
||||||
# cloud: true
|
# cloud: true
|
||||||
# # update-existing (optional) is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
# # update-existing is the boolean which tells if the existing, opened issue should be updated or new one should be created
|
||||||
# update-existing: false
|
# update-existing: false
|
||||||
# # URL is the Jira application URL
|
# # URL is the jira application url
|
||||||
# url: ""
|
# url: https://localhost/jira
|
||||||
# # account-id is the account-id of the Jira user or username in case of on-prem Jira
|
# # account-id is the account-id of the Jira user or username in case of on-prem Jira
|
||||||
# account-id: ""
|
# account-id: test-account-id
|
||||||
# # email is the email of the user for Jira instance
|
# # email is the email of the user for Jira instance
|
||||||
# email: ""
|
# email: test@test.com
|
||||||
# # token is the token for Jira instance or password in case of on-prem Jira
|
# # token is the token for Jira instance or password in case of on-prem Jira
|
||||||
# token: ""
|
# token: test-token
|
||||||
# # project-name is the name of the project.
|
# # project-name is the name of the project.
|
||||||
# project-name: ""
|
# project-name: test-project-name
|
||||||
# # issue-type is the name of the created issue type
|
# # issue-type is the name of the created issue type
|
||||||
# issue-type: ""
|
# issue-type: bug
|
||||||
|
#
|
||||||
# elasticsearch contains configuration options for elasticsearch exporter
|
# elasticsearch contains configuration options for elasticsearch exporter
|
||||||
#elasticsearch:
|
#elasticsearch:
|
||||||
# # IP for elasticsearch instance
|
# # IP for elasticsearch instance
|
||||||
|
@ -64,11 +58,11 @@
|
||||||
# port: 9200
|
# port: 9200
|
||||||
# # IndexName is the name of the elasticsearch index
|
# # IndexName is the name of the elasticsearch index
|
||||||
# index-name: nuclei
|
# index-name: nuclei
|
||||||
# # SSL (optional) enables ssl for elasticsearch connection
|
# # SSL enables ssl for elasticsearch connection
|
||||||
# ssl: false
|
# ssl: false
|
||||||
# # SSLVerification (optional) disables SSL verification for elasticsearch
|
# # SSLVerification disables SSL verification for elasticsearch
|
||||||
# ssl-verification: false
|
# ssl-verification: false
|
||||||
# # Username for the elasticsearch instance
|
# # Username for the elasticsearch instance
|
||||||
# username: test
|
# username: test
|
||||||
# # Password is the password for elasticsearch instance
|
# # Password is the password for elasticsearch instance
|
||||||
# password: test
|
# password: test
|
17
v2/go.mod
17
v2/go.mod
|
@ -3,7 +3,6 @@ module github.com/projectdiscovery/nuclei/v2
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Ice3man543/nvd v1.0.8
|
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
|
||||||
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725
|
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725
|
||||||
github.com/andygrunwald/go-jira v1.14.0
|
github.com/andygrunwald/go-jira v1.14.0
|
||||||
|
@ -47,7 +46,6 @@ require (
|
||||||
github.com/shirou/gopsutil/v3 v3.21.9
|
github.com/shirou/gopsutil/v3 v3.21.9
|
||||||
github.com/spaolacci/murmur3 v1.1.0
|
github.com/spaolacci/murmur3 v1.1.0
|
||||||
github.com/spf13/cast v1.4.1
|
github.com/spf13/cast v1.4.1
|
||||||
github.com/stretchr/testify v1.7.0
|
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible
|
github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible
|
||||||
github.com/valyala/fasttemplate v1.2.1
|
github.com/valyala/fasttemplate v1.2.1
|
||||||
|
@ -58,21 +56,31 @@ require (
|
||||||
go.uber.org/atomic v1.9.0
|
go.uber.org/atomic v1.9.0
|
||||||
go.uber.org/multierr v1.7.0
|
go.uber.org/multierr v1.7.0
|
||||||
go.uber.org/ratelimit v0.2.0
|
go.uber.org/ratelimit v0.2.0
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
|
||||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
|
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
|
||||||
golang.org/x/text v0.3.7
|
golang.org/x/text v0.3.7
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
moul.io/http2curl v1.0.0
|
moul.io/http2curl v1.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/aws/aws-sdk-go v1.42.3
|
||||||
|
|
||||||
require github.com/projectdiscovery/folderutil v0.0.0-20211206150108-b4e7ea80f36e
|
require github.com/projectdiscovery/folderutil v0.0.0-20211206150108-b4e7ea80f36e
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Ice3man543/nvd v1.0.8
|
||||||
|
github.com/openrdap/rdap v0.9.1-0.20191017185644-af93e7ef17b7
|
||||||
|
github.com/stretchr/testify v1.7.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
|
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
|
||||||
github.com/Mzack9999/ldapserver v1.0.2-0.20211214172138-8f1cdd128383 // indirect
|
github.com/Mzack9999/ldapserver v1.0.2-0.20211214172138-8f1cdd128383 // indirect
|
||||||
github.com/PuerkitoBio/goquery v1.6.0 // indirect
|
github.com/PuerkitoBio/goquery v1.6.0 // indirect
|
||||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||||
github.com/akrylysov/pogreb v0.10.1 // indirect
|
github.com/akrylysov/pogreb v0.10.1 // indirect
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||||
github.com/andybalholm/cascadia v1.1.0 // indirect
|
github.com/andybalholm/cascadia v1.1.0 // indirect
|
||||||
github.com/antchfx/xpath v1.2.0 // indirect
|
github.com/antchfx/xpath v1.2.0 // indirect
|
||||||
|
@ -103,6 +111,7 @@ require (
|
||||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||||
github.com/itchyny/timefmt-go v0.1.3 // indirect
|
github.com/itchyny/timefmt-go v0.1.3 // indirect
|
||||||
github.com/jasonlvhit/gocron v0.0.1 // indirect
|
github.com/jasonlvhit/gocron v0.0.1 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/karlseguin/ccache/v2 v2.0.8 // indirect
|
github.com/karlseguin/ccache/v2 v2.0.8 // indirect
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||||
|
@ -110,6 +119,7 @@ require (
|
||||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
@ -133,6 +143,7 @@ require (
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
|
||||||
gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
|
gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
)
|
)
|
||||||
|
|
23
v2/go.sum
23
v2/go.sum
|
@ -73,9 +73,12 @@ github.com/alecthomas/jsonschema v0.0.0-20210818095345-1014919a589c/go.mod h1:/n
|
||||||
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 h1:NjwIgLQlD46o79bheVG4SCdRnnOz4XtgUN1WABX5DLA=
|
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 h1:NjwIgLQlD46o79bheVG4SCdRnnOz4XtgUN1WABX5DLA=
|
||||||
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
|
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
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=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
||||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
|
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
|
||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||||
|
@ -104,6 +107,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
|
||||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
|
github.com/aws/aws-sdk-go v1.42.3 h1:lBKr3tQ06m1uykiychMNKLK1bRfOzaIEQpsI/S3QiNc=
|
||||||
|
github.com/aws/aws-sdk-go v1.42.3/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||||
|
@ -404,10 +409,16 @@ github.com/itchyny/gojq v0.12.5 h1:6SJ1BQ1VAwJAlIvLSIZmqHP/RUEq3qfVWvsRxrqhsD0=
|
||||||
github.com/itchyny/gojq v0.12.5/go.mod h1:3e1hZXv+Kwvdp6V9HXpVrvddiHVApi5EDZwS+zLFeiE=
|
github.com/itchyny/gojq v0.12.5/go.mod h1:3e1hZXv+Kwvdp6V9HXpVrvddiHVApi5EDZwS+zLFeiE=
|
||||||
github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU=
|
github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU=
|
||||||
github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
|
github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
|
||||||
|
github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=
|
||||||
|
github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||||
github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU=
|
github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU=
|
||||||
github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4=
|
github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4=
|
||||||
github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY=
|
github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
@ -508,6 +519,7 @@ github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tB
|
||||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
|
@ -558,6 +570,8 @@ github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7
|
||||||
github.com/onsi/gomega v1.12.0 h1:p4oGGk2M2UJc0wWN4lHFvIB71lxsh0T/UiKCCgFADY8=
|
github.com/onsi/gomega v1.12.0 h1:p4oGGk2M2UJc0wWN4lHFvIB71lxsh0T/UiKCCgFADY8=
|
||||||
github.com/onsi/gomega v1.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
github.com/onsi/gomega v1.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
|
github.com/openrdap/rdap v0.9.1-0.20191017185644-af93e7ef17b7 h1:3Xn/CN6GVY+7mVuGgt5bfp0F9JwcWqnvwfb23Jf8Vxg=
|
||||||
|
github.com/openrdap/rdap v0.9.1-0.20191017185644-af93e7ef17b7/go.mod h1:inRbqVxN7ri77yTJY3ZtGtKegIFa3Qnarh7Xp9P7LgY=
|
||||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
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/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
@ -865,8 +879,9 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
@ -957,8 +972,8 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -1221,6 +1236,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -1246,6 +1262,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
|
|
@ -29,6 +29,10 @@ func ParseOptions(options *types.Options) {
|
||||||
// Show the user the banner
|
// Show the user the banner
|
||||||
showBanner()
|
showBanner()
|
||||||
|
|
||||||
|
if !filepath.IsAbs(options.TemplatesDirectory) {
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
options.TemplatesDirectory = filepath.Join(cwd, options.TemplatesDirectory)
|
||||||
|
}
|
||||||
if options.Version {
|
if options.Version {
|
||||||
gologger.Info().Msgf("Current Version: %s\n", config.Version)
|
gologger.Info().Msgf("Current Version: %s\n", config.Version)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
|
@ -73,7 +73,7 @@ func New(options *types.Options) (*Runner, error) {
|
||||||
options.NoUpdateTemplates = true
|
options.NoUpdateTemplates = true
|
||||||
}
|
}
|
||||||
if err := runner.updateTemplates(); err != nil {
|
if err := runner.updateTemplates(); err != nil {
|
||||||
gologger.Warning().Msgf("Could not update templates: %s\n", err)
|
gologger.Error().Msgf("Could not update templates: %s\n", err)
|
||||||
}
|
}
|
||||||
if options.Headless {
|
if options.Headless {
|
||||||
if engine.MustDisableSandbox() {
|
if engine.MustDisableSandbox() {
|
||||||
|
|
|
@ -119,7 +119,7 @@ func (r *Runner) updateTemplates() error { // TODO this method does more than ju
|
||||||
if err := config.WriteConfiguration(r.templatesConfig); err != nil {
|
if err := config.WriteConfiguration(r.templatesConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gologger.Info().Msgf("Successfully downloaded nuclei-templates (v%s). GoodLuck!\n", version.String())
|
gologger.Info().Msgf("Successfully downloaded nuclei-templates (v%s) to %s. GoodLuck!\n", version.String(), r.templatesConfig.TemplatesDirectory)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,13 +135,13 @@ func (r *Runner) updateTemplates() error { // TODO this method does more than ju
|
||||||
return config.WriteConfiguration(r.templatesConfig)
|
return config.WriteConfiguration(r.templatesConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := updateTemplates(latestVersion, currentVersion, r, ctx); err != nil {
|
if err := r.updateTemplatesWithVersion(latestVersion, currentVersion, r, ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateTemplates(latestVersion semver.Version, currentVersion semver.Version, runner *Runner, ctx context.Context) error {
|
func (r *Runner) updateTemplatesWithVersion(latestVersion semver.Version, currentVersion semver.Version, runner *Runner, ctx context.Context) error {
|
||||||
if latestVersion.GT(currentVersion) {
|
if latestVersion.GT(currentVersion) {
|
||||||
gologger.Info().Msgf("Your current nuclei-templates v%s are outdated. Latest is v%s\n", currentVersion, latestVersion.String())
|
gologger.Info().Msgf("Your current nuclei-templates v%s are outdated. Latest is v%s\n", currentVersion, latestVersion.String())
|
||||||
gologger.Info().Msgf("Downloading latest release...")
|
gologger.Info().Msgf("Downloading latest release...")
|
||||||
|
@ -163,7 +163,7 @@ func updateTemplates(latestVersion semver.Version, currentVersion semver.Version
|
||||||
if err := config.WriteConfiguration(runner.templatesConfig); err != nil {
|
if err := config.WriteConfiguration(runner.templatesConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gologger.Info().Msgf("Successfully updated nuclei-templates (v%s). GoodLuck!\n", latestVersion.String())
|
gologger.Info().Msgf("Successfully updated nuclei-templates (v%s) to %s. GoodLuck!\n", latestVersion.String(), r.templatesConfig.TemplatesDirectory)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -200,10 +200,6 @@ func (r *Runner) readInternalConfigurationFile(home, configDir string) error {
|
||||||
return readErr
|
return readErr
|
||||||
}
|
}
|
||||||
r.templatesConfig = configuration
|
r.templatesConfig = configuration
|
||||||
|
|
||||||
if configuration.TemplatesDirectory != "" && configuration.TemplatesDirectory != filepath.Join(home, "nuclei-templates") {
|
|
||||||
r.options.TemplatesDirectory = configuration.TemplatesDirectory
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ func TestDownloadReleaseAndUnzipDeletion(t *testing.T) {
|
||||||
require.Equal(t, "base.yaml", results.deletions[0], "could not get correct new deletions")
|
require.Equal(t, "base.yaml", results.deletions[0], "could not get correct new deletions")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalculateTemplateAbsolutePath(t *testing.T) {
|
func TestCalculateTemplateAbsolutePathPositiveScenario(t *testing.T) {
|
||||||
configuredTemplateDirectory := filepath.Join(os.TempDir(), "templates")
|
configuredTemplateDirectory := filepath.Join(os.TempDir(), "templates")
|
||||||
defer os.RemoveAll(configuredTemplateDirectory)
|
defer os.RemoveAll(configuredTemplateDirectory)
|
||||||
|
|
||||||
|
@ -136,24 +136,6 @@ func TestCalculateTemplateAbsolutePath(t *testing.T) {
|
||||||
require.False(t, skipFile)
|
require.False(t, skipFile)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("negative scenarios", func(t *testing.T) {
|
|
||||||
filePathsFromZip := []string{
|
|
||||||
"./../nuclei-templates/../cve/test.yaml",
|
|
||||||
"nuclei-templates/../cve/test.yaml",
|
|
||||||
"nuclei-templates/cve/../test.yaml",
|
|
||||||
"nuclei-templates/././../cve/test.yaml",
|
|
||||||
"nuclei-templates/.././../cve/test.yaml",
|
|
||||||
"nuclei-templates/.././../cve/../test.yaml",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, filePathFromZip := range filePathsFromZip {
|
|
||||||
calculatedTemplateAbsPath, skipFile, err := calculateTemplateAbsolutePath(filePathFromZip, configuredTemplateDirectory)
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.True(t, skipFile)
|
|
||||||
require.Equal(t, "", calculatedTemplateAbsPath)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func zipFromDirectory(zipPath, directory string) error {
|
func zipFromDirectory(zipPath, directory string) error {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package runner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCalculateTemplateAbsolutePathNegativeScenario(t *testing.T) {
|
||||||
|
configuredTemplateDirectory := filepath.Join(os.TempDir(), "templates")
|
||||||
|
defer os.RemoveAll(configuredTemplateDirectory)
|
||||||
|
|
||||||
|
t.Run("negative scenarios", func(t *testing.T) {
|
||||||
|
filePathsFromZip := []string{
|
||||||
|
"./../nuclei-templates/../cve/test.yaml",
|
||||||
|
"nuclei-templates/../cve/test.yaml",
|
||||||
|
"nuclei-templates/cve/../test.yaml",
|
||||||
|
"nuclei-templates/././../cve/test.yaml",
|
||||||
|
"nuclei-templates/.././../cve/test.yaml",
|
||||||
|
"nuclei-templates/.././../cve/../test.yaml",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filePathFromZip := range filePathsFromZip {
|
||||||
|
calculatedTemplateAbsPath, skipFile, err := calculateTemplateAbsolutePath(filePathFromZip, configuredTemplateDirectory)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.True(t, skipFile)
|
||||||
|
require.Equal(t, "", calculatedTemplateAbsPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ type Config struct {
|
||||||
const nucleiConfigFilename = ".templates-config.json"
|
const nucleiConfigFilename = ".templates-config.json"
|
||||||
|
|
||||||
// Version is the current version of nuclei
|
// Version is the current version of nuclei
|
||||||
const Version = `2.5.6-dev`
|
const Version = `2.5.8-dev`
|
||||||
|
|
||||||
func getConfigDetails() (string, error) {
|
func getConfigDetails() (string, error) {
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
|
|
|
@ -154,7 +154,7 @@ func (matcher *Matcher) MatchBinary(corpus string) (bool, []string) {
|
||||||
|
|
||||||
// MatchDSL matches on a generic map result
|
// MatchDSL matches on a generic map result
|
||||||
func (matcher *Matcher) MatchDSL(data map[string]interface{}) bool {
|
func (matcher *Matcher) MatchDSL(data map[string]interface{}) bool {
|
||||||
logExpressionEvaluationFailure := func (matcherName string, err error) {
|
logExpressionEvaluationFailure := func(matcherName string, err error) {
|
||||||
gologger.Warning().Msgf("Could not evaluate expression: %s, error: %s", matcherName, err.Error())
|
gologger.Warning().Msgf("Could not evaluate expression: %s, error: %s", matcherName, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
package projectfile
|
package projectfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/projectdiscovery/hmap/store/hybrid"
|
"github.com/projectdiscovery/hmap/store/hybrid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotFound = errors.New("not found")
|
||||||
|
regexUserAgent = regexp.MustCompile(`(?mi)\r\nUser-Agent: .+\r\n`)
|
||||||
|
regexDefaultInteract = regexp.MustCompile(`(?mi)[a-zA-Z1-9%.]+interact.sh`)
|
||||||
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Path string
|
Path string
|
||||||
Cleanup bool
|
Cleanup bool
|
||||||
|
@ -31,15 +39,22 @@ func New(options *Options) (*ProjectFile, error) {
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pf *ProjectFile) cleanupData(data []byte) []byte {
|
||||||
|
// ignore all user agents
|
||||||
|
data = regexUserAgent.ReplaceAll(data, []byte("\r\n"))
|
||||||
|
// ignore interact markers
|
||||||
|
return regexDefaultInteract.ReplaceAll(data, []byte(""))
|
||||||
|
}
|
||||||
|
|
||||||
func (pf *ProjectFile) Get(req []byte) (*http.Response, error) {
|
func (pf *ProjectFile) Get(req []byte) (*http.Response, error) {
|
||||||
reqHash, err := hash(req)
|
reqHash, err := hash(pf.cleanupData(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, ok := pf.hm.Get(reqHash)
|
data, ok := pf.hm.Get(reqHash)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("not found")
|
return nil, ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpRecord HTTPRecord
|
var httpRecord HTTPRecord
|
||||||
|
@ -52,7 +67,7 @@ func (pf *ProjectFile) Get(req []byte) (*http.Response, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pf *ProjectFile) Set(req []byte, resp *http.Response, data []byte) error {
|
func (pf *ProjectFile) Set(req []byte, resp *http.Response, data []byte) error {
|
||||||
reqHash, err := hash(req)
|
reqHash, err := hash(pf.cleanupData(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,49 +16,66 @@ func ContainsUnresolvedVariables(items ...string) error {
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
errorString := &strings.Builder{}
|
var unresolvedVariables []string
|
||||||
errorString.WriteString("unresolved variables found: ")
|
for _, match := range matches {
|
||||||
|
|
||||||
for i, match := range matches {
|
|
||||||
if len(match) < 2 {
|
if len(match) < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
errorString.WriteString(match[1])
|
unresolvedVariables = append(unresolvedVariables, match[1])
|
||||||
if i != len(matches)-1 {
|
|
||||||
errorString.WriteString(",")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
errorMessage := errorString.String()
|
return errors.New("unresolved variables found: " + strings.Join(unresolvedVariables, ","))
|
||||||
return errors.New(errorMessage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainsVariablesWithNames returns an error with variable names if the passed
|
||||||
|
// input contains unresolved {{<pattern-here>}} variables within the provided list
|
||||||
func ContainsVariablesWithNames(names map[string]interface{}, items ...string) error {
|
func ContainsVariablesWithNames(names map[string]interface{}, items ...string) error {
|
||||||
for _, data := range items {
|
for _, data := range items {
|
||||||
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
|
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
|
||||||
if len(matches) == 0 {
|
if len(matches) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
errorString := &strings.Builder{}
|
var unresolvedVariables []string
|
||||||
errorString.WriteString("unresolved variables with values found: ")
|
for _, match := range matches {
|
||||||
|
|
||||||
for i, match := range matches {
|
|
||||||
if len(match) < 2 {
|
if len(match) < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matchName := match[1]
|
matchName := match[1]
|
||||||
if _, ok := names[matchName]; !ok {
|
if _, ok := names[matchName]; !ok {
|
||||||
errorString.WriteString(matchName)
|
unresolvedVariables = append(unresolvedVariables, matchName)
|
||||||
if i != len(matches)-1 {
|
|
||||||
errorString.WriteString(",")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorMessage := errorString.String()
|
return errors.New("unresolved variables with values found: " + strings.Join(unresolvedVariables, ","))
|
||||||
return errors.New(errorMessage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainsVariablesWithIgnoreList returns an error with variable names if the passed
|
||||||
|
// input contains unresolved {{<pattern-here>}} other than the ones listed in the ignore list
|
||||||
|
func ContainsVariablesWithIgnoreList(skipNames map[string]interface{}, items ...string) error {
|
||||||
|
var unresolvedVariables []string
|
||||||
|
for _, data := range items {
|
||||||
|
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, match := range matches {
|
||||||
|
if len(match) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
matchName := match[1]
|
||||||
|
if _, ok := skipNames[matchName]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
unresolvedVariables = append(unresolvedVariables, matchName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(unresolvedVariables) > 0 {
|
||||||
|
return errors.New("unresolved variables with values found: " + strings.Join(unresolvedVariables, ","))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -165,6 +165,7 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d
|
||||||
data.Event.InternalEvent["interactsh_protocol"] = interaction.Protocol
|
data.Event.InternalEvent["interactsh_protocol"] = interaction.Protocol
|
||||||
data.Event.InternalEvent["interactsh_request"] = interaction.RawRequest
|
data.Event.InternalEvent["interactsh_request"] = interaction.RawRequest
|
||||||
data.Event.InternalEvent["interactsh_response"] = interaction.RawResponse
|
data.Event.InternalEvent["interactsh_response"] = interaction.RawResponse
|
||||||
|
data.Event.InternalEvent["interactsh_ip"] = interaction.RemoteAddress
|
||||||
result, matched := data.Operators.Execute(data.Event.InternalEvent, data.MatchFunc, data.ExtractFunc, false)
|
result, matched := data.Operators.Execute(data.Event.InternalEvent, data.MatchFunc, data.ExtractFunc, false)
|
||||||
if !matched || result == nil {
|
if !matched || result == nil {
|
||||||
return false // if we don't match, return
|
return false // if we don't match, return
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns/dnsclientpool"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns/dnsclientpool"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/signerpool"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/network/networkclientpool"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/network/networkclientpool"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -23,6 +24,9 @@ func Init(options *types.Options) error {
|
||||||
if err := httpclientpool.Init(options); err != nil {
|
if err := httpclientpool.Init(options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := signerpool.Init(options); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return networkclientpool.Init(options)
|
return networkclientpool.Init(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -19,13 +20,13 @@ type Request struct {
|
||||||
// - value: '[]string{".txt", ".go", ".json"}'
|
// - value: '[]string{".txt", ".go", ".json"}'
|
||||||
Extensions []string `yaml:"extensions,omitempty" jsonschema:"title=extensions to match,description=List of extensions to perform matching on"`
|
Extensions []string `yaml:"extensions,omitempty" jsonschema:"title=extensions to match,description=List of extensions to perform matching on"`
|
||||||
// description: |
|
// description: |
|
||||||
// ExtensionDenylist is the list of file extensions to deny during matching.
|
// DenyList is the list of file, directories or extensions to deny during matching.
|
||||||
//
|
//
|
||||||
// By default, it contains some non-interesting extensions that are hardcoded
|
// By default, it contains some non-interesting extensions that are hardcoded
|
||||||
// in nuclei.
|
// in nuclei.
|
||||||
// examples:
|
// examples:
|
||||||
// - value: '[]string{".avi", ".mov", ".mp3"}'
|
// - value: '[]string{".avi", ".mov", ".mp3"}'
|
||||||
ExtensionDenylist []string `yaml:"denylist,omitempty" jsonschema:"title=extensions to deny match,description=List of file extensions to deny during matching"`
|
DenyList []string `yaml:"denylist,omitempty" jsonschema:"title=denylist, directories and extentions to deny match,description=List of files, directories and extensions to deny during matching"`
|
||||||
|
|
||||||
// ID is the optional id of the request
|
// ID is the optional id of the request
|
||||||
ID string `yaml:"id,omitempty" jsonschema:"title=id of the request,description=ID is the optional ID for the request"`
|
ID string `yaml:"id,omitempty" jsonschema:"title=id of the request,description=ID is the optional ID for the request"`
|
||||||
|
@ -41,9 +42,9 @@ type Request struct {
|
||||||
CompiledOperators *operators.Operators `yaml:"-"`
|
CompiledOperators *operators.Operators `yaml:"-"`
|
||||||
|
|
||||||
// cache any variables that may be needed for operation.
|
// cache any variables that may be needed for operation.
|
||||||
options *protocols.ExecuterOptions
|
options *protocols.ExecuterOptions
|
||||||
extensions map[string]struct{}
|
extensions map[string]struct{}
|
||||||
extensionDenylist map[string]struct{}
|
denyList map[string]struct{}
|
||||||
|
|
||||||
// description: |
|
// description: |
|
||||||
// NoRecursive specifies whether to not do recursive checks if folders are provided.
|
// NoRecursive specifies whether to not do recursive checks if folders are provided.
|
||||||
|
@ -89,7 +90,7 @@ func (request *Request) Compile(options *protocols.ExecuterOptions) error {
|
||||||
request.options = options
|
request.options = options
|
||||||
|
|
||||||
request.extensions = make(map[string]struct{})
|
request.extensions = make(map[string]struct{})
|
||||||
request.extensionDenylist = make(map[string]struct{})
|
request.denyList = make(map[string]struct{})
|
||||||
|
|
||||||
for _, extension := range request.Extensions {
|
for _, extension := range request.Extensions {
|
||||||
if extension == "all" {
|
if extension == "all" {
|
||||||
|
@ -101,17 +102,17 @@ func (request *Request) Compile(options *protocols.ExecuterOptions) error {
|
||||||
request.extensions[extension] = struct{}{}
|
request.extensions[extension] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, extension := range defaultDenylist {
|
// process default denylist (extensions)
|
||||||
if !strings.HasPrefix(extension, ".") {
|
for _, excludeItem := range defaultDenylist {
|
||||||
extension = "." + extension
|
if !strings.HasPrefix(excludeItem, ".") {
|
||||||
|
excludeItem = "." + excludeItem
|
||||||
}
|
}
|
||||||
request.extensionDenylist[extension] = struct{}{}
|
request.denyList[excludeItem] = struct{}{}
|
||||||
}
|
}
|
||||||
for _, extension := range request.ExtensionDenylist {
|
for _, excludeItem := range request.DenyList {
|
||||||
if !strings.HasPrefix(extension, ".") {
|
request.denyList[excludeItem] = struct{}{}
|
||||||
extension = "." + extension
|
// also add a cleaned version as the exclusion path can be dirty (eg. /a/b/c, /a/b/c/, a///b///c/../d)
|
||||||
}
|
request.denyList[filepath.Clean(excludeItem)] = struct{}{}
|
||||||
request.extensionDenylist[extension] = struct{}{}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,11 @@ func TestFileCompile(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"all", ".lock"},
|
Extensions: []string{"all", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
}
|
}
|
||||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
|
@ -29,7 +29,7 @@ func TestFileCompile(t *testing.T) {
|
||||||
err := request.Compile(executerOpts)
|
err := request.Compile(executerOpts)
|
||||||
require.Nil(t, err, "could not compile file request")
|
require.Nil(t, err, "could not compile file request")
|
||||||
|
|
||||||
require.Contains(t, request.extensionDenylist, ".go", "could not get .go in denylist")
|
require.Contains(t, request.denyList, ".go", "could not get .go in denylist")
|
||||||
require.NotContains(t, request.extensions, ".go", "could get .go in allowlist")
|
require.NotContains(t, request.extensions, ".go", "could get .go in allowlist")
|
||||||
require.True(t, request.allExtensions, "could not get correct allExtensions")
|
require.True(t, request.allExtensions, "could not get correct allExtensions")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/karrick/godirwalk"
|
"github.com/karrick/godirwalk"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/projectdiscovery/folderutil"
|
||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func (request *Request) findGlobPathMatches(absPath string, processed map[string
|
||||||
return errors.Errorf("wildcard found, but unable to glob: %s\n", err)
|
return errors.Errorf("wildcard found, but unable to glob: %s\n", err)
|
||||||
}
|
}
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
if !request.validatePath(match) {
|
if !request.validatePath(absPath, match) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := processed[match]; !ok {
|
if _, ok := processed[match]; !ok {
|
||||||
|
@ -73,7 +73,7 @@ func (request *Request) findFileMatches(absPath string, processed map[string]str
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
if _, ok := processed[absPath]; !ok {
|
if _, ok := processed[absPath]; !ok {
|
||||||
if !request.validatePath(absPath) {
|
if !request.validatePath(absPath, absPath) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
processed[absPath] = struct{}{}
|
processed[absPath] = struct{}{}
|
||||||
|
@ -93,7 +93,7 @@ func (request *Request) findDirectoryMatches(absPath string, processed map[strin
|
||||||
if d.IsDir() {
|
if d.IsDir() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !request.validatePath(path) {
|
if !request.validatePath(absPath, path) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, ok := processed[path]; !ok {
|
if _, ok := processed[path]; !ok {
|
||||||
|
@ -107,7 +107,7 @@ func (request *Request) findDirectoryMatches(absPath string, processed map[strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// validatePath validates a file path for blacklist and whitelist options
|
// validatePath validates a file path for blacklist and whitelist options
|
||||||
func (request *Request) validatePath(item string) bool {
|
func (request *Request) validatePath(absPath, item string) bool {
|
||||||
extension := filepath.Ext(item)
|
extension := filepath.Ext(item)
|
||||||
|
|
||||||
if len(request.extensions) > 0 {
|
if len(request.extensions) > 0 {
|
||||||
|
@ -117,9 +117,81 @@ func (request *Request) validatePath(item string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := request.extensionDenylist[extension]; ok {
|
if matchingRule, ok := request.isInDenyList(absPath, item); ok {
|
||||||
gologger.Verbose().Msgf("Ignoring path %s due to denylist item %s\n", item, extension)
|
gologger.Verbose().Msgf("Ignoring path %s due to denylist item %s\n", item, matchingRule)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (request *Request) isInDenyList(absPath, item string) (string, bool) {
|
||||||
|
extension := filepath.Ext(item)
|
||||||
|
// check for possible deny rules
|
||||||
|
// - extension is in deny list
|
||||||
|
if _, ok := request.denyList[extension]; ok {
|
||||||
|
return extension, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// - full path is in deny list
|
||||||
|
if _, ok := request.denyList[item]; ok {
|
||||||
|
return item, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// file is in a forbidden subdirectory
|
||||||
|
filename := filepath.Base(item)
|
||||||
|
fullPathWithoutFilename := strings.TrimSuffix(item, filename)
|
||||||
|
relativePathWithFilename := strings.TrimPrefix(item, absPath)
|
||||||
|
relativePath := strings.TrimSuffix(relativePathWithFilename, filename)
|
||||||
|
|
||||||
|
// - filename is in deny list
|
||||||
|
if _, ok := request.denyList[filename]; ok {
|
||||||
|
return filename, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// - relative path is in deny list
|
||||||
|
if _, ok := request.denyList[relativePath]; ok {
|
||||||
|
return relativePath, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// relative path + filename are in the forbidden list
|
||||||
|
if _, ok := request.denyList[relativePathWithFilename]; ok {
|
||||||
|
return relativePathWithFilename, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// root path + relative path are in the forbidden list
|
||||||
|
if _, ok := request.denyList[fullPathWithoutFilename]; ok {
|
||||||
|
return fullPathWithoutFilename, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// check any progressive combined part of the relative and absolute path with filename for matches within rules prefixes
|
||||||
|
if pathTreeItem, ok := request.isAnyChunkInDenyList(relativePath, false); ok {
|
||||||
|
return pathTreeItem, true
|
||||||
|
}
|
||||||
|
if pathTreeItem, ok := request.isAnyChunkInDenyList(item, true); ok {
|
||||||
|
return pathTreeItem, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (request *Request) isAnyChunkInDenyList(path string, splitWithUtils bool) (string, bool) {
|
||||||
|
var paths []string
|
||||||
|
|
||||||
|
if splitWithUtils {
|
||||||
|
pathInfo, _ := folderutil.NewPathInfo(path)
|
||||||
|
paths, _ = pathInfo.Paths()
|
||||||
|
} else {
|
||||||
|
pathTree := strings.Split(path, string(os.PathSeparator))
|
||||||
|
for i := range pathTree {
|
||||||
|
paths = append(paths, filepath.Join(pathTree[:i]...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, pathTreeItem := range paths {
|
||||||
|
if _, ok := request.denyList[pathTreeItem]; ok {
|
||||||
|
return pathTreeItem, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ func TestFindInputPaths(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"all", ".lock"},
|
Extensions: []string{"all", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
}
|
}
|
||||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
|
|
|
@ -20,11 +20,11 @@ func TestResponseToDSLMap(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"*", ".lock"},
|
Extensions: []string{"*", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
}
|
}
|
||||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
|
@ -45,11 +45,11 @@ func TestFileOperatorMatch(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"*", ".lock"},
|
Extensions: []string{"*", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
}
|
}
|
||||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
|
@ -133,11 +133,11 @@ func TestFileOperatorExtract(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"*", ".lock"},
|
Extensions: []string{"*", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
}
|
}
|
||||||
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
|
@ -240,11 +240,11 @@ func testFileMakeResult(t *testing.T, matchers []*matchers.Matcher, matcherCondi
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"*", ".lock"},
|
Extensions: []string{"*", ".lock"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
Operators: operators.Operators{
|
Operators: operators.Operators{
|
||||||
MatchersCondition: matcherCondition,
|
MatchersCondition: matcherCondition,
|
||||||
Matchers: matchers,
|
Matchers: matchers,
|
||||||
|
|
|
@ -23,11 +23,11 @@ func TestFileExecuteWithResults(t *testing.T) {
|
||||||
testutils.Init(options)
|
testutils.Init(options)
|
||||||
templateID := "testing-file"
|
templateID := "testing-file"
|
||||||
request := &Request{
|
request := &Request{
|
||||||
ID: templateID,
|
ID: templateID,
|
||||||
MaxSize: 1024,
|
MaxSize: 1024,
|
||||||
NoRecursive: false,
|
NoRecursive: false,
|
||||||
Extensions: []string{"all"},
|
Extensions: []string{"all"},
|
||||||
ExtensionDenylist: []string{".go"},
|
DenyList: []string{".go"},
|
||||||
Operators: operators.Operators{
|
Operators: operators.Operators{
|
||||||
Matchers: []*matchers.Matcher{{
|
Matchers: []*matchers.Matcher{{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/expressions"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/replacer"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/race"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/race"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/raw"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/raw"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
|
@ -121,13 +122,32 @@ func (r *requestGenerator) makeSelfContainedRequest(data string, payloads, dynam
|
||||||
if len(parts) < 3 {
|
if len(parts) < 3 {
|
||||||
return nil, fmt.Errorf("malformed request supplied")
|
return nil, fmt.Errorf("malformed request supplied")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
payloads := generators.BuildPayloadFromOptions(r.request.options.Options)
|
||||||
|
// in case cases (eg requests signing, some variables uses default values if missing)
|
||||||
|
if defaultList := GetVariablesDefault(r.request.Signature.Value); defaultList != nil {
|
||||||
|
payloads = generators.MergeMaps(defaultList, payloads)
|
||||||
|
}
|
||||||
|
parts[1] = replacer.Replace(parts[1], payloads)
|
||||||
|
|
||||||
|
// the url might contain placeholders with ignore list
|
||||||
|
if ignoreList := GetVariablesNamesSkipList(r.request.Signature.Value); ignoreList != nil {
|
||||||
|
if err := expressions.ContainsVariablesWithIgnoreList(ignoreList, parts[1]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else { // the url might contain placeholders
|
||||||
|
if err := expressions.ContainsUnresolvedVariables(parts[1]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parsed, err := url.Parse(parts[1])
|
parsed, err := url.Parse(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse request URL: %w", err)
|
return nil, fmt.Errorf("could not parse request URL: %w", err)
|
||||||
}
|
}
|
||||||
values := generators.MergeMaps(
|
values := generators.MergeMaps(
|
||||||
generators.MergeMaps(dynamicValues, generateVariables(parsed, false)),
|
generators.MergeMaps(dynamicValues, generateVariables(parsed, false)),
|
||||||
generators.BuildPayloadFromOptions(r.request.options.Options),
|
payloads,
|
||||||
)
|
)
|
||||||
|
|
||||||
return r.makeHTTPRequestFromRaw(ctx, parsed.String(), data, values, payloads)
|
return r.makeHTTPRequestFromRaw(ctx, parsed.String(), data, values, payloads)
|
||||||
|
|
|
@ -128,6 +128,12 @@ type Request struct {
|
||||||
// SelfContained specifies if the request is self-contained.
|
// SelfContained specifies if the request is self-contained.
|
||||||
SelfContained bool `yaml:"-" json:"-"`
|
SelfContained bool `yaml:"-" json:"-"`
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// Signature is the request signature method
|
||||||
|
// values:
|
||||||
|
// - "AWS"
|
||||||
|
Signature SignatureTypeHolder `yaml:"signature,omitempty" jsonschema:"title=signature is the http request signature method,description=Signature is the HTTP Request signature Method,enum=AWS"`
|
||||||
|
|
||||||
// description: |
|
// description: |
|
||||||
// CookieReuse is an optional setting that enables cookie reuse for
|
// CookieReuse is an optional setting that enables cookie reuse for
|
||||||
// all requests defined in raw section.
|
// all requests defined in raw section.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/projectdiscovery/rawhttp/client"
|
"github.com/projectdiscovery/rawhttp/client"
|
||||||
|
@ -30,7 +30,7 @@ func Parse(request, baseURL string, unsafe bool) (*Request, error) {
|
||||||
rawRequest := &Request{
|
rawRequest := &Request{
|
||||||
Headers: make(map[string]string),
|
Headers: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedURL, err := url.Parse(baseURL)
|
parsedURL, err := url.Parse(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse request URL: %w", err)
|
return nil, fmt.Errorf("could not parse request URL: %w", err)
|
||||||
|
@ -143,7 +143,7 @@ func Parse(request, baseURL string, unsafe bool) (*Request, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixUnsafeRequestPath(baseURL *url.URL, requestPath string, request []byte) []byte {
|
func fixUnsafeRequestPath(baseURL *url.URL, requestPath string, request []byte) []byte {
|
||||||
fixedPath := filepath.Join(baseURL.Path, requestPath)
|
fixedPath := path.Join(baseURL.Path, requestPath)
|
||||||
fixed := bytes.Replace(request, []byte(requestPath), []byte(fixedPath), 1)
|
fixed := bytes.Replace(request, []byte(requestPath), []byte(fixedPath), 1)
|
||||||
return fixed
|
return fixed
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,10 @@ import (
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/tostring"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/tostring"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/httpclientpool"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/signer"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/signerpool"
|
||||||
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
"github.com/projectdiscovery/rawhttp"
|
"github.com/projectdiscovery/rawhttp"
|
||||||
"github.com/projectdiscovery/stringsutil"
|
"github.com/projectdiscovery/stringsutil"
|
||||||
)
|
)
|
||||||
|
@ -336,24 +339,27 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Dump request for variables checks
|
||||||
// For race conditions we can't dump the request body at this point as it's already waiting the open-gate event, already handled with a similar code within the race function
|
// For race conditions we can't dump the request body at this point as it's already waiting the open-gate event, already handled with a similar code within the race function
|
||||||
if !generatedRequest.original.Race {
|
if !generatedRequest.original.Race {
|
||||||
var dumpError error
|
var dumpError error
|
||||||
|
// TODO: dump is currently not working with post-processors - somehow it alters the signature
|
||||||
dumpedRequest, dumpError = dump(generatedRequest, reqURL)
|
dumpedRequest, dumpError = dump(generatedRequest, reqURL)
|
||||||
if dumpError != nil {
|
if dumpError != nil {
|
||||||
return dumpError
|
return dumpError
|
||||||
}
|
}
|
||||||
dumpedRequestString := string(dumpedRequest)
|
dumpedRequestString := string(dumpedRequest)
|
||||||
|
|
||||||
// Check if are there any unresolved variables. If yes, skip unless overridden by user.
|
if ignoreList := GetVariablesNamesSkipList(generatedRequest.original.Signature.Value); ignoreList != nil {
|
||||||
if varErr := expressions.ContainsUnresolvedVariables(dumpedRequestString); varErr != nil && !request.SkipVariablesCheck {
|
if varErr := expressions.ContainsVariablesWithIgnoreList(ignoreList, dumpedRequestString); varErr != nil && !request.SkipVariablesCheck {
|
||||||
gologger.Warning().Msgf("[%s] Could not make http request for %s: %v\n", request.options.TemplateID, reqURL, varErr)
|
gologger.Warning().Msgf("[%s] Could not make http request for %s: %v\n", request.options.TemplateID, reqURL, varErr)
|
||||||
return errStopExecution
|
return errStopExecution
|
||||||
}
|
}
|
||||||
|
} else { // Check if are there any unresolved variables. If yes, skip unless overridden by user.
|
||||||
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
if varErr := expressions.ContainsUnresolvedVariables(dumpedRequestString); varErr != nil && !request.SkipVariablesCheck {
|
||||||
gologger.Info().Msgf("[%s] Dumped HTTP request for %s\n\n", request.options.TemplateID, reqURL)
|
gologger.Warning().Msgf("[%s] Could not make http request for %s: %v\n", request.options.TemplateID, reqURL, varErr)
|
||||||
gologger.Print().Msgf("%s", dumpedRequestString)
|
return errStopExecution
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var formedURL string
|
var formedURL string
|
||||||
|
@ -391,9 +397,27 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
|
if errSignature := request.handleSignature(generatedRequest); errSignature != nil {
|
||||||
|
return errSignature
|
||||||
|
}
|
||||||
resp, err = request.httpClient.Do(generatedRequest.request)
|
resp, err = request.httpClient.Do(generatedRequest.request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dump the requests containing all headers
|
||||||
|
if !generatedRequest.original.Race {
|
||||||
|
var dumpError error
|
||||||
|
dumpedRequest, dumpError = dump(generatedRequest, reqURL)
|
||||||
|
if dumpError != nil {
|
||||||
|
return dumpError
|
||||||
|
}
|
||||||
|
dumpedRequestString := string(dumpedRequest)
|
||||||
|
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||||
|
gologger.Info().Msgf("[%s] Dumped HTTP request for %s\n\n", request.options.TemplateID, reqURL)
|
||||||
|
gologger.Print().Msgf("%s", dumpedRequestString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// rawhttp doesn't support draining response bodies.
|
// rawhttp doesn't support draining response bodies.
|
||||||
if resp != nil && resp.Body != nil && generatedRequest.rawRequest == nil {
|
if resp != nil && resp.Body != nil && generatedRequest.rawRequest == nil {
|
||||||
|
@ -533,6 +557,40 @@ func (request *Request) executeRequest(reqURL string, generatedRequest *generate
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleSignature of the http request
|
||||||
|
func (request *Request) handleSignature(generatedRequest *generatedRequest) error {
|
||||||
|
switch request.Signature.Value {
|
||||||
|
case AWSSignature:
|
||||||
|
var awsSigner signer.Signer
|
||||||
|
payloads := request.options.Options.Vars.AsMap()
|
||||||
|
awsAccessKeyId := types.ToString(payloads["aws-id"])
|
||||||
|
awsSecretAccessKey := types.ToString(payloads["aws-secret"])
|
||||||
|
awsSignerArgs := signer.AwsSignerArgs{AwsId: awsAccessKeyId, AwsSecretToken: awsSecretAccessKey}
|
||||||
|
service := types.ToString(payloads["service"])
|
||||||
|
region := types.ToString(payloads["region"])
|
||||||
|
// if region is empty use default value
|
||||||
|
if region == "" {
|
||||||
|
region = types.ToString(signer.AwsDefaultVars["region"])
|
||||||
|
}
|
||||||
|
awsSignatureArguments := signer.AwsSignatureArguments{
|
||||||
|
Service: types.ToString(service),
|
||||||
|
Region: types.ToString(region),
|
||||||
|
Time: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
awsSigner, err := signerpool.Get(request.options.Options, &signerpool.Configuration{SignerArgs: awsSignerArgs})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = awsSigner.SignHTTP(generatedRequest.request.Request, awsSignatureArguments)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// setCustomHeaders sets the custom headers for generated request
|
// setCustomHeaders sets the custom headers for generated request
|
||||||
func (request *Request) setCustomHeaders(req *generatedRequest) {
|
func (request *Request) setCustomHeaders(req *generatedRequest) {
|
||||||
for k, v := range request.customHeaders {
|
for k, v := range request.customHeaders {
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/alecthomas/jsonschema"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/signer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SignatureType is the type of signature
|
||||||
|
type SignatureType int
|
||||||
|
|
||||||
|
// Supported values for the SignatureType
|
||||||
|
const (
|
||||||
|
AWSSignature SignatureType = iota + 1
|
||||||
|
signatureLimit
|
||||||
|
)
|
||||||
|
|
||||||
|
// signatureTypeMappings is a table for conversion of signature type from string.
|
||||||
|
var signatureTypeMappings = map[SignatureType]string{
|
||||||
|
AWSSignature: "AWS",
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSupportedSignaturesTypes() []SignatureType {
|
||||||
|
var result []SignatureType
|
||||||
|
for index := SignatureType(1); index < signatureLimit; index++ {
|
||||||
|
result = append(result, index)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func toSignatureType(valueToMap string) (SignatureType, error) {
|
||||||
|
normalizedValue := normalizeValue(valueToMap)
|
||||||
|
for key, currentValue := range signatureTypeMappings {
|
||||||
|
if normalizedValue == currentValue {
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, errors.New("invalid signature type: " + valueToMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t SignatureType) String() string {
|
||||||
|
return signatureTypeMappings[t]
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureTypeHolder is used to hold internal type of the signature
|
||||||
|
type SignatureTypeHolder struct {
|
||||||
|
Value SignatureType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (holder SignatureTypeHolder) JSONSchemaType() *jsonschema.Type {
|
||||||
|
gotType := &jsonschema.Type{
|
||||||
|
Type: "string",
|
||||||
|
Title: "type of the signature",
|
||||||
|
Description: "Type of the signature",
|
||||||
|
}
|
||||||
|
for _, types := range GetSupportedSignaturesTypes() {
|
||||||
|
gotType.Enum = append(gotType.Enum, types.String())
|
||||||
|
}
|
||||||
|
return gotType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (holder *SignatureTypeHolder) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var marshalledTypes string
|
||||||
|
if err := unmarshal(&marshalledTypes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
computedType, err := toSignatureType(marshalledTypes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.Value = computedType
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (holder *SignatureTypeHolder) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(holder.Value.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (holder SignatureTypeHolder) MarshalYAML() (interface{}, error) {
|
||||||
|
return holder.Value.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var ErrNoIgnoreList = errors.New("uknown signature types")
|
||||||
|
|
||||||
|
// GetVariablesNamesSkipList depending on the signature type
|
||||||
|
func GetVariablesNamesSkipList(signature SignatureType) map[string]interface{} {
|
||||||
|
switch signature {
|
||||||
|
case AWSSignature:
|
||||||
|
return signer.AwsSkipList
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVariablesNamesSkipList depending on the signature type
|
||||||
|
func GetVariablesDefault(signature SignatureType) map[string]interface{} {
|
||||||
|
switch signature {
|
||||||
|
case AWSSignature:
|
||||||
|
return signer.AwsDefaultVars
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
package signer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
|
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AwsSigner struct {
|
||||||
|
creds *credentials.Credentials
|
||||||
|
signer *v4.Signer
|
||||||
|
}
|
||||||
|
|
||||||
|
type AwsSignerArgs struct {
|
||||||
|
AwsId string
|
||||||
|
AwsSecretToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSignerArgs AwsSignerArgs) Validate() error {
|
||||||
|
if awsSignerArgs.AwsId == "" {
|
||||||
|
return errors.New("empty id")
|
||||||
|
}
|
||||||
|
if awsSignerArgs.AwsSecretToken == "" {
|
||||||
|
return errors.New("empty token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AwsSignatureArguments struct {
|
||||||
|
Service string
|
||||||
|
Region string
|
||||||
|
Time time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSignatureArguments AwsSignatureArguments) Validate() error {
|
||||||
|
if awsSignatureArguments.Region == "" {
|
||||||
|
return errors.New("empty region")
|
||||||
|
}
|
||||||
|
if awsSignatureArguments.Service == "" {
|
||||||
|
return errors.New("empty service")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAwsSigner(args AwsSignerArgs) (*AwsSigner, error) {
|
||||||
|
if err := args.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
creds := credentials.NewStaticCredentials(args.AwsId, args.AwsSecretToken, "")
|
||||||
|
if creds == nil {
|
||||||
|
return nil, errors.New("couldn't create the credentials structure")
|
||||||
|
}
|
||||||
|
signer := v4.NewSigner(creds)
|
||||||
|
return &AwsSigner{creds: creds, signer: signer}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAwsSignerFromEnv() (*AwsSigner, error) {
|
||||||
|
creds := credentials.NewEnvCredentials()
|
||||||
|
if creds == nil {
|
||||||
|
return nil, errors.New("couldn't create the credentials structure")
|
||||||
|
}
|
||||||
|
signer := v4.NewSigner(creds)
|
||||||
|
return &AwsSigner{creds: creds, signer: signer}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAwsSignerFromFile() (*AwsSigner, error) {
|
||||||
|
creds := credentials.NewSharedCredentials("", "")
|
||||||
|
if creds == nil {
|
||||||
|
return nil, errors.New("couldn't create the credentials structure")
|
||||||
|
}
|
||||||
|
signer := v4.NewSigner(creds)
|
||||||
|
return &AwsSigner{creds: creds, signer: signer}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSigner *AwsSigner) SignHTTP(request *http.Request, args interface{}) error {
|
||||||
|
signatureArgs, err := awsSigner.checkSignatureArgs(args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
awsSigner.prepareRequest(request)
|
||||||
|
var body *bytes.Reader
|
||||||
|
if request.Body != nil {
|
||||||
|
bodyBytes, err := ioutil.ReadAll(request.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
request.Body.Close()
|
||||||
|
body = bytes.NewReader(bodyBytes)
|
||||||
|
}
|
||||||
|
if _, err := awsSigner.signer.Sign(request, body, signatureArgs.Service, signatureArgs.Region, signatureArgs.Time); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSigner *AwsSigner) CalculateHTTPHeaders(request *http.Request, args interface{}) (map[string]string, error) {
|
||||||
|
signatureArgs, err := awsSigner.checkSignatureArgs(args)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reqClone := request.Clone(context.Background())
|
||||||
|
awsSigner.prepareRequest(reqClone)
|
||||||
|
err = awsSigner.SignHTTP(reqClone, signatureArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
headers := make(map[string]string)
|
||||||
|
headers["X-Amz-Date"] = reqClone.Header.Get("X-Amz-Date")
|
||||||
|
headers["Authorization"] = reqClone.Header.Get("Authorization")
|
||||||
|
return headers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSigner *AwsSigner) checkSignatureArgs(args interface{}) (AwsSignatureArguments, error) {
|
||||||
|
if signatureArgs, ok := args.(AwsSignatureArguments); ok {
|
||||||
|
return signatureArgs, signatureArgs.Validate()
|
||||||
|
}
|
||||||
|
return AwsSignatureArguments{}, errors.New("wrong signature type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (awsSigner *AwsSigner) prepareRequest(request *http.Request) {
|
||||||
|
request.Header.Del("Host")
|
||||||
|
}
|
||||||
|
|
||||||
|
var AwsSkipList = map[string]interface{}{
|
||||||
|
"region": struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var AwsDefaultVars = map[string]interface{}{
|
||||||
|
"region": "us-east-2",
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package signer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Signer interface {
|
||||||
|
SignHTTP(request *http.Request, args interface{}) error
|
||||||
|
CalculateHTTPHeaders(request *http.Request, args interface{}) (map[string]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignerArgs interface {
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignatureArguments interface {
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSigner(args SignerArgs) (signer Signer, err error) {
|
||||||
|
switch signerArgs := args.(type) {
|
||||||
|
case AwsSignerArgs:
|
||||||
|
awsSigner, err := NewAwsSigner(signerArgs)
|
||||||
|
if err != nil {
|
||||||
|
// $HOME/.aws/credentials
|
||||||
|
awsSigner, err = NewAwsSignerFromFile()
|
||||||
|
if err != nil {
|
||||||
|
// env variables
|
||||||
|
awsSigner, err = NewAwsSignerFromEnv()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return awsSigner, err
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown signature arguments type")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package signerpool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/http/signer"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
poolMutex *sync.RWMutex
|
||||||
|
clientPool map[string]signer.Signer
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init initializes the clientpool implementation
|
||||||
|
func Init(options *types.Options) error {
|
||||||
|
poolMutex = &sync.RWMutex{}
|
||||||
|
clientPool = make(map[string]signer.Signer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration contains the custom configuration options for a client
|
||||||
|
type Configuration struct {
|
||||||
|
SignerArgs signer.SignerArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash returns the hash of the configuration to allow client pooling
|
||||||
|
func (c *Configuration) Hash() string {
|
||||||
|
builder := &strings.Builder{}
|
||||||
|
builder.WriteString(fmt.Sprintf("%v", c.SignerArgs))
|
||||||
|
hash := builder.String()
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get creates or gets a client for the protocol based on custom configuration
|
||||||
|
func Get(options *types.Options, configuration *Configuration) (signer.Signer, error) {
|
||||||
|
hash := configuration.Hash()
|
||||||
|
poolMutex.RLock()
|
||||||
|
if client, ok := clientPool[hash]; ok {
|
||||||
|
poolMutex.RUnlock()
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
poolMutex.RUnlock()
|
||||||
|
|
||||||
|
client, err := signer.NewSigner(configuration.SignerArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
poolMutex.Lock()
|
||||||
|
clientPool[hash] = client
|
||||||
|
poolMutex.Unlock()
|
||||||
|
return client, nil
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
package whois
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/openrdap/rdap"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/gologger"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators/extractors"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/operators/matchers"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/output"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/eventcreator"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/helpers/responsehighlighter"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/replacer"
|
||||||
|
templateTypes "github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request is a request for the WHOIS protocol
|
||||||
|
type Request struct {
|
||||||
|
// Operators for the current request go here.
|
||||||
|
operators.Operators `yaml:",inline,omitempty"`
|
||||||
|
CompiledOperators *operators.Operators `yaml:"-"`
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// Query contains query for the request
|
||||||
|
Query string `yaml:"query,omitempty" jsonschema:"title=query for the WHOIS request,description=Query contains query for the request"`
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// Optional WHOIS server URL.
|
||||||
|
//
|
||||||
|
// If present, specifies the WHOIS server to execute the Request on.
|
||||||
|
// Otherwise, nil enables bootstrapping
|
||||||
|
Server string `yaml:"server,omitempty" jsonschema:"title=server url to execute the WHOIS request on,description=Server contains the server url to execute the WHOIS request on"`
|
||||||
|
// cache any variables that may be needed for operation.
|
||||||
|
client *rdap.Client
|
||||||
|
options *protocols.ExecuterOptions
|
||||||
|
parsedServerURL *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile compiles the request generators preparing any requests possible.
|
||||||
|
func (request *Request) Compile(options *protocols.ExecuterOptions) error {
|
||||||
|
var err error
|
||||||
|
if request.Server != "" {
|
||||||
|
request.parsedServerURL, err = url.Parse(request.Server)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to parse server URL")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.options = options
|
||||||
|
request.client = &rdap.Client{}
|
||||||
|
|
||||||
|
if len(request.Matchers) > 0 || len(request.Extractors) > 0 {
|
||||||
|
compiled := &request.Operators
|
||||||
|
if err := compiled.Compile(); err != nil {
|
||||||
|
return errors.Wrap(err, "could not compile operators")
|
||||||
|
}
|
||||||
|
request.CompiledOperators = compiled
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requests returns the total number of requests the rule will perform
|
||||||
|
func (request *Request) Requests() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetID returns the ID for the request if any.
|
||||||
|
func (request *Request) GetID() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteWithResults executes the protocol requests and returns results instead of writing them.
|
||||||
|
func (request *Request) ExecuteWithResults(input string, dynamicValues, previous output.InternalEvent, callback protocols.OutputEventCallback) error {
|
||||||
|
// generate variables
|
||||||
|
variables := generateVariables(input)
|
||||||
|
// and replace placeholders
|
||||||
|
query := replacer.Replace(request.Query, variables)
|
||||||
|
// build an rdap request
|
||||||
|
rdapReq := rdap.NewAutoRequest(query)
|
||||||
|
rdapReq.Server = request.parsedServerURL
|
||||||
|
res, err := request.client.Do(rdapReq)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not make whois request")
|
||||||
|
}
|
||||||
|
gologger.Verbose().Msgf("Sent WHOIS request to %s", query)
|
||||||
|
if request.options.Options.Debug || request.options.Options.DebugRequests {
|
||||||
|
gologger.Debug().Msgf("[%s] Dumped WHOIS request for %s", request.options.TemplateID, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
var response interface{}
|
||||||
|
switch rdapReq.Type {
|
||||||
|
case rdap.DomainRequest:
|
||||||
|
// convert the rdap response to a whois style response (for domain request type only)
|
||||||
|
whoisResp := res.ToWhoisStyleResponse()
|
||||||
|
for k, v := range whoisResp.Data {
|
||||||
|
data[strings.ToLower(k)] = strings.Join(v, ",")
|
||||||
|
}
|
||||||
|
response = whoisResp
|
||||||
|
default:
|
||||||
|
response = res.Object
|
||||||
|
}
|
||||||
|
jsonData, _ := jsoniter.Marshal(response)
|
||||||
|
jsonDataString := string(jsonData)
|
||||||
|
|
||||||
|
data["type"] = request.Type().String()
|
||||||
|
data["host"] = query
|
||||||
|
data["response"] = jsonDataString
|
||||||
|
|
||||||
|
event := eventcreator.CreateEvent(request, data, request.options.Options.Debug || request.options.Options.DebugResponse)
|
||||||
|
if request.options.Options.Debug || request.options.Options.DebugResponse {
|
||||||
|
gologger.Debug().Msgf("[%s] Dumped WHOIS response for %s", request.options.TemplateID, query)
|
||||||
|
gologger.Print().Msgf("%s", responsehighlighter.Highlight(event.OperatorsResult, jsonDataString, request.options.Options.NoColor, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(event)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match performs matching operation for a matcher on model and returns:
|
||||||
|
// true and a list of matched snippets if the matcher type is supports it
|
||||||
|
// otherwise false and an empty string slice
|
||||||
|
func (request *Request) Match(data map[string]interface{}, matcher *matchers.Matcher) (bool, []string) {
|
||||||
|
return protocols.MakeDefaultMatchFunc(data, matcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract performs extracting operation for an extractor on model and returns true or false.
|
||||||
|
func (request *Request) Extract(data map[string]interface{}, matcher *extractors.Extractor) map[string]struct{} {
|
||||||
|
return protocols.MakeDefaultExtractFunc(data, matcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeResultEvent creates a result event from internal wrapped event
|
||||||
|
func (request *Request) MakeResultEvent(wrapped *output.InternalWrappedEvent) []*output.ResultEvent {
|
||||||
|
return protocols.MakeDefaultResultEvent(request, wrapped)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCompiledOperators returns a list of the compiled operators
|
||||||
|
func (request *Request) GetCompiledOperators() []*operators.Operators {
|
||||||
|
return []*operators.Operators{request.CompiledOperators}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent) *output.ResultEvent {
|
||||||
|
data := &output.ResultEvent{
|
||||||
|
TemplateID: types.ToString(request.options.TemplateID),
|
||||||
|
TemplatePath: types.ToString(request.options.TemplatePath),
|
||||||
|
Info: request.options.TemplateInfo,
|
||||||
|
Type: types.ToString(wrapped.InternalEvent["type"]),
|
||||||
|
Host: types.ToString(wrapped.InternalEvent["host"]),
|
||||||
|
Metadata: wrapped.OperatorsResult.PayloadValues,
|
||||||
|
ExtractedResults: wrapped.OperatorsResult.OutputExtracts,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
MatcherStatus: true,
|
||||||
|
Request: types.ToString(wrapped.InternalEvent["request"]),
|
||||||
|
Response: types.ToString(wrapped.InternalEvent["response"]),
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the type of the protocol request
|
||||||
|
func (request *Request) Type() templateTypes.ProtocolType {
|
||||||
|
return templateTypes.WHOISProtocol
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateVariables will create default variables after parsing a url
|
||||||
|
func generateVariables(input string) map[string]interface{} {
|
||||||
|
var domain string
|
||||||
|
|
||||||
|
parsed, err := url.Parse(input)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]interface{}{"Input": input}
|
||||||
|
}
|
||||||
|
domain = parsed.Host
|
||||||
|
if domain == "" {
|
||||||
|
domain = input
|
||||||
|
}
|
||||||
|
if strings.Contains(domain, ":") {
|
||||||
|
domain = strings.Split(domain, ":")[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]interface{}{
|
||||||
|
"Input": input,
|
||||||
|
"Hostname": parsed.Host,
|
||||||
|
"Host": domain,
|
||||||
|
}
|
||||||
|
}
|
|
@ -108,6 +108,11 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Execute
|
||||||
|
|
||||||
// parseSelfContainedRequests parses the self contained template requests.
|
// parseSelfContainedRequests parses the self contained template requests.
|
||||||
func (template *Template) parseSelfContainedRequests() {
|
func (template *Template) parseSelfContainedRequests() {
|
||||||
|
if template.Signature.Value.String() != "" {
|
||||||
|
for _, request := range template.RequestsHTTP {
|
||||||
|
request.Signature = template.Signature
|
||||||
|
}
|
||||||
|
}
|
||||||
if !template.SelfContained {
|
if !template.SelfContained {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -128,7 +133,8 @@ func (template *Template) Requests() int {
|
||||||
len(template.RequestsHeadless) +
|
len(template.RequestsHeadless) +
|
||||||
len(template.Workflows) +
|
len(template.Workflows) +
|
||||||
len(template.RequestsSSL) +
|
len(template.RequestsSSL) +
|
||||||
len(template.RequestsWebsocket)
|
len(template.RequestsWebsocket) +
|
||||||
|
len(template.RequestsWHOIS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compileProtocolRequests compiles all the protocol requests for the template
|
// compileProtocolRequests compiles all the protocol requests for the template
|
||||||
|
@ -166,6 +172,9 @@ func (template *Template) compileProtocolRequests(options protocols.ExecuterOpti
|
||||||
|
|
||||||
case len(template.RequestsWebsocket) > 0:
|
case len(template.RequestsWebsocket) > 0:
|
||||||
requests = template.convertRequestToProtocolsRequest(template.RequestsWebsocket)
|
requests = template.convertRequestToProtocolsRequest(template.RequestsWebsocket)
|
||||||
|
|
||||||
|
case len(template.RequestsWHOIS) > 0:
|
||||||
|
requests = template.convertRequestToProtocolsRequest(template.RequestsWHOIS)
|
||||||
}
|
}
|
||||||
template.Executer = executer.NewExecuter(requests, &options)
|
template.Executer = executer.NewExecuter(requests, &options)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
validate "github.com/go-playground/validator/v10"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
"github.com/projectdiscovery/nuclei/v2/pkg/model"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/dns"
|
||||||
|
@ -11,8 +14,11 @@ import (
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/network"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/network"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/ssl"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/ssl"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/websocket"
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/websocket"
|
||||||
|
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/whois"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
"github.com/projectdiscovery/nuclei/v2/pkg/templates/types"
|
||||||
"github.com/projectdiscovery/nuclei/v2/pkg/workflows"
|
"github.com/projectdiscovery/nuclei/v2/pkg/workflows"
|
||||||
|
"go.uber.org/multierr"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Template is a YAML input file which defines all the requests and
|
// Template is a YAML input file which defines all the requests and
|
||||||
|
@ -66,6 +72,9 @@ type Template struct {
|
||||||
// Websocket contains the Websocket request to make in the template.
|
// Websocket contains the Websocket request to make in the template.
|
||||||
RequestsWebsocket []*websocket.Request `yaml:"websocket,omitempty" json:"websocket,omitempty" jsonschema:"title=websocket requests to make,description=Websocket requests to make for the template"`
|
RequestsWebsocket []*websocket.Request `yaml:"websocket,omitempty" json:"websocket,omitempty" jsonschema:"title=websocket requests to make,description=Websocket requests to make for the template"`
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// WHOIS contains the WHOIS request to make in the template.
|
||||||
|
RequestsWHOIS []*whois.Request `yaml:"whois,omitempty" json:"whois,omitempty" jsonschema:"title=whois requests to make,description=WHOIS requests to make for the template"`
|
||||||
// description: |
|
// description: |
|
||||||
// Workflows is a yaml based workflow declaration code.
|
// Workflows is a yaml based workflow declaration code.
|
||||||
workflows.Workflow `yaml:",inline,omitempty" jsonschema:"title=workflows to run,description=Workflows to run for the template"`
|
workflows.Workflow `yaml:",inline,omitempty" jsonschema:"title=workflows to run,description=Workflows to run for the template"`
|
||||||
|
@ -78,6 +87,12 @@ type Template struct {
|
||||||
// Stop execution once first match is found
|
// Stop execution once first match is found
|
||||||
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop at first match for the template"`
|
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop at first match for the template"`
|
||||||
|
|
||||||
|
// description: |
|
||||||
|
// Signature is the request signature method
|
||||||
|
// values:
|
||||||
|
// - "AWS"
|
||||||
|
Signature http.SignatureTypeHolder `yaml:"signature,omitempty" jsonschema:"title=signature is the http request signature method,description=Signature is the HTTP Request signature Method,enum=AWS"`
|
||||||
|
|
||||||
// TotalRequests is the total number of requests for the template.
|
// TotalRequests is the total number of requests for the template.
|
||||||
TotalRequests int `yaml:"-" json:"-"`
|
TotalRequests int `yaml:"-" json:"-"`
|
||||||
// Executer is the actual template executor for running template requests
|
// Executer is the actual template executor for running template requests
|
||||||
|
@ -96,6 +111,7 @@ var TemplateProtocols = []string{
|
||||||
"workflow",
|
"workflow",
|
||||||
"ssl",
|
"ssl",
|
||||||
"websocket",
|
"websocket",
|
||||||
|
"whois",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the type of the template
|
// Type returns the type of the template
|
||||||
|
@ -117,7 +133,47 @@ func (template *Template) Type() types.ProtocolType {
|
||||||
return types.SSLProtocol
|
return types.SSLProtocol
|
||||||
case len(template.RequestsWebsocket) > 0:
|
case len(template.RequestsWebsocket) > 0:
|
||||||
return types.WebsocketProtocol
|
return types.WebsocketProtocol
|
||||||
|
case len(template.RequestsWHOIS) > 0:
|
||||||
|
return types.WHOISProtocol
|
||||||
default:
|
default:
|
||||||
return types.InvalidProtocol
|
return types.InvalidProtocol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalYAML forces recursive struct validation during marshal operation
|
||||||
|
func (template *Template) MarshalYAML() ([]byte, error) {
|
||||||
|
out, marshalErr := yaml.Marshal(template)
|
||||||
|
errValidate := validate.New().Struct(template)
|
||||||
|
return out, multierr.Append(marshalErr, errValidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalYAML forces recursive struct validation after unmarshal operation
|
||||||
|
func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
type Alias Template
|
||||||
|
alias := &Alias{}
|
||||||
|
err := unmarshal(alias)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*template = Template(*alias)
|
||||||
|
return validate.New().Struct(template)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON forces recursive struct validation during marshal operation
|
||||||
|
func (template *Template) MarshalJSON() ([]byte, error) {
|
||||||
|
out, marshalErr := json.Marshal(template)
|
||||||
|
errValidate := validate.New().Struct(template)
|
||||||
|
return out, multierr.Append(marshalErr, errValidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON forces recursive struct validation after unmarshal operation
|
||||||
|
func (template *Template) UnmarshalJSON(data []byte) error {
|
||||||
|
type Alias Template
|
||||||
|
alias := &Alias{}
|
||||||
|
err := json.Unmarshal(data, alias)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*template = Template(*alias)
|
||||||
|
return validate.New().Struct(template)
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ var (
|
||||||
ExtractorTypeHolderDoc encoder.Doc
|
ExtractorTypeHolderDoc encoder.Doc
|
||||||
GENERATORSAttackTypeHolderDoc encoder.Doc
|
GENERATORSAttackTypeHolderDoc encoder.Doc
|
||||||
HTTPMethodTypeHolderDoc encoder.Doc
|
HTTPMethodTypeHolderDoc encoder.Doc
|
||||||
|
SignatureTypeHolderDoc encoder.Doc
|
||||||
DNSRequestDoc encoder.Doc
|
DNSRequestDoc encoder.Doc
|
||||||
DNSRequestTypeHolderDoc encoder.Doc
|
DNSRequestTypeHolderDoc encoder.Doc
|
||||||
FILERequestDoc encoder.Doc
|
FILERequestDoc encoder.Doc
|
||||||
|
@ -33,15 +34,17 @@ var (
|
||||||
SSLRequestDoc encoder.Doc
|
SSLRequestDoc encoder.Doc
|
||||||
WEBSOCKETRequestDoc encoder.Doc
|
WEBSOCKETRequestDoc encoder.Doc
|
||||||
WEBSOCKETInputDoc encoder.Doc
|
WEBSOCKETInputDoc encoder.Doc
|
||||||
|
WHOISRequestDoc encoder.Doc
|
||||||
WORKFLOWSWorkflowTemplateDoc encoder.Doc
|
WORKFLOWSWorkflowTemplateDoc encoder.Doc
|
||||||
WORKFLOWSMatcherDoc encoder.Doc
|
WORKFLOWSMatcherDoc encoder.Doc
|
||||||
|
HTTPSignatureTypeHolderDoc encoder.Doc
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
TemplateDoc.Type = "Template"
|
TemplateDoc.Type = "Template"
|
||||||
TemplateDoc.Comments[encoder.LineComment] = " Template is a YAML input file which defines all the requests and"
|
TemplateDoc.Comments[encoder.LineComment] = " Template is a YAML input file which defines all the requests and"
|
||||||
TemplateDoc.Description = "Template is a YAML input file which defines all the requests and\n other metadata for a template."
|
TemplateDoc.Description = "Template is a YAML input file which defines all the requests and\n other metadata for a template."
|
||||||
TemplateDoc.Fields = make([]encoder.Doc, 12)
|
TemplateDoc.Fields = make([]encoder.Doc, 14)
|
||||||
TemplateDoc.Fields[0].Name = "id"
|
TemplateDoc.Fields[0].Name = "id"
|
||||||
TemplateDoc.Fields[0].Type = "string"
|
TemplateDoc.Fields[0].Type = "string"
|
||||||
TemplateDoc.Fields[0].Note = ""
|
TemplateDoc.Fields[0].Note = ""
|
||||||
|
@ -99,21 +102,34 @@ func init() {
|
||||||
TemplateDoc.Fields[8].Note = ""
|
TemplateDoc.Fields[8].Note = ""
|
||||||
TemplateDoc.Fields[8].Description = "Websocket contains the Websocket request to make in the template."
|
TemplateDoc.Fields[8].Description = "Websocket contains the Websocket request to make in the template."
|
||||||
TemplateDoc.Fields[8].Comments[encoder.LineComment] = "Websocket contains the Websocket request to make in the template."
|
TemplateDoc.Fields[8].Comments[encoder.LineComment] = "Websocket contains the Websocket request to make in the template."
|
||||||
TemplateDoc.Fields[9].Name = "workflows"
|
TemplateDoc.Fields[9].Name = "whois"
|
||||||
TemplateDoc.Fields[9].Type = "[]workflows.WorkflowTemplate"
|
TemplateDoc.Fields[9].Type = "[]whois.Request"
|
||||||
TemplateDoc.Fields[9].Note = ""
|
TemplateDoc.Fields[9].Note = ""
|
||||||
TemplateDoc.Fields[9].Description = "Workflows is a list of workflows to execute for a template."
|
TemplateDoc.Fields[9].Description = "WHOIS contains the WHOIS request to make in the template."
|
||||||
TemplateDoc.Fields[9].Comments[encoder.LineComment] = "Workflows is a list of workflows to execute for a template."
|
TemplateDoc.Fields[9].Comments[encoder.LineComment] = "WHOIS contains the WHOIS request to make in the template."
|
||||||
TemplateDoc.Fields[10].Name = "self-contained"
|
TemplateDoc.Fields[10].Name = "workflows"
|
||||||
TemplateDoc.Fields[10].Type = "bool"
|
TemplateDoc.Fields[10].Type = "[]workflows.WorkflowTemplate"
|
||||||
TemplateDoc.Fields[10].Note = ""
|
TemplateDoc.Fields[10].Note = ""
|
||||||
TemplateDoc.Fields[10].Description = "Self Contained marks Requests for the template as self-contained"
|
TemplateDoc.Fields[10].Description = "Workflows is a list of workflows to execute for a template."
|
||||||
TemplateDoc.Fields[10].Comments[encoder.LineComment] = "Self Contained marks Requests for the template as self-contained"
|
TemplateDoc.Fields[10].Comments[encoder.LineComment] = "Workflows is a list of workflows to execute for a template."
|
||||||
TemplateDoc.Fields[11].Name = "stop-at-first-match"
|
TemplateDoc.Fields[11].Name = "self-contained"
|
||||||
TemplateDoc.Fields[11].Type = "bool"
|
TemplateDoc.Fields[11].Type = "bool"
|
||||||
TemplateDoc.Fields[11].Note = ""
|
TemplateDoc.Fields[11].Note = ""
|
||||||
TemplateDoc.Fields[11].Description = "Stop execution once first match is found"
|
TemplateDoc.Fields[11].Description = "Self Contained marks Requests for the template as self-contained"
|
||||||
TemplateDoc.Fields[11].Comments[encoder.LineComment] = "Stop execution once first match is found"
|
TemplateDoc.Fields[11].Comments[encoder.LineComment] = "Self Contained marks Requests for the template as self-contained"
|
||||||
|
TemplateDoc.Fields[12].Name = "stop-at-first-match"
|
||||||
|
TemplateDoc.Fields[12].Type = "bool"
|
||||||
|
TemplateDoc.Fields[12].Note = ""
|
||||||
|
TemplateDoc.Fields[12].Description = "Stop execution once first match is found"
|
||||||
|
TemplateDoc.Fields[12].Comments[encoder.LineComment] = "Stop execution once first match is found"
|
||||||
|
TemplateDoc.Fields[13].Name = "signature"
|
||||||
|
TemplateDoc.Fields[13].Type = "http.SignatureTypeHolder"
|
||||||
|
TemplateDoc.Fields[13].Note = ""
|
||||||
|
TemplateDoc.Fields[13].Description = "Signature is the request signature method"
|
||||||
|
TemplateDoc.Fields[13].Comments[encoder.LineComment] = "Signature is the request signature method"
|
||||||
|
TemplateDoc.Fields[13].Values = []string{
|
||||||
|
"AWS",
|
||||||
|
}
|
||||||
|
|
||||||
MODELInfoDoc.Type = "model.Info"
|
MODELInfoDoc.Type = "model.Info"
|
||||||
MODELInfoDoc.Comments[encoder.LineComment] = " Info contains metadata information about a template"
|
MODELInfoDoc.Comments[encoder.LineComment] = " Info contains metadata information about a template"
|
||||||
|
@ -372,7 +388,7 @@ func init() {
|
||||||
Value: "HTTP response headers in name:value format",
|
Value: "HTTP response headers in name:value format",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
HTTPRequestDoc.Fields = make([]encoder.Doc, 27)
|
HTTPRequestDoc.Fields = make([]encoder.Doc, 28)
|
||||||
HTTPRequestDoc.Fields[0].Name = "matchers"
|
HTTPRequestDoc.Fields[0].Name = "matchers"
|
||||||
HTTPRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
HTTPRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
||||||
HTTPRequestDoc.Fields[0].Note = ""
|
HTTPRequestDoc.Fields[0].Note = ""
|
||||||
|
@ -492,51 +508,59 @@ func init() {
|
||||||
HTTPRequestDoc.Fields[17].Comments[encoder.LineComment] = "MaxSize is the maximum size of http response body to read in bytes."
|
HTTPRequestDoc.Fields[17].Comments[encoder.LineComment] = "MaxSize is the maximum size of http response body to read in bytes."
|
||||||
|
|
||||||
HTTPRequestDoc.Fields[17].AddExample("Read max 2048 bytes of the response", 2048)
|
HTTPRequestDoc.Fields[17].AddExample("Read max 2048 bytes of the response", 2048)
|
||||||
HTTPRequestDoc.Fields[18].Name = "cookie-reuse"
|
HTTPRequestDoc.Fields[18].Name = "signature"
|
||||||
HTTPRequestDoc.Fields[18].Type = "bool"
|
HTTPRequestDoc.Fields[18].Type = "SignatureTypeHolder"
|
||||||
HTTPRequestDoc.Fields[18].Note = ""
|
HTTPRequestDoc.Fields[18].Note = ""
|
||||||
HTTPRequestDoc.Fields[18].Description = "CookieReuse is an optional setting that enables cookie reuse for\nall requests defined in raw section."
|
HTTPRequestDoc.Fields[18].Description = "Signature is the request signature method"
|
||||||
HTTPRequestDoc.Fields[18].Comments[encoder.LineComment] = "CookieReuse is an optional setting that enables cookie reuse for"
|
HTTPRequestDoc.Fields[18].Comments[encoder.LineComment] = "Signature is the request signature method"
|
||||||
HTTPRequestDoc.Fields[19].Name = "redirects"
|
HTTPRequestDoc.Fields[18].Values = []string{
|
||||||
|
"AWS",
|
||||||
|
}
|
||||||
|
HTTPRequestDoc.Fields[19].Name = "cookie-reuse"
|
||||||
HTTPRequestDoc.Fields[19].Type = "bool"
|
HTTPRequestDoc.Fields[19].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[19].Note = ""
|
HTTPRequestDoc.Fields[19].Note = ""
|
||||||
HTTPRequestDoc.Fields[19].Description = "Redirects specifies whether redirects should be followed by the HTTP Client.\n\nThis can be used in conjunction with `max-redirects` to control the HTTP request redirects."
|
HTTPRequestDoc.Fields[19].Description = "CookieReuse is an optional setting that enables cookie reuse for\nall requests defined in raw section."
|
||||||
HTTPRequestDoc.Fields[19].Comments[encoder.LineComment] = "Redirects specifies whether redirects should be followed by the HTTP Client."
|
HTTPRequestDoc.Fields[19].Comments[encoder.LineComment] = "CookieReuse is an optional setting that enables cookie reuse for"
|
||||||
HTTPRequestDoc.Fields[20].Name = "pipeline"
|
HTTPRequestDoc.Fields[20].Name = "redirects"
|
||||||
HTTPRequestDoc.Fields[20].Type = "bool"
|
HTTPRequestDoc.Fields[20].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[20].Note = ""
|
HTTPRequestDoc.Fields[20].Note = ""
|
||||||
HTTPRequestDoc.Fields[20].Description = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining\n\nAll requests must be idempotent (GET/POST). This can be used for race conditions/billions requests."
|
HTTPRequestDoc.Fields[20].Description = "Redirects specifies whether redirects should be followed by the HTTP Client.\n\nThis can be used in conjunction with `max-redirects` to control the HTTP request redirects."
|
||||||
HTTPRequestDoc.Fields[20].Comments[encoder.LineComment] = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining"
|
HTTPRequestDoc.Fields[20].Comments[encoder.LineComment] = "Redirects specifies whether redirects should be followed by the HTTP Client."
|
||||||
HTTPRequestDoc.Fields[21].Name = "unsafe"
|
HTTPRequestDoc.Fields[21].Name = "pipeline"
|
||||||
HTTPRequestDoc.Fields[21].Type = "bool"
|
HTTPRequestDoc.Fields[21].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[21].Note = ""
|
HTTPRequestDoc.Fields[21].Note = ""
|
||||||
HTTPRequestDoc.Fields[21].Description = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests.\n\nThis uses the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine to achieve complete\ncontrol over the request, with no normalization performed by the client."
|
HTTPRequestDoc.Fields[21].Description = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining\n\nAll requests must be idempotent (GET/POST). This can be used for race conditions/billions requests."
|
||||||
HTTPRequestDoc.Fields[21].Comments[encoder.LineComment] = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests."
|
HTTPRequestDoc.Fields[21].Comments[encoder.LineComment] = "Pipeline defines if the attack should be performed with HTTP 1.1 Pipelining"
|
||||||
HTTPRequestDoc.Fields[22].Name = "race"
|
HTTPRequestDoc.Fields[22].Name = "unsafe"
|
||||||
HTTPRequestDoc.Fields[22].Type = "bool"
|
HTTPRequestDoc.Fields[22].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[22].Note = ""
|
HTTPRequestDoc.Fields[22].Note = ""
|
||||||
HTTPRequestDoc.Fields[22].Description = "Race determines if all the request have to be attempted at the same time (Race Condition)\n\nThe actual number of requests that will be sent is determined by the `race_count` field."
|
HTTPRequestDoc.Fields[22].Description = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests.\n\nThis uses the [rawhttp](https://github.com/projectdiscovery/rawhttp) engine to achieve complete\ncontrol over the request, with no normalization performed by the client."
|
||||||
HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "Race determines if all the request have to be attempted at the same time (Race Condition)"
|
HTTPRequestDoc.Fields[22].Comments[encoder.LineComment] = "Unsafe specifies whether to use rawhttp engine for sending Non RFC-Compliant requests."
|
||||||
HTTPRequestDoc.Fields[23].Name = "req-condition"
|
HTTPRequestDoc.Fields[23].Name = "race"
|
||||||
HTTPRequestDoc.Fields[23].Type = "bool"
|
HTTPRequestDoc.Fields[23].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[23].Note = ""
|
HTTPRequestDoc.Fields[23].Note = ""
|
||||||
HTTPRequestDoc.Fields[23].Description = "ReqCondition automatically assigns numbers to requests and preserves their history.\n\nThis allows matching on them later for multi-request conditions."
|
HTTPRequestDoc.Fields[23].Description = "Race determines if all the request have to be attempted at the same time (Race Condition)\n\nThe actual number of requests that will be sent is determined by the `race_count` field."
|
||||||
HTTPRequestDoc.Fields[23].Comments[encoder.LineComment] = "ReqCondition automatically assigns numbers to requests and preserves their history."
|
HTTPRequestDoc.Fields[23].Comments[encoder.LineComment] = "Race determines if all the request have to be attempted at the same time (Race Condition)"
|
||||||
HTTPRequestDoc.Fields[24].Name = "stop-at-first-match"
|
HTTPRequestDoc.Fields[24].Name = "req-condition"
|
||||||
HTTPRequestDoc.Fields[24].Type = "bool"
|
HTTPRequestDoc.Fields[24].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[24].Note = ""
|
HTTPRequestDoc.Fields[24].Note = ""
|
||||||
HTTPRequestDoc.Fields[24].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
HTTPRequestDoc.Fields[24].Description = "ReqCondition automatically assigns numbers to requests and preserves their history.\n\nThis allows matching on them later for multi-request conditions."
|
||||||
HTTPRequestDoc.Fields[24].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
HTTPRequestDoc.Fields[24].Comments[encoder.LineComment] = "ReqCondition automatically assigns numbers to requests and preserves their history."
|
||||||
HTTPRequestDoc.Fields[25].Name = "skip-variables-check"
|
HTTPRequestDoc.Fields[25].Name = "stop-at-first-match"
|
||||||
HTTPRequestDoc.Fields[25].Type = "bool"
|
HTTPRequestDoc.Fields[25].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[25].Note = ""
|
HTTPRequestDoc.Fields[25].Note = ""
|
||||||
HTTPRequestDoc.Fields[25].Description = "SkipVariablesCheck skips the check for unresolved variables in request"
|
HTTPRequestDoc.Fields[25].Description = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||||
HTTPRequestDoc.Fields[25].Comments[encoder.LineComment] = "SkipVariablesCheck skips the check for unresolved variables in request"
|
HTTPRequestDoc.Fields[25].Comments[encoder.LineComment] = "StopAtFirstMatch stops the execution of the requests and template as soon as a match is found."
|
||||||
HTTPRequestDoc.Fields[26].Name = "iterate-all"
|
HTTPRequestDoc.Fields[26].Name = "skip-variables-check"
|
||||||
HTTPRequestDoc.Fields[26].Type = "bool"
|
HTTPRequestDoc.Fields[26].Type = "bool"
|
||||||
HTTPRequestDoc.Fields[26].Note = ""
|
HTTPRequestDoc.Fields[26].Note = ""
|
||||||
HTTPRequestDoc.Fields[26].Description = "IterateAll iterates all the values extracted from internal extractors"
|
HTTPRequestDoc.Fields[26].Description = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||||
HTTPRequestDoc.Fields[26].Comments[encoder.LineComment] = "IterateAll iterates all the values extracted from internal extractors"
|
HTTPRequestDoc.Fields[26].Comments[encoder.LineComment] = "SkipVariablesCheck skips the check for unresolved variables in request"
|
||||||
|
HTTPRequestDoc.Fields[27].Name = "iterate-all"
|
||||||
|
HTTPRequestDoc.Fields[27].Type = "bool"
|
||||||
|
HTTPRequestDoc.Fields[27].Note = ""
|
||||||
|
HTTPRequestDoc.Fields[27].Description = "IterateAll iterates all the values extracted from internal extractors"
|
||||||
|
HTTPRequestDoc.Fields[27].Comments[encoder.LineComment] = "IterateAll iterates all the values extracted from internal extractors"
|
||||||
|
|
||||||
MATCHERSMatcherDoc.Type = "matchers.Matcher"
|
MATCHERSMatcherDoc.Type = "matchers.Matcher"
|
||||||
MATCHERSMatcherDoc.Comments[encoder.LineComment] = " Matcher is used to match a part in the output from a protocol."
|
MATCHERSMatcherDoc.Comments[encoder.LineComment] = " Matcher is used to match a part in the output from a protocol."
|
||||||
|
@ -570,6 +594,10 @@ func init() {
|
||||||
TypeName: "websocket.Request",
|
TypeName: "websocket.Request",
|
||||||
FieldName: "matchers",
|
FieldName: "matchers",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TypeName: "whois.Request",
|
||||||
|
FieldName: "matchers",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
MATCHERSMatcherDoc.Fields = make([]encoder.Doc, 13)
|
MATCHERSMatcherDoc.Fields = make([]encoder.Doc, 13)
|
||||||
MATCHERSMatcherDoc.Fields[0].Name = "type"
|
MATCHERSMatcherDoc.Fields[0].Name = "type"
|
||||||
|
@ -731,6 +759,10 @@ func init() {
|
||||||
TypeName: "websocket.Request",
|
TypeName: "websocket.Request",
|
||||||
FieldName: "extractors",
|
FieldName: "extractors",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
TypeName: "whois.Request",
|
||||||
|
FieldName: "extractors",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
EXTRACTORSExtractorDoc.Fields = make([]encoder.Doc, 11)
|
EXTRACTORSExtractorDoc.Fields = make([]encoder.Doc, 11)
|
||||||
EXTRACTORSExtractorDoc.Fields[0].Name = "name"
|
EXTRACTORSExtractorDoc.Fields[0].Name = "name"
|
||||||
|
@ -892,6 +924,17 @@ func init() {
|
||||||
"PURGE",
|
"PURGE",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SignatureTypeHolderDoc.Type = "SignatureTypeHolder"
|
||||||
|
SignatureTypeHolderDoc.Comments[encoder.LineComment] = " SignatureTypeHolder is used to hold internal type of the signature"
|
||||||
|
SignatureTypeHolderDoc.Description = "SignatureTypeHolder is used to hold internal type of the signature"
|
||||||
|
SignatureTypeHolderDoc.AppearsIn = []encoder.Appearance{
|
||||||
|
{
|
||||||
|
TypeName: "http.Request",
|
||||||
|
FieldName: "signature",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
SignatureTypeHolderDoc.Fields = make([]encoder.Doc, 0)
|
||||||
|
|
||||||
DNSRequestDoc.Type = "dns.Request"
|
DNSRequestDoc.Type = "dns.Request"
|
||||||
DNSRequestDoc.Comments[encoder.LineComment] = " Request contains a DNS protocol request to be made from a template"
|
DNSRequestDoc.Comments[encoder.LineComment] = " Request contains a DNS protocol request to be made from a template"
|
||||||
DNSRequestDoc.Description = "Request contains a DNS protocol request to be made from a template"
|
DNSRequestDoc.Description = "Request contains a DNS protocol request to be made from a template"
|
||||||
|
@ -1139,8 +1182,8 @@ func init() {
|
||||||
FILERequestDoc.Fields[4].Name = "denylist"
|
FILERequestDoc.Fields[4].Name = "denylist"
|
||||||
FILERequestDoc.Fields[4].Type = "[]string"
|
FILERequestDoc.Fields[4].Type = "[]string"
|
||||||
FILERequestDoc.Fields[4].Note = ""
|
FILERequestDoc.Fields[4].Note = ""
|
||||||
FILERequestDoc.Fields[4].Description = "ExtensionDenylist is the list of file extensions to deny during matching.\n\nBy default, it contains some non-interesting extensions that are hardcoded\nin nuclei."
|
FILERequestDoc.Fields[4].Description = "DenyList is the list of file, directories or extensions to deny during matching.\n\nBy default, it contains some non-interesting extensions that are hardcoded\nin nuclei."
|
||||||
FILERequestDoc.Fields[4].Comments[encoder.LineComment] = "ExtensionDenylist is the list of file extensions to deny during matching."
|
FILERequestDoc.Fields[4].Comments[encoder.LineComment] = "DenyList is the list of file, directories or extensions to deny during matching."
|
||||||
|
|
||||||
FILERequestDoc.Fields[4].AddExample("", []string{".avi", ".mov", ".mp3"})
|
FILERequestDoc.Fields[4].AddExample("", []string{".avi", ".mov", ".mp3"})
|
||||||
FILERequestDoc.Fields[5].Name = "id"
|
FILERequestDoc.Fields[5].Name = "id"
|
||||||
|
@ -1645,6 +1688,46 @@ func init() {
|
||||||
|
|
||||||
WEBSOCKETInputDoc.Fields[1].AddExample("", "prefix")
|
WEBSOCKETInputDoc.Fields[1].AddExample("", "prefix")
|
||||||
|
|
||||||
|
WHOISRequestDoc.Type = "whois.Request"
|
||||||
|
WHOISRequestDoc.Comments[encoder.LineComment] = " Request is a request for the WHOIS protocol"
|
||||||
|
WHOISRequestDoc.Description = "Request is a request for the WHOIS protocol"
|
||||||
|
WHOISRequestDoc.AppearsIn = []encoder.Appearance{
|
||||||
|
{
|
||||||
|
TypeName: "Template",
|
||||||
|
FieldName: "whois",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
WHOISRequestDoc.Fields = make([]encoder.Doc, 5)
|
||||||
|
WHOISRequestDoc.Fields[0].Name = "matchers"
|
||||||
|
WHOISRequestDoc.Fields[0].Type = "[]matchers.Matcher"
|
||||||
|
WHOISRequestDoc.Fields[0].Note = ""
|
||||||
|
WHOISRequestDoc.Fields[0].Description = "Matchers contains the detection mechanism for the request to identify\nwhether the request was successful by doing pattern matching\non request/responses.\n\nMultiple matchers can be combined with `matcher-condition` flag\nwhich accepts either `and` or `or` as argument."
|
||||||
|
WHOISRequestDoc.Fields[0].Comments[encoder.LineComment] = "Matchers contains the detection mechanism for the request to identify"
|
||||||
|
WHOISRequestDoc.Fields[1].Name = "extractors"
|
||||||
|
WHOISRequestDoc.Fields[1].Type = "[]extractors.Extractor"
|
||||||
|
WHOISRequestDoc.Fields[1].Note = ""
|
||||||
|
WHOISRequestDoc.Fields[1].Description = "Extractors contains the extraction mechanism for the request to identify\nand extract parts of the response."
|
||||||
|
WHOISRequestDoc.Fields[1].Comments[encoder.LineComment] = "Extractors contains the extraction mechanism for the request to identify"
|
||||||
|
WHOISRequestDoc.Fields[2].Name = "matchers-condition"
|
||||||
|
WHOISRequestDoc.Fields[2].Type = "string"
|
||||||
|
WHOISRequestDoc.Fields[2].Note = ""
|
||||||
|
WHOISRequestDoc.Fields[2].Description = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||||
|
WHOISRequestDoc.Fields[2].Comments[encoder.LineComment] = "MatchersCondition is the condition between the matchers. Default is OR."
|
||||||
|
WHOISRequestDoc.Fields[2].Values = []string{
|
||||||
|
"and",
|
||||||
|
"or",
|
||||||
|
}
|
||||||
|
WHOISRequestDoc.Fields[3].Name = "query"
|
||||||
|
WHOISRequestDoc.Fields[3].Type = "string"
|
||||||
|
WHOISRequestDoc.Fields[3].Note = ""
|
||||||
|
WHOISRequestDoc.Fields[3].Description = "Query contains query for the request"
|
||||||
|
WHOISRequestDoc.Fields[3].Comments[encoder.LineComment] = "Query contains query for the request"
|
||||||
|
WHOISRequestDoc.Fields[4].Name = "server"
|
||||||
|
WHOISRequestDoc.Fields[4].Type = "string"
|
||||||
|
WHOISRequestDoc.Fields[4].Note = ""
|
||||||
|
WHOISRequestDoc.Fields[4].Description = "description: |\n Optional WHOIS server URL.\n\n If present, specifies the WHOIS server to execute the Request on.\n Otherwise, nil enables bootstrapping"
|
||||||
|
WHOISRequestDoc.Fields[4].Comments[encoder.LineComment] = " description: |"
|
||||||
|
|
||||||
WORKFLOWSWorkflowTemplateDoc.Type = "workflows.WorkflowTemplate"
|
WORKFLOWSWorkflowTemplateDoc.Type = "workflows.WorkflowTemplate"
|
||||||
WORKFLOWSWorkflowTemplateDoc.Comments[encoder.LineComment] = ""
|
WORKFLOWSWorkflowTemplateDoc.Comments[encoder.LineComment] = ""
|
||||||
WORKFLOWSWorkflowTemplateDoc.Description = ""
|
WORKFLOWSWorkflowTemplateDoc.Description = ""
|
||||||
|
@ -1708,6 +1791,17 @@ func init() {
|
||||||
WORKFLOWSMatcherDoc.Fields[1].Note = ""
|
WORKFLOWSMatcherDoc.Fields[1].Note = ""
|
||||||
WORKFLOWSMatcherDoc.Fields[1].Description = "Subtemplates are run if the name of matcher matches."
|
WORKFLOWSMatcherDoc.Fields[1].Description = "Subtemplates are run if the name of matcher matches."
|
||||||
WORKFLOWSMatcherDoc.Fields[1].Comments[encoder.LineComment] = "Subtemplates are run if the name of matcher matches."
|
WORKFLOWSMatcherDoc.Fields[1].Comments[encoder.LineComment] = "Subtemplates are run if the name of matcher matches."
|
||||||
|
|
||||||
|
HTTPSignatureTypeHolderDoc.Type = "http.SignatureTypeHolder"
|
||||||
|
HTTPSignatureTypeHolderDoc.Comments[encoder.LineComment] = " SignatureTypeHolder is used to hold internal type of the signature"
|
||||||
|
HTTPSignatureTypeHolderDoc.Description = "SignatureTypeHolder is used to hold internal type of the signature"
|
||||||
|
HTTPSignatureTypeHolderDoc.AppearsIn = []encoder.Appearance{
|
||||||
|
{
|
||||||
|
TypeName: "Template",
|
||||||
|
FieldName: "signature",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
HTTPSignatureTypeHolderDoc.Fields = make([]encoder.Doc, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTemplateDoc returns documentation for the file templates_doc.go.
|
// GetTemplateDoc returns documentation for the file templates_doc.go.
|
||||||
|
@ -1728,6 +1822,7 @@ func GetTemplateDoc() *encoder.FileDoc {
|
||||||
&ExtractorTypeHolderDoc,
|
&ExtractorTypeHolderDoc,
|
||||||
&GENERATORSAttackTypeHolderDoc,
|
&GENERATORSAttackTypeHolderDoc,
|
||||||
&HTTPMethodTypeHolderDoc,
|
&HTTPMethodTypeHolderDoc,
|
||||||
|
&SignatureTypeHolderDoc,
|
||||||
&DNSRequestDoc,
|
&DNSRequestDoc,
|
||||||
&DNSRequestTypeHolderDoc,
|
&DNSRequestTypeHolderDoc,
|
||||||
&FILERequestDoc,
|
&FILERequestDoc,
|
||||||
|
@ -1740,8 +1835,10 @@ func GetTemplateDoc() *encoder.FileDoc {
|
||||||
&SSLRequestDoc,
|
&SSLRequestDoc,
|
||||||
&WEBSOCKETRequestDoc,
|
&WEBSOCKETRequestDoc,
|
||||||
&WEBSOCKETInputDoc,
|
&WEBSOCKETInputDoc,
|
||||||
|
&WHOISRequestDoc,
|
||||||
&WORKFLOWSWorkflowTemplateDoc,
|
&WORKFLOWSWorkflowTemplateDoc,
|
||||||
&WORKFLOWSMatcherDoc,
|
&WORKFLOWSMatcherDoc,
|
||||||
|
&HTTPSignatureTypeHolderDoc,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ const (
|
||||||
SSLProtocol
|
SSLProtocol
|
||||||
// name:websocket
|
// name:websocket
|
||||||
WebsocketProtocol
|
WebsocketProtocol
|
||||||
|
// name:whois
|
||||||
|
WHOISProtocol
|
||||||
limit
|
limit
|
||||||
InvalidProtocol
|
InvalidProtocol
|
||||||
)
|
)
|
||||||
|
@ -49,6 +51,7 @@ var protocolMappings = map[ProtocolType]string{
|
||||||
WorkflowProtocol: "workflow",
|
WorkflowProtocol: "workflow",
|
||||||
SSLProtocol: "ssl",
|
SSLProtocol: "ssl",
|
||||||
WebsocketProtocol: "websocket",
|
WebsocketProtocol: "websocket",
|
||||||
|
WHOISProtocol: "whois",
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSupportedProtocolTypes() ProtocolTypes {
|
func GetSupportedProtocolTypes() ProtocolTypes {
|
||||||
|
|
Loading…
Reference in New Issue