Address review feedback:
- Skip Sec-WebSocket-Protocol values containing CR or LF before negotiating
them, since gobwas/ws writes subprotocols into the handshake request line and
a line break could smuggle extra handshake headers.
- Tighten the test server to reject the upgrade unless the client offers the
vite-hmr subprotocol, so the test fails if negotiation does not happen.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The websocket protocol sent a Sec-WebSocket-Protocol header as a raw handshake
header but never set gobwas/ws Dialer.Protocols. gobwas validates the
server-selected subprotocol against Dialer.Protocols and rejects one that was
only sent as a header, so any server that requires and echoes a subprotocol
(e.g. a Vite HMR dev server advertising "vite-hmr") failed the handshake with
"unexpected protocol in Sec-WebSocket-Protocol header".
Route a Sec-WebSocket-Protocol request header into Dialer.Protocols (comma
splitting, trimming) instead of the raw header map, so the subprotocol is
offered in the handshake and the server's echo is accepted. Adds a regression
test with a server that only upgrades when "vite-hmr" is negotiated.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
go.mod takes dev's versions, including fastdialer v0.5.25, and keeps
fastdialer replaced by the branch of projectdiscovery/fastdialer#580,
which now includes v0.5.25.
Scanning a vhost on a given server, or an origin behind a CDN, needs the
hostname in the Host header, SNI and template variables while the
connection goes to another ip, and one host often has to be scanned on
several ips. -sa scans the ips DNS returns, and a target of the ip with
a Host header sends no SNI and sets {{Hostname}} to the ip.
A target line can now pin its target to an ip, like curl --resolve:
{"target": "https://app.example", "ip": "192.0.2.10"}
Each target and ip pair is a separate target with its own template
selection. The ip is validated and canonicalized, the target must have
a hostname, -sa and -iv don't resolve a pinned target, and an ip the
network policy denies is skipped. Pinned targets are refused with
-proxy and -automatic-scan.
The engine pins the host of every target with a CustomIP, from a target
line or -sa, with fastdialer.WithResolveOverride on the context each
template runs with. HTTP, network, websocket and javascript templates
then connect to the ip, while redirects to other hosts and the proxy
dial are no longer pinned. HTTP keeps a client per pinned ip, network
and websocket results report the ip, and scheme-less targets are probed
through it.
The host errors cache keys a failed dial of a pinned target by its ip,
also for IDN hosts, and -mup counts the urls of each ip apart, so a url
listed with several ips, or resolved to several with -sa, is kept on
each of them.
go.mod points fastdialer at a fork commit with WithResolveOverride until
a fastdialer release includes it.
Pass scan options through rendering, variables, matchers, and extractors
so resolve(), public_ip()/publicip(), and jarm() honor -lna and -eh.
These helpers previously performed network I/O outside the scan's network
policy.
Use the scan dialer for HTTP and JARM connections and reject restricted
IP addresses in DNS answers. Validate original and normalized hostnames
to prevent exclusion bypasses through DNS escapes and trailing dots.
Enforce -eh with or without -lna, including in unsigned templates.
Keep local access available without -lna unless excluded, and preserve
configured DNS resolvers, including local ones.
Bind helpers at evaluation time without storing scan state in cached
expressions. Reject network helper calls without initialized scan
context.
Fixes#7769
Signed-off-by: Dwi Siswanto <[email protected]>
* refactor(protocols): template rendering boundary
Stop treating every marker-shaped string as
template source after it has entered runtime data.
Template-authored text is rendered once, while
values from payload results, previous responses,
overrides, constants, and rendered outputs stay as
data.
Route protocol payload rendering through a shared
render boundary. Authored Interactsh markers still
allocate OAST URLs, including when helper-
transformed, but runtime marker-shaped values stay
literal and do not allocate stale URLs or trigger
another DSL pass.
Keep the same boundary inside helper expressions.
Placeholders embedded in authored govaluate string
literals are escaped before compilation, so a
value used by `{{contains('{{body}}', 'x')}}`
cannot become new expression syntax.
Track fuzz value provenance explicitly instead of
inferring it from merged map values, and share
govaluate string escaping with the matcher
fallback.
Signed-off-by: Dwi Siswanto <[email protected]>
* Update pkg/protocols/websocket/websocket.go
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* refactor(variables): preserve ownership across eval
Carry variable inputs thru an owner-aware scope
instead of merging template text and runtime data
into the same plain map before eval.
This keeps declared template variables renderable
when later values satisfy their dependencies,
while keeping runtime, extracted, previous, option,
constant, and generated values as terminal data.
A dynamic value can still shadow a declared
variable (though), but the selected value is not
eval'ed again and does not allocate Interactsh
URLs.
Store template-owned values separately in template
context so flow and multiprotocol execution can
reuse declared variable text w/o turning
extracted data into template source.
Migrate fuzz, HTTP, JavaScript, network, headless,
code, DNS, SSL, websocket, whois, flow, and
multiprotocol paths to the owner-aware evaluation
path, and add regressions for equal-value
overrides, lazy declared variables, Interactsh
allocation, and context ownership.
Signed-off-by: Dwi Siswanto <[email protected]>
* fix(protocols): keep interactsh render state explicit
Do not let Interactsh allocation failures
disappear behind a successful render. Return the
partial render state with the error so callers can
keep URLs that were already allocated, and fix the
encoded marker regexp so `|` is not treated as a
brace digit.
Preserve caller-provided Interactsh URLs in fuzz
execution, propagate payload render errors, and
avoid persisting network precompile output when
data introduces a marker that runtime would later
treat as source.
Also keep previous/template-context values in SSL,
WebSocket, and WHOIS render scopes, and make
multiproto compile retain constants and CLI vars
as read-only data without marking them as
template-owned values.
Signed-off-by: Dwi Siswanto <[email protected]>
* refactor(render): centralize interactsh marker scanning
Move default interactsh marker detection into the
common marker pkg and use a small scanner instead
of duplicated regexes in render and interactsh.
Raw and fully URL-encoded markers still work, but
mixed raw/encoded brace pairs and bad numeric
suffixes are rejected.
Keep partially rendered map values when `RenderMap`
stops on an error.
Signed-off-by: Dwi Siswanto <[email protected]>
---------
Signed-off-by: Dwi Siswanto <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Use proxy for dns and ssl templates
- while using template execute level function we need to override custom dialer
* rename overridedialer to customdialer
* Add proxy into hash
- proxy client is shared between non proxy requests
* add dialer into request object
- use request.dialer instead of global variable
* resolve comments
* rename dialer
* introduce `template-encoded` field
* remove IsCustomTemplate func
* refactor and move encoding to `MakeResultEventItem` func
* encode template in case of no results were found
* commit to last commit
* don't encode templates when`-ms` is used