nuclei/v2/pkg/protocols/http/request_annotations.go

84 lines
2.2 KiB
Go
Raw Normal View History

2022-04-04 09:32:41 +02:00
package http
import (
"context"
2022-04-13 17:41:02 +02:00
"net"
2022-04-04 09:32:41 +02:00
"net/http"
"regexp"
"strings"
2022-04-13 17:41:02 +02:00
"github.com/projectdiscovery/fastdialer/fastdialer"
2022-04-13 17:41:02 +02:00
"github.com/projectdiscovery/iputil"
"github.com/projectdiscovery/stringsutil"
"github.com/projectdiscovery/urlutil"
2022-04-04 09:32:41 +02:00
)
var (
// @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*$`)
)
2022-04-04 09:32:41 +02:00
// parseAnnotations and override requests settings
func parseAnnotations(rawRequest string, request *http.Request) (*http.Request, bool) {
2022-04-04 09:32:41 +02:00
// parse request for known ovverride annotations
var modified bool
// @Host:target
2022-04-04 09:32:41 +02:00
if hosts := reHostAnnotation.FindStringSubmatch(rawRequest); len(hosts) > 0 {
2022-04-13 17:41:02 +02:00
value := strings.TrimSpace(hosts[1])
// handle scheme
switch {
case stringsutil.HasPrefixI(value, "http://"):
request.URL.Scheme = urlutil.HTTP
case stringsutil.HasPrefixI(value, "https://"):
request.URL.Scheme = urlutil.HTTPS
}
value = stringsutil.TrimPrefixAny(value, "http://", "https://")
if isHostPort(value) {
request.URL.Host = value
2022-04-14 12:59:21 +02:00
} else {
hostPort := value
port := request.URL.Port()
if port != "" {
hostPort = net.JoinHostPort(hostPort, port)
}
request.URL.Host = hostPort
2022-04-13 17:41:02 +02:00
}
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
2022-04-13 17:41:02 +02:00
}
return request, modified
2022-04-13 17:41:02 +02:00
}
func isHostPort(value string) bool {
_, port, err := net.SplitHostPort(value)
if err != nil {
return false
}
if !iputil.IsPort(port) {
return false
2022-04-04 09:32:41 +02:00
}
2022-04-13 17:41:02 +02:00
return true
2022-04-04 09:32:41 +02:00
}