mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 17:35:26 +00:00
Adding SNI override via request annotations (#1970)
* Adding SNI override via request annotations * adding cli flag priority
This commit is contained in:
parent
6ca4374f91
commit
39c7317ec3
18
integration_tests/http/get-override-sni.yaml
Normal file
18
integration_tests/http/get-override-sni.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
id: basic-raw-http-example
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: Test RAW GET Template
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
|
||||||
|
requests:
|
||||||
|
- raw:
|
||||||
|
- |
|
||||||
|
@tls-sni:request.host
|
||||||
|
GET / HTTP/1.1
|
||||||
|
Host: test
|
||||||
|
|
||||||
|
matchers:
|
||||||
|
- type: word
|
||||||
|
words:
|
||||||
|
- "test-ok"
|
||||||
@ -48,6 +48,7 @@ var httpTestcases = map[string]testutils.TestCase{
|
|||||||
"http/stop-at-first-match.yaml": &httpStopAtFirstMatch{},
|
"http/stop-at-first-match.yaml": &httpStopAtFirstMatch{},
|
||||||
"http/stop-at-first-match-with-extractors.yaml": &httpStopAtFirstMatchWithExtractors{},
|
"http/stop-at-first-match-with-extractors.yaml": &httpStopAtFirstMatchWithExtractors{},
|
||||||
"http/variables.yaml": &httpVariables{},
|
"http/variables.yaml": &httpVariables{},
|
||||||
|
"http/get-override-sni.yaml": &httpSniAnnotation{},
|
||||||
"http/get-sni.yaml": &customCLISNI{},
|
"http/get-sni.yaml": &customCLISNI{},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,3 +834,25 @@ func (h *customCLISNI) Execute(filePath string) error {
|
|||||||
}
|
}
|
||||||
return expectResultsCount(results, 1)
|
return expectResultsCount(results, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type httpSniAnnotation struct{}
|
||||||
|
|
||||||
|
// Execute executes a test case and returns an error if occurred
|
||||||
|
func (h *httpSniAnnotation) Execute(filePath string) error {
|
||||||
|
router := httprouter.New()
|
||||||
|
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
if r.TLS.ServerName == "test" {
|
||||||
|
_, _ = w.Write([]byte("test-ok"))
|
||||||
|
} else {
|
||||||
|
_, _ = w.Write([]byte("test-ko"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ts := httptest.NewTLSServer(router)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return expectResultsCount(results, 1)
|
||||||
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/projectdiscovery/clistats v0.0.8
|
github.com/projectdiscovery/clistats v0.0.8
|
||||||
github.com/projectdiscovery/cryptoutil v1.0.0
|
github.com/projectdiscovery/cryptoutil v1.0.0
|
||||||
github.com/projectdiscovery/fastdialer v0.0.15-0.20220127193345-f06b0fd54d47
|
github.com/projectdiscovery/fastdialer v0.0.16-0.20220509174423-0e57a7c8cf83
|
||||||
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08
|
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08
|
||||||
github.com/projectdiscovery/fileutil v0.0.0-20220427234316-40b2541a84b8
|
github.com/projectdiscovery/fileutil v0.0.0-20220427234316-40b2541a84b8
|
||||||
github.com/projectdiscovery/goflags v0.0.8-0.20220412061559-5119d6086323
|
github.com/projectdiscovery/goflags v0.0.8-0.20220412061559-5119d6086323
|
||||||
|
|||||||
@ -437,6 +437,8 @@ github.com/projectdiscovery/cryptoutil v1.0.0/go.mod h1:VJvSNE8f8A1MgpjgAL2GPJSQ
|
|||||||
github.com/projectdiscovery/fastdialer v0.0.12/go.mod h1:RkRbxqDCcCFhfNUbkzBIz/ieD4uda2JuUA4WJ+RLee0=
|
github.com/projectdiscovery/fastdialer v0.0.12/go.mod h1:RkRbxqDCcCFhfNUbkzBIz/ieD4uda2JuUA4WJ+RLee0=
|
||||||
github.com/projectdiscovery/fastdialer v0.0.15-0.20220127193345-f06b0fd54d47 h1:TUsZiwez9uFmph1hlTsiH7rdB+wi4524+lMuV2z6FaM=
|
github.com/projectdiscovery/fastdialer v0.0.15-0.20220127193345-f06b0fd54d47 h1:TUsZiwez9uFmph1hlTsiH7rdB+wi4524+lMuV2z6FaM=
|
||||||
github.com/projectdiscovery/fastdialer v0.0.15-0.20220127193345-f06b0fd54d47/go.mod h1:GbQvP1ezGlQn0af3lVcl08b5eRQu960T7A9pwazybSo=
|
github.com/projectdiscovery/fastdialer v0.0.15-0.20220127193345-f06b0fd54d47/go.mod h1:GbQvP1ezGlQn0af3lVcl08b5eRQu960T7A9pwazybSo=
|
||||||
|
github.com/projectdiscovery/fastdialer v0.0.16-0.20220509174423-0e57a7c8cf83 h1:1hzvl0lsWpvQ8nn1s9YMyBjO13/Z+f/T4W2jroOohfo=
|
||||||
|
github.com/projectdiscovery/fastdialer v0.0.16-0.20220509174423-0e57a7c8cf83/go.mod h1:wn6jSJ1fIO6kLplFEbFIkRB6Kj/Q6VngnzKuBHLVPiI=
|
||||||
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08 h1:NwD1R/du1dqrRKN3SJl9kT6tN3K9puuWFXEvYF2ihew=
|
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08 h1:NwD1R/du1dqrRKN3SJl9kT6tN3K9puuWFXEvYF2ihew=
|
||||||
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08/go.mod h1:paLCnwV8sL7ppqIwVQodQrk3F6mnWafwTDwRd7ywZwQ=
|
github.com/projectdiscovery/filekv v0.0.0-20210915124239-3467ef45dd08/go.mod h1:paLCnwV8sL7ppqIwVQodQrk3F6mnWafwTDwRd7ywZwQ=
|
||||||
github.com/projectdiscovery/fileutil v0.0.0-20210914153648-31f843feaad4/go.mod h1:U+QCpQnX8o2N2w0VUGyAzjM3yBAe4BKedVElxiImsx0=
|
github.com/projectdiscovery/fileutil v0.0.0-20210914153648-31f843feaad4/go.mod h1:U+QCpQnX8o2N2w0VUGyAzjM3yBAe4BKedVElxiImsx0=
|
||||||
|
|||||||
@ -21,6 +21,7 @@ func Init(options *types.Options) error {
|
|||||||
}
|
}
|
||||||
opts.WithDialerHistory = true
|
opts.WithDialerHistory = true
|
||||||
opts.WithZTLS = options.ZTLS
|
opts.WithZTLS = options.ZTLS
|
||||||
|
opts.SNIName = options.SNI
|
||||||
dialer, err := fastdialer.NewDialer(opts)
|
dialer, err := fastdialer.NewDialer(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not create dialer")
|
return errors.Wrap(err, "could not create dialer")
|
||||||
|
|||||||
@ -41,6 +41,7 @@ func newHttpClient(options *types.Options) (*http.Client, error) {
|
|||||||
|
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
DialContext: dialer.Dial,
|
DialContext: dialer.Dial,
|
||||||
|
DialTLSContext: dialer.DialTLS,
|
||||||
MaxIdleConns: 500,
|
MaxIdleConns: 500,
|
||||||
MaxIdleConnsPerHost: 500,
|
MaxIdleConnsPerHost: 500,
|
||||||
MaxConnsPerHost: 500,
|
MaxConnsPerHost: 500,
|
||||||
|
|||||||
@ -290,7 +290,10 @@ func (r *requestGenerator) handleRawWithPayloads(ctx context.Context, rawRequest
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parseAnnotations(rawRequest, req)
|
if reqWithAnnotations, hasAnnotations := parseAnnotations(rawRequest, req); hasAnnotations {
|
||||||
|
req = reqWithAnnotations
|
||||||
|
request = request.WithContext(req.Context())
|
||||||
|
}
|
||||||
|
|
||||||
return &generatedRequest{request: request, meta: generatorValues, original: r.request, dynamicValues: finalValues, interactshURLs: r.interactshURLs}, nil
|
return &generatedRequest{request: request, meta: generatorValues, original: r.request, dynamicValues: finalValues, interactshURLs: r.interactshURLs}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -191,6 +191,7 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
|
|||||||
|
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
DialContext: Dialer.Dial,
|
DialContext: Dialer.Dial,
|
||||||
|
DialTLSContext: Dialer.DialTLS,
|
||||||
MaxIdleConns: maxIdleConns,
|
MaxIdleConns: maxIdleConns,
|
||||||
MaxIdleConnsPerHost: maxIdleConnsPerHost,
|
MaxIdleConnsPerHost: maxIdleConnsPerHost,
|
||||||
MaxConnsPerHost: maxConnsPerHost,
|
MaxConnsPerHost: maxConnsPerHost,
|
||||||
|
|||||||
@ -1,22 +1,33 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/projectdiscovery/fastdialer/fastdialer"
|
||||||
"github.com/projectdiscovery/iputil"
|
"github.com/projectdiscovery/iputil"
|
||||||
"github.com/projectdiscovery/stringsutil"
|
"github.com/projectdiscovery/stringsutil"
|
||||||
"github.com/projectdiscovery/urlutil"
|
"github.com/projectdiscovery/urlutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Host:target overrides the input target with the annotated one (similar to self-contained requests)
|
var (
|
||||||
var reHostAnnotation = regexp.MustCompile(`(?m)^@Host:\s*(.+)\s*$`)
|
// @Host:target overrides the input target with the annotated one (similar to self-contained requests)
|
||||||
|
reHostAnnotation = regexp.MustCompile(`(?m)^@Host:\s*(.+)\s*$`)
|
||||||
|
// @tls-sni:target overrides the input target with the annotated one
|
||||||
|
// special values:
|
||||||
|
// request.host: takes the value from the host header
|
||||||
|
// target: overiddes with the specific value
|
||||||
|
reSniAnnotation = regexp.MustCompile(`(?m)^@tls-sni:\s*(.+)\s*$`)
|
||||||
|
)
|
||||||
|
|
||||||
// parseAnnotations and override requests settings
|
// parseAnnotations and override requests settings
|
||||||
func parseAnnotations(rawRequest string, request *http.Request) {
|
func parseAnnotations(rawRequest string, request *http.Request) (*http.Request, bool) {
|
||||||
// parse request for known ovverride annotations
|
// parse request for known ovverride annotations
|
||||||
|
var modified bool
|
||||||
|
// @Host:target
|
||||||
if hosts := reHostAnnotation.FindStringSubmatch(rawRequest); len(hosts) > 0 {
|
if hosts := reHostAnnotation.FindStringSubmatch(rawRequest); len(hosts) > 0 {
|
||||||
value := strings.TrimSpace(hosts[1])
|
value := strings.TrimSpace(hosts[1])
|
||||||
// handle scheme
|
// handle scheme
|
||||||
@ -39,7 +50,25 @@ func parseAnnotations(rawRequest string, request *http.Request) {
|
|||||||
}
|
}
|
||||||
request.URL.Host = hostPort
|
request.URL.Host = hostPort
|
||||||
}
|
}
|
||||||
|
modified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @tls-sni:target
|
||||||
|
if hosts := reSniAnnotation.FindStringSubmatch(rawRequest); len(hosts) > 0 {
|
||||||
|
value := strings.TrimSpace(hosts[1])
|
||||||
|
value = stringsutil.TrimPrefixAny(value, "http://", "https://")
|
||||||
|
if idxForwardSlash := strings.Index(value, "/"); idxForwardSlash >= 0 {
|
||||||
|
value = value[:idxForwardSlash]
|
||||||
|
}
|
||||||
|
|
||||||
|
if stringsutil.EqualFoldAny(value, "request.host") {
|
||||||
|
value = request.Host
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(request.Context(), fastdialer.SniName, value)
|
||||||
|
request = request.Clone(ctx)
|
||||||
|
modified = true
|
||||||
|
}
|
||||||
|
return request, modified
|
||||||
}
|
}
|
||||||
|
|
||||||
func isHostPort(value string) bool {
|
func isHostPort(value string) bool {
|
||||||
|
|||||||
@ -63,6 +63,7 @@ func New(option *Options) (*Exporter, error) {
|
|||||||
MaxIdleConns: 10,
|
MaxIdleConns: 10,
|
||||||
MaxIdleConnsPerHost: 10,
|
MaxIdleConnsPerHost: 10,
|
||||||
DialContext: protocolstate.Dialer.Dial,
|
DialContext: protocolstate.Dialer.Dial,
|
||||||
|
DialTLSContext: protocolstate.Dialer.DialTLS,
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: option.SSLVerification},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: option.SSLVerification},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user