bettercap/modules/syn_scan/http_grabber.go
2021-04-03 18:42:14 +02:00

94 lines
2.1 KiB
Go

package syn_scan
import (
"crypto/tls"
"crypto/x509"
"fmt"
"golang.org/x/net/html"
"net/http"
"strings"
)
func isTitleElement(n *html.Node) bool {
return n.Type == html.ElementNode && strings.ToLower(n.Data) == "title"
}
func searchForTitle(n *html.Node) string {
if isTitleElement(n) && n.FirstChild != nil {
return n.FirstChild.Data
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
if result := searchForTitle(c); result != "" {
return result
}
}
return ""
}
func httpGrabber(mod *SynScanner, ip string, port int) string {
schema := "http"
client := &http.Client{
Timeout: bannerGrabTimeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return nil
},
}
sport := fmt.Sprintf("%d", port)
if strings.Contains(sport, "443") {
schema = "https"
client = &http.Client{
Timeout: bannerGrabTimeout,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
return nil
},
},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return nil
},
}
}
// https://stackoverflow.com/questions/12260003/connect-returns-invalid-argument-with-ipv6-address
if strings.Contains(ip, ":") {
ip = fmt.Sprintf("[%s%%25%s]", ip, mod.Session.Interface.Name())
}
url := fmt.Sprintf("%s://%s:%d/", schema, ip, port)
resp, err := client.Get(url)
if err != nil {
mod.Debug("error while grabbing banner from %s: %v", url, err)
return ""
}
defer resp.Body.Close()
fallback := ""
for name, values := range resp.Header {
for _, value := range values {
header := strings.ToLower(name)
if len(value) > len(fallback) && (header == "x-powered-by" || header == "server") {
mod.Debug("found header %s for %s:%d -> %s", header, ip, port, value)
fallback = value
}
}
}
doc, err := html.Parse(resp.Body)
if err != nil {
mod.Debug("error while reading and parsing response from %s: %v", url, err)
return fallback
}
if title := searchForTitle(doc); title != "" {
return title
}
return fallback
}