Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add flow support in template (i.e javascript scripting) #4015

Merged
merged 39 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
94656f8
add flow logic
tarunKoyalwar Aug 1, 2023
0250230
progress
tarunKoyalwar Aug 1, 2023
d9bddd5
working POC
tarunKoyalwar Aug 1, 2023
fdf2eb6
fix string slice normalization issue in variables
tarunKoyalwar Aug 2, 2023
cffe9ce
update
tarunKoyalwar Aug 2, 2023
14012ab
fix nil panic
tarunKoyalwar Aug 3, 2023
1bca35f
remove poll()
tarunKoyalwar Aug 3, 2023
953f2f1
resolve merge conflicts
tarunKoyalwar Aug 4, 2023
6099997
load file with sandbox and more
tarunKoyalwar Aug 7, 2023
41f13bc
fix failing integration tests
tarunKoyalwar Aug 7, 2023
3677ff2
JS: log: print in vardump format
tarunKoyalwar Aug 7, 2023
b7cc2c3
fix missing id in protocols
tarunKoyalwar Aug 7, 2023
4fffe10
fix proto prefix in template context
tarunKoyalwar Aug 7, 2023
bc4ec8d
flow: add unit tests
tarunKoyalwar Aug 7, 2023
816d4cc
conditional flow support using flow
tarunKoyalwar Aug 7, 2023
e329f5c
fix proto callbacks + more unit tests
tarunKoyalwar Aug 8, 2023
74e69af
adds integration test
tarunKoyalwar Aug 9, 2023
64098b6
conditional flow: check if req has any matchers
tarunKoyalwar Aug 9, 2023
aa5da2b
fix lint error
tarunKoyalwar Aug 9, 2023
ab36aee
deprecate iterate-all+ missing multi-proto implementation
tarunKoyalwar Aug 10, 2023
02f4237
fix ip input in raw request
tarunKoyalwar Aug 13, 2023
9c79cb4
JS: feat dedupe object+ more builtin funcs
tarunKoyalwar Aug 13, 2023
787fe5e
feat: hide protocol result using hide
tarunKoyalwar Aug 13, 2023
f4abe7a
feat: async execution
tarunKoyalwar Aug 13, 2023
2a32933
complete async execution support
tarunKoyalwar Aug 13, 2023
f4150de
fix condition-flow without any matchers
tarunKoyalwar Aug 21, 2023
3f4e885
refactor: template executer package (tmplexec)
tarunKoyalwar Aug 21, 2023
2f39929
flow executor working
tarunKoyalwar Aug 22, 2023
cd94876
fix data race in templateCtx
tarunKoyalwar Aug 22, 2023
c57aee9
templateCtx redesign
tarunKoyalwar Aug 22, 2023
7de01ea
fix failing unit test
tarunKoyalwar Aug 22, 2023
5dfff5b
add multiprotocol support to deprecated syntax
tarunKoyalwar Aug 22, 2023
286ede4
fix race condition in utils & tlsx
tarunKoyalwar Aug 22, 2023
2850dae
add documentation in flow package
tarunKoyalwar Aug 22, 2023
08c33c4
remove regions.txt file
tarunKoyalwar Aug 22, 2023
20368ed
fix minor issue with self contained templates
tarunKoyalwar Aug 22, 2023
f5ac33a
fix typos of copilot
tarunKoyalwar Aug 23, 2023
5a38b2f
dep + misc update
ehsandeep Aug 27, 2023
4f079d9
fix reqID: use req.Type instead of template.Type
tarunKoyalwar Aug 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions integration_tests/flow/conditional-flow-negative.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
id: ghost-blog-detection
info:
name: Ghost blog detection
author: pdteam
severity: info


flow: dns() && http()

dns:
- name: "{{FQDN}}"
type: CNAME

matchers:
- type: word
words:
- "ghost.io"

http:
- method: GET
path:
- "{{BaseURL}}"

