yellow.git


yellow

~ opinionated web scanning pipeline for pentesters in a hurry
git clone https://github.com/djnnvx/yellow.git
log | files | refs | archive | README | LICENSE

net.go (3652B)

      1 package helper
      2 
      3 import (
      4 	"crypto/tls"
      5 	"fmt"
      6 	"io"
      7 	"net/http"
      8 	"net/url"
      9 	"time"
     10 
     11 	"os"
     12 	"strings"
     13 
     14 	"github.com/go-rod/rod/lib/launcher"
     15 )
     16 
     17 const HttpTimeout = 15 * time.Second
     18 
     19 const MaxBodySize = 10 << 20
     20 
     21 // ReadCappedBody stops at MaxBodySize so a target cannot pick our memory usage.
     22 func ReadCappedBody(r io.Reader) (body []byte, truncated bool, err error) {
     23 	b, err := io.ReadAll(io.LimitReader(r, MaxBodySize+1))
     24 	if len(b) > MaxBodySize {
     25 		return b[:MaxBodySize], true, err
     26 	}
     27 	return b, false, err
     28 }
     29 
     30 func GetHttpTransport() *http.Transport {
     31 	var proxy = os.Getenv("HTTP_PROXY")
     32 	url, err := url.Parse(proxy)
     33 
     34 	if proxy != "" && err == nil {
     35 		return &http.Transport{
     36 			DisableKeepAlives: true,
     37 			Proxy:             http.ProxyURL(url),
     38 		}
     39 	}
     40 	return &http.Transport{}
     41 }
     42 
     43 func GetHttpClient(insecure bool) *http.Client {
     44 	transport := GetHttpTransport()
     45 	if insecure {
     46 		transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
     47 	}
     48 
     49 	return &http.Client{
     50 		Transport: transport,
     51 		Timeout:   HttpTimeout,
     52 	}
     53 }
     54 
     55 // SystemChromePath returns an installed Chrome/Chromium, or "" to let the
     56 // headless tooling download its own.
     57 func SystemChromePath() string {
     58 	path, ok := launcher.LookPath()
     59 	if !ok {
     60 		return ""
     61 	}
     62 	return path
     63 }
     64 
     65 func GetUserAgent() string {
     66 	return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
     67 }
     68 
     69 func GetCurrentIP() string {
     70 	ua := GetUserAgent()
     71 
     72 	cli := GetHttpClient(false)
     73 
     74 	req, err := http.NewRequest("GET", "http://icanhazip.com", nil)
     75 	if err != nil {
     76 		fmt.Printf("[!] Could not query public IP address: %s\n", err.Error())
     77 		return "127.0.0.1" // if the service is offline or not reachable, we should be able to keep going
     78 	}
     79 
     80 	req.Header.Add("User-Agent", ua)
     81 	resp, err := cli.Do(req)
     82 
     83 	if err != nil || resp == nil {
     84 		fmt.Printf("[!] Could not query public IP address: %v\n", err)
     85 		return "127.0.0.1" // service offline or unreachable, we should be able to keep going
     86 	}
     87 	defer resp.Body.Close()
     88 
     89 	result, _, err := ReadCappedBody(resp.Body)
     90 	if err != nil {
     91 		fmt.Printf("[!] Could not read public IP address: %v\n", err)
     92 		return "127.0.0.1"
     93 	}
     94 
     95 	return strings.TrimSpace(string(result))
     96 }
     97 
     98 func DisplayNetInfo() {
     99 	ip := GetCurrentIP()
    100 	ua := GetUserAgent()
    101 
    102 	fmt.Println("[~] Current Public IP: " + ip)
    103 	fmt.Println("[~] Prefered User-Agent: " + ua)
    104 }
    105 
    106 func CheckProxy(proxy string) {
    107 	os.Setenv("HTTP_PROXY", proxy)
    108 	os.Setenv("HTTPS_PROXY", proxy)
    109 
    110 	if proxy != "" {
    111 		fmt.Printf("[+] Proxy configuration: %s\n", proxy)
    112 	} else {
    113 		fmt.Println("[+] No proxy has been set")
    114 	}
    115 }
    116 
    117 // ResolveWebTarget probes https first and falls back to http, so a host that
    118 // only serves plaintext is still scanned instead of skipped.
    119 func ResolveWebTarget(domain string, forceInsecure bool) (string, bool) {
    120 	return resolveWebTarget(domain, forceInsecure, HasUnavailableWebInterface)
    121 }
    122 
    123 func resolveWebTarget(domain string, forceInsecure bool, unavailable func(string) bool) (string, bool) {
    124 	schemes := []string{"https://", "http://"}
    125 	if forceInsecure {
    126 		schemes = []string{"http://"}
    127 	}
    128 	for _, scheme := range schemes {
    129 		if target := scheme + domain; !unavailable(target) {
    130 			return target, true
    131 		}
    132 	}
    133 	return "", false
    134 }
    135 
    136 func HasUnavailableWebInterface(url string) bool {
    137 	url = strings.TrimSuffix(url, "/")
    138 
    139 	client := GetHttpClient(true)
    140 
    141 	req, err := http.NewRequest("GET", url, nil)
    142 	if err != nil {
    143 		return true
    144 	}
    145 	req.Header.Add("User-Agent", GetUserAgent())
    146 	resp, err := client.Do(req)
    147 	if err != nil || resp == nil {
    148 		return true
    149 	}
    150 	defer resp.Body.Close()
    151 
    152 	return resp.StatusCode >= http.StatusBadGateway
    153 }