mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 17:05:29 +00:00
bug fixes in js , network protocol and flow (#4313)
* fix net read * only return N bytes if extra available * use ConnReadN from readerutil * add integration test * print unsigned warning in stderr * fix js protocol in flow #4318 * fix integration test: url encoding issue * fix network protocol issue + integration tests * multiple improvements to integration test * replace all conn.Read() from tests * disable network-basic.yaml in windows * disable code protocol in win CI * fix bitwise login ps1-snippet.yaml * hide previous matcher events in flow * remove dead code+ update integration tests --------- Co-authored-by: Sandeep Singh <sandeep@projectdiscovery.io>
This commit is contained in:
parent
c79d2f05c4
commit
595ba8e3a5
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
osutils "github.com/projectdiscovery/utils/os"
|
osutils "github.com/projectdiscovery/utils/os"
|
||||||
@ -12,14 +13,16 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var isCodeDisabled = func() bool { return osutils.IsWindows() && os.Getenv("CI") == "true" }
|
||||||
|
|
||||||
var codeTestCases = []TestCaseInfo{
|
var codeTestCases = []TestCaseInfo{
|
||||||
{Path: "protocols/code/py-snippet.yaml", TestCase: &codeSnippet{}},
|
{Path: "protocols/code/py-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/py-file.yaml", TestCase: &codeFile{}},
|
{Path: "protocols/code/py-file.yaml", TestCase: &codeFile{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/py-env-var.yaml", TestCase: &codeEnvVar{}},
|
{Path: "protocols/code/py-env-var.yaml", TestCase: &codeEnvVar{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/unsigned.yaml", TestCase: &unsignedCode{}},
|
{Path: "protocols/code/unsigned.yaml", TestCase: &unsignedCode{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/py-nosig.yaml", TestCase: &codePyNoSig{}},
|
{Path: "protocols/code/py-nosig.yaml", TestCase: &codePyNoSig{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/py-interactsh.yaml", TestCase: &codeSnippet{}},
|
{Path: "protocols/code/py-interactsh.yaml", TestCase: &codeSnippet{}, DisableOn: isCodeDisabled},
|
||||||
{Path: "protocols/code/ps1-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: func() bool { return !osutils.IsWindows() }},
|
{Path: "protocols/code/ps1-snippet.yaml", TestCase: &codeSnippet{}, DisableOn: func() bool { return !osutils.IsWindows() || isCodeDisabled() }},
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -30,6 +33,10 @@ const (
|
|||||||
var testcertpath = ""
|
var testcertpath = ""
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
if isCodeDisabled() {
|
||||||
|
// skip executing code protocol in CI on windows
|
||||||
|
return
|
||||||
|
}
|
||||||
// allow local file access to load content of file references in template
|
// allow local file access to load content of file references in template
|
||||||
// in order to sign them for testing purposes
|
// in order to sign them for testing purposes
|
||||||
templates.TemplateSignerLFA()
|
templates.TemplateSignerLFA()
|
||||||
|
|||||||
@ -15,6 +15,7 @@ var flowTestcases = []TestCaseInfo{
|
|||||||
{Path: "flow/conditional-flow-negative.yaml", TestCase: &conditionalFlowNegative{}},
|
{Path: "flow/conditional-flow-negative.yaml", TestCase: &conditionalFlowNegative{}},
|
||||||
{Path: "flow/iterate-values-flow.yaml", TestCase: &iterateValuesFlow{}},
|
{Path: "flow/iterate-values-flow.yaml", TestCase: &iterateValuesFlow{}},
|
||||||
{Path: "flow/dns-ns-probe.yaml", TestCase: &dnsNsProbe{}},
|
{Path: "flow/dns-ns-probe.yaml", TestCase: &dnsNsProbe{}},
|
||||||
|
{Path: "flow/flow-hide-matcher.yaml", TestCase: &flowHideMatcher{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
type conditionalFlow struct{}
|
type conditionalFlow struct{}
|
||||||
@ -24,7 +25,7 @@ func (t *conditionalFlow) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return expectResultsCount(results, 2)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
type conditionalFlowNegative struct{}
|
type conditionalFlowNegative struct{}
|
||||||
@ -66,7 +67,7 @@ func (t *iterateValuesFlow) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return expectResultsCount(results, 2)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
type dnsNsProbe struct{}
|
type dnsNsProbe struct{}
|
||||||
@ -76,9 +77,20 @@ func (t *dnsNsProbe) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return expectResultsCount(results, 3)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBase64(input string) string {
|
func getBase64(input string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(input))
|
return base64.StdEncoding.EncodeToString([]byte(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type flowHideMatcher struct{}
|
||||||
|
|
||||||
|
func (t *flowHideMatcher) Execute(filePath string) error {
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// this matcher should not return any results
|
||||||
|
return expectResultsCount(results, 0)
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ var jsTestcases = []TestCaseInfo{
|
|||||||
{Path: "protocols/javascript/redis-pass-brute.yaml", TestCase: &javascriptRedisPassBrute{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
{Path: "protocols/javascript/redis-pass-brute.yaml", TestCase: &javascriptRedisPassBrute{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||||
{Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
{Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
|
||||||
{Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}},
|
{Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}},
|
||||||
|
{Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -23,6 +24,16 @@ var (
|
|||||||
defaultRetry = 3
|
defaultRetry = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type javascriptNetHttps struct{}
|
||||||
|
|
||||||
|
func (j *javascriptNetHttps) Execute(filePath string) error {
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return expectResultsCount(results, 1)
|
||||||
|
}
|
||||||
|
|
||||||
type javascriptRedisPassBrute struct{}
|
type javascriptRedisPassBrute struct{}
|
||||||
|
|
||||||
func (j *javascriptRedisPassBrute) Execute(filePath string) error {
|
func (j *javascriptRedisPassBrute) Execute(filePath string) error {
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
|
||||||
osutils "github.com/projectdiscovery/utils/os"
|
osutils "github.com/projectdiscovery/utils/os"
|
||||||
|
"github.com/projectdiscovery/utils/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
var networkTestcases = []TestCaseInfo{
|
var networkTestcases = []TestCaseInfo{
|
||||||
@ -16,6 +20,8 @@ var networkTestcases = []TestCaseInfo{
|
|||||||
{Path: "protocols/network/variables.yaml", TestCase: &networkVariables{}},
|
{Path: "protocols/network/variables.yaml", TestCase: &networkVariables{}},
|
||||||
{Path: "protocols/network/same-address.yaml", TestCase: &networkBasic{}},
|
{Path: "protocols/network/same-address.yaml", TestCase: &networkBasic{}},
|
||||||
{Path: "protocols/network/network-port.yaml", TestCase: &networkPort{}},
|
{Path: "protocols/network/network-port.yaml", TestCase: &networkPort{}},
|
||||||
|
{Path: "protocols/network/net-https.yaml", TestCase: &networkhttps{}},
|
||||||
|
{Path: "protocols/network/net-https-timeout.yaml", TestCase: &networkhttps{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultStaticPort = 5431
|
const defaultStaticPort = 5431
|
||||||
@ -29,22 +35,26 @@ func (h *networkBasic) Execute(filePath string) error {
|
|||||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
data := make([]byte, 4)
|
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
routerErr = err
|
routerErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if string(data) == "PING" {
|
if string(data) == "PING" {
|
||||||
_, _ = conn.Write([]byte("PONG"))
|
_, _ = conn.Write([]byte("PONG"))
|
||||||
|
} else {
|
||||||
|
routerErr = fmt.Errorf("invalid data received: %s", string(data))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Could not run nuclei: %s\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "routerErr: %s\n", routerErr)
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +70,8 @@ func (h *networkMultiStep) Execute(filePath string) error {
|
|||||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
data := make([]byte, 5)
|
data, err := reader.ConnReadNWithTimeout(conn, 5, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
routerErr = err
|
routerErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -69,8 +79,8 @@ func (h *networkMultiStep) Execute(filePath string) error {
|
|||||||
_, _ = conn.Write([]byte("PING"))
|
_, _ = conn.Write([]byte("PING"))
|
||||||
}
|
}
|
||||||
|
|
||||||
data = make([]byte, 6)
|
data, err = reader.ConnReadNWithTimeout(conn, 6, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
routerErr = err
|
routerErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -126,8 +136,8 @@ func (h *networkVariables) Execute(filePath string) error {
|
|||||||
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
data := make([]byte, 4)
|
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
routerErr = err
|
routerErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -154,8 +164,8 @@ func (n *networkPort) Execute(filePath string) error {
|
|||||||
ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) {
|
ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
data := make([]byte, 4)
|
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if string(data) == "PING" {
|
if string(data) == "PING" {
|
||||||
@ -187,8 +197,8 @@ func (n *networkPort) Execute(filePath string) error {
|
|||||||
ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) {
|
ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
data := make([]byte, 4)
|
data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||||
if _, err := conn.Read(data); err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if string(data) == "PING" {
|
if string(data) == "PING" {
|
||||||
@ -206,3 +216,14 @@ func (n *networkPort) Execute(filePath string) error {
|
|||||||
|
|
||||||
return expectResultsCount(results, 1)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type networkhttps struct{}
|
||||||
|
|
||||||
|
// Execute executes a test case and returns an error if occurred
|
||||||
|
func (h *networkhttps) Execute(filePath string) error {
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "scanme.sh", debug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return expectResultsCount(results, 1)
|
||||||
|
}
|
||||||
|
|||||||
4
go.mod
4
go.mod
@ -91,7 +91,7 @@ require (
|
|||||||
github.com/projectdiscovery/sarif v0.0.1
|
github.com/projectdiscovery/sarif v0.0.1
|
||||||
github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766
|
github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766
|
||||||
github.com/projectdiscovery/uncover v1.0.7
|
github.com/projectdiscovery/uncover v1.0.7
|
||||||
github.com/projectdiscovery/utils v0.0.58
|
github.com/projectdiscovery/utils v0.0.61-0.20231031205429-0bc6a3c60ca6
|
||||||
github.com/projectdiscovery/wappalyzergo v0.0.109
|
github.com/projectdiscovery/wappalyzergo v0.0.109
|
||||||
github.com/redis/go-redis/v9 v9.1.0
|
github.com/redis/go-redis/v9 v9.1.0
|
||||||
github.com/ropnop/gokrb5/v8 v8.0.0-20201111231119-729746023c02
|
github.com/ropnop/gokrb5/v8 v8.0.0-20201111231119-729746023c02
|
||||||
@ -166,7 +166,7 @@ require (
|
|||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/mackerelio/go-osstat v0.2.4 // indirect
|
github.com/mackerelio/go-osstat v0.2.4 // indirect
|
||||||
github.com/minio/selfupdate v0.6.0 // indirect
|
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
|
|||||||
12
go.sum
12
go.sum
@ -679,8 +679,8 @@ github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7
|
|||||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||||
github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
|
github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
|
||||||
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
|
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 h1:yRZGarbxsRytL6EGgbqK2mCY+Lk5MWKQYKJT2gEglhc=
|
||||||
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
||||||
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=
|
||||||
@ -722,8 +722,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
|
||||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
@ -837,8 +837,8 @@ github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766 h1:wa2wak7
|
|||||||
github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766/go.mod h1:bFATagikCvdPOsmaN1h5VQSbZjTW8bCQ6bjoQEePUq8=
|
github.com/projectdiscovery/tlsx v1.1.6-0.20231016194953-a3ff9518c766/go.mod h1:bFATagikCvdPOsmaN1h5VQSbZjTW8bCQ6bjoQEePUq8=
|
||||||
github.com/projectdiscovery/uncover v1.0.7 h1:ut+2lTuvmftmveqF5RTjMWAgyLj8ltPQC7siFy9sj0A=
|
github.com/projectdiscovery/uncover v1.0.7 h1:ut+2lTuvmftmveqF5RTjMWAgyLj8ltPQC7siFy9sj0A=
|
||||||
github.com/projectdiscovery/uncover v1.0.7/go.mod h1:HFXgm1sRPuoN0D4oATljPIdmbo/EEh1wVuxQqo/dwFE=
|
github.com/projectdiscovery/uncover v1.0.7/go.mod h1:HFXgm1sRPuoN0D4oATljPIdmbo/EEh1wVuxQqo/dwFE=
|
||||||
github.com/projectdiscovery/utils v0.0.58 h1:kk2AkSO84QZc9rDRI8jWA2Iia4uzb4sUcfh4h0xA20I=
|
github.com/projectdiscovery/utils v0.0.61-0.20231031205429-0bc6a3c60ca6 h1:60DKG3aueYiy93ZPt78yyZW0N+b7pWbK8Ub1UH6o08I=
|
||||||
github.com/projectdiscovery/utils v0.0.58/go.mod h1:rsR5Kzjrb+/Yp7JSnEblLk4LfU4zH5Z7wQn8RzaGSdY=
|
github.com/projectdiscovery/utils v0.0.61-0.20231031205429-0bc6a3c60ca6/go.mod h1:vt4oY4rvRWTdkBMhLlAGPbapa/R8pa+xZBYuNZIKJgQ=
|
||||||
github.com/projectdiscovery/wappalyzergo v0.0.109 h1:BERfwTRn1dvB1tbhyc5m67R8VkC9zbVuPsEq4VEm07k=
|
github.com/projectdiscovery/wappalyzergo v0.0.109 h1:BERfwTRn1dvB1tbhyc5m67R8VkC9zbVuPsEq4VEm07k=
|
||||||
github.com/projectdiscovery/wappalyzergo v0.0.109/go.mod h1:4Z3DKhi75zIPMuA+qSDDWxZvnhL4qTLmDx4dxNMu7MA=
|
github.com/projectdiscovery/wappalyzergo v0.0.109/go.mod h1:4Z3DKhi75zIPMuA+qSDDWxZvnhL4qTLmDx4dxNMu7MA=
|
||||||
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
github.com/projectdiscovery/yamldoc-go v1.0.4 h1:eZoESapnMw6WAHiVgRwNqvbJEfNHEH148uthhFbG5jE=
|
||||||
|
|||||||
28
integration_tests/flow/flow-hide-matcher.yaml
Normal file
28
integration_tests/flow/flow-hide-matcher.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
id: flow-hide-matcher
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: Test HTTP Template
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
description: In flow matcher output of previous step is hidden and only last event matcher output is shown
|
||||||
|
|
||||||
|
flow: http(1) && http(2)
|
||||||
|
|
||||||
|
http:
|
||||||
|
- method: GET
|
||||||
|
path:
|
||||||
|
- "{{BaseURL}}"
|
||||||
|
|
||||||
|
matchers:
|
||||||
|
- type: word
|
||||||
|
words:
|
||||||
|
- ok
|
||||||
|
|
||||||
|
- method: GET
|
||||||
|
path:
|
||||||
|
- "{{BaseURL}}"
|
||||||
|
|
||||||
|
matchers:
|
||||||
|
- type: word
|
||||||
|
words:
|
||||||
|
- "Failed event"
|
||||||
@ -20,4 +20,4 @@ code:
|
|||||||
- type: word
|
- type: word
|
||||||
words:
|
words:
|
||||||
- "hello from input baz"
|
- "hello from input baz"
|
||||||
# digest: 4a0a00473045022100d407a3b848664b4c271abb4462a89a53fa2da6c21fd66011974ac395e2dc041c0220129a752a792337f6efe2e96562989016fe2709820b9583fd933f02be3b9d074f:4a3eb6b4988d95847d4203be25ed1d46
|
# digest: 4a0a00473045022100b290a0c40f27573f0de9a950be13457a9bf59ade1ff2f497bf01a3b526e5db750220761942acffd6d27e2714ddaa1c73c699ccd7de48839f08cff1d6a9456bc8ff1f:4a3eb6b4988d95847d4203be25ed1d46
|
||||||
@ -18,4 +18,4 @@ code:
|
|||||||
- type: word
|
- type: word
|
||||||
words:
|
words:
|
||||||
- "hello from input"
|
- "hello from input"
|
||||||
# digest: 4b0a004830460221009db4541aa2af10aae5f39fe6e8789e2717c96ebbdadfdf33114ec0e82ec4da73022100fa98ee6611b606befc139946a169cca717f16ebf71beac97fdde1fe0c7fba774:4a3eb6b4988d95847d4203be25ed1d46
|
# digest: 490a004630440220335663a6a4db720ee6276ab7179a87a6be0b4030771ec5ee82ecf6982342113602200a2570db7eb9721f6ceb1a89543fc436ee62b30d1b720c75ea3834ed3d2b64f3:4a3eb6b4988d95847d4203be25ed1d46
|
||||||
@ -26,4 +26,4 @@ code:
|
|||||||
part: interactsh_protocol
|
part: interactsh_protocol
|
||||||
words:
|
words:
|
||||||
- "http"
|
- "http"
|
||||||
# digest: 4a0a0047304502205ebee72972ea0005ecdbcf7cd676ab861f3a44477a4b85dc1e745b7a628d2d7a022100ec4604673a1d43311ab343005464be5d4ee26b5a1f39206aa841056f3e2057dd:4a3eb6b4988d95847d4203be25ed1d46
|
# digest: 490a004630440220400892730a62fa1bbb1064e4d88eea760dbf8f01c6b630ff0f5b126fd1952839022025a6d52e730c1f1cfcbd440e6269f93489db3a77cb2a27d0f47522c0819dc8d3:4a3eb6b4988d95847d4203be25ed1d46
|
||||||
@ -21,4 +21,4 @@ code:
|
|||||||
- type: word
|
- type: word
|
||||||
words:
|
words:
|
||||||
- "hello from input"
|
- "hello from input"
|
||||||
# digest: 4b0a004830460221009a87b77e770e688bb1ce05e75ac075cdb3f318aad18a6dbc3fc2ec729a8ba5990221009020d69ba3baf47f9d835d4b6bd644a9e4f2d699369acc2a15983f5c270d2e79:4a3eb6b4988d95847d4203be25ed1d46
|
# digest: 490a0046304402206b14abdc0d5fc13466f5c292da9fb2a19d1b2c5e683cc052037fe367b372f82b02202c00b9acbd8106a769eb411794c567d3019433671397bf909e16b286105ed69e:4a3eb6b4988d95847d4203be25ed1d46
|
||||||
25
integration_tests/protocols/javascript/net-https.yaml
Normal file
25
integration_tests/protocols/javascript/net-https.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
id: net-https
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: net-https
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
description: send and receive https data using net module
|
||||||
|
|
||||||
|
|
||||||
|
javascript:
|
||||||
|
- code: |
|
||||||
|
let m = require('nuclei/net');
|
||||||
|
let name=Host+':'+Port;
|
||||||
|
let conn = m.OpenTLS('tcp', name);
|
||||||
|
conn.Send('GET / HTTP/1.1\r\nHost:'+name+'\r\nConnection: close\r\n\r\n');
|
||||||
|
resp = conn.RecvString();
|
||||||
|
|
||||||
|
args:
|
||||||
|
Host: "{{Host}}"
|
||||||
|
Port: "443"
|
||||||
|
|
||||||
|
matchers:
|
||||||
|
- type: word
|
||||||
|
words:
|
||||||
|
- "HTTP/1.1 200 OK"
|
||||||
25
integration_tests/protocols/network/net-https-timeout.yaml
Normal file
25
integration_tests/protocols/network/net-https-timeout.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
id: net-https-timeout
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: Example Network template which times out
|
||||||
|
author: pdteam
|
||||||
|
severity: high
|
||||||
|
description: Example Network template to send HTTPS request which times out
|
||||||
|
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
- host:
|
||||||
|
- "tls://{{Hostname}}"
|
||||||
|
port: 443
|
||||||
|
inputs:
|
||||||
|
# noticable difference between this and net-https.yaml is that here we don't send the Connection: close header
|
||||||
|
# and hence connection will remain open until server closes it. This can be a DOS vector in nuclei
|
||||||
|
# as it waits for server to close the connection. now we have set a default timeout of 5 seconds and if server responds but doesn't close the connection
|
||||||
|
# then nuclei will close connection but doesn't fail the request since we already have response data from server
|
||||||
|
# this feature is only required for `read-all: true` to work properly
|
||||||
|
- data: "GET / HTTP/1.1\r\nHost: {{Hostname}}\r\n\r\n"
|
||||||
|
read-all: true
|
||||||
|
extractors:
|
||||||
|
- type: dsl
|
||||||
|
dsl:
|
||||||
|
- "len(data)"
|
||||||
20
integration_tests/protocols/network/net-https.yaml
Normal file
20
integration_tests/protocols/network/net-https.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
id: net-https
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: Example Network template to send HTTPS request
|
||||||
|
author: pdteam
|
||||||
|
severity: high
|
||||||
|
description: Example Network template to send HTTPS request
|
||||||
|
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
- host:
|
||||||
|
- "tls://{{Hostname}}"
|
||||||
|
port: 443
|
||||||
|
inputs:
|
||||||
|
- data: "GET / HTTP/1.1\r\nHost: {{Hostname}}\r\nConnection: close\r\n\r\n"
|
||||||
|
read-all: true
|
||||||
|
extractors:
|
||||||
|
- type: dsl
|
||||||
|
dsl:
|
||||||
|
- "len(data)"
|
||||||
@ -692,7 +692,7 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
|
|||||||
if k != templates.Unsigned {
|
if k != templates.Unsigned {
|
||||||
gologger.Info().Msgf("Executing %d signed templates from %s", v.Load(), k)
|
gologger.Info().Msgf("Executing %d signed templates from %s", v.Load(), k)
|
||||||
} else if !r.options.Silent && !config.DefaultConfig.HideTemplateSigWarning {
|
} else if !r.options.Silent && !config.DefaultConfig.HideTemplateSigWarning {
|
||||||
gologger.DefaultLogger.Print().Msgf("[%v] Executing %d unsigned templates. Use with caution.", aurora.BrightYellow("WRN"), v.Load())
|
gologger.Print().Msgf("[%v] Executing %d unsigned templates. Use with caution.", aurora.BrightYellow("WRN"), v.Load())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,6 +72,7 @@ func ExampleThreadSafeNucleiEngine() {
|
|||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [nameserver-fingerprint] scanme.sh
|
// [nameserver-fingerprint] scanme.sh
|
||||||
|
// [caa-fingerprint] honey.scanme.sh
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|||||||
@ -20,8 +20,8 @@ class NetConn {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @description Recv receives data from the connection with a timeout. If N is 0, it will read up to 4096 bytes.
|
* @description Recv receives data from the connection with a timeout. If N is 0, it will read all available data.
|
||||||
* @param {number} N - The number of bytes to receive.
|
* @param {number} [N=0] - The number of bytes to receive.
|
||||||
* @returns {Uint8Array} - The received data in an array.
|
* @returns {Uint8Array} - The received data in an array.
|
||||||
* @throws {error} - The error encountered during data receiving.
|
* @throws {error} - The error encountered during data receiving.
|
||||||
* @example
|
* @example
|
||||||
@ -35,8 +35,8 @@ class NetConn {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @description RecvHex receives data from the connection with a timeout in hex format. If N is 0, it will read up to 4096 bytes.
|
* @description RecvHex receives data from the connection with a timeout in hex format. If N is 0, it will read all available data.
|
||||||
* @param {number} N - The number of bytes to receive.
|
* @param {number} [N=0] - The number of bytes to receive.
|
||||||
* @returns {string} - The received data in hex format.
|
* @returns {string} - The received data in hex format.
|
||||||
* @throws {error} - The error encountered during data receiving.
|
* @throws {error} - The error encountered during data receiving.
|
||||||
* @example
|
* @example
|
||||||
@ -50,8 +50,8 @@ class NetConn {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @method
|
* @method
|
||||||
* @description RecvString receives data from the connection with a timeout. Output is returned as a string. If N is 0, it will read up to 4096 bytes.
|
* @description RecvString receives data from the connection with a timeout. Output is returned as a string. If N is 0, it will read all available data.
|
||||||
* @param {number} N - The number of bytes to receive.
|
* @param {number} [N=0] - The number of bytes to receive.
|
||||||
* @returns {string} - The received data as a string.
|
* @returns {string} - The received data as a string.
|
||||||
* @throws {error} - The error encountered during data receiving.
|
* @throws {error} - The error encountered during data receiving.
|
||||||
* @example
|
* @example
|
||||||
|
|||||||
@ -4,14 +4,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||||
|
errorutil "github.com/projectdiscovery/utils/errors"
|
||||||
|
"github.com/projectdiscovery/utils/reader"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultTimeout = time.Duration(5) * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open opens a new connection to the address with a timeout.
|
// Open opens a new connection to the address with a timeout.
|
||||||
@ -21,13 +25,13 @@ func Open(protocol, address string) (*NetConn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &NetConn{conn: conn}, nil
|
return &NetConn{conn: conn, timeout: defaultTimeout}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens a new connection to the address with a timeout.
|
// Open opens a new connection to the address with a timeout.
|
||||||
// supported protocols: tcp, udp
|
// supported protocols: tcp, udp
|
||||||
func OpenTLS(protocol, address string) (*NetConn, error) {
|
func OpenTLS(protocol, address string) (*NetConn, error) {
|
||||||
config := &tls.Config{InsecureSkipVerify: true}
|
config := &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10}
|
||||||
host, _, _ := net.SplitHostPort(address)
|
host, _, _ := net.SplitHostPort(address)
|
||||||
if host != "" {
|
if host != "" {
|
||||||
c := config.Clone()
|
c := config.Clone()
|
||||||
@ -38,7 +42,7 @@ func OpenTLS(protocol, address string) (*NetConn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &NetConn{conn: conn}, nil
|
return &NetConn{conn: conn, timeout: defaultTimeout}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetConn is a connection to a remote host.
|
// NetConn is a connection to a remote host.
|
||||||
@ -67,9 +71,15 @@ func (c *NetConn) setDeadLine() {
|
|||||||
_ = c.conn.SetDeadline(time.Now().Add(c.timeout))
|
_ = c.conn.SetDeadline(time.Now().Add(c.timeout))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unsetDeadLine unsets read/write deadline for the connection.
|
||||||
|
func (c *NetConn) unsetDeadLine() {
|
||||||
|
_ = c.conn.SetDeadline(time.Time{})
|
||||||
|
}
|
||||||
|
|
||||||
// SendArray sends array data to connection
|
// SendArray sends array data to connection
|
||||||
func (c *NetConn) SendArray(data []interface{}) error {
|
func (c *NetConn) SendArray(data []interface{}) error {
|
||||||
c.setDeadLine()
|
c.setDeadLine()
|
||||||
|
defer c.unsetDeadLine()
|
||||||
input := types.ToByteSlice(data)
|
input := types.ToByteSlice(data)
|
||||||
length, err := c.conn.Write(input)
|
length, err := c.conn.Write(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,6 +94,7 @@ func (c *NetConn) SendArray(data []interface{}) error {
|
|||||||
// SendHex sends hex data to connection
|
// SendHex sends hex data to connection
|
||||||
func (c *NetConn) SendHex(data string) error {
|
func (c *NetConn) SendHex(data string) error {
|
||||||
c.setDeadLine()
|
c.setDeadLine()
|
||||||
|
defer c.unsetDeadLine()
|
||||||
bin, err := hex.DecodeString(data)
|
bin, err := hex.DecodeString(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -101,6 +112,7 @@ func (c *NetConn) SendHex(data string) error {
|
|||||||
// Send sends data to the connection with a timeout.
|
// Send sends data to the connection with a timeout.
|
||||||
func (c *NetConn) Send(data string) error {
|
func (c *NetConn) Send(data string) error {
|
||||||
c.setDeadLine()
|
c.setDeadLine()
|
||||||
|
defer c.unsetDeadLine()
|
||||||
bin := []byte(data)
|
bin := []byte(data)
|
||||||
length, err := c.conn.Write(bin)
|
length, err := c.conn.Write(bin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,30 +125,24 @@ func (c *NetConn) Send(data string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recv receives data from the connection with a timeout.
|
// Recv receives data from the connection with a timeout.
|
||||||
// If N is 0, it will read up to 4096 bytes.
|
// If N is 0, it will read all data sent by the server with 8MB limit.
|
||||||
func (c *NetConn) Recv(N int) ([]byte, error) {
|
func (c *NetConn) Recv(N int) ([]byte, error) {
|
||||||
c.setDeadLine()
|
c.setDeadLine()
|
||||||
var response []byte
|
defer c.unsetDeadLine()
|
||||||
if N > 0 {
|
if N == 0 {
|
||||||
response = make([]byte, N)
|
// in utils we use -1 to indicate read all rather than 0
|
||||||
} else {
|
N = -1
|
||||||
response = make([]byte, 4096)
|
|
||||||
}
|
}
|
||||||
length, err := c.conn.Read(response)
|
bin, err := reader.ConnReadNWithTimeout(c.conn, int64(N), c.timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var netErr net.Error
|
return []byte{}, errorutil.NewWithErr(err).Msgf("failed to read %d bytes", N)
|
||||||
if (errors.As(err, &netErr) && netErr.Timeout()) ||
|
|
||||||
errors.Is(err, syscall.ECONNREFUSED) { // timeout error or connection refused
|
|
||||||
return response, nil
|
|
||||||
}
|
}
|
||||||
return response[:length], err
|
return bin, nil
|
||||||
}
|
|
||||||
return response[:length], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecvString receives data from the connection with a timeout
|
// RecvString receives data from the connection with a timeout
|
||||||
// output is returned as a string.
|
// output is returned as a string.
|
||||||
// If N is 0, it will read up to 4096 bytes.
|
// If N is 0, it will read all data sent by the server with 8MB limit.
|
||||||
func (c *NetConn) RecvString(N int) (string, error) {
|
func (c *NetConn) RecvString(N int) (string, error) {
|
||||||
bin, err := c.Recv(N)
|
bin, err := c.Recv(N)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -147,7 +153,7 @@ func (c *NetConn) RecvString(N int) (string, error) {
|
|||||||
|
|
||||||
// RecvHex receives data from the connection with a timeout
|
// RecvHex receives data from the connection with a timeout
|
||||||
// in hex format.
|
// in hex format.
|
||||||
// If N is 0, it will read up to 4096 bytes.
|
// If N is 0,it will read all data sent by the server with 8MB limit.
|
||||||
func (c *NetConn) RecvHex(N int) (string, error) {
|
func (c *NetConn) RecvHex(N int) (string, error) {
|
||||||
bin, err := c.Recv(N)
|
bin, err := c.Recv(N)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs"
|
"github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||||
|
"github.com/projectdiscovery/utils/reader"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -31,10 +32,8 @@ func (c *SMBClient) DetectSMBGhost(host string, port int) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
buff, _ := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second)
|
||||||
buff := make([]byte, 4)
|
args, err := structs.Unpack(">I", buff)
|
||||||
nb, _ := conn.Read(buff)
|
|
||||||
args, err := structs.Unpack(">I", buff[:nb])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -43,13 +42,14 @@ func (c *SMBClient) DetectSMBGhost(host string, port int) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
length := args[0].(int)
|
length := args[0].(int)
|
||||||
data := make([]byte, length)
|
|
||||||
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
|
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||||
n, err := conn.Read(data)
|
data, err := reader.ConnReadNWithTimeout(conn, int64(length), time.Duration(5)*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
data = data[:n]
|
if len(data) < 72 {
|
||||||
|
return false, errors.New("invalid response expected at least 72 bytes")
|
||||||
|
}
|
||||||
|
|
||||||
if !bytes.Equal(data[68:70], []byte("\x11\x03")) || !bytes.Equal(data[70:72], []byte("\x02\x00")) {
|
if !bytes.Equal(data[68:70], []byte("\x11\x03")) || !bytes.Equal(data[70:72], []byte("\x02\x00")) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|||||||
@ -435,7 +435,7 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
|
|||||||
request.options.Progress.IncrementRequests()
|
request.options.Progress.IncrementRequests()
|
||||||
|
|
||||||
requestOptions.Output.Request(requestOptions.TemplateID, hostPort, request.Type().String(), err)
|
requestOptions.Output.Request(requestOptions.TemplateID, hostPort, request.Type().String(), err)
|
||||||
gologger.Verbose().Msgf("[%s] Sent Javascript request to %s", request.TemplateID, hostPort)
|
gologger.Verbose().Msgf("[%s] Sent Javascript request to %s", request.options.TemplateID, hostPort)
|
||||||
|
|
||||||
if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse {
|
if requestOptions.Options.Debug || requestOptions.Options.DebugRequests || requestOptions.Options.StoreResponse {
|
||||||
msg := fmt.Sprintf("[%s] Dumped Javascript request for %s:\nVariables:\n %v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(argsCopy.Args))
|
msg := fmt.Sprintf("[%s] Dumped Javascript request for %s:\nVariables:\n %v", requestOptions.TemplateID, input.MetaInput.Input, vardump.DumpVariables(argsCopy.Args))
|
||||||
|
|||||||
@ -4,10 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -30,6 +28,13 @@ import (
|
|||||||
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
||||||
errorutil "github.com/projectdiscovery/utils/errors"
|
errorutil "github.com/projectdiscovery/utils/errors"
|
||||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||||
|
"github.com/projectdiscovery/utils/reader"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TODO: make this configurable
|
||||||
|
// DefaultReadTimeout is the default read timeout for network requests
|
||||||
|
DefaultReadTimeout = time.Duration(5) * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ protocols.Request = &Request{}
|
var _ protocols.Request = &Request{}
|
||||||
@ -196,15 +201,14 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
if input.Read > 0 {
|
if input.Read > 0 {
|
||||||
buffer := make([]byte, input.Read)
|
buffer, err := reader.ConnReadNWithTimeout(conn, int64(input.Read), DefaultReadTimeout)
|
||||||
n, err := conn.Read(buffer)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorutil.NewWithErr(err).Msgf("could not read response from connection")
|
return errorutil.NewWithErr(err).Msgf("could not read response from connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
responseBuilder.Write(buffer[:n])
|
responseBuilder.Write(buffer)
|
||||||
|
|
||||||
bufferStr := string(buffer[:n])
|
bufferStr := string(buffer)
|
||||||
if input.Name != "" {
|
if input.Name != "" {
|
||||||
inputEvents[input.Name] = bufferStr
|
inputEvents[input.Name] = bufferStr
|
||||||
interimValues[input.Name] = bufferStr
|
interimValues[input.Name] = bufferStr
|
||||||
@ -243,51 +247,19 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
|
|||||||
if request.ReadSize != 0 {
|
if request.ReadSize != 0 {
|
||||||
bufferSize = request.ReadSize
|
bufferSize = request.ReadSize
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
final []byte
|
|
||||||
n int
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.ReadAll {
|
if request.ReadAll {
|
||||||
readInterval := time.NewTimer(time.Second * 1)
|
bufferSize = -1
|
||||||
// stop the timer and drain the channel
|
|
||||||
closeTimer := func(t *time.Timer) {
|
|
||||||
if !t.Stop() {
|
|
||||||
<-t.C
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
readSocket:
|
final, err := reader.ConnReadNWithTimeout(conn, int64(bufferSize), DefaultReadTimeout)
|
||||||
for {
|
if err != nil {
|
||||||
select {
|
|
||||||
case <-readInterval.C:
|
|
||||||
closeTimer(readInterval)
|
|
||||||
break readSocket
|
|
||||||
default:
|
|
||||||
buf := make([]byte, bufferSize)
|
|
||||||
nBuf, err := conn.Read(buf)
|
|
||||||
if err != nil && !os.IsTimeout(err) && err != io.EOF {
|
|
||||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
|
||||||
closeTimer(readInterval)
|
|
||||||
return errors.Wrap(err, "could not read from server")
|
|
||||||
}
|
|
||||||
responseBuilder.Write(buf[:nBuf])
|
|
||||||
final = append(final, buf...)
|
|
||||||
n += nBuf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final = make([]byte, bufferSize)
|
|
||||||
n, err = conn.Read(final)
|
|
||||||
if err != nil && !os.IsTimeout(err) && err != io.EOF {
|
|
||||||
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
request.options.Output.Request(request.options.TemplatePath, address, request.Type().String(), err)
|
||||||
return errors.Wrap(err, "could not read from server")
|
return errors.Wrap(err, "could not read from server")
|
||||||
}
|
}
|
||||||
responseBuilder.Write(final[:n])
|
responseBuilder.Write(final)
|
||||||
}
|
|
||||||
|
|
||||||
response := responseBuilder.String()
|
response := responseBuilder.String()
|
||||||
outputEvent := request.responseToDSLMap(reqBuilder.String(), string(final[:n]), response, input.MetaInput.Input, actualAddress)
|
outputEvent := request.responseToDSLMap(reqBuilder.String(), string(final), response, input.MetaInput.Input, actualAddress)
|
||||||
// add response fields to template context and merge templatectx variables to output event
|
// add response fields to template context and merge templatectx variables to output event
|
||||||
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent)
|
request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent)
|
||||||
outputEvent = generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll())
|
outputEvent = generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll())
|
||||||
|
|||||||
@ -58,7 +58,7 @@ var protocolMappings = map[ProtocolType]string{
|
|||||||
WebsocketProtocol: "websocket",
|
WebsocketProtocol: "websocket",
|
||||||
WHOISProtocol: "whois",
|
WHOISProtocol: "whois",
|
||||||
CodeProtocol: "code",
|
CodeProtocol: "code",
|
||||||
JavascriptProtocol: "js",
|
JavascriptProtocol: "javascript",
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSupportedProtocolTypes() ProtocolTypes {
|
func GetSupportedProtocolTypes() ProtocolTypes {
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
@ -29,6 +28,13 @@ var (
|
|||||||
ErrInvalidRequestID = errorutil.NewWithFmt("[%s] invalid request id '%s' provided")
|
ErrInvalidRequestID = errorutil.NewWithFmt("[%s] invalid request id '%s' provided")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ProtoOptions are options that can be passed to flow protocol callback
|
||||||
|
// ex: dns(protoOptions) <- protoOptions are optional and can be anything
|
||||||
|
type ProtoOptions struct {
|
||||||
|
protoName string
|
||||||
|
reqIDS []string
|
||||||
|
}
|
||||||
|
|
||||||
// FlowExecutor is a flow executor for executing a flow
|
// FlowExecutor is a flow executor for executing a flow
|
||||||
type FlowExecutor struct {
|
type FlowExecutor struct {
|
||||||
input *contextargs.Context
|
input *contextargs.Context
|
||||||
@ -37,14 +43,13 @@ type FlowExecutor struct {
|
|||||||
// javascript runtime reference and compiled program
|
// javascript runtime reference and compiled program
|
||||||
jsVM *goja.Runtime
|
jsVM *goja.Runtime
|
||||||
program *goja.Program // compiled js program
|
program *goja.Program // compiled js program
|
||||||
|
lastEvent *output.InternalWrappedEvent // contains last event that was emitted
|
||||||
|
|
||||||
// protocol requests and their callback functions
|
// protocol requests and their callback functions
|
||||||
allProtocols map[string][]protocols.Request
|
allProtocols map[string][]protocols.Request
|
||||||
protoFunctions map[string]func(call goja.FunctionCall) goja.Value // reqFunctions contains functions that allow executing requests/protocols from js
|
protoFunctions map[string]func(call goja.FunctionCall) goja.Value // reqFunctions contains functions that allow executing requests/protocols from js
|
||||||
callback func(event *output.InternalWrappedEvent) // result event callback
|
|
||||||
|
|
||||||
// logic related variables
|
// logic related variables
|
||||||
wg sync.WaitGroup
|
|
||||||
results *atomic.Bool
|
results *atomic.Bool
|
||||||
allErrs mapsutil.SyncLockMap[string, error]
|
allErrs mapsutil.SyncLockMap[string, error]
|
||||||
}
|
}
|
||||||
@ -72,6 +77,8 @@ func NewFlowExecutor(requests []protocols.Request, input *contextargs.Context, o
|
|||||||
allprotos[templateTypes.WHOISProtocol.String()] = append(allprotos[templateTypes.WHOISProtocol.String()], req)
|
allprotos[templateTypes.WHOISProtocol.String()] = append(allprotos[templateTypes.WHOISProtocol.String()], req)
|
||||||
case templateTypes.CodeProtocol:
|
case templateTypes.CodeProtocol:
|
||||||
allprotos[templateTypes.CodeProtocol.String()] = append(allprotos[templateTypes.CodeProtocol.String()], req)
|
allprotos[templateTypes.CodeProtocol.String()] = append(allprotos[templateTypes.CodeProtocol.String()], req)
|
||||||
|
case templateTypes.JavascriptProtocol:
|
||||||
|
allprotos[templateTypes.JavascriptProtocol.String()] = append(allprotos[templateTypes.JavascriptProtocol.String()], req)
|
||||||
default:
|
default:
|
||||||
gologger.Error().Msgf("invalid request type %s", req.Type().String())
|
gologger.Error().Msgf("invalid request type %s", req.Type().String())
|
||||||
}
|
}
|
||||||
@ -143,22 +150,10 @@ func (f *FlowExecutor) Compile() error {
|
|||||||
}
|
}
|
||||||
for _, v := range call.Arguments {
|
for _, v := range call.Arguments {
|
||||||
switch value := v.Export().(type) {
|
switch value := v.Export().(type) {
|
||||||
case map[string]interface{}:
|
|
||||||
opts.LoadOptions(value)
|
|
||||||
default:
|
default:
|
||||||
opts.reqIDS = append(opts.reqIDS, types.ToString(value))
|
opts.reqIDS = append(opts.reqIDS, types.ToString(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// parallel execution of protocols
|
|
||||||
if opts.Async {
|
|
||||||
f.wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer f.wg.Done()
|
|
||||||
f.requestExecutor(reqMap, opts)
|
|
||||||
}()
|
|
||||||
return f.jsVM.ToValue(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.jsVM.ToValue(f.requestExecutor(reqMap, opts))
|
return f.jsVM.ToValue(f.requestExecutor(reqMap, opts))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +169,6 @@ func (f *FlowExecutor) ExecuteWithResults(input *contextargs.Context, callback p
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
f.callback = callback
|
|
||||||
f.input = input
|
f.input = input
|
||||||
// -----Load all types of variables-----
|
// -----Load all types of variables-----
|
||||||
// add all input args to template context
|
// add all input args to template context
|
||||||
@ -183,7 +177,7 @@ func (f *FlowExecutor) ExecuteWithResults(input *contextargs.Context, callback p
|
|||||||
f.options.GetTemplateCtx(f.input.MetaInput).Set(key, value)
|
f.options.GetTemplateCtx(f.input.MetaInput).Set(key, value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if f.callback == nil {
|
if callback == nil {
|
||||||
return fmt.Errorf("output callback cannot be nil")
|
return fmt.Errorf("output callback cannot be nil")
|
||||||
}
|
}
|
||||||
// pass flow and execute the js vm and handle errors
|
// pass flow and execute the js vm and handle errors
|
||||||
@ -191,11 +185,12 @@ func (f *FlowExecutor) ExecuteWithResults(input *contextargs.Context, callback p
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow)
|
return errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow)
|
||||||
}
|
}
|
||||||
f.wg.Wait()
|
|
||||||
runtimeErr := f.GetRuntimeErrors()
|
runtimeErr := f.GetRuntimeErrors()
|
||||||
if runtimeErr != nil {
|
if runtimeErr != nil {
|
||||||
return errorutil.NewWithErr(runtimeErr).Msgf("got following errors while executing flow")
|
return errorutil.NewWithErr(runtimeErr).Msgf("got following errors while executing flow")
|
||||||
}
|
}
|
||||||
|
// this is where final result is generated/created
|
||||||
|
callback(f.lastEvent)
|
||||||
if value.Export() != nil {
|
if value.Export() != nil {
|
||||||
f.results.Store(value.ToBoolean())
|
f.results.Store(value.ToBoolean())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -34,34 +34,7 @@ func (f *FlowExecutor) requestExecutor(reqMap mapsutil.Map[string, protocols.Req
|
|||||||
// execution logic for http()/dns() etc
|
// execution logic for http()/dns() etc
|
||||||
for index := range f.allProtocols[opts.protoName] {
|
for index := range f.allProtocols[opts.protoName] {
|
||||||
req := f.allProtocols[opts.protoName][index]
|
req := f.allProtocols[opts.protoName][index]
|
||||||
err := req.ExecuteWithResults(f.input, output.InternalEvent(f.options.GetTemplateCtx(f.input.MetaInput).GetAll()), nil, func(result *output.InternalWrappedEvent) {
|
err := req.ExecuteWithResults(f.input, output.InternalEvent(f.options.GetTemplateCtx(f.input.MetaInput).GetAll()), nil, f.getProtoRequestCallback(req, matcherStatus, opts))
|
||||||
if result != nil {
|
|
||||||
f.results.CompareAndSwap(false, true)
|
|
||||||
if !opts.Hide {
|
|
||||||
f.callback(result)
|
|
||||||
}
|
|
||||||
// export dynamic values from operators (i.e internal:true)
|
|
||||||
// add add it to template context
|
|
||||||
// this is a conflicting behaviour with iterate-all
|
|
||||||
if result.HasOperatorResult() {
|
|
||||||
matcherStatus.CompareAndSwap(false, result.OperatorsResult.Matched)
|
|
||||||
if !result.OperatorsResult.Matched && !hasMatchers(req.GetCompiledOperators()) {
|
|
||||||
// if matcher status is false . check if template/request contains any matcher at all
|
|
||||||
// if it does then we need to set matcher status to true
|
|
||||||
matcherStatus.CompareAndSwap(false, true)
|
|
||||||
}
|
|
||||||
if len(result.OperatorsResult.DynamicValues) > 0 {
|
|
||||||
for k, v := range result.OperatorsResult.DynamicValues {
|
|
||||||
f.options.GetTemplateCtx(f.input.MetaInput).Set(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if !result.HasOperatorResult() && !hasOperators(req.GetCompiledOperators()) {
|
|
||||||
// if matcher status is false . check if template/request contains any matcher at all
|
|
||||||
// if it does then we need to set matcher status to true
|
|
||||||
matcherStatus.CompareAndSwap(false, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// save all errors in a map with id as key
|
// save all errors in a map with id as key
|
||||||
// its less likely that there will be race condition but just in case
|
// its less likely that there will be race condition but just in case
|
||||||
@ -90,25 +63,7 @@ func (f *FlowExecutor) requestExecutor(reqMap mapsutil.Map[string, protocols.Req
|
|||||||
}
|
}
|
||||||
return matcherStatus.Load()
|
return matcherStatus.Load()
|
||||||
}
|
}
|
||||||
err := req.ExecuteWithResults(f.input, output.InternalEvent(f.options.GetTemplateCtx(f.input.MetaInput).GetAll()), nil, func(result *output.InternalWrappedEvent) {
|
err := req.ExecuteWithResults(f.input, output.InternalEvent(f.options.GetTemplateCtx(f.input.MetaInput).GetAll()), nil, f.getProtoRequestCallback(req, matcherStatus, opts))
|
||||||
if result != nil {
|
|
||||||
f.results.CompareAndSwap(false, true)
|
|
||||||
if !opts.Hide {
|
|
||||||
f.callback(result)
|
|
||||||
}
|
|
||||||
// export dynamic values from operators (i.e internal:true)
|
|
||||||
// add add it to template context
|
|
||||||
if result.HasOperatorResult() {
|
|
||||||
matcherStatus.CompareAndSwap(false, result.OperatorsResult.Matched)
|
|
||||||
if len(result.OperatorsResult.DynamicValues) > 0 {
|
|
||||||
for k, v := range result.OperatorsResult.DynamicValues {
|
|
||||||
f.options.GetTemplateCtx(f.input.MetaInput).Set(k, v)
|
|
||||||
}
|
|
||||||
_ = f.jsVM.Set("template", f.options.GetTemplateCtx(f.input.MetaInput).GetAll())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
index := id
|
index := id
|
||||||
err = f.allErrs.Set(opts.protoName+":"+index, err)
|
err = f.allErrs.Set(opts.protoName+":"+index, err)
|
||||||
@ -120,6 +75,39 @@ func (f *FlowExecutor) requestExecutor(reqMap mapsutil.Map[string, protocols.Req
|
|||||||
return matcherStatus.Load()
|
return matcherStatus.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getProtoRequestCallback returns a callback that is executed
|
||||||
|
// after execution of each protocol request
|
||||||
|
func (f *FlowExecutor) getProtoRequestCallback(req protocols.Request, matcherStatus *atomic.Bool, opts *ProtoOptions) func(result *output.InternalWrappedEvent) {
|
||||||
|
return func(result *output.InternalWrappedEvent) {
|
||||||
|
if result != nil {
|
||||||
|
f.results.CompareAndSwap(false, true)
|
||||||
|
f.lastEvent = result
|
||||||
|
// export dynamic values from operators (i.e internal:true)
|
||||||
|
// add add it to template context
|
||||||
|
// this is a conflicting behaviour with iterate-all
|
||||||
|
if result.HasOperatorResult() {
|
||||||
|
// this is to handle case where there is any operator result (matcher or extractor)
|
||||||
|
matcherStatus.CompareAndSwap(false, result.OperatorsResult.Matched)
|
||||||
|
if !result.OperatorsResult.Matched && !hasMatchers(req.GetCompiledOperators()) {
|
||||||
|
// if matcher status is false . check if template/request contains any matcher at all
|
||||||
|
// if it does then we need to set matcher status to true
|
||||||
|
matcherStatus.CompareAndSwap(false, true)
|
||||||
|
}
|
||||||
|
if len(result.OperatorsResult.DynamicValues) > 0 {
|
||||||
|
for k, v := range result.OperatorsResult.DynamicValues {
|
||||||
|
f.options.GetTemplateCtx(f.input.MetaInput).Set(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !result.HasOperatorResult() && !hasOperators(req.GetCompiledOperators()) {
|
||||||
|
// this is to handle case where there are no operator result and there was no matcher in operators
|
||||||
|
// if matcher status is false . check if template/request contains any matcher at all
|
||||||
|
// if it does then we need to set matcher status to true
|
||||||
|
matcherStatus.CompareAndSwap(false, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// registerBuiltInFunctions registers all built in functions for the flow
|
// registerBuiltInFunctions registers all built in functions for the flow
|
||||||
func (f *FlowExecutor) registerBuiltInFunctions() error {
|
func (f *FlowExecutor) registerBuiltInFunctions() error {
|
||||||
// currently we register following builtin functions
|
// currently we register following builtin functions
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
package flow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ProtoOptions are options that can be passed to flow protocol callback
|
|
||||||
// ex: dns(protoOptions) <- protoOptions are optional and can be anything
|
|
||||||
type ProtoOptions struct {
|
|
||||||
Hide bool
|
|
||||||
Async bool
|
|
||||||
protoName string
|
|
||||||
reqIDS []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Examples
|
|
||||||
// dns() <- callback without any options
|
|
||||||
// dns(1) or dns(1,3) <- callback with index of protocol in template request at 1 or 1 and 3
|
|
||||||
// dns("probe-http") or dns("extract-vpc","probe-http") <- callback with id's instead of index of request in template
|
|
||||||
// dns({hide:true}) or dns({hide:true,async:true}) <- callback with protocol options
|
|
||||||
// hide - hides result/event from output & sdk
|
|
||||||
// async - executes protocols in parallel (implicit wait no need to specify wait)
|
|
||||||
// Note: all of these options are optional and can be combined together in any order
|
|
||||||
|
|
||||||
// LoadOptions loads the protocol options from a map
|
|
||||||
func (P *ProtoOptions) LoadOptions(m map[string]interface{}) {
|
|
||||||
P.Hide = GetBool(m["hide"])
|
|
||||||
P.Async = GetBool(m["async"])
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBool returns bool value from interface
|
|
||||||
func GetBool(value interface{}) bool {
|
|
||||||
if value == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch v := value.(type) {
|
|
||||||
case bool:
|
|
||||||
return v
|
|
||||||
default:
|
|
||||||
tmpValue := types.ToString(value)
|
|
||||||
if strings.EqualFold(tmpValue, "true") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user