From aea67626ef4777c85929bc5081fc6b1b8b8b3978 Mon Sep 17 00:00:00 2001 From: Robert Reichel Date: Wed, 10 Mar 2021 11:28:48 -0500 Subject: [PATCH] Added pages check --- cmd/dangling_pages.go | 90 +++++++++++++++++++++++++++++++++++++++++++ cmd/utils/loadjson.go | 27 +++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 cmd/dangling_pages.go create mode 100644 cmd/utils/loadjson.go diff --git a/cmd/dangling_pages.go b/cmd/dangling_pages.go new file mode 100644 index 0000000..faac7d5 --- /dev/null +++ b/cmd/dangling_pages.go @@ -0,0 +1,90 @@ +package cmd + +import ( + "fmt" + "io/ioutil" + "net/http" + "os/exec" + "strings" + + "github.com/rreichel3/hunttools/cmd/utils" + + "github.com/spf13/cobra" +) + +func init() { + danglingPagesCmd.Flags().StringVarP(&DomainJsonListPath, "infile", "i", "", "Json list of subdomains") + danglingPagesCmd.MarkFlagRequired("infile") + danglingPagesCmd.Flags().StringVarP(&RootDomain, "rootdomain", "d", "", "The root domain for the provided subdomain lists") + danglingPagesCmd.MarkFlagRequired("rootdomain") + + rootCmd.AddCommand(danglingPagesCmd) +} + +var DomainJsonListPath string +var RootDomain string + +var danglingPagesCmd = &cobra.Command{ + Use: "find-dangling-pages", + Short: "Finds dangling GitHub pages", + Long: `Takes a JSON list of subdomains (The format from Azure DNS is what's expected), then iterates over them to discover takeoverable domains`, + RunE: func(cmd *cobra.Command, args []string) error { + + var addresses, err = utils.LoadJsonList(DomainJsonListPath) + if err != nil { + return err + } + + for _, address := range addresses { + hostname := fmt.Sprintf("%v.%s", address["name"], RootDomain) + if VerboseOutput { + fmt.Println("Processing host: " + hostname) + } + if isDangling(hostname) { + fmt.Printf("%s\n", hostname) + } + } + return nil + + }, +} + +func isPages(addr string) bool { + cmd := exec.Command("dig", addr) + out, err := cmd.Output() + if err != nil { + if VerboseOutput { + fmt.Println(err) + } + return false + } + output := string(out) + return strings.Contains(output, "github.io") +} + +func isUnallocated(addr string) bool { + resp, err := http.Get("https://" + addr) + if err != nil { + if VerboseOutput { + fmt.Println(err) + } + return false + } + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + if VerboseOutput { + fmt.Println(err) + } + return false + } + bodyString := string(bodyBytes) + return resp.StatusCode == http.StatusNotFound && strings.Contains(bodyString, "There isn't a GitHub Pages site here.") +} + +func isDangling(addr string) bool { + if isPages(addr) && isUnallocated(addr) { + return true + } + return false + +} diff --git a/cmd/utils/loadjson.go b/cmd/utils/loadjson.go new file mode 100644 index 0000000..eb9483a --- /dev/null +++ b/cmd/utils/loadjson.go @@ -0,0 +1,27 @@ +package utils + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" +) + +func LoadJsonList(sourceFilePath string) ([]map[string]interface{}, error) { + jsonFile, err := os.Open(sourceFilePath) + // if we os.Open returns an error then handle it + if err != nil { + fmt.Println(err) + return nil, err + } + // defer the closing of our jsonFile so that we can parse it later on + defer jsonFile.Close() + + byteValue, _ := ioutil.ReadAll(jsonFile) + + var result []map[string]interface{} + json.Unmarshal([]byte(byteValue), &result) + + return result, nil + +}