mirror of
https://github.com/bettercap/bettercap
synced 2025-07-16 10:03:39 -07:00
new: now request object can be changed during OnRequest handlers (closes #135)
This commit is contained in:
parent
cb58258bd7
commit
07fe790ad1
3 changed files with 111 additions and 34 deletions
|
@ -77,9 +77,12 @@ func NewHTTPProxy(s *session.Session) *HTTPProxy {
|
|||
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 {
|
||||
jsres := p.Script.OnRequest(req)
|
||||
if jsres != nil {
|
||||
p.logAction(req, jsres)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +94,9 @@ func NewHTTPProxy(s *session.Session) *HTTPProxy {
|
|||
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)
|
||||
_, jsres := p.Script.OnResponse(res)
|
||||
if jsres != nil {
|
||||
p.logAction(res.Request, jsres)
|
||||
p.logResponseAction(res.Request, jsres)
|
||||
return jsres.ToResponse(res.Request)
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +107,23 @@ func NewHTTPProxy(s *session.Session) *HTTPProxy {
|
|||
return p
|
||||
}
|
||||
|
||||
func (p *HTTPProxy) logAction(req *http.Request, jsres *JSResponse) {
|
||||
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
|
||||
|
|
|
@ -24,7 +24,10 @@ type JSRequest struct {
|
|||
ContentType string
|
||||
Headers []JSHeader
|
||||
Body string
|
||||
|
||||
req *http.Request
|
||||
refHash string
|
||||
bodyRead bool
|
||||
}
|
||||
|
||||
func NewJSRequest(req *http.Request) *JSRequest {
|
||||
|
@ -41,7 +44,7 @@ func NewJSRequest(req *http.Request) *JSRequest {
|
|||
}
|
||||
}
|
||||
|
||||
return &JSRequest{
|
||||
jreq := &JSRequest{
|
||||
Client: strings.Split(req.RemoteAddr, ":")[0],
|
||||
Method: req.Method,
|
||||
Version: fmt.Sprintf("%d.%d", req.ProtoMajor, req.ProtoMinor),
|
||||
|
@ -52,7 +55,37 @@ func NewJSRequest(req *http.Request) *JSRequest {
|
|||
Headers: headers,
|
||||
|
||||
req: req,
|
||||
bodyRead: false,
|
||||
}
|
||||
jreq.UpdateHash()
|
||||
|
||||
return jreq
|
||||
}
|
||||
|
||||
func (j *JSRequest) NewHash() string {
|
||||
hash := fmt.Sprintf("%s.%s.%s.%s.%s.%s.%s", j.Client, j.Method, j.Version, j.Hostname, j.Path, j.Query, j.ContentType)
|
||||
for _, h := range j.Headers {
|
||||
hash += fmt.Sprintf(".%s-%s", h.Name, h.Value)
|
||||
}
|
||||
hash += "." + j.Body
|
||||
return hash
|
||||
}
|
||||
|
||||
func (j *JSRequest) UpdateHash() {
|
||||
j.refHash = j.NewHash()
|
||||
}
|
||||
|
||||
func (j *JSRequest) WasModified() bool {
|
||||
// body was read
|
||||
if j.bodyRead == true {
|
||||
return true
|
||||
}
|
||||
// check if any of the fields has been changed
|
||||
newHash := j.NewHash()
|
||||
if newHash != j.refHash {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (j *JSRequest) ReadBody() string {
|
||||
|
@ -62,6 +95,7 @@ func (j *JSRequest) ReadBody() string {
|
|||
}
|
||||
|
||||
j.Body = string(raw)
|
||||
j.bodyRead = true
|
||||
// reset the request body to the original unread state
|
||||
j.req.Body = ioutil.NopCloser(bytes.NewBuffer(raw))
|
||||
|
||||
|
@ -90,3 +124,26 @@ func (j *JSRequest) ParseForm() map[string]string {
|
|||
|
||||
return form
|
||||
}
|
||||
|
||||
func (j *JSRequest) ToRequest() (req *http.Request) {
|
||||
url := fmt.Sprintf("%s://%s:%s%s?%s", j.req.URL.Scheme, j.Hostname, j.req.URL.Port(), j.Path, j.Query)
|
||||
if j.Body == "" {
|
||||
req, _ = http.NewRequest(j.Method, url, j.req.Body)
|
||||
} else {
|
||||
req, _ = http.NewRequest(j.Method, url, strings.NewReader(j.Body))
|
||||
}
|
||||
|
||||
hadType := false
|
||||
for _, h := range j.Headers {
|
||||
req.Header.Set(h.Name, h.Value)
|
||||
if h.Name == "Content-Type" {
|
||||
hadType = true
|
||||
}
|
||||
}
|
||||
|
||||
if hadType == false && j.ContentType != "" {
|
||||
req.Header.Set("Content-Type", j.ContentType)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -60,9 +60,8 @@ func LoadHttpProxyScript(path string, sess *session.Session) (err error, s *Http
|
|||
return LoadHttpProxyScriptSource(path, string(raw), sess)
|
||||
}
|
||||
|
||||
func (s *HttpProxyScript) doRequestDefines(req *http.Request) (err error, jsres *JSResponse) {
|
||||
// convert request and define empty response to be optionally filled
|
||||
jsreq := NewJSRequest(req)
|
||||
func (s *HttpProxyScript) doRequestDefines(req *http.Request) (err error, jsreq *JSRequest, jsres *JSResponse) {
|
||||
jsreq = NewJSRequest(req)
|
||||
if err = s.VM.Set("req", jsreq); err != nil {
|
||||
log.Error("Error while defining request: %s", err)
|
||||
return
|
||||
|
@ -76,9 +75,8 @@ func (s *HttpProxyScript) doRequestDefines(req *http.Request) (err error, jsres
|
|||
return
|
||||
}
|
||||
|
||||
func (s *HttpProxyScript) doResponseDefines(res *http.Response) (err error, jsres *JSResponse) {
|
||||
// convert both request and response
|
||||
jsreq := NewJSRequest(res.Request)
|
||||
func (s *HttpProxyScript) doResponseDefines(res *http.Response) (err error, jsreq *JSRequest, jsres *JSResponse) {
|
||||
jsreq = NewJSRequest(res.Request)
|
||||
if err = s.VM.Set("req", jsreq); err != nil {
|
||||
log.Error("Error while defining request: %s", err)
|
||||
return
|
||||
|
@ -93,54 +91,57 @@ func (s *HttpProxyScript) doResponseDefines(res *http.Response) (err error, jsre
|
|||
return
|
||||
}
|
||||
|
||||
func (s *HttpProxyScript) OnRequest(req *http.Request) *JSResponse {
|
||||
func (s *HttpProxyScript) OnRequest(original *http.Request) (jsreq *JSRequest, jsres *JSResponse) {
|
||||
var err error
|
||||
|
||||
if s.onRequestScript != nil {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
err, jsres := s.doRequestDefines(req)
|
||||
if err != nil {
|
||||
if err, jsreq, jsres = s.doRequestDefines(original); err != nil {
|
||||
log.Error("Error while running bootstrap definitions: %s", err)
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err = s.VM.Run(s.onRequestScript)
|
||||
if err != nil {
|
||||
if _, err = s.VM.Run(s.onRequestScript); err != nil {
|
||||
log.Error("Error while executing onRequest callback: %s", err)
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if jsres.WasModified() {
|
||||
if jsreq.WasModified() {
|
||||
jsreq.UpdateHash()
|
||||
return jsreq, nil
|
||||
} else if jsres.WasModified() {
|
||||
jsres.UpdateHash()
|
||||
return jsres
|
||||
return nil, jsres
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *HttpProxyScript) OnResponse(res *http.Response) *JSResponse {
|
||||
func (s *HttpProxyScript) OnResponse(res *http.Response) (jsreq *JSRequest, jsres *JSResponse) {
|
||||
var err error
|
||||
|
||||
if s.onResponseScript != nil {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
err, jsres := s.doResponseDefines(res)
|
||||
if err != nil {
|
||||
if err, jsreq, jsres = s.doResponseDefines(res); err != nil {
|
||||
log.Error("Error while running bootstrap definitions: %s", err)
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err = s.VM.Run(s.onResponseScript)
|
||||
if err != nil {
|
||||
if _, err = s.VM.Run(s.onResponseScript); err != nil {
|
||||
log.Error("Error while executing onRequest callback: %s", err)
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if jsres.WasModified() {
|
||||
jsres.UpdateHash()
|
||||
return jsres
|
||||
return nil, jsres
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue