Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin'
Browse files Browse the repository at this point in the history
  • Loading branch information
ehsandeep committed Apr 25, 2024
2 parents 39b6ca9 + 295f458 commit 4d12271
Show file tree
Hide file tree
Showing 119 changed files with 2,291 additions and 386 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/build-test.yml
Expand Up @@ -42,13 +42,15 @@ jobs:
- name: Test
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
run: go test ./...

- name: Integration Tests
timeout-minutes: 50
env:
GH_ACTION: true
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
run: |
chmod +x run.sh
bash run.sh ${{ matrix.os }}
Expand All @@ -66,3 +68,7 @@ jobs:
- name: Example SDK Advanced
run: go run .
working-directory: examples/advanced/

- name: Example SDK with speed control
run: go run .
working-directory: examples/with_speed_control/
2 changes: 1 addition & 1 deletion .github/workflows/lint-test.yml
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v3

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3.6.0
uses: golangci/golangci-lint-action@v4.0.0
with:
version: latest
args: --timeout 5m
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -36,5 +36,8 @@ pkg/protocols/headless/engine/.cache
/fuzzplayground
integration_tests/fuzzplayground
/dsl.md
/nuclei-stats
/nuclei-stats-*
/scan-charts


9 changes: 9 additions & 0 deletions Makefile
Expand Up @@ -11,9 +11,18 @@ ifneq ($(shell go env GOOS),darwin)
LDFLAGS := -extldflags "-static"
endif

.PHONY: all build build-stats scan-charts docs test integration functional tidy devtools jsupdate ts fuzzplayground memogen dsl-docs

all: build
build:
rm -f nuclei 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "nuclei" cmd/nuclei/main.go
build-stats:
rm -f nuclei-stats 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -tags=stats -o "nuclei-stats" cmd/nuclei/main.go
scan-charts:
rm -f scan-charts 2>/dev/null
$(GOBUILD) $(GOFLAGS) -ldflags '$(LDFLAGS)' -o "scan-charts" cmd/scan-charts/main.go
docs:
if ! which dstdocgen > /dev/null; then
echo -e "Command not found! Install? (y/n) \c"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -22,7 +22,7 @@
<a href="#install-nuclei">Install</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/">Documentation</a> •
<a href="#credits">Credits</a> •
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
<a href="https://discord.gg/projectdiscovery">Join Discord</a>
</p>

Expand Down
8 changes: 4 additions & 4 deletions README_CN.md
Expand Up @@ -23,8 +23,8 @@
<a href="#对于安全工程师">对于安全工程师</a> •
<a href="#对于开发和组织">对于开发者</a> •
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">文档</a> •
<a href="#c致谢">致谢</a> •
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">常见问题</a> •
<a href="#致谢">致谢</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">常见问题</a> •
<a href="https://discord.gg/projectdiscovery">加入Discord</a>
</p>

Expand All @@ -39,7 +39,7 @@

Nuclei使用零误报的定制模板向目标发送请求,同时可以对主机进行批量快速扫描。Nuclei提供TCP、DNS、HTTP、FILE等各类协议的扫描,通过强大且灵活的模板,可以使用Nuclei模拟各种安全检查。