matchers:
- type: word
words:
- "ghost.io"
27 changes: 27 additions & 0 deletions integration_tests/flow/conditional-flow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
id: ghost-blog-detection
info:
name: Ghost blog detection
author: pdteam
severity: info


flow: dns() && http()

dns:
- name: "{{FQDN}}"
type: CNAME

matchers:
- type: word
words:
- "ghost.io"

http:
- method: GET
path:
- "{{BaseURL}}"

matchers:
- type: word
words:
- "ghost.io"
42 changes: 42 additions & 0 deletions integration_tests/flow/dns-ns-probe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
id: dns-ns-probe

info:
name: Nuclei flow dns ns probe
author: pdteam
severity: info
description: Description of the Template
reference: https://example-reference-link

flow: |
dns("fetch-ns");
for(let ns of template["nameservers"]) {
set("nameserver",ns);
dns("probe-ns");
};

dns:
- id: "fetch-ns"
name: "{{FQDN}}"
type: NS
matchers:
- type: word
words:
- "IN\tNS"
extractors:
- type: regex
internal: true
name: "nameservers"
group: 1
regex:
- "IN\tNS\t(.+)"

- id: "probe-ns"
name: "{{nameserver}}"
type: A
class: inet
retries: 3
recursion: true
extractors:
- type: dsl
dsl:
- "a"
35 changes: 35 additions & 0 deletions integration_tests/flow/iterate-values-flow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
id: extract-emails

info:
name: Extract Email IDs from Response
author: pdteam
severity: info


flow: |
http(0)
for(let email of template["emails"]) {
set("email",email);
http(1);
}

http:
- method: GET
path:
- "{{BaseURL}}"

extractors:
- type: regex
name: emails
internal: true
regex:
- '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'

- method: GET
path:
- "{{BaseURL}}/user/{{base64(email)}}"

matchers:
- type: word
words:
- "Welcome"
2 changes: 1 addition & 1 deletion integration_tests/protocols/code/py-env-var.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ code:
- type: word
words:
- "hello from input baz"
# digest: 4b0a00483046022100cd2b9d34169cdb716caee25976fed763880435f2f1e2979c9d7c9d2bd7b8e409022100dd0ba8bd3fa6a6be5f964ca3b0ce8bdbb20d865553133cf494ef64fbeebff345
# digest: 4a0a00473045022100e17c7a809fd64419baf401b5331edab3a68a4c182f7777614beb1862eb6ea8b7022011b95fc0e22d7f82e08e01b56ce87afdbe03027c238ba290a058d695226173ae
2 changes: 1 addition & 1 deletion integration_tests/protocols/code/py-file.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ code:
- type: word
words:
- "hello from input"
# digest: 4b0a00483046022100f663e5afaf5c118b21b9c5918cba12d7cc83edc2a3ee0f338c07e3cd1fe40e20022100b46193e3275c490a4ad3897c6e2ca51ce09f408538b17d041e0063d40f4df833
# digest: 490a004630440220241d7faae14ab5760dbe7acf621a3923d0650148bc14a52a9be06ba76e8e0abf02201885fcc432d354d3c99ea97b964838719451bc97f148229f187f61eee7525eb6
2 changes: 1 addition & 1 deletion integration_tests/protocols/code/py-interactsh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ code:
part: interactsh_protocol
words:
- "http"
# digest: 4b0a00483046022100c45cd27b9d49879663e1ea3c877dc362d06b8a0aea64b1ab06be3af5aa9a32ee0221008f5ee347245a2c1e04c46528e4c70a5a851f95c6ba49d2834ef7c3784bca47a9
# digest: 490a004630440220427cb7100f0b7d95224f490a6f4f626186782cb26c69f2551d6aefcdbc7c17d20220206161ad3a98afe8fcef9dd06d9a6dd5f34c5f7e3cd3ab7f81328f033dcd2b48
2 changes: 1 addition & 1 deletion integration_tests/protocols/code/py-snippet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ code:
- type: word
words:
- "hello from input"
# digest: 4a0a00473045022100df57bf446d6d8e73ff9424b1055faebcea9038e5d5934834ed8e619b77bdfd5e02201754c1cebe9f65883315b3830755a0689999f33db7102cd8d5469e4c01cc6a66
# digest: 4a0a00473045022056092462597e85139626656d37df123094cb3861bdf583450c38814bac8df9cb022100e83a8c552f8f8a098f6b7ec8a32c6b448b995e000884beadb50cb0f2720117de
2 changes: 1 addition & 1 deletion integration_tests/protocols/http/matcher-status.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
id: matchet-status
id: matcher-status

