Added Netcraft Data Source
parent
508a5ca974
commit
13e0c9e013
|
@ -6,24 +6,80 @@
|
||||||
// Copyrights (C) 2018 Ice3man
|
// Copyrights (C) 2018 Ice3man
|
||||||
//
|
//
|
||||||
|
|
||||||
package threatcrowd
|
package netcraft
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"subfinder/libsubfinder/helper"
|
"subfinder/libsubfinder/helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Struct containing json data we actually need
|
// Contains all subdomains found
|
||||||
type netcraft_object struct {
|
var globalSubdomains []string
|
||||||
Subdomains []string `json:"subdomains"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// array of all results returned
|
//
|
||||||
var netcraft_data netcraft_object
|
// Local function to recursively enumerate subdomains until no subdomains
|
||||||
|
// are left :-)
|
||||||
|
//
|
||||||
|
// @param baseUrl : Base URL is the URL with which to begin enumerating
|
||||||
|
// In recursion, it will be used to pass next Subdomains Link
|
||||||
|
//
|
||||||
|
func enumerate(state *helper.State, baseUrl string) (err error) {
|
||||||
|
|
||||||
|
// Make a http request to Netcraft
|
||||||
|
resp, err := helper.GetHTTPResponse(baseUrl, 3000)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the response body
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
src := string(body)
|
||||||
|
|
||||||
|
// Regex for Netcraft
|
||||||
|
// NOTE : HTML Parsing using Regex is flawed and anyone who does so is banished from community.
|
||||||
|
// But, I had to make it work and other things were simply not working. Currently, it's acceptable
|
||||||
|
|
||||||
|
// TODO : Change it in near future
|
||||||
|
re := regexp.MustCompile("<a href=\"http://toolbar.netcraft.com/site_report\\?url=(.*)\">")
|
||||||
|
match := re.FindAllStringSubmatch(src, -1)
|
||||||
|
|
||||||
|
for _, subdomain := range match {
|
||||||
|
// Dirty Logic
|
||||||
|
finishedSub := strings.Split(subdomain[1], "//")[1]
|
||||||
|
|
||||||
|
if state.Verbose == true {
|
||||||
|
if state.Color == true {
|
||||||
|
fmt.Printf("\n[\033[31;1;4mNETCRAFT\033[0m] %s", finishedSub)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\n[NETCRAFT] %s", finishedSub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalSubdomains = append(globalSubdomains, finishedSub)
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have another page full of juicy subdomains
|
||||||
|
if strings.Contains(src, "Next page") {
|
||||||
|
// Checkout the link for the next page
|
||||||
|
re_next := regexp.MustCompile("<A href=\"(.*?)\"><b>Next page</b></a>")
|
||||||
|
match := re_next.FindStringSubmatch(src)
|
||||||
|
|
||||||
|
// Replace spaces with + characters in URL Query since they don't allow request to happen
|
||||||
|
finalQuery := strings.Replace(match[1], " ", "+", -1)
|
||||||
|
enumerate(state, "https://searchdns.netcraft.com"+finalQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, all subdomains found :-)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Query : Queries awesome Netcraft service for subdomains
|
// Query : Queries awesome Netcraft service for subdomains
|
||||||
|
@ -34,42 +90,11 @@ var netcraft_data netcraft_object
|
||||||
//
|
//
|
||||||
func Query(state *helper.State) (subdomains []string, err error) {
|
func Query(state *helper.State) (subdomains []string, err error) {
|
||||||
|
|
||||||
// Make a http request to Netcraft
|
// Query using first page. Everything from there would be recursive
|
||||||
resp, err := helper.GetHTTPResponse("https://searchdns.netcraft.com/?restriction=site+ends+with&host="+state.Domain+"&lookup=wait..&position=limited", 3000)
|
err = enumerate(state, "https://searchdns.netcraft.com/?restriction=site+ends+with&host="+state.Domain+"&lookup=wait..&position=limited")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return subdomains, err
|
return subdomains, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the response body
|
return globalSubdomains, nil
|
||||||
resp_body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return subdomains, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the json format
|
|
||||||
err = json.Unmarshal([]byte(resp_body), &threatcrowd_data)
|
|
||||||
if err != nil {
|
|
||||||
return subdomains, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append each subdomain found to subdomains array
|
|
||||||
for _, subdomain := range threatcrowd_data.Subdomains {
|
|
||||||
|
|
||||||
// Fix Wildcard subdomains containg asterisk before them
|
|
||||||
if strings.Contains(subdomain, "*.") {
|
|
||||||
subdomain = strings.Split(subdomain, "*.")[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.Verbose == true {
|
|
||||||
if state.Color == true {
|
|
||||||
fmt.Printf("\n[\033[31;1;4mTHREATCROWD\033[0m] %s", subdomain)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("\n[THREATCROWD] %s", subdomain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subdomains = append(subdomains, subdomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
return subdomains, nil
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue