From 7fe4088dba354ef44272808d313fe2e3efd21a26 Mon Sep 17 00:00:00 2001 From: Rahul Zhade Date: Tue, 25 Oct 2022 16:10:17 -0700 Subject: [PATCH 1/3] Add go.mod updates --- go.mod | 26 +++++++++++++++++++++ go.sum | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5fcb428 --- /dev/null +++ b/go.mod @@ -0,0 +1,26 @@ +module github.com/haccer/subjack + +go 1.19 + +require ( + github.com/haccer/available v0.0.0-20200921032034-0d552efb6cd4 + github.com/miekg/dns v1.1.50 + github.com/valyala/fasthttp v1.41.0 +) + +require ( + github.com/PuerkitoBio/goquery v1.8.0 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/andybalholm/cascadia v1.3.1 // indirect + github.com/domainr/whois v0.1.0 // indirect + github.com/klauspost/compress v1.15.9 // indirect + github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/zonedb/zonedb v1.0.3544 // indirect + golang.org/x/mod v0.4.2 // indirect + golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..009dcae --- /dev/null +++ b/go.sum @@ -0,0 +1,71 @@ +github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= +github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= +github.com/domainr/whois v0.1.0 h1:36I1Hu+5pfvJzSXjnxN3lmIXeNNlZJmM5fkk9zlRF2o= +github.com/domainr/whois v0.1.0/go.mod h1:/6Ej6qU9Xcl/8we/QKFWhJlvUlqmEDGXgHzOwbazVpo= +github.com/domainr/whoistest v0.0.0-20180714175718-26cad4b7c941 h1:E7ehdIemEeScp8nVs0JXNXEbzb2IsHCk13ijvwKqRWI= +github.com/domainr/whoistest v0.0.0-20180714175718-26cad4b7c941/go.mod h1:iuCHv1qZDoHJNQs56ZzzoKRSKttGgTr2yByGpSlKsII= +github.com/haccer/available v0.0.0-20200921032034-0d552efb6cd4 h1:MxQoqqy0scTAXWDH36lXAbRWbr3t8+e/aCmxvzTxlpQ= +github.com/haccer/available v0.0.0-20200921032034-0d552efb6cd4/go.mod h1:CvVDzx8GCt0H9avR2A0NnFViM9QhXQghxKnZaosoaSU= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/miekg/dns v1.1.46/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= +github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY= +github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zonedb/zonedb v1.0.3544 h1:u5a3xOaI338FclecJ/H6J7fiImVEZ/qZomJnVYIlTeM= +github.com/zonedb/zonedb v1.0.3544/go.mod h1:h9mfHV/S6lboOkltULrbNY52cd7JZo6MbxIiqKMWPLg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo= +golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From c5a35d1fdd0666f5c3ed8b56236299636406f641 Mon Sep 17 00:00:00 2001 From: Rahul Zhade Date: Tue, 25 Oct 2022 17:04:23 -0700 Subject: [PATCH 2/3] Embed default fingerprints --- main.go | 18 +++++++++++------- subjack/file.go | 47 +++++++++++++++++++++------------------------- subjack/subjack.go | 35 ++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/main.go b/main.go index 4f9e9ad..30edf19 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + _ "embed" "flag" "fmt" "os" @@ -8,12 +9,10 @@ import ( "github.com/haccer/subjack/subjack" ) -func main() { - GOPATH := os.Getenv("GOPATH") - Project := "/src/github.com/haccer/subjack/" - configFile := "fingerprints.json" - defaultConfig := GOPATH + Project + configFile +//go:embed fingerprints.json +var defaultConfig string +func main() { o := subjack.Options{} flag.StringVar(&o.Domain, "d", "", "Domain.") @@ -24,7 +23,7 @@ func main() { flag.BoolVar(&o.All, "a", false, "Find those hidden gems by sending requests to every URL. (Default: Requests are only sent to URLs with identified CNAMEs).") flag.BoolVar(&o.Verbose, "v", false, "Display more information per each request.") flag.StringVar(&o.Output, "o", "", "Output results to file (Subjack will write JSON if file ends with '.json').") - flag.StringVar(&o.Config, "c", defaultConfig, "Path to configuration file.") + flag.StringVar(&o.ConfigFile, "c", "", "Path to configuration file.") flag.BoolVar(&o.Manual, "m", false, "Flag the presence of a dead record, but valid CNAME entry.") flag.Parse() @@ -39,5 +38,10 @@ func main() { os.Exit(1) } - subjack.Process(&o) + o.Config = defaultConfig + err := subjack.Process(&o) + if err != nil { + fmt.Println(err) + os.Exit(1) + } } diff --git a/subjack/file.go b/subjack/file.go index 78ac6b6..01d5b73 100644 --- a/subjack/file.go +++ b/subjack/file.go @@ -3,7 +3,7 @@ package subjack import ( "bufio" "encoding/json" - "io/ioutil" + "io" "log" "os" "strings" @@ -16,23 +16,6 @@ type Results struct { Domain string `json:"nonexist_domain,omitempty"` } -func open(path string) (lines []string, Error error) { - file, err := os.Open(path) - if err != nil { - log.Fatalln(err) - } - - defer file.Close() - - scanner := bufio.NewScanner(file) - - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - - return lines, scanner.Err() -} - func chkJSON(output string) (json bool) { json = false @@ -90,7 +73,7 @@ func writeJSON(service, url, output string) { defer f.Close() - file, err := ioutil.ReadAll(f) + file, err := io.ReadAll(f) if err != nil { log.Fatalln(err) } @@ -111,16 +94,28 @@ func writeJSON(service, url, output string) { wf.Write(results) } -func fingerprints(file string) (data []Fingerprints) { - config, err := ioutil.ReadFile(file) +func readFile(filename string) (content []byte, Error error) { + return os.ReadFile(filename) +} + +func readFileLines(filename string) (lines []string, Error error) { + file, err := os.Open(filename) if err != nil { - log.Fatalln(err) + return nil, err } - err = json.Unmarshal(config, &data) - if err != nil { - log.Fatalln(err) + defer file.Close() + + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + lines = append(lines, scanner.Text()) } - return data + return lines, scanner.Err() +} + +func fingerprints(config []byte) (data []Fingerprints, Error error) { + err := json.Unmarshal(config, &data) + return data, err } diff --git a/subjack/subjack.go b/subjack/subjack.go index f992aba..a90e876 100644 --- a/subjack/subjack.go +++ b/subjack/subjack.go @@ -1,7 +1,6 @@ package subjack import ( - "log" "sync" ) @@ -15,6 +14,7 @@ type Options struct { All bool Verbose bool Config string + ConfigFile string Manual bool Fingerprints []Fingerprints } @@ -24,23 +24,37 @@ type Subdomain struct { } /* Start processing subjack from the defined options. */ -func Process(o *Options) { +func Process(o *Options) (err error) { var list []string - var err error urls := make(chan *Subdomain, o.Threads*10) - - if(len(o.Domain) > 0){ + + // Load fingerprints + if o.ConfigFile != "" { + custom_fingerprints, err := readFile(o.ConfigFile) + if err != nil { + return err + } + o.Fingerprints, err = fingerprints(custom_fingerprints) + if err != nil { + return err + } + } else { + // No error checking here because the default fingerprints are + // hard-coded into the binary. + o.Fingerprints, _ = fingerprints([]byte(o.Config)) + } + + // Load domain list + if len(o.Domain) > 0 { list = append(list, o.Domain) } else { - list, err = open(o.Wordlist) + list, err = readFileLines(o.Wordlist) } - + if err != nil { - log.Fatalln(err) + return err } - - o.Fingerprints = fingerprints(o.Config) wg := new(sync.WaitGroup) @@ -61,4 +75,5 @@ func Process(o *Options) { close(urls) wg.Wait() + return nil } From 119fe3c07cf93aebc3cf6d6f783aabae2d38d94b Mon Sep 17 00:00:00 2001 From: Rahul Zhade Date: Wed, 26 Oct 2022 11:06:09 -0700 Subject: [PATCH 3/3] Add some rudimentary tests --- subjack/file_test.go | 104 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 subjack/file_test.go diff --git a/subjack/file_test.go b/subjack/file_test.go new file mode 100644 index 0000000..bfe0542 --- /dev/null +++ b/subjack/file_test.go @@ -0,0 +1,104 @@ +package subjack + +import ( + "log" + "os" + "testing" +) + +func TestReadFileLines(t *testing.T) { + // Read a file that does not exist. + _, err := readFileLines("does_not_exist.txt") + if err == nil { + t.Errorf("Expected error, got nil") + } + + // Read a file that does exist. + tmpfile, err := os.CreateTemp("", "subjack_test") + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmpfile.Name()) + + if _, err := tmpfile.Write([]byte("test\nFoobar")); err != nil { + log.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + log.Fatal(err) + } + + lines, err := readFileLines(tmpfile.Name()) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + if len(lines) != 2 { + t.Errorf("Expected 2 lines, got %d", len(lines)) + } +} + +func TestReadFile(t *testing.T) { + // Read a file that does not exist. + _, err := readFile("does_not_exist.txt") + if err == nil { + t.Errorf("Expected error, got nil") + } + + // Read a file that does exist. + tmpfile, err := os.CreateTemp("", "subjack_test") + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmpfile.Name()) + + if _, err := tmpfile.Write([]byte("test\nFoobar")); err != nil { + log.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + log.Fatal(err) + } + + lines, err := readFile(tmpfile.Name()) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + if string(lines) != "test\nFoobar" { + t.Errorf("Expected 'test\nFoobar', got %v", lines) + } +} + +func TestFingerprints(t *testing.T) { + invalid_fingerprints := []byte(`[ + { + "service": ", + "cname": [, + "fingerprint": [, + "nxdomain": [, + } + ]`) + + _, err := fingerprints(invalid_fingerprints) + if err == nil { + t.Errorf("Expected error, got nil") + } + + valid_fingerprints := []byte(`[ + { + "service": "fastly", + "cname": [ + "fastly" + ], + "fingerprint": [ + "Fastly error: unknown domain" + ], + "nxdomain": false + } + ]`) + fs, err := fingerprints(valid_fingerprints) + if err != nil { + t.Errorf("Expected nil, got %v", err) + } + if len(fs) != 1 { + t.Errorf("Expected 1 fingerprint, got %d", len(fs)) + } + +}