info:
name: Test Matcher Status
Expand Down
84 changes: 84 additions & 0 deletions v2/cmd/integration-test/flow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import (
"encoding/base64"
"fmt"
"net/http"
"net/http/httptest"

"github.com/julienschmidt/httprouter"
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
)

var flowTestcases = []TestCaseInfo{
{Path: "flow/conditional-flow.yaml", TestCase: &conditionalFlow{}},
{Path: "flow/conditional-flow-negative.yaml", TestCase: &conditionalFlowNegative{}},
{Path: "flow/iterate-values-flow.yaml", TestCase: &iterateValuesFlow{}},
{Path: "flow/dns-ns-probe.yaml", TestCase: &dnsNsProbe{}},
}

type conditionalFlow struct{}

func (t *conditionalFlow) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "blog.projectdiscovery.io", debug)
if err != nil {
return err
}
return expectResultsCount(results, 2)
}

type conditionalFlowNegative struct{}

func (t *conditionalFlowNegative) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
if err != nil {
return err
}
return expectResultsCount(results, 0)
}

type iterateValuesFlow struct{}

func (t *iterateValuesFlow) Execute(filePath string) error {
router := httprouter.New()
testemails := []string{
"[email protected]",
"[email protected]",
}
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(fmt.Sprint(testemails)))
})
router.GET("/user/"+getBase64(testemails[0]), func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Welcome ! This is test matcher text"))
})

router.GET("/user/"+getBase64(testemails[1]), func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Welcome ! This is test matcher text"))
})

ts := httptest.NewServer(router)
defer ts.Close()

results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
if err != nil {
return err
}
return expectResultsCount(results, 2)
}

type dnsNsProbe struct{}

func (t *dnsNsProbe) Execute(filePath string) error {
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "oast.fun", debug)
if err != nil {
return err
}
return expectResultsCount(results, 3)
}

func getBase64(input string) string {
return base64.StdEncoding.EncodeToString([]byte(input))
}
1 change: 1 addition & 0 deletions v2/cmd/integration-test/integration-test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var (
"multi": multiProtoTestcases,
"generic": genericTestcases,
"dsl": dslTestcases,
"flow": flowTestcases,
}

// For debug purposes
Expand Down
4 changes: 3 additions & 1 deletion v2/cmd/integration-test/multi.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import "github.com/projectdiscovery/nuclei/v2/pkg/testutils"
import (
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
)

var multiProtoTestcases = []TestCaseInfo{
{Path: "protocols/multi/dynamic-values.yaml", TestCase: &multiProtoDynamicExtractor{}},
Expand Down
2 changes: 1 addition & 1 deletion v2/cmd/integration-test/template-path.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var templatesPathTestCases = []TestCaseInfo{
//template folder path issue
{Path: "protocols/http/get.yaml", TestCase: &folderPathTemplateTest{}},
//cwd
{Path: "./dns/cname-fingerprint.yaml", TestCase: &cwdTemplateTest{}},
{Path: "./protocols/dns/cname-fingerprint.yaml", TestCase: &cwdTemplateTest{}},
//relative path
{Path: "dns/dns-saas-service-detection.yaml", TestCase: &relativePathTemplateTest{}},
//absolute path
Expand Down
Loading
Loading