mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 17:45:28 +00:00
Merge remote-tracking branch 'origin'
This commit is contained in:
commit
ba0f995a38
27
.github/stale.yml
vendored
27
.github/stale.yml
vendored
@ -1,27 +0,0 @@
|
|||||||
# Number of days of inactivity before an issue becomes stale
|
|
||||||
daysUntilStale: 7
|
|
||||||
|
|
||||||
# Number of days of inactivity before a stale issue is closed
|
|
||||||
daysUntilClose: 7
|
|
||||||
|
|
||||||
# Issues with these labels will never be considered stale
|
|
||||||
# exemptLabels:
|
|
||||||
# - pinned
|
|
||||||
# - security
|
|
||||||
|
|
||||||
# Only issues or pull requests with all of these labels are check if stale.
|
|
||||||
onlyLabels:
|
|
||||||
- "Status: Abandoned"
|
|
||||||
- "Type: Question"
|
|
||||||
|
|
||||||
# Label to use when marking as stale
|
|
||||||
staleLabel: stale
|
|
||||||
|
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
|
||||||
markComment: >
|
|
||||||
This issue has been automatically marked as stale because it has not had
|
|
||||||
recent activity. It will be closed if no further activity occurs. Thank you
|
|
||||||
for your contributions.
|
|
||||||
|
|
||||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
|
||||||
closeComment: false
|
|
||||||
41
.github/workflows/stale.yaml
vendored
Normal file
41
.github/workflows/stale.yaml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: 💤 Stale
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # Weekly
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
contents: write # only for delete-branch option
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
|
with:
|
||||||
|
days-before-stale: 90
|
||||||
|
days-before-close: 7
|
||||||
|
stale-issue-label: "Status: Stale"
|
||||||
|
stale-pr-label: "Status: Stale"
|
||||||
|
stale-issue-message: >
|
||||||
|
This issue has been automatically marked as stale because it has not
|
||||||
|
had recent activity. It will be closed in 7 days if no further
|
||||||
|
activity occurs. Thank you for your contributions!
|
||||||
|
stale-pr-message: >
|
||||||
|
This pull request has been automatically marked as stale due to
|
||||||
|
inactivity. It will be closed in 7 days if no further activity
|
||||||
|
occurs. Please update if you wish to keep it open.
|
||||||
|
close-issue-message: >
|
||||||
|
This issue has been automatically closed due to inactivity. If you
|
||||||
|
think this is a mistake or would like to continue the discussion,
|
||||||
|
please comment or feel free to reopen it.
|
||||||
|
close-pr-message: >
|
||||||
|
This pull request has been automatically closed due to inactivity.
|
||||||
|
If you think this is a mistake or would like to continue working on
|
||||||
|
it, please comment or feel free to reopen it.
|
||||||
|
close-issue-label: "Status: Abandoned"
|
||||||
|
close-pr-label: "Status: Abandoned"
|
||||||
|
exempt-issue-labels: "Status: Abandoned"
|
||||||
|
exempt-pr-labels: "Status: Abandoned"
|
||||||
2
.github/workflows/tests.yaml
vendored
2
.github/workflows/tests.yaml
vendored
@ -94,7 +94,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: projectdiscovery/actions/setup/go@v1
|
- uses: projectdiscovery/actions/setup/go@v1
|
||||||
- uses: projectdiscovery/actions/setup/python@v1
|
- uses: projectdiscovery/actions/setup/python@v1
|
||||||
- run: bash run.sh "${{ matrix.os }}"
|
- run: bash run.sh
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
working-directory: cmd/functional-test/
|
working-directory: cmd/functional-test/
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">`Korean`</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">`Korean`</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">`Indonesia`</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">`Indonesia`</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">`Spanish`</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">`Spanish`</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">`日本語`</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">`日本語`</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">`Portuguese`</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">`Portuguese`</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中国語</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中国語</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">韓国語</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">韓国語</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">インドネシア語</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">インドネシア語</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">ポルトガル語</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">ポルトガル語</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">포르투갈어</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">포르투갈어</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
|
||||||
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ var (
|
|||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
debug := os.Getenv("DEBUG") == "true"
|
debug := os.Getenv("DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1"
|
||||||
|
|
||||||
if err, errored := runFunctionalTests(debug); err != nil {
|
if err, errored := runFunctionalTests(debug); err != nil {
|
||||||
log.Fatalf("Could not run functional tests: %s\n", err)
|
log.Fatalf("Could not run functional tests: %s\n", err)
|
||||||
|
|||||||
@ -1,27 +1,43 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# reading os type from arguments
|
if [ "${RUNNER_OS}" == "Windows" ]; then
|
||||||
CURRENT_OS=$1
|
EXT=".exe"
|
||||||
|
elif [ "${RUNNER_OS}" == "macOS" ]; then
|
||||||
|
if [ "${CI}" == "true" ]; then
|
||||||
|
sudo sysctl -w kern.maxfiles{,perproc}=524288
|
||||||
|
sudo launchctl limit maxfiles 65536 524288
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "${CURRENT_OS}" == "windows-latest" ];then
|
ORIGINAL_ULIMIT="$(ulimit -n)"
|
||||||
extension=.exe
|
ulimit -n 65536 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mkdir -p .nuclei-config/nuclei/
|
||||||
|
touch .nuclei-config/nuclei/.nuclei-ignore
|
||||||
|
|
||||||
echo "::group::Building functional-test binary"
|
echo "::group::Building functional-test binary"
|
||||||
go build -o functional-test$extension
|
go build -o "functional-test${EXT}"
|
||||||
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$extension ../nuclei
|
go build -o "nuclei-dev${EXT}" ../nuclei
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Installing nuclei templates"
|
|
||||||
./nuclei_dev$extension -update-templates
|
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Building latest release of nuclei"
|
echo "::group::Building latest release of nuclei"
|
||||||
go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
|
go build -o "nuclei${EXT}" -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo 'Starting Nuclei functional test'
|
echo "::group::Installing nuclei templates"
|
||||||
./functional-test$extension -main ./nuclei$extension -dev ./nuclei_dev$extension -testcases testcases.txt
|
eval "./nuclei-dev${EXT} -update-templates"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Validating templates"
|
||||||
|
eval "./nuclei-dev${EXT} -validate"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "Starting Nuclei functional test"
|
||||||
|
eval "./functional-test${EXT} -main ./nuclei${EXT} -dev ./nuclei-dev${EXT} -testcases testcases.txt"
|
||||||
|
|
||||||
|
if [ "${RUNNER_OS}" == "macOS" ]; then
|
||||||
|
ulimit -n "${ORIGINAL_ULIMIT}" || true
|
||||||
|
fi
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -86,7 +86,7 @@ require (
|
|||||||
github.com/microsoft/go-mssqldb v1.6.0
|
github.com/microsoft/go-mssqldb v1.6.0
|
||||||
github.com/ory/dockertest/v3 v3.10.0
|
github.com/ory/dockertest/v3 v3.10.0
|
||||||
github.com/praetorian-inc/fingerprintx v1.1.9
|
github.com/praetorian-inc/fingerprintx v1.1.9
|
||||||
github.com/projectdiscovery/dsl v0.4.2
|
github.com/projectdiscovery/dsl v0.4.3
|
||||||
github.com/projectdiscovery/fasttemplate v0.0.2
|
github.com/projectdiscovery/fasttemplate v0.0.2
|
||||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
|
||||||
github.com/projectdiscovery/goflags v0.1.74
|
github.com/projectdiscovery/goflags v0.1.74
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -860,6 +860,8 @@ github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB7
|
|||||||
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
|
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
|
||||||
github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI=
|
github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI=
|
||||||
github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U=
|
github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U=
|
||||||
|
github.com/projectdiscovery/dsl v0.4.3 h1:ZrbRkyK38hRiYMX7s6ohaTorDpq321ErqJuBUDmh49g=
|
||||||
|
github.com/projectdiscovery/dsl v0.4.3/go.mod h1:cyt2IaYhS5SlyZ1D2BdK0QwIBXQW/u9zaBmRAKYKAmk=
|
||||||
github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w=
|
github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w=
|
||||||
github.com/projectdiscovery/fastdialer v0.4.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ=
|
github.com/projectdiscovery/fastdialer v0.4.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ=
|
||||||
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
|
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{{- if .Values.interactsh.ingress.enabled -}}
|
{{- if .Values.interactsh.ingress.enabled -}}
|
||||||
{{- $fullName := include "nuclei.fullname" . -}}
|
{{- $fullName := include "nuclei.fullname" . -}}
|
||||||
{{- $svcPort := .Values.service.port -}}
|
{{- $svcPort := .Values.interactsh.service.port -}}
|
||||||
|
{{- $svcName := .Values.interactsh.service.name -}}
|
||||||
{{- if and .Values.interactsh.ingress.className (not (semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion)) }}
|
{{- if and .Values.interactsh.ingress.className (not (semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||||
{{- if not (hasKey .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class") }}
|
{{- if not (hasKey .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||||
{{- $_ := set .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class" .Values.interactsh.ingress.className}}
|
{{- $_ := set .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class" .Values.interactsh.ingress.className}}
|
||||||
@ -49,11 +50,11 @@ spec:
|
|||||||
backend:
|
backend:
|
||||||
{{- if semverCompare ">=1.20-0" $.Capabilities.KubeVersion.GitVersion }}
|
{{- if semverCompare ">=1.20-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
service:
|
service:
|
||||||
name: {{ $fullName }}
|
name: {{ $svcName }}
|
||||||
port:
|
port:
|
||||||
number: {{ $svcPort }}
|
number: {{ $svcPort }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
serviceName: {{ $fullName }}
|
serviceName: {{ $svcName }}
|
||||||
servicePort: {{ $svcPort }}
|
servicePort: {{ $svcPort }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@ -463,6 +463,14 @@ func EnablePassiveMode() NucleiSDKOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableMatcherStatus allows enabling matcher status
|
||||||
|
func EnableMatcherStatus() NucleiSDKOptions {
|
||||||
|
return func(e *NucleiEngine) error {
|
||||||
|
e.opts.MatcherStatus = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithAuthProvider allows setting a custom authprovider implementation
|
// WithAuthProvider allows setting a custom authprovider implementation
|
||||||
func WithAuthProvider(provider authprovider.AuthProvider) NucleiSDKOptions {
|
func WithAuthProvider(provider authprovider.AuthProvider) NucleiSDKOptions {
|
||||||
return func(e *NucleiEngine) error {
|
return func(e *NucleiEngine) error {
|
||||||
|
|||||||
@ -52,14 +52,19 @@ func (d *Dynamic) GetDomainAndDomainRegex() ([]string, []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dynamic) UnmarshalJSON(data []byte) error {
|
func (d *Dynamic) UnmarshalJSON(data []byte) error {
|
||||||
if err := json.Unmarshal(data, &d); err != nil {
|
if d == nil {
|
||||||
|
return errorutil.New("cannot unmarshal into nil Dynamic struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use an alias type (auxiliary) to avoid a recursive call in this method.
|
||||||
|
type Alias Dynamic
|
||||||
|
|
||||||
|
// If d.Secret was nil, json.Unmarshal will allocate a new Secret object
|
||||||
|
// and populate it from the top level JSON fields.
|
||||||
|
if err := json.Unmarshal(data, (*Alias)(d)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var s Secret
|
|
||||||
if err := json.Unmarshal(data, &s); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.Secret = &s
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
125
pkg/authprovider/authx/dynamic_test.go
Normal file
125
pkg/authprovider/authx/dynamic_test.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package authx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDynamicUnmarshalJSON(t *testing.T) {
|
||||||
|
t.Run("basic-unmarshal", func(t *testing.T) {
|
||||||
|
data := []byte(`{
|
||||||
|
"template": "test-template.yaml",
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"key": "username",
|
||||||
|
"value": "testuser"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"secrets": [
|
||||||
|
{
|
||||||
|
"type": "BasicAuth",
|
||||||
|
"domains": ["example.com"],
|
||||||
|
"username": "user1",
|
||||||
|
"password": "pass1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "BasicAuth",
|
||||||
|
"domains": ["test.com"],
|
||||||
|
"username": "testuser",
|
||||||
|
"password": "testpass"
|
||||||
|
}`)
|
||||||
|
|
||||||
|
var d Dynamic
|
||||||
|
err := d.UnmarshalJSON(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Secret
|
||||||
|
require.NotNil(t, d.Secret)
|
||||||
|
require.Equal(t, "BasicAuth", d.Secret.Type)
|
||||||
|
require.Equal(t, []string{"test.com"}, d.Secret.Domains)
|
||||||
|
require.Equal(t, "testuser", d.Secret.Username)
|
||||||
|
require.Equal(t, "testpass", d.Secret.Password)
|
||||||
|
|
||||||
|
// Dynamic fields
|
||||||
|
require.Equal(t, "test-template.yaml", d.TemplatePath)
|
||||||
|
require.Len(t, d.Variables, 1)
|
||||||
|
require.Equal(t, "username", d.Variables[0].Key)
|
||||||
|
require.Equal(t, "testuser", d.Variables[0].Value)
|
||||||
|
require.Len(t, d.Secrets, 1)
|
||||||
|
require.Equal(t, "BasicAuth", d.Secrets[0].Type)
|
||||||
|
require.Equal(t, []string{"example.com"}, d.Secrets[0].Domains)
|
||||||
|
require.Equal(t, "user1", d.Secrets[0].Username)
|
||||||
|
require.Equal(t, "pass1", d.Secrets[0].Password)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("complex-unmarshal", func(t *testing.T) {
|
||||||
|
data := []byte(`{
|
||||||
|
"template": "test-template.yaml",
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "Bearer xyz"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"secrets": [
|
||||||
|
{
|
||||||
|
"type": "CookiesAuth",
|
||||||
|
"domains": ["example.com"],
|
||||||
|
"cookies": [
|
||||||
|
{
|
||||||
|
"key": "session",
|
||||||
|
"value": "abc123"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "HeadersAuth",
|
||||||
|
"domains": ["api.test.com"],
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"key": "X-API-Key",
|
||||||
|
"value": "secret-key"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`)
|
||||||
|
|
||||||
|
var d Dynamic
|
||||||
|
err := d.UnmarshalJSON(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Secret
|
||||||
|
require.NotNil(t, d.Secret)
|
||||||
|
require.Equal(t, "HeadersAuth", d.Secret.Type)
|
||||||
|
require.Equal(t, []string{"api.test.com"}, d.Secret.Domains)
|
||||||
|
require.Len(t, d.Secret.Headers, 1)
|
||||||
|
require.Equal(t, "X-API-Key", d.Secret.Headers[0].Key)
|
||||||
|
require.Equal(t, "secret-key", d.Secret.Headers[0].Value)
|
||||||
|
|
||||||
|
// Dynamic fields
|
||||||
|
require.Equal(t, "test-template.yaml", d.TemplatePath)
|
||||||
|
require.Len(t, d.Variables, 1)
|
||||||
|
require.Equal(t, "token", d.Variables[0].Key)
|
||||||
|
require.Equal(t, "Bearer xyz", d.Variables[0].Value)
|
||||||
|
require.Len(t, d.Secrets, 1)
|
||||||
|
require.Equal(t, "CookiesAuth", d.Secrets[0].Type)
|
||||||
|
require.Equal(t, []string{"example.com"}, d.Secrets[0].Domains)
|
||||||
|
require.Len(t, d.Secrets[0].Cookies, 1)
|
||||||
|
require.Equal(t, "session", d.Secrets[0].Cookies[0].Key)
|
||||||
|
require.Equal(t, "abc123", d.Secrets[0].Cookies[0].Value)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid-json", func(t *testing.T) {
|
||||||
|
data := []byte(`{invalid json}`)
|
||||||
|
var d Dynamic
|
||||||
|
err := d.UnmarshalJSON(data)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty-json", func(t *testing.T) {
|
||||||
|
data := []byte(`{}`)
|
||||||
|
var d Dynamic
|
||||||
|
err := d.UnmarshalJSON(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
@ -140,10 +141,8 @@ func (c Catalog) ResolvePath(templateName, second string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if templateName is already an absolute path to c key
|
// check if templateName is already an absolute path to c key
|
||||||
for _, key := range keys {
|
if slices.Contains(keys, templateName) {
|
||||||
if key == templateName {
|
return templateName, nil
|
||||||
return templateName, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("no such path found: %s%s for keys: %v", second, templateName, keys)
|
return "", fmt.Errorf("no such path found: %s%s for keys: %v", second, templateName, keys)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package aws
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -250,13 +251,7 @@ func (m mocks3svc) getAllKeys() ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mocks3svc) downloadKey(name string) (io.ReadCloser, error) {
|
func (m mocks3svc) downloadKey(name string) (io.ReadCloser, error) {
|
||||||
found := false
|
found := slices.Contains(m.keys, name)
|
||||||
for _, key := range m.keys {
|
|
||||||
if key == name {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("key not found")
|
return nil, errors.New("key not found")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const (
|
|||||||
CLIConfigFileName = "config.yaml"
|
CLIConfigFileName = "config.yaml"
|
||||||
ReportingConfigFilename = "reporting-config.yaml"
|
ReportingConfigFilename = "reporting-config.yaml"
|
||||||
// Version is the current version of nuclei
|
// Version is the current version of nuclei
|
||||||
Version = `v3.4.4`
|
Version = `v3.4.5`
|
||||||
// Directory Names of custom templates
|
// Directory Names of custom templates
|
||||||
CustomS3TemplatesDirName = "s3"
|
CustomS3TemplatesDirName = "s3"
|
||||||
CustomGitHubTemplatesDirName = "github"
|
CustomGitHubTemplatesDirName = "github"
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/projectdiscovery/goflags"
|
"github.com/projectdiscovery/goflags"
|
||||||
@ -334,12 +335,7 @@ func (c *Config) copyIgnoreFile() {
|
|||||||
// this could be a feature specific to debugging like PPROF or printing stats
|
// this could be a feature specific to debugging like PPROF or printing stats
|
||||||
// of max host error etc
|
// of max host error etc
|
||||||
func (c *Config) IsDebugArgEnabled(arg string) bool {
|
func (c *Config) IsDebugArgEnabled(arg string) bool {
|
||||||
for _, v := range c.debugArgs {
|
return slices.Contains(c.debugArgs, arg)
|
||||||
if v == arg {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseDebugArgs from string
|
// parseDebugArgs from string
|
||||||
|
|||||||
@ -38,7 +38,7 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te
|
|||||||
match, err = template.Executer.Execute(ctx)
|
match, err = template.Executer.Execute(ctx)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err)
|
gologger.Warning().Msgf("[%s] Could not execute step (self-contained): %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err)
|
||||||
}
|
}
|
||||||
results.CompareAndSwap(false, match)
|
results.CompareAndSwap(false, match)
|
||||||
}(v)
|
}(v)
|
||||||
@ -140,7 +140,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err)
|
gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err)
|
||||||
}
|
}
|
||||||
results.CompareAndSwap(false, match)
|
results.CompareAndSwap(false, match)
|
||||||
}(index, skip, scannedValue)
|
}(index, skip, scannedValue)
|
||||||
@ -206,7 +206,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err)
|
gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err)
|
||||||
}
|
}
|
||||||
results.CompareAndSwap(false, match)
|
results.CompareAndSwap(false, match)
|
||||||
}(tpl, target, sg)
|
}(tpl, target, sg)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package openapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
"github.com/getkin/kin-openapi/openapi3"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -84,13 +85,7 @@ func excludeFromMode(schema *openapi3.Schema) bool {
|
|||||||
|
|
||||||
// isRequired checks whether a key is actually required.
|
// isRequired checks whether a key is actually required.
|
||||||
func isRequired(schema *openapi3.Schema, key string) bool {
|
func isRequired(schema *openapi3.Schema, key string) bool {
|
||||||
for _, req := range schema.Required {
|
return slices.Contains(schema.Required, key)
|
||||||
if req == key {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type cachedSchema struct {
|
type cachedSchema struct {
|
||||||
|
|||||||
@ -185,6 +185,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
|||||||
func (request *Request) getDnsClient(options *protocols.ExecutorOptions, metadata map[string]interface{}) (*retryabledns.Client, error) {
|
func (request *Request) getDnsClient(options *protocols.ExecutorOptions, metadata map[string]interface{}) (*retryabledns.Client, error) {
|
||||||
dnsClientOptions := &dnsclientpool.Configuration{
|
dnsClientOptions := &dnsclientpool.Configuration{
|
||||||
Retries: request.Retries,
|
Retries: request.Retries,
|
||||||
|
Proxy: options.Options.AliveSocksProxy,
|
||||||
}
|
}
|
||||||
if len(request.Resolvers) > 0 {
|
if len(request.Resolvers) > 0 {
|
||||||
if len(request.Resolvers) > 0 {
|
if len(request.Resolvers) > 0 {
|
||||||
|
|||||||
@ -51,6 +51,8 @@ type Configuration struct {
|
|||||||
Retries int
|
Retries int
|
||||||
// Resolvers contains the specific per request resolvers
|
// Resolvers contains the specific per request resolvers
|
||||||
Resolvers []string
|
Resolvers []string
|
||||||
|
// Proxy contains the proxy to use for the dns client
|
||||||
|
Proxy string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash returns the hash of the configuration to allow client pooling
|
// Hash returns the hash of the configuration to allow client pooling
|
||||||
@ -60,6 +62,8 @@ func (c *Configuration) Hash() string {
|
|||||||
builder.WriteString(strconv.Itoa(c.Retries))
|
builder.WriteString(strconv.Itoa(c.Retries))
|
||||||
builder.WriteString("l")
|
builder.WriteString("l")
|
||||||
builder.WriteString(strings.Join(c.Resolvers, ""))
|
builder.WriteString(strings.Join(c.Resolvers, ""))
|
||||||
|
builder.WriteString("p")
|
||||||
|
builder.WriteString(c.Proxy)
|
||||||
hash := builder.String()
|
hash := builder.String()
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
@ -83,7 +87,11 @@ func Get(options *types.Options, configuration *Configuration) (*retryabledns.Cl
|
|||||||
} else if len(configuration.Resolvers) > 0 {
|
} else if len(configuration.Resolvers) > 0 {
|
||||||
resolvers = configuration.Resolvers
|
resolvers = configuration.Resolvers
|
||||||
}
|
}
|
||||||
client, err := retryabledns.New(resolvers, configuration.Retries)
|
client, err := retryabledns.NewWithOptions(retryabledns.Options{
|
||||||
|
BaseResolvers: resolvers,
|
||||||
|
MaxRetries: configuration.Retries,
|
||||||
|
Proxy: options.AliveSocksProxy,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not create dns client")
|
return nil, errors.Wrap(err, "could not create dns client")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,15 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||||
fileutil "github.com/projectdiscovery/utils/file"
|
fileutil "github.com/projectdiscovery/utils/file"
|
||||||
osutils "github.com/projectdiscovery/utils/os"
|
osutils "github.com/projectdiscovery/utils/os"
|
||||||
processutil "github.com/projectdiscovery/utils/process"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Browser is a browser structure for nuclei headless module
|
// Browser is a browser structure for nuclei headless module
|
||||||
type Browser struct {
|
type Browser struct {
|
||||||
customAgent string
|
customAgent string
|
||||||
tempDir string
|
tempDir string
|
||||||
previousPIDs map[int32]struct{} // track already running PIDs
|
engine *rod.Browser
|
||||||
engine *rod.Browser
|
options *types.Options
|
||||||
options *types.Options
|
launcher *launcher.Launcher
|
||||||
// use getHTTPClient to get the http client
|
// use getHTTPClient to get the http client
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
httpClientOnce *sync.Once
|
httpClientOnce *sync.Once
|
||||||
@ -36,7 +35,6 @@ func New(options *types.Options) (*Browser, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not create temporary directory")
|
return nil, errors.Wrap(err, "could not create temporary directory")
|
||||||
}
|
}
|
||||||
previousPIDs := processutil.FindProcesses(processutil.IsChromeProcess)
|
|
||||||
|
|
||||||
chromeLauncher := launcher.New().
|
chromeLauncher := launcher.New().
|
||||||
Leakless(false).
|
Leakless(false).
|
||||||
@ -110,8 +108,8 @@ func New(options *types.Options) (*Browser, error) {
|
|||||||
engine: browser,
|
engine: browser,
|
||||||
options: options,
|
options: options,
|
||||||
httpClientOnce: &sync.Once{},
|
httpClientOnce: &sync.Once{},
|
||||||
|
launcher: chromeLauncher,
|
||||||
}
|
}
|
||||||
engine.previousPIDs = previousPIDs
|
|
||||||
return engine, nil
|
return engine, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +141,6 @@ func (b *Browser) getHTTPClient() (*http.Client, error) {
|
|||||||
// Close closes the browser engine
|
// Close closes the browser engine
|
||||||
func (b *Browser) Close() {
|
func (b *Browser) Close() {
|
||||||
b.engine.Close()
|
b.engine.Close()
|
||||||
|
b.launcher.Kill()
|
||||||
os.RemoveAll(b.tempDir)
|
os.RemoveAll(b.tempDir)
|
||||||
processutil.CloseProcesses(processutil.IsChromeProcess, b.previousPIDs)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -223,10 +223,15 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dumpResponse(event *output.InternalWrappedEvent, requestOptions *protocols.ExecutorOptions, responseBody string, input string) {
|
func dumpResponse(event *output.InternalWrappedEvent, requestOptions *protocols.ExecutorOptions, responseBody string, input string) {
|
||||||
cliOptions := requestOptions.Options
|
if requestOptions.Options.Debug || requestOptions.Options.DebugResponse || requestOptions.Options.StoreResponse {
|
||||||
if cliOptions.Debug || cliOptions.DebugResponse {
|
msg := fmt.Sprintf("[%s] Dumped Headless response for %s\n\n", requestOptions.TemplateID, input)
|
||||||
highlightedResponse := responsehighlighter.Highlight(event.OperatorsResult, responseBody, cliOptions.NoColor, false)
|
if requestOptions.Options.Debug || requestOptions.Options.DebugResponse {
|
||||||
gologger.Debug().Msgf("[%s] Dumped Headless response for %s\n\n%s", requestOptions.TemplateID, input, highlightedResponse)
|
resp := responsehighlighter.Highlight(event.OperatorsResult, responseBody, requestOptions.Options.NoColor, false)
|
||||||
|
gologger.Debug().Msgf("%s%s", msg, resp)
|
||||||
|
}
|
||||||
|
if requestOptions.Options.StoreResponse {
|
||||||
|
requestOptions.Output.WriteStoreDebugData(input, requestOptions.TemplateID, "headless", fmt.Sprintf("%s%s", msg, responseBody))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
json "github.com/json-iterator/go"
|
json "github.com/json-iterator/go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/fastdialer/fastdialer"
|
||||||
_ "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers/time"
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers/time"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool"
|
||||||
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
|
||||||
httputil "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils/http"
|
httputil "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils/http"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
|
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
|
||||||
"github.com/projectdiscovery/rawhttp"
|
"github.com/projectdiscovery/rawhttp"
|
||||||
@ -144,6 +146,7 @@ type Request struct {
|
|||||||
generator *generators.PayloadGenerator // optional, only enabled when using payloads
|
generator *generators.PayloadGenerator // optional, only enabled when using payloads
|
||||||
httpClient *retryablehttp.Client
|
httpClient *retryablehttp.Client
|
||||||
rawhttpClient *rawhttp.Client
|
rawhttpClient *rawhttp.Client
|
||||||
|
dialer *fastdialer.Dialer
|
||||||
|
|
||||||
// description: |
|
// description: |
|
||||||
// SelfContained specifies if the request is self-contained.
|
// SelfContained specifies if the request is self-contained.
|
||||||
@ -348,6 +351,15 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
|||||||
}
|
}
|
||||||
request.customHeaders = make(map[string]string)
|
request.customHeaders = make(map[string]string)
|
||||||
request.httpClient = client
|
request.httpClient = client
|
||||||
|
|
||||||
|
dialer, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
|
||||||
|
CustomDialer: options.CustomFastdialer,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get dialer")
|
||||||
|
}
|
||||||
|
request.dialer = dialer
|
||||||
|
|
||||||
request.options = options
|
request.options = options
|
||||||
for _, option := range request.options.Options.CustomHeaders {
|
for _, option := range request.options.Options.CustomHeaders {
|
||||||
parts := strings.SplitN(option, ":", 2)
|
parts := strings.SplitN(option, ":", 2)
|
||||||
|
|||||||
@ -841,7 +841,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ
|
|||||||
if input.MetaInput.CustomIP != "" {
|
if input.MetaInput.CustomIP != "" {
|
||||||
outputEvent["ip"] = input.MetaInput.CustomIP
|
outputEvent["ip"] = input.MetaInput.CustomIP
|
||||||
} else {
|
} else {
|
||||||
outputEvent["ip"] = protocolstate.Dialer.GetDialedIP(hostname)
|
outputEvent["ip"] = request.dialer.GetDialedIP(hostname)
|
||||||
// try getting cname
|
// try getting cname
|
||||||
request.addCNameIfAvailable(hostname, outputEvent)
|
request.addCNameIfAvailable(hostname, outputEvent)
|
||||||
}
|
}
|
||||||
@ -1085,11 +1085,11 @@ func (request *Request) validateNFixEvent(input *contextargs.Context, gr *genera
|
|||||||
|
|
||||||
// addCNameIfAvailable adds the cname to the event if available
|
// addCNameIfAvailable adds the cname to the event if available
|
||||||
func (request *Request) addCNameIfAvailable(hostname string, outputEvent map[string]interface{}) {
|
func (request *Request) addCNameIfAvailable(hostname string, outputEvent map[string]interface{}) {
|
||||||
if protocolstate.Dialer == nil {
|
if request.dialer == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := protocolstate.Dialer.GetDNSData(hostname)
|
data, err := request.dialer.GetDNSData(hostname)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch len(data.CNAME) {
|
switch len(data.CNAME) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -32,10 +33,5 @@ func (request *Request) NeedsRequestCondition() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkRequestConditionExpressions(expressions ...string) bool {
|
func checkRequestConditionExpressions(expressions ...string) bool {
|
||||||
for _, expression := range expressions {
|
return slices.ContainsFunc(expressions, reRequestCondition.MatchString)
|
||||||
if reRequestCondition.MatchString(expression) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -237,7 +237,9 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a client for the class
|
// Create a client for the class
|
||||||
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
|
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
|
||||||
|
CustomDialer: options.CustomFastdialer,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not get network client")
|
return errors.Wrap(err, "could not get network client")
|
||||||
}
|
}
|
||||||
@ -259,7 +261,3 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
|||||||
func (request *Request) Requests() int {
|
func (request *Request) Requests() int {
|
||||||
return len(request.Address)
|
return len(request.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (request *Request) SetDialer(dialer *fastdialer.Dialer) {
|
|
||||||
request.dialer = dialer
|
|
||||||
}
|
|
||||||
|
|||||||
@ -21,7 +21,9 @@ func Init(options *types.Options) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configuration contains the custom configuration options for a client
|
// Configuration contains the custom configuration options for a client
|
||||||
type Configuration struct{}
|
type Configuration struct {
|
||||||
|
CustomDialer *fastdialer.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
// Hash returns the hash of the configuration to allow client pooling
|
// Hash returns the hash of the configuration to allow client pooling
|
||||||
func (c *Configuration) Hash() string {
|
func (c *Configuration) Hash() string {
|
||||||
@ -30,5 +32,10 @@ func (c *Configuration) Hash() string {
|
|||||||
|
|
||||||
// Get creates or gets a client for the protocol based on custom configuration
|
// Get creates or gets a client for the protocol based on custom configuration
|
||||||
func Get(options *types.Options, configuration *Configuration /*TODO review unused parameters*/) (*fastdialer.Dialer, error) {
|
func Get(options *types.Options, configuration *Configuration /*TODO review unused parameters*/) (*fastdialer.Dialer, error) {
|
||||||
|
|
||||||
|
if configuration != nil && configuration.CustomDialer != nil {
|
||||||
|
return configuration.CustomDialer, nil
|
||||||
|
}
|
||||||
|
|
||||||
return normalClient, nil
|
return normalClient, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,9 +25,9 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/eventcreator"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/eventcreator"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
|
||||||
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
|
||||||
protocolutils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
|
protocolutils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
|
||||||
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"
|
||||||
@ -64,7 +64,11 @@ func (request *Request) getOpenPorts(target *contextargs.Context) ([]string, err
|
|||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conn, err := protocolstate.Dialer.Dial(target.Context(), "tcp", addr)
|
if request.dialer == nil {
|
||||||
|
request.dialer, _ = networkclientpool.Get(request.options.Options, &networkclientpool.Configuration{})
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := request.dialer.Dial(target.Context(), "tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/fastdialer/fastdialer"
|
||||||
"github.com/projectdiscovery/ratelimit"
|
"github.com/projectdiscovery/ratelimit"
|
||||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||||
@ -132,6 +133,8 @@ type ExecutorOptions struct {
|
|||||||
ExportReqURLPattern bool
|
ExportReqURLPattern bool
|
||||||
// GlobalMatchers is the storage for global matchers with http passive templates
|
// GlobalMatchers is the storage for global matchers with http passive templates
|
||||||
GlobalMatchers *globalmatchers.Storage
|
GlobalMatchers *globalmatchers.Storage
|
||||||
|
// CustomFastdialer is a fastdialer dialer instance
|
||||||
|
CustomFastdialer *fastdialer.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: centralizing components is not feasible with current clogged architecture
|
// todo: centralizing components is not feasible with current clogged architecture
|
||||||
|
|||||||
@ -115,7 +115,9 @@ func (request *Request) IsClusterable() bool {
|
|||||||
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||||
request.options = options
|
request.options = options
|
||||||
|
|
||||||
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
|
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
|
||||||
|
CustomDialer: options.CustomFastdialer,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorutil.NewWithTag("ssl", "could not get network client").Wrap(err)
|
return errorutil.NewWithTag("ssl", "could not get network client").Wrap(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,9 @@ const (
|
|||||||
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
func (request *Request) Compile(options *protocols.ExecutorOptions) error {
|
||||||
request.options = options
|
request.options = options
|
||||||
|
|
||||||
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{})
|
client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{
|
||||||
|
CustomDialer: options.CustomFastdialer,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not get network client")
|
return errors.Wrap(err, "could not get network client")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/projectdiscovery/gologger"
|
"github.com/projectdiscovery/gologger"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
||||||
|
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils"
|
||||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,17 +64,9 @@ func (g *Generic) ExecuteWithResults(ctx *scan.ScanContext) error {
|
|||||||
// ideally this should never happen since protocol exits on error and callback is not called
|
// ideally this should never happen since protocol exits on error and callback is not called
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ID := req.GetID()
|
|
||||||
if ID != "" {
|
utils.FillPreviousEvent(req.GetID(), event, previous)
|
||||||
builder := &strings.Builder{}
|
|
||||||
for k, v := range event.InternalEvent {
|
|
||||||
builder.WriteString(ID)
|
|
||||||
builder.WriteString("_")
|
|
||||||
builder.WriteString(k)
|
|
||||||
_ = previous.Set(builder.String(), v)
|
|
||||||
builder.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if event.HasOperatorResult() {
|
if event.HasOperatorResult() {
|
||||||
g.results.CompareAndSwap(false, true)
|
g.results.CompareAndSwap(false, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package multiproto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||||
@ -10,6 +9,7 @@ import (
|
|||||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
|
||||||
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
|
||||||
|
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils"
|
||||||
mapsutil "github.com/projectdiscovery/utils/maps"
|
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||||
stringsutil "github.com/projectdiscovery/utils/strings"
|
stringsutil "github.com/projectdiscovery/utils/strings"
|
||||||
)
|
)
|
||||||
@ -90,17 +90,7 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ID := req.GetID()
|
utils.FillPreviousEvent(req.GetID(), event, previous)
|
||||||
if ID != "" {
|
|
||||||
builder := &strings.Builder{}
|
|
||||||
for k, v := range event.InternalEvent {
|
|
||||||
builder.WriteString(ID)
|
|
||||||
builder.WriteString("_")
|
|
||||||
builder.WriteString(k)
|
|
||||||
_ = previous.Set(builder.String(), v)
|
|
||||||
builder.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log event and generate result for the event
|
// log event and generate result for the event
|
||||||
ctx.LogEvent(event)
|
ctx.LogEvent(event)
|
||||||
|
|||||||
34
pkg/tmplexec/utils/utils.go
Normal file
34
pkg/tmplexec/utils/utils.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||||
|
mapsutil "github.com/projectdiscovery/utils/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FillPreviousEvent is a helper function to get the previous event from the event
|
||||||
|
// without leading to duplicate prefixes
|
||||||
|
func FillPreviousEvent(reqID string, event *output.InternalWrappedEvent, previous *mapsutil.SyncLockMap[string, any]) {
|
||||||
|
if reqID == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range event.InternalEvent {
|
||||||
|
if _, ok := previous.Get(k); ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(k, reqID+"_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString(reqID)
|
||||||
|
builder.WriteString("_")
|
||||||
|
builder.WriteString(k)
|
||||||
|
|
||||||
|
_ = previous.Set(builder.String(), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user