我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300**安全研究员和工程师提供的模板。
我们的[模板仓库](https://github.com/projectdiscovery/nuclei-templates)包含**超过300名**安全研究员和工程师提供的模板。



Expand Down Expand Up @@ -439,7 +439,7 @@ Nuclei构建很简单,通过数百名安全研究员的社区模板,Nuclei
</a>
</p>

另外您可以其他类似的开源项目
另外您可以了解其他类似的开源项目

[FFuF](https://github.com/ffuf/ffuf), [Qsfuzz](https://github.com/ameenmaali/qsfuzz), [Inception](https://github.com/proabiral/inception), [Snallygaster](https://github.com/hannob/snallygaster), [Gofingerprint](https://github.com/Static-Flow/gofingerprint), [Sn1per](https://github.com/1N3/Sn1per/tree/master/templates), [Google tsunami](https://github.com/google/tsunami-security-scanner), [Jaeles](https://github.com/jaeles-project/jaeles), [ChopChop](https://github.com/michelin/ChopChop)

Expand Down
2 changes: 1 addition & 1 deletion README_ID.md
Expand Up @@ -24,7 +24,7 @@
<a href="#untuk-pengembang-dan-organisasi">Untuk Pengembang</a> •
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">Dokumentasi</a> •
<a href="#kredit">Kredit</a> •
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">Tanya Jawab</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">Tanya Jawab</a> •
<a href="https://discord.gg/projectdiscovery">Gabung Discord</a>
</p>

Expand Down
2 changes: 1 addition & 1 deletion README_KR.md
Expand Up @@ -23,7 +23,7 @@
<a href="#개발자를-위한">개발자를 위한</a> •
<a href="https://nuclei.projectdiscovery.io/nuclei/get-started/">문서</a> •
<a href="#credits">Credits</a> •
<a href="https://nuclei.projectdiscovery.io/faq/nuclei/">FAQs</a> •
<a href="https://docs.projectdiscovery.io/tools/nuclei/faq">FAQs</a> •
<a href="https://discord.gg/projectdiscovery"> Discord 참가</a>
</p>

Expand Down
2 changes: 2 additions & 0 deletions SYNTAX-REFERENCE.md
Expand Up @@ -2750,6 +2750,8 @@ Enum Values:
- <code>TLSA</code>

- <code>ANY</code>

- <code>SRV</code>
</div>

<hr />
Expand Down
7 changes: 6 additions & 1 deletion cmd/integration-test/dns.go
Expand Up @@ -5,7 +5,12 @@ import (
)

var dnsTestCases = []TestCaseInfo{
{Path: "protocols/dns/basic.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/a.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/aaaa.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/cname.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/srv.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/ns.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/txt.yaml", TestCase: &dnsBasic{}},
{Path: "protocols/dns/ptr.yaml", TestCase: &dnsPtr{}},
{Path: "protocols/dns/caa.yaml", TestCase: &dnsCAA{}},
{Path: "protocols/dns/tlsa.yaml", TestCase: &dnsTLSA{}},
Expand Down
27 changes: 27 additions & 0 deletions cmd/integration-test/fuzz.go
Expand Up @@ -18,6 +18,7 @@ const (

var fuzzingTestCases = []TestCaseInfo{
{Path: "fuzz/fuzz-mode.yaml", TestCase: &fuzzModeOverride{}},
{Path: "fuzz/fuzz-multi-mode.yaml", TestCase: &fuzzMultipleMode{}},
{Path: "fuzz/fuzz-type.yaml", TestCase: &fuzzTypeOverride{}},
{Path: "fuzz/fuzz-query.yaml", TestCase: &httpFuzzQuery{}},
{Path: "fuzz/fuzz-headless.yaml", TestCase: &HeadlessFuzzingQuery{}},
Expand Down Expand Up @@ -174,3 +175,29 @@ func (h *HeadlessFuzzingQuery) Execute(filePath string) error {
}
return expectResultsCount(got, 2)
}

type fuzzMultipleMode struct{}

// Execute executes a test case and returns an error if occurred
func (h *fuzzMultipleMode) Execute(filePath string) error {
router := httprouter.New()
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
xClientId := r.Header.Get("X-Client-Id")
xSecretId := r.Header.Get("X-Secret-Id")
if xClientId != "nuclei-v3" || xSecretId != "nuclei-v3" {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "text/html")
resp := fmt.Sprintf("<html><body><h1>This is multi-mode fuzzing test: %v <h1></body></html>", xClientId)
fmt.Fprint(w, resp)
})
ts := httptest.NewTLSServer(router)
defer ts.Close()

got, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL+"?url=https://scanme.sh", debug, "-jsonl", "-fuzz")
if err != nil {
return err
}
return expectResultsCount(got, 1)
}
2 changes: 1 addition & 1 deletion cmd/integration-test/library.go
Expand Up @@ -128,7 +128,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
}
store.Load()

_ = engine.Execute(store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
engine.WorkPool().Wait() // Wait for the scan to finish

return results, nil
Expand Down
96 changes: 96 additions & 0 deletions cmd/integration-test/workflow.go
Expand Up @@ -3,11 +3,15 @@ package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"strings"

"github.com/julienschmidt/httprouter"

"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
)

Expand All @@ -16,11 +20,40 @@ var workflowTestcases = []TestCaseInfo{
{Path: "workflow/condition-matched.yaml", TestCase: &workflowConditionMatched{}},
{Path: "workflow/condition-unmatched.yaml", TestCase: &workflowConditionUnmatch{}},
{Path: "workflow/matcher-name.yaml", TestCase: &workflowMatcherName{}},
{Path: "workflow/complex-conditions.yaml", TestCase: &workflowComplexConditions{}},
{Path: "workflow/http-value-share-workflow.yaml", TestCase: &workflowHttpKeyValueShare{}},
{Path: "workflow/dns-value-share-workflow.yaml", TestCase: &workflowDnsKeyValueShare{}},
{Path: "workflow/code-value-share-workflow.yaml", TestCase: &workflowCodeKeyValueShare{}, DisableOn: isCodeDisabled}, // isCodeDisabled declared in code.go
{Path: "workflow/multiprotocol-value-share-workflow.yaml", TestCase: &workflowMultiProtocolKeyValueShare{}},
{Path: "workflow/shared-cookie.yaml", TestCase: &workflowSharedCookies{}},
}

func init() {
// sign code templates (unless they are disabled)
if !isCodeDisabled() {
// allow local file access to load content of file references in template
// in order to sign them for testing purposes
templates.TemplateSignerLFA()

// testCertFile and testKeyFile are declared in code.go
tsigner, err := signer.NewTemplateSignerFromFiles(testCertFile, testKeyFile)
if err != nil {
panic(err)
}

// only the code templates are necessary to be signed
var templatesToSign = []string{
"workflow/code-template-1.yaml",
"workflow/code-template-2.yaml",
}
for _, templatePath := range templatesToSign {
if err := templates.SignTemplate(tsigner, templatePath); err != nil {
log.Fatalf("Could not sign template %v got: %s\n", templatePath, err)
}
}
}
}

type workflowBasic struct{}

// Execute executes a test case and returns an error if occurred
Expand Down Expand Up @@ -97,6 +130,30 @@ func (h *workflowMatcherName) Execute(filePath string) error {
return expectResultsCount(results, 1)
}

type workflowComplexConditions struct{}

// Execute executes a test case and returns an error if occurred
func (h *workflowComplexConditions) Execute(filePath string) error {
router := httprouter.New()
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "This is test matcher text")
})
ts := httptest.NewServer(router)
defer ts.Close()

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

for _, result := range results {
if !strings.Contains(result, "test-matcher-3") {
return fmt.Errorf("incorrect result: the \"basic-get-third:test-matcher-3\" and only that should be matched!\nResults:\n\t%s", strings.Join(results, "\n\t"))
}
}
return expectResultsCount(results, 2)
}

type workflowHttpKeyValueShare struct{}

// Execute executes a test case and returns an error if occurred
Expand Down Expand Up @@ -133,6 +190,45 @@ func (h *workflowDnsKeyValueShare) Execute(filePath string) error {
return expectResultsCount(results, 1)
}

type workflowCodeKeyValueShare struct{}

// Execute executes a test case and returns an error if occurred
func (h *workflowCodeKeyValueShare) Execute(filePath string) error {
// provide the Certificate File that the code templates are signed with
certEnvVar := signer.CertEnvVarName + "=" + testCertFile

results, err := testutils.RunNucleiArgsWithEnvAndGetResults(debug, []string{certEnvVar}, "-workflows", filePath, "-target", "input", "-code")
if err != nil {
return err
}

return expectResultsCount(results, 1)
}

type workflowMultiProtocolKeyValueShare struct{}

// Execute executes a test case and returns an error if occurred
func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error {
router := httprouter.New()
// the response of path1 contains a domain that will be extracted and shared with the second template
router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "href=\"blog.projectdiscovery.io\"")
})
// path2 responds with the value of the "extracted" query parameter, e.g.: /path2?extracted=blog.projectdiscovery.io => blog.projectdiscovery.io
router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprintf(w, "%s", r.URL.Query().Get("extracted"))
})
ts := httptest.NewServer(router)
defer ts.Close()

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

return expectResultsCount(results, 2)
}

type workflowSharedCookies struct{}

// Execute executes a test case and returns an error if occurred
Expand Down
13 changes: 9 additions & 4 deletions cmd/nuclei/main.go
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/env"
_ "github.com/projectdiscovery/utils/pprof"
stringsutil "github.com/projectdiscovery/utils/strings"

