This commit is contained in:
Gorgias 2018-08-03 14:22:26 +00:00 committed by GitHub
commit 6854e0eaf4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 283 additions and 20 deletions

View file

@ -74,7 +74,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
action, "PREROUTING", action, "PREROUTING",
"-i", r.Interface, "-i", r.Interface,
"-p", r.Protocol, "-p", r.Protocol,
"--dport", fmt.Sprintf("%d", r.SrcPort), "--dport", fmt.Sprintf("%s", r.SrcPort),
"-j", "DNAT", "-j", "DNAT",
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort), "--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
} }
@ -85,7 +85,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
"-i", r.Interface, "-i", r.Interface,
"-p", r.Protocol, "-p", r.Protocol,
"-d", r.SrcAddress, "-d", r.SrcAddress,
"--dport", fmt.Sprintf("%d", r.SrcPort), "--dport", fmt.Sprintf("%s", r.SrcPort),
"-j", "DNAT", "-j", "DNAT",
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort), "--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
} }

View file

@ -1,17 +1,28 @@
package firewall package firewall
import "fmt" import (
"fmt"
"strconv"
)
type Redirection struct { type Redirection struct {
Interface string Interface string
Protocol string Protocol string
SrcAddress string SrcAddress string
SrcPort int SrcPort string
DstAddress string DstAddress string
DstPort int DstPort int
MultiPort bool
} }
func NewRedirection(iface string, proto string, port_from int, addr_to string, port_to int) *Redirection { func NewRedirection(iface string, proto string, port_from string, addr_to string, port_to int) *Redirection {
_, err := strconv.Atoi(port_from)
multi_port := false
if err != nil {
multi_port = true
} else {
multi_port = false
}
return &Redirection{ return &Redirection{
Interface: iface, Interface: iface,
Protocol: proto, Protocol: proto,
@ -19,6 +30,7 @@ func NewRedirection(iface string, proto string, port_from int, addr_to string, p
SrcPort: port_from, SrcPort: port_from,
DstAddress: addr_to, DstAddress: addr_to,
DstPort: port_to, DstPort: port_to,
MultiPort: multi_port,
} }
} }

View file

@ -45,6 +45,7 @@ func main() {
sess.Register(modules.NewTcpProxy(sess)) sess.Register(modules.NewTcpProxy(sess))
sess.Register(modules.NewHttpProxy(sess)) sess.Register(modules.NewHttpProxy(sess))
sess.Register(modules.NewHttpsProxy(sess)) sess.Register(modules.NewHttpsProxy(sess))
sess.Register(modules.NewCustomHttpProxy(sess))
sess.Register(modules.NewHttpServer(sess)) sess.Register(modules.NewHttpServer(sess))
sess.Register(modules.NewRestAPI(sess)) sess.Register(modules.NewRestAPI(sess))
sess.Register(modules.NewWOL(sess)) sess.Register(modules.NewWOL(sess))

View file

@ -0,0 +1,99 @@
package modules
import (
"github.com/bettercap/bettercap/session"
)
type CustomHttpProxy struct {
session.SessionModule
proxy *CustomProxy
}
func NewCustomHttpProxy(s *session.Session) *CustomHttpProxy {
p := &CustomHttpProxy{
SessionModule: session.NewSessionModule("custom.http.proxy", s),
proxy: NewCustomProxy(s),
}
p.AddParam(session.NewStringParameter("custom.http.port",
"80", session.PortsValidator,
"HTTP port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("custom.http.proxy.address",
session.ParamIfaceAddress,
session.IPv4Validator,
"Address to bind the Custom HTTP proxy to."))
p.AddParam(session.NewIntParameter("custom.http.proxy.port",
"8080",
"Port to bind the Custom HTTP proxy to."))
p.AddParam(session.NewBoolParameter("custom.http.proxy.sslstrip",
"false",
"Enable or disable SSL stripping."))
p.AddHandler(session.NewModuleHandler("custom.http.proxy on", "",
"Start Custom HTTP proxy.",
func(args []string) error {
return p.Start()
}))
p.AddHandler(session.NewModuleHandler("custom.http.proxy off", "",
"Stop Custom HTTP proxy.",
func(args []string) error {
return p.Stop()
}))
return p
}
func (p *CustomHttpProxy) Name() string {
return "custom.http.proxy"
}
func (p *CustomHttpProxy) Description() string {
return "Use a custom HTTP proxy server instead of the builtin one."
}
func (p *CustomHttpProxy) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>"
}
func (p *CustomHttpProxy) Configure() error {
var err error
var address string
var proxyPort int
var httpPort string
var stripSSL bool
if p.Running() {
return session.ErrAlreadyStarted
} else if err, address = p.StringParam("custom.http.proxy.address"); err != nil {
return err
} else if err, proxyPort = p.IntParam("custom.http.proxy.port"); err != nil {
return err
} else if err, httpPort = p.StringParam("custom.http.port"); err != nil {
return err
} else if err, stripSSL = p.BoolParam("custom.http.proxy.sslstrip"); err != nil {
return err
}
return p.proxy.Configure(address, proxyPort, httpPort, stripSSL)
}
func (p *CustomHttpProxy) Start() error {
if err := p.Configure(); err != nil {
return err
}
return p.SetRunning(true, func() {
p.proxy.Start()
})
}
func (p *CustomHttpProxy) Stop() error {
return p.SetRunning(false, func() {
p.proxy.Stop()
})
}

View file

@ -0,0 +1,114 @@
package modules
import (
"net/http"
"github.com/bettercap/bettercap/firewall"
"net"
"github.com/bettercap/bettercap/session"
"strings"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/core"
)
type CustomProxy struct {
Name string
Address string
Redirection *firewall.Redirection
isTLS bool
isRunning bool
stripper *SSLStripper
sniListener net.Listener
sess *session.Session
}
func NewCustomProxy(s *session.Session) *CustomProxy {
p := &CustomProxy{
Name: "custom.proxy",
sess: s,
stripper: NewSSLStripper(s, false),
}
return p
}
func (p *CustomProxy) doProxy(req *http.Request) bool {
blacklist := []string{
"localhost",
"127.0.0.1",
}
if req.Host == "" {
log.Error("Got request with empty host: %v", req)
return false
}
for _, blacklisted := range blacklist {
if strings.Split(req.Host, ":")[0] == blacklisted {
log.Error("Got request with blacklisted host: %s", req.Host)
return false
}
}
return true
}
func (p *CustomProxy) stripPort(s string) string {
ix := strings.IndexRune(s, ':')
if ix == -1 {
return s
}
return s[:ix]
}
func (p *CustomProxy) Configure(proxyAddress string, proxyPort int, srcPort string, stripSSL bool) error {
p.stripper.Enable(stripSSL)
p.Address = proxyAddress
if !p.sess.Firewall.IsForwardingEnabled() {
log.Info("Enabling forwarding.")
p.sess.Firewall.EnableForwarding(true)
}
p.Redirection = firewall.NewRedirection(p.sess.Interface.Name(),
"TCP",
srcPort,
p.Address,
proxyPort)
if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil {
return err
}
log.Debug("Applied redirection %s", p.Redirection.String())
return nil
}
func (p *CustomProxy) Start() {
go func() {
var err error
strip := core.Yellow("enabled")
if !p.stripper.Enabled() {
strip = core.Dim("disabled")
}
log.Info("%s started on %s (sslstrip %s)", core.Green(p.Name), p.Address, strip)
if err != nil && err.Error() != "http: Server closed" {
log.Fatal("%s", err)
}
}()
}
func (p *CustomProxy) Stop() error {
if p.Redirection != nil {
log.Debug("Disabling redirection %s", p.Redirection.String())
if err := p.sess.Firewall.EnableRedirection(p.Redirection, false); err != nil {
return err
}
p.Redirection = nil
}
return nil
}

View file

@ -15,8 +15,8 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
proxy: NewHTTPProxy(s), proxy: NewHTTPProxy(s),
} }
p.AddParam(session.NewIntParameter("http.port", p.AddParam(session.NewStringParameter("http.port",
"80", "80", session.PortsValidator,
"HTTP port to redirect when the proxy is activated.")) "HTTP port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("http.proxy.address", p.AddParam(session.NewStringParameter("http.proxy.address",
@ -68,7 +68,7 @@ func (p *HttpProxy) Configure() error {
var err error var err error
var address string var address string
var proxyPort int var proxyPort int
var httpPort int var httpPort string
var scriptPath string var scriptPath string
var stripSSL bool var stripSSL bool
@ -78,7 +78,7 @@ func (p *HttpProxy) Configure() error {
return err return err
} else if err, proxyPort = p.IntParam("http.proxy.port"); err != nil { } else if err, proxyPort = p.IntParam("http.proxy.port"); err != nil {
return err return err
} else if err, httpPort = p.IntParam("http.port"); err != nil { } else if err, httpPort = p.StringParam("http.port"); err != nil {
return err return err
} else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil { } else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil {
return err return err

View file

@ -106,7 +106,7 @@ func (p *HTTPProxy) doProxy(req *http.Request) bool {
return true return true
} }
func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scriptPath string, stripSSL bool) error { func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort string, scriptPath string, stripSSL bool) error {
var err error var err error
p.stripper.Enable(stripSSL) p.stripper.Enable(stripSSL)
@ -141,7 +141,6 @@ func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scrip
if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil { if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil {
return err return err
} }
log.Debug("Applied redirection %s", p.Redirection.String()) log.Debug("Applied redirection %s", p.Redirection.String())
p.sess.UnkCmdCallback = func(cmd string) bool { p.sess.UnkCmdCallback = func(cmd string) bool {
@ -187,7 +186,7 @@ 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, stripSSL bool) (err error) { func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort string, scriptPath string, certFile string, keyFile string, stripSSL bool) (err error) {
if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil { if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil {
return err return err
} }

View file

@ -0,0 +1,37 @@
package modules
import (
"net/http"
"testing"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
)
func getScript(src string) *HttpProxyScript {
sess := session.Session{}
sess.Env = session.NewEnvironment(&sess, "")
err, script := LoadHttpProxyScriptSource("", src, &sess)
if err != nil {
log.Fatal("%s", err)
}
return script
}
func getRequest() *http.Request {
req, err := http.NewRequest("GET", "http://www.google.com/", nil)
if err != nil {
log.Fatal("%s", err)
}
return req
}
func BenchmarkOnRequest(b *testing.B) {
script := getScript("function onRequest(req,res){}")
req := getRequest()
for n := 0; n < b.N; n++ {
script.OnRequest(req)
}
}

View file

@ -18,8 +18,8 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy {
proxy: NewHTTPProxy(s), proxy: NewHTTPProxy(s),
} }
p.AddParam(session.NewIntParameter("https.port", p.AddParam(session.NewStringParameter("https.port",
"443", "443", session.PortsValidator,
"HTTPS port to redirect when the proxy is activated.")) "HTTPS port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("https.proxy.address", p.AddParam(session.NewStringParameter("https.proxy.address",
@ -81,7 +81,7 @@ func (p *HttpsProxy) Configure() error {
var err error var err error
var address string var address string
var proxyPort int var proxyPort int
var httpPort int var httpsPort string
var scriptPath string var scriptPath string
var certFile string var certFile string
var keyFile string var keyFile string
@ -93,7 +93,7 @@ func (p *HttpsProxy) Configure() error {
return err return err
} else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil { } else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil {
return err return err
} else if err, httpPort = p.IntParam("https.port"); err != nil { } else if err, httpsPort = p.StringParam("https.port"); err != nil {
return err return err
} else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil { } else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil {
return err return err
@ -120,7 +120,7 @@ func (p *HttpsProxy) Configure() error {
log.Info("Loading proxy certification authority TLS certificate from %s", certFile) log.Info("Loading proxy certification authority TLS certificate from %s", certFile)
} }
return p.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile, stripSSL) return p.proxy.ConfigureTLS(address, proxyPort, httpsPort, scriptPath, certFile, keyFile, stripSSL)
} }
func (p *HttpsProxy) Start() error { func (p *HttpsProxy) Start() error {

View file

@ -87,7 +87,7 @@ func (p *TcpProxy) Author() string {
func (p *TcpProxy) Configure() error { func (p *TcpProxy) Configure() error {
var err error var err error
var port int var port string
var proxyPort int var proxyPort int
var address string var address string
var proxyAddress string var proxyAddress string
@ -103,7 +103,7 @@ func (p *TcpProxy) Configure() error {
return err return err
} else if err, proxyPort = p.IntParam("tcp.proxy.port"); err != nil { } else if err, proxyPort = p.IntParam("tcp.proxy.port"); err != nil {
return err return err
} else if err, port = p.IntParam("tcp.port"); err != nil { } else if err, port = p.StringParam("tcp.port"); err != nil {
return err return err
} else if err, tunnelAddress = p.StringParam("tcp.tunnel.address"); err != nil { } else if err, tunnelAddress = p.StringParam("tcp.tunnel.address"); err != nil {
return err return err
@ -113,7 +113,7 @@ func (p *TcpProxy) Configure() error {
return err return err
} else if p.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil { } else if p.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil {
return err return err
} else if p.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil { } else if p.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", address, port)); err != nil {
return err return err
} else if p.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil { } else if p.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil {
return err return err

View file

@ -9,6 +9,7 @@ import (
) )
const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$` const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`
const PortsValidator = `^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+[,]+)*(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+)$|^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+):(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+)$`
type ModuleHandler struct { type ModuleHandler struct {
Name string Name string