github.com/projectdiscovery/nuclei/v2@v2.9.15/pkg/protocols/utils/variables.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "path" 6 "strings" 7 8 "github.com/projectdiscovery/gologger" 9 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs" 10 "github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/generators" 11 maputil "github.com/projectdiscovery/utils/maps" 12 urlutil "github.com/projectdiscovery/utils/url" 13 "github.com/weppos/publicsuffix-go/publicsuffix" 14 ) 15 16 // KnownVariables are the variables that are known to input requests 17 var KnownVariables maputil.Map[KnownVariable, string] 18 19 func init() { 20 KnownVariables = maputil.Map[KnownVariable, string]{ 21 BaseURL: "BaseURL", 22 RootURL: "RootURL", 23 Hostname: "Hostname", 24 Host: "Host", 25 Port: "Port", 26 Path: "Path", 27 File: "File", 28 Scheme: "Scheme", 29 Input: "Input", 30 Fqdn: "FQDN", 31 Rdn: "RDN", 32 Dn: "DN", 33 Tld: "TLD", 34 Sd: "SD", 35 } 36 } 37 38 type KnownVariable uint16 39 40 const ( 41 BaseURL KnownVariable = iota 42 RootURL 43 Hostname 44 Host 45 Port 46 Path 47 File 48 Scheme 49 Input 50 Fqdn 51 Rdn 52 Dn 53 Tld 54 Sd 55 ) 56 57 // GenerateVariables will create default variables with context args 58 func GenerateVariablesWithContextArgs(input *contextargs.Context, trailingSlash bool) map[string]interface{} { 59 parsed, err := urlutil.Parse(input.MetaInput.Input) 60 if err != nil { 61 return nil 62 } 63 return GenerateVariables(parsed, trailingSlash, contextargs.GenerateVariables(input)) 64 } 65 66 // GenerateDNSVariables from a dns name 67 // This function is used by dns and ssl protocol to generate variables 68 func GenerateDNSVariables(domain string) map[string]interface{} { 69 parsed, err := publicsuffix.Parse(strings.TrimSuffix(domain, ".")) 70 if err != nil { 71 return map[string]interface{}{"FQDN": domain} 72 } 73 74 domainName := strings.Join([]string{parsed.SLD, parsed.TLD}, ".") 75 dnsVariables := make(map[string]interface{}) 76 for k, v := range KnownVariables { 77 switch k { 78 case Fqdn: 79 dnsVariables[v] = domain 80 case Rdn: 81 dnsVariables[v] = domainName 82 case Dn: 83 dnsVariables[v] = parsed.SLD 84 case Tld: 85 dnsVariables[v] = parsed.TLD 86 case Sd: 87 dnsVariables[v] = parsed.TRD 88 } 89 } 90 return dnsVariables 91 } 92 93 // GenerateVariables accepts string or *urlutil.URL object as input 94 // Returns the map of KnownVariables keys 95 // This function is used by http, headless, websocket, network and whois protocols to generate protocol variables 96 func GenerateVariables(input interface{}, removeTrailingSlash bool, additionalVars map[string]interface{}) map[string]interface{} { 97 var vars = make(map[string]interface{}) 98 switch input := input.(type) { 99 case string: 100 parsed, err := urlutil.Parse(input) 101 if err != nil { 102 return map[string]interface{}{KnownVariables[Input]: input, KnownVariables[Hostname]: input} 103 } 104 vars = generateVariables(parsed, removeTrailingSlash) 105 case *urlutil.URL: 106 vars = generateVariables(input, removeTrailingSlash) 107 case urlutil.URL: 108 vars = generateVariables(&input, removeTrailingSlash) 109 default: 110 // return a non-fatal error 111 gologger.Error().Msgf("unknown type %T for input %v", input, input) 112 } 113 return generators.MergeMaps(vars, additionalVars) 114 } 115 116 func generateVariables(inputURL *urlutil.URL, removeTrailingSlash bool) map[string]interface{} { 117 parsed := inputURL.Clone() 118 parsed.Params = urlutil.NewOrderedParams() 119 port := parsed.Port() 120 if port == "" { 121 if parsed.Scheme == "https" { 122 port = "443" 123 } else if parsed.Scheme == "http" { 124 port = "80" 125 } 126 } 127 if removeTrailingSlash { 128 parsed.Path = strings.TrimSuffix(parsed.Path, "/") 129 } 130 escapedPath := parsed.EscapedPath() 131 requestPath := path.Dir(escapedPath) 132 if requestPath == "." { 133 requestPath = "" 134 } 135 136 base := path.Base(escapedPath) 137 if base == "." { 138 base = "" 139 } 140 141 if parsed.Scheme == "ws" { 142 if values := urlutil.GetParams(parsed.URL.Query()); len(values) > 0 { 143 requestPath = escapedPath + "?" + values.Encode() 144 } 145 } 146 knownVariables := make(map[string]interface{}) 147 for k, v := range KnownVariables { 148 switch k { 149 case BaseURL: 150 knownVariables[v] = parsed.String() 151 case RootURL: 152 knownVariables[v] = fmt.Sprintf("%s://%s", parsed.Scheme, parsed.Host) 153 case Hostname: 154 knownVariables[v] = parsed.Host 155 case Host: 156 knownVariables[v] = parsed.Hostname() 157 case Port: 158 knownVariables[v] = port 159 case Path: 160 knownVariables[v] = requestPath 161 case File: 162 knownVariables[v] = base 163 case Scheme: 164 knownVariables[v] = parsed.Scheme 165 case Input: 166 knownVariables[v] = parsed.String() 167 } 168 } 169 return generators.MergeMaps(knownVariables, GenerateDNSVariables(parsed.Hostname())) 170 }