"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
Expand Down Expand Up @@ -295,10 +296,12 @@ on extensive configurability, massive extensibility and ease of use.`)
flagSet.StringVarP(&options.Interface, "interface", "i", "", "network interface to use for network scan"),
flagSet.StringVarP(&options.AttackType, "attack-type", "at", "", "type of payload combinations to perform (batteringram,pitchfork,clusterbomb)"),
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 10*1024*1024, "max response size to read in bytes"),
flagSet.IntVarP(&options.ResponseReadSize, "response-size-read", "rsr", 0, "max response size to read in bytes"),
flagSet.IntVarP(&options.ResponseSaveSize, "response-size-save", "rss", 1*1024*1024, "max response size to read in bytes"),
flagSet.DurationVarP(&options.ResponseReadTimeout, "response-read-timeout", "rrt", time.Duration(5*time.Second), "response read timeout in seconds"),
flagSet.CallbackVar(resetCallback, "reset", "reset removes all nuclei configuration and data files (including nuclei-templates)"),
flagSet.BoolVarP(&options.TlsImpersonate, "tls-impersonate", "tlsi", false, "enable experimental client hello (ja3) tls randomization"),
flagSet.StringVarP(&options.HttpApiEndpoint, "http-api-endpoint", "hae", "", "experimental http api endpoint"),
)

flagSet.CreateGroup("interactsh", "interactsh",
Expand Down Expand Up @@ -329,13 +332,15 @@ on extensive configurability, massive extensibility and ease of use.`)

flagSet.CreateGroup("rate-limit", "Rate-Limit",
flagSet.IntVarP(&options.RateLimit, "rate-limit", "rl", 150, "maximum number of requests to send per second"),
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute"),
flagSet.DurationVarP(&options.RateLimitDuration, "rate-limit-duration", "rld", time.Second, "maximum number of requests to send per second"),
flagSet.IntVarP(&options.RateLimitMinute, "rate-limit-minute", "rlm", 0, "maximum number of requests to send per minute (DEPRECATED)"),
flagSet.IntVarP(&options.BulkSize, "bulk-size", "bs", 25, "maximum number of hosts to be analyzed in parallel per template"),
flagSet.IntVarP(&options.TemplateThreads, "concurrency", "c", 25, "maximum number of templates to be executed in parallel"),
flagSet.IntVarP(&options.HeadlessBulkSize, "headless-bulk-size", "hbs", 10, "maximum number of headless hosts to be analyzed in parallel per template"),
flagSet.IntVarP(&options.HeadlessTemplateThreads, "headless-concurrency", "headc", 10, "maximum number of headless templates to be executed in parallel"),
flagSet.IntVarP(&options.JsConcurrency, "js-concurrency", "jsc", 120, "maximum number of javascript runtimes to be executed in parallel"),
flagSet.IntVarP(&options.PayloadConcurrency, "payload-concurrency", "pc", 25, "max payload concurrency for each template"),
flagSet.IntVarP(&options.ProbeConcurrency, "probe-concurrency", "prc", 50, "http probe concurrency with httpx"),
)
flagSet.CreateGroup("optimization", "Optimizations",
flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"),
Expand Down Expand Up @@ -597,10 +602,10 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
gologger.Fatal().Msgf("could not read response: %s", err)
}
resp = strings.TrimSpace(resp)
if strings.EqualFold(resp, "y") || strings.EqualFold(resp, "yes") {
if stringsutil.EqualFoldAny(resp, "y", "yes") {
break
}
if strings.EqualFold(resp, "n") || strings.EqualFold(resp, "no") || resp == "" {
if stringsutil.EqualFoldAny(resp, "n", "no", "") {
fmt.Println("Exiting...")
os.Exit(0)
}
Expand Down
18 changes: 18 additions & 0 deletions cmd/nuclei/srv.yaml
@@ -0,0 +1,18 @@
id: basic-dns-a-example

info:
name: Test DNS A Query Template
author: pdteam
severity: info

dns:
- name: "{{FQDN}}"
type: SRV
class: inet
recursion: true
retries: 3
matchers:
- type: word
part: all
words:
- "SRV"

0 comments on commit 4d12271

Please sign in to comment.