mirror of
https://github.com/bettercap/bettercap
synced 2025-07-12 08:07:00 -07:00
new: implemented http.proxy.injectjs and https.proxy.injectjs to inject javascript code, files or URLs without a proxy module
This commit is contained in:
parent
7839a90c82
commit
6c3157e9c4
4 changed files with 74 additions and 12 deletions
|
@ -33,6 +33,11 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
|
||||||
"",
|
"",
|
||||||
"Path of a proxy JS script."))
|
"Path of a proxy JS script."))
|
||||||
|
|
||||||
|
p.AddParam(session.NewStringParameter("http.proxy.injectjs",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"URL, path or javascript code to inject into every HTML page."))
|
||||||
|
|
||||||
p.AddParam(session.NewBoolParameter("http.proxy.sslstrip",
|
p.AddParam(session.NewBoolParameter("http.proxy.sslstrip",
|
||||||
"false",
|
"false",
|
||||||
"Enable or disable SSL stripping."))
|
"Enable or disable SSL stripping."))
|
||||||
|
@ -71,6 +76,7 @@ func (p *HttpProxy) Configure() error {
|
||||||
var httpPort int
|
var httpPort int
|
||||||
var scriptPath string
|
var scriptPath string
|
||||||
var stripSSL bool
|
var stripSSL bool
|
||||||
|
var jsToInject string
|
||||||
|
|
||||||
if p.Running() {
|
if p.Running() {
|
||||||
return session.ErrAlreadyStarted
|
return session.ErrAlreadyStarted
|
||||||
|
@ -84,9 +90,11 @@ func (p *HttpProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, stripSSL = p.BoolParam("http.proxy.sslstrip"); err != nil {
|
} else if err, stripSSL = p.BoolParam("http.proxy.sslstrip"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err, jsToInject = p.StringParam("http.proxy.injectjs"); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.proxy.Configure(address, proxyPort, httpPort, scriptPath, stripSSL)
|
return p.proxy.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HttpProxy) Start() error {
|
func (p *HttpProxy) Start() error {
|
||||||
|
|
|
@ -40,6 +40,7 @@ type HTTPProxy struct {
|
||||||
CertFile string
|
CertFile string
|
||||||
KeyFile string
|
KeyFile string
|
||||||
|
|
||||||
|
jsHook string
|
||||||
isTLS bool
|
isTLS bool
|
||||||
isRunning bool
|
isRunning bool
|
||||||
stripper *SSLStripper
|
stripper *SSLStripper
|
||||||
|
@ -106,12 +107,29 @@ 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 int, scriptPath string, jsToInject string, stripSSL bool) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
p.stripper.Enable(stripSSL)
|
p.stripper.Enable(stripSSL)
|
||||||
p.Address = address
|
p.Address = address
|
||||||
|
|
||||||
|
if strings.HasPrefix(jsToInject, "http://") || strings.HasPrefix(jsToInject, "https://") {
|
||||||
|
p.jsHook = fmt.Sprintf("<script src=\"%s\" type=\"text/javascript\"></script></head>", jsToInject)
|
||||||
|
} else if core.Exists(jsToInject) {
|
||||||
|
if data, err := ioutil.ReadFile(jsToInject); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
jsToInject = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.jsHook == "" && jsToInject != "" {
|
||||||
|
if strings.HasPrefix(jsToInject, "<script ") == false {
|
||||||
|
jsToInject = fmt.Sprintf("<script type=\"text/javascript\">%s</script>", jsToInject)
|
||||||
|
}
|
||||||
|
p.jsHook = fmt.Sprintf("%s</head>", jsToInject)
|
||||||
|
}
|
||||||
|
|
||||||
if scriptPath != "" {
|
if scriptPath != "" {
|
||||||
if err, p.Script = LoadHttpProxyScript(scriptPath, p.sess); err != nil {
|
if err, p.Script = LoadHttpProxyScript(scriptPath, p.sess); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -187,8 +205,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, stripSSL bool) (err error) {
|
func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, scriptPath string, certFile string, keyFile string, jsToInject string, stripSSL bool) (err error) {
|
||||||
if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil {
|
if p.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package modules
|
package modules
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -40,6 +41,17 @@ func (p *HTTPProxy) onRequestFilter(req *http.Request, ctx *goproxy.ProxyCtx) (*
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getContentType(res *http.Response) string {
|
||||||
|
for name, values := range res.Header {
|
||||||
|
for _, value := range values {
|
||||||
|
if strings.ToLower(name) == "content-type" {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
|
func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response {
|
||||||
// sometimes it happens ¯\_(ツ)_/¯
|
// sometimes it happens ¯\_(ツ)_/¯
|
||||||
if res == nil {
|
if res == nil {
|
||||||
|
@ -52,15 +64,31 @@ func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx)
|
||||||
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 {
|
||||||
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, jsres := p.Script.OnResponse(res)
|
// inject javascript code if specified and needed
|
||||||
if jsres != nil {
|
if cType := getContentType(res); p.jsHook != "" && strings.Contains(cType, "text/html") {
|
||||||
// the response has been changed by the script
|
log.Info("(%s) > injecting javascript (%d bytes) into %s for %s", core.Green(p.Name), len(p.jsHook), core.Yellow(req.Host+req.URL.Path), core.Bold(req.RemoteAddr))
|
||||||
p.logResponseAction(res.Request, jsres)
|
defer res.Body.Close()
|
||||||
return jsres.ToResponse(res.Request)
|
|
||||||
|
raw, _ := ioutil.ReadAll(res.Body)
|
||||||
|
html := strings.Replace(string(raw), "</head>", p.jsHook, -1)
|
||||||
|
|
||||||
|
newResp := goproxy.NewResponse(req, cType, res.StatusCode, html)
|
||||||
|
for k, vv := range res.Header {
|
||||||
|
for _, v := range vv {
|
||||||
|
newResp.Header.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newResp
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
|
@ -35,6 +35,11 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy {
|
||||||
"false",
|
"false",
|
||||||
"Enable or disable SSL stripping."))
|
"Enable or disable SSL stripping."))
|
||||||
|
|
||||||
|
p.AddParam(session.NewStringParameter("https.proxy.injectjs",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"URL, path or javascript code to inject into every HTML page."))
|
||||||
|
|
||||||
p.AddParam(session.NewStringParameter("https.proxy.certificate",
|
p.AddParam(session.NewStringParameter("https.proxy.certificate",
|
||||||
"~/.bettercap-ca.cert.pem",
|
"~/.bettercap-ca.cert.pem",
|
||||||
"",
|
"",
|
||||||
|
@ -86,6 +91,7 @@ func (p *HttpsProxy) Configure() error {
|
||||||
var certFile string
|
var certFile string
|
||||||
var keyFile string
|
var keyFile string
|
||||||
var stripSSL bool
|
var stripSSL bool
|
||||||
|
var jsToInject string
|
||||||
|
|
||||||
if p.Running() {
|
if p.Running() {
|
||||||
return session.ErrAlreadyStarted
|
return session.ErrAlreadyStarted
|
||||||
|
@ -107,6 +113,8 @@ func (p *HttpsProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, scriptPath = p.StringParam("https.proxy.script"); err != nil {
|
} else if err, scriptPath = p.StringParam("https.proxy.script"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err, jsToInject = p.StringParam("https.proxy.injectjs"); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !core.Exists(certFile) || !core.Exists(keyFile) {
|
if !core.Exists(certFile) || !core.Exists(keyFile) {
|
||||||
|
@ -120,7 +128,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, httpPort, scriptPath, certFile, keyFile, jsToInject, stripSSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HttpsProxy) Start() error {
|
func (p *HttpsProxy) Start() error {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue