mirror of
https://github.com/bettercap/bettercap
synced 2025-07-07 05:22:04 -07:00
new: implemented (http|https).proxy.whitelist and (http|https).proxy.blacklist parameters (closes #508)
This commit is contained in:
parent
6785650887
commit
cfd93c555a
4 changed files with 118 additions and 55 deletions
|
@ -2,6 +2,8 @@ package http_proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/str"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpProxy struct {
|
type HttpProxy struct {
|
||||||
|
@ -38,6 +40,12 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
|
||||||
"",
|
"",
|
||||||
"URL, path or javascript code to inject into every HTML page."))
|
"URL, path or javascript code to inject into every HTML page."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("http.proxy.blacklist", "", "",
|
||||||
|
"Comma separated list of hostnames to skip while proxying (wildcard expressions can be used)."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("http.proxy.whitelist", "", "",
|
||||||
|
"Comma separated list of hostnames to proxy if the blacklist is used (wildcard expressions can be used)."))
|
||||||
|
|
||||||
mod.AddParam(session.NewBoolParameter("http.proxy.sslstrip",
|
mod.AddParam(session.NewBoolParameter("http.proxy.sslstrip",
|
||||||
"false",
|
"false",
|
||||||
"Enable or disable SSL stripping."))
|
"Enable or disable SSL stripping."))
|
||||||
|
@ -77,6 +85,8 @@ func (mod *HttpProxy) Configure() error {
|
||||||
var scriptPath string
|
var scriptPath string
|
||||||
var stripSSL bool
|
var stripSSL bool
|
||||||
var jsToInject string
|
var jsToInject string
|
||||||
|
var blacklist string
|
||||||
|
var whitelist string
|
||||||
|
|
||||||
if mod.Running() {
|
if mod.Running() {
|
||||||
return session.ErrAlreadyStarted
|
return session.ErrAlreadyStarted
|
||||||
|
@ -92,8 +102,15 @@ func (mod *HttpProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, jsToInject = mod.StringParam("http.proxy.injectjs"); err != nil {
|
} else if err, jsToInject = mod.StringParam("http.proxy.injectjs"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err, blacklist = mod.StringParam("http.proxy.blacklist"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, whitelist = mod.StringParam("http.proxy.whitelist"); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod.proxy.Blacklist = str.Comma(blacklist)
|
||||||
|
mod.proxy.Whitelist = str.Comma(whitelist)
|
||||||
|
|
||||||
return mod.proxy.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL)
|
return mod.proxy.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -41,6 +42,8 @@ type HTTPProxy struct {
|
||||||
Script *HttpProxyScript
|
Script *HttpProxyScript
|
||||||
CertFile string
|
CertFile string
|
||||||
KeyFile string
|
KeyFile string
|
||||||
|
Blacklist []string
|
||||||
|
Whitelist []string
|
||||||
|
|
||||||
jsHook string
|
jsHook string
|
||||||
isTLS bool
|
isTLS bool
|
||||||
|
@ -61,13 +64,15 @@ func stripPort(s string) string {
|
||||||
|
|
||||||
func NewHTTPProxy(s *session.Session) *HTTPProxy {
|
func NewHTTPProxy(s *session.Session) *HTTPProxy {
|
||||||
p := &HTTPProxy{
|
p := &HTTPProxy{
|
||||||
Name: "http.proxy",
|
Name: "http.proxy",
|
||||||
Proxy: goproxy.NewProxyHttpServer(),
|
Proxy: goproxy.NewProxyHttpServer(),
|
||||||
sess: s,
|
sess: s,
|
||||||
stripper: NewSSLStripper(s, false),
|
stripper: NewSSLStripper(s, false),
|
||||||
isTLS: false,
|
isTLS: false,
|
||||||
Server: nil,
|
Server: nil,
|
||||||
tag: session.AsTag("http.proxy"),
|
Blacklist: make([]string, 0),
|
||||||
|
Whitelist: make([]string, 0),
|
||||||
|
tag: session.AsTag("http.proxy"),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Proxy.Verbose = false
|
p.Proxy.Verbose = false
|
||||||
|
@ -111,20 +116,41 @@ func (p *HTTPProxy) Fatal(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPProxy) doProxy(req *http.Request) bool {
|
func (p *HTTPProxy) doProxy(req *http.Request) bool {
|
||||||
blacklist := []string{
|
|
||||||
"localhost",
|
|
||||||
"127.0.0.1",
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Host == "" {
|
if req.Host == "" {
|
||||||
p.Error("got request with empty host: %v", req)
|
p.Error("got request with empty host: %v", req)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
host := strings.Split(req.Host, ":")[0]
|
hostname := strings.Split(req.Host, ":")[0]
|
||||||
for _, blacklisted := range blacklist {
|
for _, local := range []string{"localhost", "127.0.0.1"} {
|
||||||
if host == blacklisted {
|
if hostname == local {
|
||||||
p.Error("got request with blacklisted host: %s", req.Host)
|
p.Error("got request with localed host: %s", req.Host)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HTTPProxy) shouldProxy(req *http.Request) bool {
|
||||||
|
hostname := strings.Split(req.Host, ":")[0]
|
||||||
|
|
||||||
|
// check for the whitelist
|
||||||
|
for _, expr := range p.Whitelist {
|
||||||
|
if matched, err := filepath.Match(expr, hostname); err != nil {
|
||||||
|
p.Error("error while using proxy whitelist expression '%s': %v", expr, err)
|
||||||
|
} else if matched {
|
||||||
|
p.Debug("hostname '%s' matched whitelisted element '%s'", hostname, expr)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then the blacklist
|
||||||
|
for _, expr := range p.Blacklist {
|
||||||
|
if matched, err := filepath.Match(expr, hostname); err != nil {
|
||||||
|
p.Error("error while using proxy blacklist expression '%s': %v", expr, err)
|
||||||
|
} else if matched {
|
||||||
|
p.Debug("hostname '%s' matched blacklisted element '%s'", hostname, expr)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,32 +19,34 @@ func (p *HTTPProxy) fixRequestHeaders(req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPProxy) onRequestFilter(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
|
func (p *HTTPProxy) onRequestFilter(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
|
||||||
p.Debug("< %s %s %s%s", req.RemoteAddr, req.Method, req.Host, req.URL.Path)
|
if p.shouldProxy(req) {
|
||||||
|
p.Debug("< %s %s %s%s", req.RemoteAddr, req.Method, req.Host, req.URL.Path)
|
||||||
|
|
||||||
p.fixRequestHeaders(req)
|
p.fixRequestHeaders(req)
|
||||||
|
|
||||||
redir := p.stripper.Preprocess(req, ctx)
|
redir := p.stripper.Preprocess(req, ctx)
|
||||||
if redir != nil {
|
if redir != nil {
|
||||||
// we need to redirect the user in order to make
|
// we need to redirect the user in order to make
|
||||||
// some session cookie expire
|
// some session cookie expire
|
||||||
return req, redir
|
return req, redir
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we have a proxy script?
|
// do we have a proxy script?
|
||||||
if p.Script == nil {
|
if p.Script == nil {
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the module OnRequest callback if defined
|
// run the module OnRequest callback if defined
|
||||||
jsreq, jsres := p.Script.OnRequest(req)
|
jsreq, jsres := p.Script.OnRequest(req)
|
||||||
if jsreq != nil {
|
if jsreq != nil {
|
||||||
// the request has been changed by the script
|
// the request has been changed by the script
|
||||||
p.logRequestAction(req, jsreq)
|
p.logRequestAction(req, jsreq)
|
||||||
return jsreq.ToRequest(), nil
|
return jsreq.ToRequest(), nil
|
||||||
} else if jsres != nil {
|
} else if jsres != nil {
|
||||||
// a fake response has been returned by the script
|
// a fake response has been returned by the script
|
||||||
p.logResponseAction(req, jsres)
|
p.logResponseAction(req, jsres)
|
||||||
return req, jsres.ToResponse(req)
|
return req, jsres.ToResponse(req)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
|
@ -123,28 +125,30 @@ func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Debug("> %s %s %s%s", res.Request.RemoteAddr, res.Request.Method, res.Request.Host, res.Request.URL.Path)
|
if p.shouldProxy(res.Request) {
|
||||||
|
p.Debug("> %s %s %s%s", res.Request.RemoteAddr, res.Request.Method, res.Request.Host, res.Request.URL.Path)
|
||||||
|
|
||||||
p.fixResponseHeaders(res)
|
p.fixResponseHeaders(res)
|
||||||
|
|
||||||
p.stripper.Process(res, ctx)
|
p.stripper.Process(res, ctx)
|
||||||
|
|
||||||
// do we have a proxy script?
|
// do we have a proxy script?
|
||||||
if p.Script != nil {
|
if p.Script != nil {
|
||||||
_, jsres := p.Script.OnResponse(res)
|
_, jsres := p.Script.OnResponse(res)
|
||||||
if jsres != nil {
|
if jsres != nil {
|
||||||
// the response has been changed by the script
|
// the response has been changed by the script
|
||||||
p.logResponseAction(res.Request, jsres)
|
p.logResponseAction(res.Request, jsres)
|
||||||
return jsres.ToResponse(res.Request)
|
return jsres.ToResponse(res.Request)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// inject javascript code if specified and needed
|
// inject javascript code if specified and needed
|
||||||
if doInject, cType := p.isScriptInjectable(res); doInject {
|
if doInject, cType := p.isScriptInjectable(res); doInject {
|
||||||
if err, injectedResponse := p.doScriptInjection(res, cType); err != nil {
|
if err, injectedResponse := p.doScriptInjection(res, cType); err != nil {
|
||||||
p.Error("error while injecting javascript: %s", err)
|
p.Error("error while injecting javascript: %s", err)
|
||||||
} else if injectedResponse != nil {
|
} else if injectedResponse != nil {
|
||||||
return injectedResponse
|
return injectedResponse
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/bettercap/bettercap/tls"
|
"github.com/bettercap/bettercap/tls"
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/fs"
|
"github.com/evilsocket/islazy/fs"
|
||||||
|
"github.com/evilsocket/islazy/str"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpsProxy struct {
|
type HttpsProxy struct {
|
||||||
|
@ -58,6 +59,12 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy {
|
||||||
"",
|
"",
|
||||||
"Path of a proxy JS script."))
|
"Path of a proxy JS script."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("https.proxy.blacklist", "", "",
|
||||||
|
"Comma separated list of hostnames to skip while proxying (wildcard expressions can be used)."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("https.proxy.whitelist", "", "",
|
||||||
|
"Comma separated list of hostnames to proxy if the blacklist is used (wildcard expressions can be used)."))
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("https.proxy on", "",
|
mod.AddHandler(session.NewModuleHandler("https.proxy on", "",
|
||||||
"Start HTTPS proxy.",
|
"Start HTTPS proxy.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
@ -95,6 +102,8 @@ func (mod *HttpsProxy) Configure() error {
|
||||||
var keyFile string
|
var keyFile string
|
||||||
var stripSSL bool
|
var stripSSL bool
|
||||||
var jsToInject string
|
var jsToInject string
|
||||||
|
var whitelist string
|
||||||
|
var blacklist string
|
||||||
|
|
||||||
if mod.Running() {
|
if mod.Running() {
|
||||||
return session.ErrAlreadyStarted
|
return session.ErrAlreadyStarted
|
||||||
|
@ -118,8 +127,15 @@ func (mod *HttpsProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, jsToInject = mod.StringParam("https.proxy.injectjs"); err != nil {
|
} else if err, jsToInject = mod.StringParam("https.proxy.injectjs"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err, blacklist = mod.StringParam("https.proxy.blacklist"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, whitelist = mod.StringParam("https.proxy.whitelist"); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod.proxy.Blacklist = str.Comma(blacklist)
|
||||||
|
mod.proxy.Whitelist = str.Comma(whitelist)
|
||||||
|
|
||||||
if !fs.Exists(certFile) || !fs.Exists(keyFile) {
|
if !fs.Exists(certFile) || !fs.Exists(keyFile) {
|
||||||
err, cfg := tls.CertConfigFromModule("https.proxy", mod.SessionModule)
|
err, cfg := tls.CertConfigFromModule("https.proxy", mod.SessionModule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue