4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / utils.go GO
package main

import (
	"bufio"
	"encoding/csv"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net"
	"os"
	"path"
	"strings"
	"sync"
	"time"
)

type csvWriter struct {
	locker *sync.Mutex
	writer *csv.Writer
}

const letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func initCSVWriter(fname string) (*csvWriter, error) {
	csvf, err := os.Create(fname)
	if err != nil {
		return nil, err
	}
	wr := csv.NewWriter(csvf)
	return &csvWriter{
		locker: &sync.Mutex{},
		writer: wr,
	}, nil
}

func (wr *csvWriter) writeRow(row []string) {
	wr.locker.Lock()
	wr.writer.Write(row)
	wr.locker.Unlock()
}

func (wr *csvWriter) FlushBuffer() {
	wr.locker.Lock()
	wr.writer.Flush()
	wr.locker.Unlock()
}

// checks if a specific item is in a slice
func isItemIn(item string, allitems *[]string) bool {
	for x := range *allitems {
		if item == (*allitems)[x] {
			return true
		}
	}
	return false
}

func genRandStr(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func getLocalAddr() string {
	conn, err := net.Dial("udp", "8.8.8.8:80")
	if err != nil {
		log.Fatalln(err)
	}
	conn.Close()
	return conn.LocalAddr().String()
}

func sendPacket(hostport string, payload string, deadline int, termConn bool) (net.Conn, error) {
	conn, err := net.DialTimeout("udp", hostport, time.Duration(dialTimeout)*time.Second)
	if err != nil {
		return nil, err
	}
	conn.SetDeadline(time.Now().Add(time.Duration(deadline) * time.Second))
	_, err = conn.Write([]byte(payload))
	if err != nil {
		return nil, err
	}
	if termConn {
		err = conn.Close()
		if err != nil {
			return nil, err
		}
	}
	return conn, nil
}

func readExtensionsFromFile(fname string) *[]string {
	var exts []string
	file, err := os.Open(fname)
	if err != nil {
		log.Fatalln(err.Error())
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		exts = append(exts, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		log.Fatalln(err.Error())
	}
	return &exts
}

func readCsvFile(filePath string) [][]string {
	f, err := os.Open(filePath)
	if err != nil {
		log.Fatal("Unable to read input file "+filePath, err)
	}
	defer f.Close()

	csvReader := csv.NewReader(f)
	records, err := csvReader.ReadAll()
	if err != nil {
		log.Fatal("Unable to parse file as CSV for "+filePath, err)
	}

	return records
}

func checkAlive(targets *[]string) map[string]bool {
	var dmap = make(map[string]bool)
	for _, targ := range *targets {
		dmap[targ] = false
		conn, err := net.DialTimeout("udp", targ, time.Duration(dialTimeout)*time.Second)
		if err != nil {
			log.Println(err.Error())
			continue
		}
		defer conn.Close()

		var payload string
		payload += fmt.Sprintf("OPTIONS sip:1000@%s;transport=UDP SIP/2.0\r\n", targ)
		payload += fmt.Sprintf("Via: SIP/2.0/UDP %s;branch=z9hG4bK001b84f6;rport\r\n", conn.LocalAddr().String())
		payload += "Max-Forwards: 70\r\n"
		payload += "To: \"PewSWITCH\" <sip:[email protected]>\r\n"
		payload += "From: \"PewSWITCH\" <sip:[email protected]>;tag=61633638380343437\r\n"
		payload += "User-Agent: pewswitch\r\n"
		payload += "Call-ID: AABkh3bjAZ3k2j3br5920I0\r\n"
		payload += fmt.Sprintf("Contact: sip:1000@%s\r\n", conn.LocalAddr().String())
		payload += "CSeq: 1 OPTIONS\r\n"
		payload += "Accept: application/sdp\r\n"
		payload += "Content-Length: 0\r\n"
		payload += "\r\n"

		conn.SetDeadline(time.Now().Add(5 * time.Second))
		_, err = conn.Write([]byte(payload))
		if err != nil {
			continue
		}
		xbuf := make([]byte, 8192)
		_, err = conn.Read(xbuf)
		if err != nil {
			continue
		}
		if strings.HasPrefix(string(xbuf), "SIP/2.0") {
			dmap[targ] = true
			log.Printf("Host %s is up and responding to SIP.", targ)
		}
		server := serverHead.FindAllSubmatch(xbuf, -1)
		if server != nil {
			servstr := strings.ToLower(string(server[0][1]))
			if !strings.Contains(servstr, "freeswitch") {
				log.Println("Heuristics indicate that the server might not be FreeSWITCH!")
			} else {
				log.Println("Heuristics indicate that the server is FreeSWITCH.")
			}
		} else {
			log.Println("No server header found. Skipping heuristic checks...")
		}
	}
	return dmap
}

func postProcess(obj *[]fResult) *[]fResult {
	var (
		uniqhosts []string
		xresult   fResult
		count     = 0
		newObj    = make([]fResult, 0)
	)
	for _, x := range *obj {
		uniqhosts = append(uniqhosts, x.Host)
	}
	uniqhosts = *sortUnique(&uniqhosts)
	for _, mhost := range uniqhosts {
		xflag := false
		for _, res := range *obj {
			if res.Host == mhost {
				if !xflag {
					if count > 0 {
						newObj = append(newObj, xresult)
					}
					xresult = res
					xflag = true
					continue
				}
				xresult.Details.CVE202137624.ExploitDetails = append(xresult.Details.
					CVE202137624.ExploitDetails, res.Details.CVE202137624.ExploitDetails...)
				xresult.Details.CVE202141157.ExploitDetails = append(xresult.Details.
					CVE202141157.ExploitDetails, res.Details.CVE202141157.ExploitDetails...)
				count++
			}
		}
	}
	newObj = append(newObj, xresult)
	return &newObj
}

// writeToJSON writes the results of a scan to the specified directory
func writeToJSON(obj *[]fResult) error {
	obj = postProcess(obj)
	for _, res := range *obj {
		xdata, err := json.MarshalIndent(res, "", "    ")
		if err != nil {
			return err
		}
		if err = ioutil.WriteFile(path.Join(outdir,
			fmt.Sprintf("%s-report.json", res.Host)), xdata, 0644); err != nil {
			return err
		}
	}
	return nil
}

func writeToCSV(obj *[]fResult) error {
	var uniqhosts []string
	for _, x := range *obj {
		uniqhosts = append(uniqhosts, x.Host)
	}
	uniqhosts = *sortUnique(&uniqhosts)
	for _, xhost := range uniqhosts {
		xwriter, err := initCSVWriter(path.Join(outdir, fmt.Sprintf("%s-report.csv", xhost)))
		if err != nil {
			return err
		}
		xwriter.writeRow([]string{
			"extension",
			"host",
			"cve",
			"is_vulnerable",
			"message",
			"timestamp",
		})
		for _, res := range *obj {
			if xhost == res.Host {
				xdets := res.Details.CVE202137624.ExploitDetails
				if len(res.Details.CVE202137624.ExploitDetails) > 0 {
					for _, msg := range res.Details.CVE202137624.ExploitDetails[0].SentMessages {
						xwriter.writeRow([]string{
							xdets[0].Extension,
							xhost,
							"CVE-2021-37624",
							fmt.Sprint(res.Details.CVE202137624.IsVulnerable),
							msg.Message,
							time.Time(msg.Timestamp).Format(time.RFC3339),
						})
					}
				}
				xdetx := res.Details.CVE202141157.ExploitDetails
				if len(res.Details.CVE202141157.ExploitDetails) > 0 {
					for _, msg := range res.Details.CVE202141157.ExploitDetails[0].NotifsRecvd {
						xwriter.writeRow([]string{
							xdetx[0].Extension,
							xhost,
							"CVE-2021-41157",
							fmt.Sprint(res.Details.CVE202137624.IsVulnerable),
							// santizing the CSV so it doesn't span across lines
							sanitiseRex.ReplaceAllLiteralString(msg.Message, "\\n"),
							time.Time(msg.Timestamp).Format(time.RFC3339),
						})
					}
				}
			}
		}
		xwriter.FlushBuffer()
	}
	return nil
}

func sortUnique(sSlice *[]string) *[]string {
	var keys = make(map[string]bool)
	var list []string
	for _, entry := range *sSlice {
		if _, value := keys[entry]; !value {
			keys[entry] = true
			list = append(list, entry)
		}
	}
	return &list
}