diff --git a/modules/http_proxy/http_proxy.go b/modules/http_proxy/http_proxy.go index 150d9c34..003a4b77 100644 --- a/modules/http_proxy/http_proxy.go +++ b/modules/http_proxy/http_proxy.go @@ -54,9 +54,9 @@ func NewHttpProxy(s *session.Session) *HttpProxy { "false", "Enable or disable SSL stripping.")) - mod.AddParam(session.NewBoolParameter("http.proxy.sslstrip.useIDN", - "false", - "Use an Internationalized Domain Name to bypass HSTS. Otherwise, double the last TLD's character")) + mod.AddParam(session.NewStringParameter("http.proxy.sslstrip.replacements", + "com:corn net:nel org:orq", "(.*:.*\\s*$)+", + "Space separated list of ':', and ordered by priority. Use '*' for any domain. Internationalized Domain Names are allowed. If the domain to strip isn't found in this parameter, the last char of the top-level domain will be duplicated.")) mod.AddHandler(session.NewModuleHandler("http.proxy on", "", "Start HTTP proxy.", @@ -95,7 +95,7 @@ func (mod *HttpProxy) Configure() error { var doRedirect bool var scriptPath string var stripSSL bool - var useIDN bool + var replacements string var jsToInject string var blacklist string var whitelist string @@ -114,7 +114,7 @@ func (mod *HttpProxy) Configure() error { return err } else if err, stripSSL = mod.BoolParam("http.proxy.sslstrip"); err != nil { return err - } else if err, useIDN = mod.BoolParam("http.proxy.sslstrip.useIDN"); err != nil { + } else if err, replacements = mod.StringParam("http.proxy.sslstrip.replacements"); err != nil { return err } else if err, jsToInject = mod.StringParam("http.proxy.injectjs"); err != nil { return err @@ -127,7 +127,7 @@ func (mod *HttpProxy) Configure() error { mod.proxy.Blacklist = str.Comma(blacklist) mod.proxy.Whitelist = str.Comma(whitelist) - error := mod.proxy.Configure(address, proxyPort, httpPort, doRedirect, scriptPath, jsToInject, stripSSL, useIDN) + error := mod.proxy.Configure(address, proxyPort, httpPort, doRedirect, scriptPath, jsToInject, stripSSL, replacements) // save stripper to share it with other http(s) proxies mod.State.Store("stripper", mod.proxy.Stripper) diff --git a/modules/http_proxy/http_proxy_base.go b/modules/http_proxy/http_proxy_base.go index b810f864..cff5d2ee 100644 --- a/modules/http_proxy/http_proxy_base.go +++ b/modules/http_proxy/http_proxy_base.go @@ -77,7 +77,7 @@ func NewHTTPProxy(s *session.Session, tag string) *HTTPProxy { Name: "http.proxy", Proxy: goproxy.NewProxyHttpServer(), Sess: s, - Stripper: NewSSLStripper(s, false, false), + Stripper: NewSSLStripper(s, false, ""), isTLS: false, doRedirect: true, Server: nil, @@ -170,7 +170,7 @@ func (p *HTTPProxy) shouldProxy(req *http.Request) bool { } func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, doRedirect bool, scriptPath string, - jsToInject string, stripSSL bool, useIDN bool) error { + jsToInject string, stripSSL bool, replacements string) error { var err error // check if another http(s) proxy is using sslstrip and merge strippers @@ -192,7 +192,7 @@ func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, doRed } } - p.Stripper.Enable(stripSSL, useIDN) + p.Stripper.Enable(stripSSL, replacements) p.Address = address p.doRedirect = doRedirect p.jsHook = "" @@ -297,8 +297,8 @@ func (p *HTTPProxy) TLSConfigFromCA(ca *tls.Certificate) func(host string, ctx * func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, doRedirect bool, scriptPath string, certFile string, - keyFile string, jsToInject string, stripSSL bool, useIDN bool) (err error) { - if err = p.Configure(address, proxyPort, httpPort, doRedirect, scriptPath, jsToInject, stripSSL, useIDN); err != nil { + keyFile string, jsToInject string, stripSSL bool, replacements string) (err error) { + if err = p.Configure(address, proxyPort, httpPort, doRedirect, scriptPath, jsToInject, stripSSL, replacements); err != nil { return err } diff --git a/modules/http_proxy/http_proxy_base_sslstriper.go b/modules/http_proxy/http_proxy_base_sslstriper.go index 39cedbf2..c355b15f 100644 --- a/modules/http_proxy/http_proxy_base_sslstriper.go +++ b/modules/http_proxy/http_proxy_base_sslstriper.go @@ -30,7 +30,7 @@ var ( type SSLStripper struct { enabled bool - useIDN bool + replacements string session *session.Session cookies *CookieTracker hosts *HostTracker @@ -38,16 +38,16 @@ type SSLStripper struct { pktSourceChan chan gopacket.Packet } -func NewSSLStripper(s *session.Session, enabled bool, useIDN bool) *SSLStripper { +func NewSSLStripper(s *session.Session, enabled bool, replacements string) *SSLStripper { strip := &SSLStripper{ - enabled: false, - useIDN: false, + enabled: enabled, + replacements: replacements, cookies: NewCookieTracker(), hosts: NewHostTracker(), session: s, handle: nil, } - strip.Enable(enabled, useIDN) + strip.Enable(enabled, replacements) return strip } @@ -70,7 +70,7 @@ func (s *SSLStripper) onPacket(pkt gopacket.Packet) { domain := string(q.Name) original := s.hosts.Unstrip(domain) if original != nil && original.Address != nil { - redir, who := dns_spoof.DnsReply(s.session, 1024, pkt, eth, udp, domain, original.Address, dns, eth.SrcMAC) + redir, who := dns_spoof.DnsReply(s.session, 5, pkt, eth, udp, domain, original.Address, dns, eth.SrcMAC) if redir != "" && who != "" { log.Debug("[%s] Sending spoofed DNS reply for %s %s to %s.", tui.Green("dns"), tui.Red(domain), tui.Dim(redir), tui.Bold(who)) } @@ -79,9 +79,9 @@ func (s *SSLStripper) onPacket(pkt gopacket.Packet) { } } -func (s *SSLStripper) Enable(enabled bool, useIDN bool) { +func (s *SSLStripper) Enable(enabled bool, replacements string) { s.enabled = enabled - s.useIDN = useIDN + s.replacements = replacements if enabled && s.handle == nil { var err error @@ -141,9 +141,24 @@ func (s *SSLStripper) processURL(url string) string { if iPort == -1 { iPort = iEndHost } - if s.useIDN { - // add an international character to the domain name & strip HTTPS port (if any) - url = url[:iPort] + "ノ" + url[iEndHost:] + // search for domain's part to replace according to the settings + replacement := []string{} + for _, r := range strings.Fields(s.replacements) { + rep := strings.Split(r, ":") + if rep[0] == "*" { + rep[0] = url[:iPort] + } + if strings.Contains(url[:iPort], rep[0]) { + replacement = rep + break + } + } + if len(replacement) != 0{ + // replace domain according to the settings & strip HTTPS port (if any) + url = url[:iPort] + url[iEndHost:] + iReplacement := strings.LastIndex(url, replacement[0]) + replaceto := strings.ReplaceAll(replacement[1], "*", replacement[0]) + url = url[:iReplacement] + replaceto + url[iReplacement+len(replacement[0]):] } else { // double the last TLD's character & strip HTTPS port (if any) url = url[:iPort] + string(url[iPort-1]) + url[iEndHost:] @@ -247,8 +262,8 @@ func (s *SSLStripper) Process(res *http.Response, ctx *goproxy.ProxyCtx) { newHost := location.Host newURL := location.String() - // are we getting redirected from http to https? - if orig.Scheme == "http" && location.Scheme == "https" { + // are we getting redirected to https? + if location.Scheme == "https" { log.Info("[%s] Got redirection from HTTP to HTTPS: %s -> %s", tui.Green("sslstrip"), tui.Yellow("http://"+origHost), tui.Bold("https://"+newHost)) diff --git a/modules/https_proxy/https_proxy.go b/modules/https_proxy/https_proxy.go index fbf3df74..596bbd4f 100644 --- a/modules/https_proxy/https_proxy.go +++ b/modules/https_proxy/https_proxy.go @@ -41,9 +41,9 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy { "false", "Enable or disable SSL stripping.")) - mod.AddParam(session.NewBoolParameter("https.proxy.sslstrip.useIDN", - "false", - "Use an Internationalized Domain Name to bypass HSTS. Otherwise, double the last TLD's character")) + mod.AddParam(session.NewStringParameter("http.proxy.sslstrip.replacements", + "com:corn net:nel org:orq", "(.*:.*\\s*$)+", + "Space separated list of ':', and ordered by priority. Use '*' for any domain. You can use Internationalized Domain Names. If the domain to strip isn't found in this parameter, the last char of the top-level domain will be duplicated.")) mod.AddParam(session.NewStringParameter("https.proxy.injectjs", "", @@ -112,7 +112,7 @@ func (mod *HttpsProxy) Configure() error { var certFile string var keyFile string var stripSSL bool - var useIDN bool + var replacements string var jsToInject string var whitelist string var blacklist string @@ -129,7 +129,7 @@ func (mod *HttpsProxy) Configure() error { return err } else if err, stripSSL = mod.BoolParam("https.proxy.sslstrip"); err != nil { return err - } else if err, useIDN = mod.BoolParam("https.proxy.sslstrip.useIDN"); err != nil { + } else if err, replacements = mod.StringParam("https.proxy.sslstrip.replacements"); err != nil { return err } else if err, certFile = mod.StringParam("https.proxy.certificate"); err != nil { return err @@ -170,7 +170,7 @@ func (mod *HttpsProxy) Configure() error { } error := mod.proxy.ConfigureTLS(address, proxyPort, httpPort, doRedirect, scriptPath, certFile, keyFile, jsToInject, - stripSSL, useIDN) + stripSSL, replacements) // save stripper to share it with other http(s) proxies mod.State.Store("stripper", mod.proxy.Stripper)