onionscan/protocol/http_scanner.go

111 lines
3.5 KiB
Go

package protocol
import (
"crypto/tls"
"fmt"
"github.com/s-rah/onionscan/config"
"github.com/s-rah/onionscan/report"
"github.com/s-rah/onionscan/scans"
"github.com/s-rah/onionscan/utils"
"h12.me/socks"
"io/ioutil"
"net/http"
"strings"
)
type HTTPProtocolScanner struct {
Client *http.Client
}
var (
CommonDirectories = []string{"/style", "/styles", "/css", "/uploads", "/images", "/img", "/static",
// Lots of Wordpress installs which don't lock down directory listings
"/wp-content/uploads",
// Common with torshops created onions
"/products", "/products/cat"}
)
func (hps *HTTPProtocolScanner) ScanProtocol(hiddenService string, osc *config.OnionscanConfig, report *report.OnionScanReport) {
// HTTP
osc.LogInfo(fmt.Sprintf("Checking %s http(80)\n", hiddenService))
conn, err := utils.GetNetworkConnection(hiddenService, 80, osc.TorProxyAddress, osc.Timeout)
if err != nil {
osc.LogInfo("Failed to connect to service on port 80\n")
report.WebDetected = false
if conn != nil {
conn.Close()
}
} else {
osc.LogInfo("Found potential service on http(80)\n")
report.WebDetected = true
conn.Close()
dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, osc.TorProxyAddress)
transportConfig := &http.Transport{
Dial: dialSocksProxy,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
hps.Client = &http.Client{
Transport: transportConfig,
}
// FIXME This should probably be moved to it's own file now.
response, err := hps.Client.Get("http://" + hiddenService)
if err == nil {
// Reading all http headers
osc.LogInfo(fmt.Sprintf("HTTP response headers: %s\n", report.ServerVersion))
responseHeaders := response.Header
for key := range responseHeaders {
value := responseHeaders.Get(key)
// normalize by strings.ToUpper(key) to avoid case sensitive checking
report.AddResponseHeader(strings.ToUpper(key), value)
}
report.ServerVersion = responseHeaders.Get("Server")
response.Body.Close()
} else {
osc.LogError(err)
}
// Apache mod-status Check
hps.ScanPage(hiddenService, "/", report, osc, scans.StandardPageScan)
hps.ScanPage(hiddenService, "/server-status", report, osc, scans.ApacheModStatus)
hps.ScanPage(hiddenService, "/private_key", report, osc, scans.PrivateKeyScan)
if osc.Fingerprint == false {
osc.LogInfo("\tScanning Common and Referenced Directories\n")
directories := append(CommonDirectories, report.PageReferencedDirectories...)
utils.RemoveDuplicates(&directories)
for _, directory := range directories {
hps.ScanPage(hiddenService, directory, report, osc, scans.CheckDirectoryListing(osc.DirectoryDepth))
}
}
}
}
func (hps *HTTPProtocolScanner) ScanPage(hiddenService string, page string, report *report.OnionScanReport, osc *config.OnionscanConfig, f func(scans.Scanner, string, int, string, *report.OnionScanReport, *config.OnionscanConfig)) {
err, contents, responseCode := hps.ScrapePage(hiddenService, page)
if err == nil {
f(hps, page, responseCode, string(contents), report, osc)
return
} else {
osc.LogError(err)
}
}
func (hps *HTTPProtocolScanner) ScrapePage(hiddenService string, page string) (error, []byte, int) {
if !strings.Contains(page, utils.WithoutSubdomains(hiddenService)) {
if !strings.HasPrefix(page, "/") {
page = "/" + page
}
page = hiddenService + page
}
response, err := hps.Client.Get("http://" + page)
if err != nil {
return err, nil, -1
}
defer response.Body.Close()
contents, _ := ioutil.ReadAll(response.Body)
return nil, contents, response.StatusCode
}