mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-09 04:09:43 -10:00
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]>
137 lines
4.3 KiB
Go
137 lines
4.3 KiB
Go
// Package render centralizes rendering of template text with runtime values.
|
|
package render
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/marker"
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
|
)
|
|
|
|
// Values contains render values. Values are inserted as data; they are not
|
|
// scanned as new template text after insertion.
|
|
type Values = map[string]interface{}
|
|
|
|
// URLSource allocates URLs for Interactsh markers found in template text.
|
|
type URLSource interface {
|
|
NewURLWithData(data string) (string, error)
|
|
}
|
|
|
|
// Input describes a render operation. Text is template text, Values are data,
|
|
// and Interactsh is optional source-level marker handling.
|
|
type Input struct {
|
|
// Options supplies scan authority separately from template-controlled values.
|
|
Options *types.Options
|
|
Text string
|
|
Values Values
|
|
Interactsh URLSource
|
|
InteractURLs []string
|
|
}
|
|
|
|
// Result is the terminal rendered data and any Interactsh URLs allocated while
|
|
// rendering template text.
|
|
type Result struct {
|
|
Text string
|
|
InteractURLs []string
|
|
}
|
|
|
|
// MapInput describes a map render operation. Source values are template text.
|
|
// Data values are terminal data that override Source and are not rendered.
|
|
type MapInput struct {
|
|
Options *types.Options
|
|
Source Values
|
|
Data Values
|
|
// Values is the evaluation context used while rendering Source.
|
|
Values Values
|
|
// Interactsh and InteractURLs carry source-level Interactsh allocations.
|
|
Interactsh URLSource
|
|
InteractURLs []string
|
|
}
|
|
|
|
// MapResult contains the complete value map after Source rendering and Data
|
|
// overlay, plus any Interactsh URLs allocated while rendering Source values.
|
|
type MapResult struct {
|
|
Values Values
|
|
InteractURLs []string
|
|
}
|
|
|
|
// Render evaluates template text with values and returns rendered data.
|
|
//
|
|
// Interactsh markers in Text are source-level render effects and are allocated
|
|
// before DSL helper evaluation, so helper transforms apply to generated URLs.
|
|
// Values are data and rendered output is terminal data; neither is rescanned for
|
|
// DSL expressions or Interactsh markers.
|
|
func Render(input Input) (Result, error) {
|
|
prepared, err := ReplaceInteractshMarkers(input.Text, input.Interactsh, input.InteractURLs)
|
|
if err != nil {
|
|
return prepared, err
|
|
}
|
|
|
|
result, err := expressions.EvaluateWithOptions(prepared.Text, input.Values, input.Options)
|
|
if err != nil {
|
|
return prepared, err
|
|
}
|
|
|
|
return Result{Text: result, InteractURLs: prepared.InteractURLs}, nil
|
|
}
|
|
|
|
// RenderMap renders Source values as template text, overlays Data values, and
|
|
// returns a complete value map. Data keys are skipped while rendering so they
|
|
// cannot produce DSL or Interactsh side effects.
|
|
//
|
|
// It is intended for already-expanded payload iteration maps, not raw payload
|
|
// definitions containing lists.
|
|
func RenderMap(input MapInput) (MapResult, error) {
|
|
values := make(Values, len(input.Source)+len(input.Data))
|
|
urls := append([]string(nil), input.InteractURLs...)
|
|
|
|
for key, value := range input.Source {
|
|
if _, ok := input.Data[key]; ok {
|
|
continue
|
|
}
|
|
|
|
result, err := Render(Input{
|
|
Options: input.Options,
|
|
Text: fmt.Sprint(value),
|
|
Values: input.Values,
|
|
Interactsh: input.Interactsh,
|
|
InteractURLs: urls,
|
|
})
|
|
if err != nil {
|
|
return MapResult{Values: values, InteractURLs: result.InteractURLs}, err
|
|
}
|
|
|
|
values[key] = result.Text
|
|
urls = result.InteractURLs
|
|
}
|
|
|
|
for key, value := range input.Data {
|
|
values[key] = value
|
|
}
|
|
|
|
return MapResult{Values: values, InteractURLs: urls}, nil
|
|
}
|
|
|
|
// ReplaceInteractshMarkers allocates Interactsh URLs for markers that appear in
|
|
// template text. It does not evaluate DSL expressions or inspect values.
|
|
func ReplaceInteractshMarkers(text string, source URLSource, interactURLs []string) (Result, error) {
|
|
urls := append([]string(nil), interactURLs...)
|
|
if source == nil {
|
|
return Result{Text: text, InteractURLs: urls}, nil
|
|
}
|
|
|
|
for _, interactshURLMarker := range marker.FindInteractshURLMarkers(text) {
|
|
url, err := source.NewURLWithData(interactshURLMarker)
|
|
if err != nil {
|
|
return Result{Text: text, InteractURLs: urls}, fmt.Errorf("replace interactsh marker %q: %w", interactshURLMarker, err)
|
|
}
|
|
|
|
urls = append(urls, url)
|
|
text = strings.Replace(text, interactshURLMarker, url, 1)
|
|
}
|
|
|
|
return Result{Text: text, InteractURLs: urls}, nil
|
|
}
|