diff --git a/modules/http_proxy.go b/modules/http_proxy.go index 002a1fb8..0218157c 100644 --- a/modules/http_proxy.go +++ b/modules/http_proxy.go @@ -33,6 +33,10 @@ func NewHttpProxy(s *session.Session) *HttpProxy { "", "Path of a proxy JS script.")) + p.AddParam(session.NewBoolParameter("http.proxy.sslstrip", + "true", + "Enable or disable SSL stripping.")) + p.AddHandler(session.NewModuleHandler("http.proxy on", "", "Start HTTP proxy.", func(args []string) error { @@ -66,6 +70,7 @@ func (p *HttpProxy) Configure() error { var proxyPort int var httpPort int var scriptPath string + var stripSSL bool if p.Running() == true { return session.ErrAlreadyStarted @@ -77,9 +82,11 @@ func (p *HttpProxy) Configure() error { return err } else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil { return err + } else if err, stripSSL = p.BoolParam("http.proxy.sslstrip"); err != nil { + return err } - return p.proxy.Configure(address, proxyPort, httpPort, scriptPath) + return p.proxy.Configure(address, proxyPort, httpPort, scriptPath, stripSSL) } func (p *HttpProxy) Start() error { diff --git a/modules/http_proxy_base.go b/modules/http_proxy_base.go index 37800978..9d92a6f0 100644 --- a/modules/http_proxy_base.go +++ b/modules/http_proxy_base.go @@ -42,6 +42,7 @@ type HTTPProxy struct { isTLS bool isRunning bool + stripSSL bool sniListener net.Listener sess *session.Session } @@ -56,11 +57,12 @@ func stripPort(s string) string { func NewHTTPProxy(s *session.Session) *HTTPProxy { p := &HTTPProxy{ - Name: "http.proxy", - Proxy: goproxy.NewProxyHttpServer(), - sess: s, - isTLS: false, - Server: nil, + Name: "http.proxy", + Proxy: goproxy.NewProxyHttpServer(), + sess: s, + isTLS: false, + stripSSL: true, + Server: nil, } p.Proxy.Verbose = false @@ -77,71 +79,12 @@ func NewHTTPProxy(s *session.Session) *HTTPProxy { }) p.Proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm) - p.Proxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { - log.Debug("(%s) < %s %s %s%s", core.Green(p.Name), req.RemoteAddr, req.Method, req.Host, req.URL.Path) - if p.Script != nil { - jsreq, jsres := p.Script.OnRequest(req) - if jsreq != nil { - p.logRequestAction(req, jsreq) - return jsreq.ToRequest(), nil - } else if jsres != nil { - p.logResponseAction(req, jsres) - return req, jsres.ToResponse(req) - } - } - return req, nil - }) - - p.Proxy.OnResponse().DoFunc(func(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response { - if res != nil { - req := res.Request - log.Debug("(%s) > %s %s %s%s", core.Green(p.Name), req.RemoteAddr, req.Method, req.Host, req.URL.Path) - if p.Script != nil { - _, jsres := p.Script.OnResponse(res) - if jsres != nil { - p.logResponseAction(res.Request, jsres) - return jsres.ToResponse(res.Request) - } - } - } - return res - }) + p.Proxy.OnRequest().DoFunc(p.onRequestFilter) + p.Proxy.OnResponse().DoFunc(p.onResponseFilter) return p } -func (p *HTTPProxy) logRequestAction(req *http.Request, jsreq *JSRequest) { - p.sess.Events.Add(p.Name+".spoofed-request", struct { - To string - Method string - Host string - Path string - Size int - }{ - strings.Split(req.RemoteAddr, ":")[0], - jsreq.Method, - jsreq.Hostname, - jsreq.Path, - len(jsreq.Body), - }) -} - -func (p *HTTPProxy) logResponseAction(req *http.Request, jsres *JSResponse) { - p.sess.Events.Add(p.Name+".spoofed-response", struct { - To string - Method string - Host string - Path string - Size int - }{ - strings.Split(req.RemoteAddr, ":")[0], - req.Method, - req.Host, - req.URL.Path, - len(jsres.Body), - }) -} - func (p *HTTPProxy) doProxy(req *http.Request) bool { blacklist := []string{ "localhost", @@ -163,9 +106,10 @@ func (p *HTTPProxy) doProxy(req *http.Request) bool { return true } -func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scriptPath string) error { +func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scriptPath string, stripSSL bool) error { var err error + p.stripSSL = stripSSL p.Address = address if scriptPath != "" { @@ -236,9 +180,8 @@ func TLSConfigFromCA(ca *tls.Certificate) func(host string, ctx *goproxy.ProxyCt } } -func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, scriptPath string, certFile string, keyFile string) error { - err := p.Configure(address, proxyPort, httpPort, scriptPath) - if err != nil { +func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, scriptPath string, certFile string, keyFile string, stripSSL bool) (err error) { + if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil { return err } @@ -249,7 +192,6 @@ func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, sc rawCert, _ := ioutil.ReadFile(p.CertFile) rawKey, _ := ioutil.ReadFile(p.KeyFile) - ourCa, err := tls.X509KeyPair(rawCert, rawKey) if err != nil { return err diff --git a/modules/http_proxy_base_filters.go b/modules/http_proxy_base_filters.go new file mode 100644 index 00000000..d43a9ee8 --- /dev/null +++ b/modules/http_proxy_base_filters.go @@ -0,0 +1,90 @@ +package modules + +import ( + "net/http" + "strings" + + "github.com/bettercap/bettercap/core" + "github.com/bettercap/bettercap/log" + + "github.com/elazarl/goproxy" +) + +func (p *HTTPProxy) onRequestFilter(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { + log.Debug("(%s) < %s %s %s%s", core.Green(p.Name), req.RemoteAddr, req.Method, req.Host, req.URL.Path) + + // do we have a proxy script? + if p.Script == nil { + return req, nil + } + + // run the module OnRequest callback if defined + jsreq, jsres := p.Script.OnRequest(req) + if jsreq != nil { + // the request has been changed by the script + p.logRequestAction(req, jsreq) + return jsreq.ToRequest(), nil + } else if jsres != nil { + // a fake response has been returned by the script + p.logResponseAction(req, jsres) + return req, jsres.ToResponse(req) + } + + return req, nil +} + +func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response { + // sometimes it happens ¯\_(ツ)_/¯ + if res == nil { + return nil + } + + req := res.Request + log.Debug("(%s) > %s %s %s%s", core.Green(p.Name), req.RemoteAddr, req.Method, req.Host, req.URL.Path) + + // do we have a proxy script? + if p.Script == nil { + return res + } + + _, jsres := p.Script.OnResponse(res) + if jsres != nil { + // the response has been changed by the script + p.logResponseAction(res.Request, jsres) + return jsres.ToResponse(res.Request) + } + + return res +} + +func (p *HTTPProxy) logRequestAction(req *http.Request, jsreq *JSRequest) { + p.sess.Events.Add(p.Name+".spoofed-request", struct { + To string + Method string + Host string + Path string + Size int + }{ + strings.Split(req.RemoteAddr, ":")[0], + jsreq.Method, + jsreq.Hostname, + jsreq.Path, + len(jsreq.Body), + }) +} + +func (p *HTTPProxy) logResponseAction(req *http.Request, jsres *JSResponse) { + p.sess.Events.Add(p.Name+".spoofed-response", struct { + To string + Method string + Host string + Path string + Size int + }{ + strings.Split(req.RemoteAddr, ":")[0], + req.Method, + req.Host, + req.URL.Path, + len(jsres.Body), + }) +} diff --git a/modules/https_proxy.go b/modules/https_proxy.go index daea7a2f..d47a7628 100644 --- a/modules/https_proxy.go +++ b/modules/https_proxy.go @@ -31,6 +31,10 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy { "8083", "Port to bind the HTTPS proxy to.")) + p.AddParam(session.NewBoolParameter("https.proxy.sslstrip", + "true", + "Enable or disable SSL stripping.")) + p.AddParam(session.NewStringParameter("https.proxy.certificate", "~/.bettercap-ca.cert.pem", "", @@ -81,36 +85,27 @@ func (p *HttpsProxy) Configure() error { var scriptPath string var certFile string var keyFile string + var stripSSL bool if p.Running() == true { return session.ErrAlreadyStarted - } - - if err, address = p.StringParam("https.proxy.address"); err != nil { + } else if err, address = p.StringParam("https.proxy.address"); err != nil { return err - } - - if err, proxyPort = p.IntParam("https.proxy.port"); err != nil { + } else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil { return err - } - - if err, httpPort = p.IntParam("https.port"); err != nil { + } else if err, httpPort = p.IntParam("https.port"); err != nil { return err - } - - if err, certFile = p.StringParam("https.proxy.certificate"); err != nil { + } else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil { + return err + } else if err, certFile = p.StringParam("https.proxy.certificate"); err != nil { return err } else if certFile, err = core.ExpandPath(certFile); err != nil { return err - } - - if err, keyFile = p.StringParam("https.proxy.key"); err != nil { + } else if err, keyFile = p.StringParam("https.proxy.key"); err != nil { return err } else if keyFile, err = core.ExpandPath(keyFile); err != nil { return err - } - - if err, scriptPath = p.StringParam("https.proxy.script"); err != nil { + } else if err, scriptPath = p.StringParam("https.proxy.script"); err != nil { return err } @@ -125,7 +120,7 @@ func (p *HttpsProxy) Configure() error { log.Info("Loading proxy certification authority TLS certificate from %s", certFile) } - return p.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile) + return p.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile, stripSSL) } func (p *HttpsProxy) Start() error {