├── subover.png ├── LICENSE ├── .gitignore ├── README.md ├── subover.go └── providers.json /subover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ice3man543/SubOver/HEAD/subover.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, Nizamul Rana 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | .static_storage/ 57 | .media/ 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # mkdocs documentation 102 | /site 103 | 104 | # mypy 105 | .mypy_cache/ 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SubOver 2 | ## Note - This project is discontinued. No more updates will be provided! Sorry! 3 | > But something more awesome will come soon! 4 | 5 | Subover is a Hostile Subdomain Takeover tool originally written in python but rewritten from scratch in Golang. Since it's redesign, it has been aimed with speed and efficiency in mind. Till date, SubOver detects 30+ services which is much more than any other tool out there. The tool uses Golang concurrency and hence is very fast. It can easily detect and report potential subdomain takeovers that exist. The list of potentially hijackable services is very comprehensive and it is what makes this tool so powerful. 6 | 7 | ## Installing 8 | 9 | You need to have Golang installed on your machine. There are no additional requirements for this tool. 10 | 11 | ```sh 12 | go get github.com/Ice3man543/SubOver 13 | ``` 14 | 15 | > NOTE - Do not change the location of providers.json file. Or the tool will not work. 16 | 17 | ## Usage 18 | 19 | ` ./SubOver -l subdomains.txt` 20 | - `-l` List of Subdomains 21 | - `-a` Check all hosts regardless of CNAME (Time Consuming and prone to fp's) 22 | - `-t` Number of concurrent threads. (Default 10) 23 | - `-v` Show verbose output (Default False) 24 | - `-https` Force HTTPS Connection (Default HTTP) 25 | - `-timeout` Set custom timeout (Default 10) 26 | - `-h` Show help message 27 | 28 | ## Currently Checked Services 29 | 30 | > Github, Heroku, Unbounce, Tumblr, Shopify, Instapage, Desk, Tictail, Campaignmonitor, Cargocollective, Statuspage, Amazonaws, Cloudfront, Bitbucket, Smartling, Acquia, Fastly, Pantheon, Zendesk, Uservoice, Ghost, Freshdesk, Pingdom, Tilda, Wordpress, Teamwork, Helpjuice, Helpscout, Cargo, Feedpress, Surge, Surveygizmo, Mashery, Intercom, Webflow, Kajabi, Thinkific, Tave, Wishpond, Aftership, Aha, Brightcove, Bigcartel, Activecompaign, Compaignmonitor, Acquia, Proposify, Simplebooklet, Getresponse, Vend, Jetbrains, Azure 31 | 32 | Count : 51 33 | 34 | ## Screenshot 35 | ![tool_in_action](https://raw.githubusercontent.com/Ice3man543/SubOver/master/subover.png) 36 | 37 | ## FAQ 38 | **Q:** What should my wordlist look like? 39 | 40 | **A:** Your wordlist should include a list of subdomains you're checking and should look something like: 41 | ``` 42 | backend.example.com 43 | something.someone.com 44 | apo-setup.fxc.something.com 45 | ``` 46 | 47 | ## Your tool sucks! 48 | 49 | Yes, you're probably correct. Feel free to: 50 | 51 | - Not use it. 52 | - Show me how to do it better. 53 | 54 | ## TODO 55 | 56 | - Add more services :-) 57 | - Improve the tool (There are many things that can be done :-) ) 58 | 59 | ## Development 60 | 61 | Want to contribute? Great! 62 | 63 | You can add more services or recommend any changes to the existing ones. Any kind of help is appreciated. 64 | 65 | Or buy me a coffee \o/ 66 | 67 | [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/Ice3man) 68 | [![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/M4M7FAVC) 69 | 70 | License 71 | ---- 72 | 73 | BSD 2-Clause "Simplified" License 74 | 75 | 76 | ## Contact 77 | 78 | Meet me on Twitter: [![Twitter](https://img.shields.io/badge/twitter-@ice3man543-blue.svg)](https://twitter.com/ice3man543) 79 | 80 | ## Changelog 81 | 82 | ### [1.2] 2018-05-19 83 | - Refactored whole code making it cleaner 84 | - Added better error handling and more verbose stuff 85 | - Implemented checking all domains 86 | - Fixed other stuff, etc... 87 | 88 | ### [1.1.1] - 2018-03-20 89 | 90 | - Providers corrected using EdOverflow's Awesome List 91 | - Added Information regarding various takeovers to the tool 92 | 93 | ### [1.1.0] - 2018-03-16 94 | 95 | - Rewritten from scratch in Golang 96 | - This time it's damn fast because of Go Concurrency. 97 | - The console output looks better :-) 98 | 99 | ### [1.0.0] - 2018-02-04 100 | 101 | - Initial Release with 35 Services written in Python. 102 | - Pretty Slow :-) 103 | 104 | ## Credits 105 | 106 | - [subjack : Hostile Subdomain Takeover Tool Written In GO](https://github.com/haccer/subjack) 107 | - [Subdomain Takeover Scanner by 0x94](https://github.com/antichown/subdomain-takeover) 108 | - [Anshumanbh : tko-subs](https://github.com/anshumanbh/tko-subs) 109 | - [EdOverflow : can-i-take-over-xyz](https://github.com/edoverflow/can-i-take-over-xyz) 110 | -------------------------------------------------------------------------------- /subover.go: -------------------------------------------------------------------------------- 1 | // SubOver is a tool for discovering subdomain takeovers 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "crypto/tls" 7 | "encoding/json" 8 | "flag" 9 | "fmt" 10 | "github.com/parnurzeal/gorequest" 11 | "io/ioutil" 12 | "log" 13 | "net" 14 | "os" 15 | "strings" 16 | "sync" 17 | "time" 18 | ) 19 | 20 | // Structure for each provider stored in providers.json file 21 | type ProviderData struct { 22 | Name string `json:"name"` 23 | Cname []string `json:"cname"` 24 | Response []string `json:"response"` 25 | } 26 | 27 | var Providers []ProviderData 28 | 29 | var Targets []string 30 | 31 | var ( 32 | HostsList string 33 | Threads int 34 | All bool 35 | Verbose bool 36 | ForceHTTPS bool 37 | Timeout int 38 | OutputFile string 39 | ) 40 | 41 | func InitializeProviders() { 42 | raw, err := ioutil.ReadFile("providers.json") 43 | if err != nil { 44 | fmt.Println(err.Error()) 45 | os.Exit(1) 46 | } 47 | 48 | err = json.Unmarshal(raw, &Providers) 49 | if err != nil { 50 | fmt.Printf("%s", err) 51 | os.Exit(1) 52 | } 53 | } 54 | 55 | func ReadFile(file string) (lines []string, err error) { 56 | fileHandle, err := os.Open(file) 57 | if err != nil { 58 | return lines, err 59 | } 60 | 61 | defer fileHandle.Close() 62 | fileScanner := bufio.NewScanner(fileHandle) 63 | 64 | for fileScanner.Scan() { 65 | lines = append(lines, fileScanner.Text()) 66 | } 67 | 68 | return lines, nil 69 | } 70 | 71 | func Get(url string, timeout int, https bool) (resp gorequest.Response, body string, errs []error) { 72 | if https == true { 73 | url = fmt.Sprintf("https://%s/", url) 74 | } else { 75 | url = fmt.Sprintf("http://%s/", url) 76 | } 77 | 78 | resp, body, errs = gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}). 79 | Timeout(time.Duration(timeout)*time.Second).Get(url). 80 | Set("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"). 81 | End() 82 | 83 | return resp, body, errs 84 | } 85 | 86 | func ParseArguments() { 87 | flag.IntVar(&Threads, "t", 20, "Number of threads to use") 88 | flag.StringVar(&HostsList, "l", "", "List of hosts to check takeovers on") 89 | flag.BoolVar(&All, "a", false, "Check all hosts regardless of CNAME") 90 | flag.BoolVar(&Verbose, "v", false, "Show verbose output") 91 | flag.BoolVar(&ForceHTTPS, "https", false, "Force HTTPS connections (Default: http://)") 92 | flag.IntVar(&Timeout, "timeout", 10, "Seconds to wait before timeout") 93 | flag.StringVar(&OutputFile, "o", "", "File to write enumeration output to") 94 | 95 | flag.Parse() 96 | } 97 | 98 | func CNAMEExists(key string) bool { 99 | for _, provider := range Providers { 100 | for _, cname := range provider.Cname { 101 | if strings.Contains(key, cname) { 102 | return true 103 | } 104 | } 105 | } 106 | 107 | return false 108 | } 109 | 110 | func Check(target string, TargetCNAME string) { 111 | _, body, errs := Get(target, Timeout, ForceHTTPS) 112 | if len(errs) <= 0 { 113 | if TargetCNAME == "ALL" { 114 | for _, provider := range Providers { 115 | for _, response := range provider.Response { 116 | if strings.Contains(body, response) == true { 117 | fmt.Printf("\n[\033[31;1;4m%s\033[0m] Takeover Possible At %s ", provider.Name, target) 118 | return 119 | } 120 | } 121 | } 122 | } else { 123 | // This is a less false positives way 124 | for _, provider := range Providers { 125 | for _, cname := range provider.Cname { 126 | if strings.Contains(TargetCNAME, cname) { 127 | for _, response := range provider.Response { 128 | if strings.Contains(body, response) == true { 129 | if provider.Name == "cloudfront" { 130 | _, body2, _ := Get(target, 120, true) 131 | if strings.Contains(body2, response) == true { 132 | fmt.Printf("\n[\033[31;1;4m%s\033[0m] Takeover Possible At : %s", provider.Name, target) 133 | } 134 | } else { 135 | fmt.Printf("\n[\033[31;1;4m%s\033[0m] Takeover Possible At %s with CNAME %s", provider.Name, target, TargetCNAME) 136 | } 137 | } 138 | return 139 | } 140 | } 141 | } 142 | } 143 | } 144 | } else { 145 | if Verbose == true { 146 | log.Printf("[ERROR] Get: %s => %v", target, errs) 147 | } 148 | } 149 | 150 | return 151 | } 152 | 153 | func Checker(target string) { 154 | TargetCNAME, err := net.LookupCNAME(target) 155 | if err != nil { 156 | return 157 | } else { 158 | if All != true && CNAMEExists(TargetCNAME) == true { 159 | if Verbose == true { 160 | log.Printf("[SELECTED] %s => %s", target, TargetCNAME) 161 | } 162 | Check(target, TargetCNAME) 163 | } else if All == true { 164 | if Verbose == true { 165 | log.Printf("[ALL] %s ", target) 166 | } 167 | Check(target, "ALL") 168 | } 169 | } 170 | } 171 | 172 | func main() { 173 | ParseArguments() 174 | 175 | fmt.Println("") 176 | fmt.Println("SubOver v.1.2 Nizamul Rana (@Ice3man)") 177 | fmt.Println("==================================================\n") 178 | 179 | if HostsList == "" { 180 | fmt.Printf("SubOver: No hosts list specified for testing!") 181 | fmt.Printf("\nUse -h for usage options\n") 182 | os.Exit(1) 183 | } 184 | 185 | InitializeProviders() 186 | Hosts, err := ReadFile(HostsList) 187 | if err != nil { 188 | fmt.Printf("\nread: %s\n", err) 189 | os.Exit(1) 190 | } 191 | 192 | Targets = append(Targets, Hosts...) 193 | 194 | hosts := make(chan string, Threads) 195 | processGroup := new(sync.WaitGroup) 196 | processGroup.Add(Threads) 197 | 198 | for i := 0; i < Threads; i++ { 199 | go func() { 200 | for { 201 | host := <-hosts 202 | if host == "" { 203 | break 204 | } 205 | 206 | Checker(host) 207 | } 208 | 209 | processGroup.Done() 210 | }() 211 | } 212 | 213 | for _, Host := range Targets { 214 | hosts <- Host 215 | } 216 | 217 | close(hosts) 218 | processGroup.Wait() 219 | 220 | fmt.Printf("\n[~] Enjoy your hunt !\n") 221 | } 222 | -------------------------------------------------------------------------------- /providers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"github", 4 | "cname":["github.io", "github.map.fastly.net"], 5 | "response":["There isn't a GitHub Pages site here.", "For root URLs (like http://example.com/) you must provide an index.html file"] 6 | }, 7 | { 8 | "name":"heroku", 9 | "cname":["herokudns.com", "herokussl.com", "herokuapp.com"], 10 | "response":["There's nothing here, yet.", "herokucdn.com/error-pages/no-such-app.html", "No such app"] 11 | }, 12 | { 13 | "name":"unbounce", 14 | "cname":["unbouncepages.com"], 15 | "response":["The requested URL / was not found on this server.", "The requested URL was not found on this server"] 16 | }, 17 | { 18 | "name":"tumblr", 19 | "cname":["tumblr.com"], 20 | "response":["There's nothing here.", "Whatever you were looking for doesn't currently exist at this address."] 21 | }, 22 | { 23 | "name":"shopify", 24 | "cname":["myshopify.com"], 25 | "response":["Sorry, this shop is currently unavailable.", "Only one step left!"] 26 | }, 27 | { 28 | "name":"instapage", 29 | "cname":["pageserve.co", "secure.pageserve.co", "https://instapage.com/"], 30 | "response":["You've Discovered A Missing Link. Our Apologies!"] 31 | }, 32 | { 33 | "name":"desk", 34 | "cname":["desk.com"], 35 | "response":["Please try again or try Desk.com free for 14 days.", "Sorry, We Couldn't Find That Page"] 36 | }, 37 | { 38 | "name":"tictail", 39 | "cname":["tictail.com", "domains.tictail.com"], 40 | "response":["Building a brand of your own?", "to target URL: Trying to access your account?"] 46 | }, 47 | { 48 | "name":"cargocollective", 49 | "cname":["cargocollective.com"], 50 | "response":["404 Not Found"] 51 | }, 52 | { 53 | "name":"statuspage", 54 | "cname":["statuspage.io"], 55 | "response":["Better Status Communication", "You are being redirected"] 56 | }, 57 | { 58 | "name":"amazonaws", 59 | "cname":["amazonaws.com"], 60 | "response":["NoSuchBucket", "The specified bucket does not exist"] 61 | }, 62 | { 63 | "name":"cloudfront", 64 | "cname":["cloudfront.net"], 65 | "response":["The request could not be satisfied", "ERROR: The request could not be satisfied"] 66 | }, 67 | { 68 | "name":"bitbucket", 69 | "cname":["bitbucket.org"], 70 | "response":["The page you have requested does not exist"] 71 | }, 72 | { 73 | "name":"smartling", 74 | "cname":["smartling.com"], 75 | "response":["Domain is not configured"] 76 | }, 77 | { 78 | "name":"acquia", 79 | "cname":["acquia.com"], 80 | "response":["If you are an Acquia Cloud customer and expect to see your site at this address"] 81 | }, 82 | { 83 | "name":"fastly", 84 | "cname":["fastly.net"], 85 | "response":["Please check that this domain has been added to a service", "Fastly error: unknown domain"] 86 | }, 87 | { 88 | "name":"pantheon", 89 | "cname":["pantheonsite.io"], 90 | "response":["The gods are wise", "The gods are wise, but do not know of the site which you seek."] 91 | }, 92 | { 93 | "name":"zendesk", 94 | "cname":["zendesk.com"], 95 | "response":["Help Center Closed | Zendesk", "Help Center Closed"] 96 | }, 97 | { 98 | "name":"uservoice", 99 | "cname":["uservoice.com"], 100 | "response":["This UserVoice subdomain is currently available!"] 101 | }, 102 | { 103 | "name":"ghost", 104 | "cname":["ghost.io"], 105 | "response":["The thing you were looking for is no longer here", "The thing you were looking for is no longer here, or never was"] 106 | }, 107 | { 108 | "name":"pingdom", 109 | "cname":["stats.pingdom.com"], 110 | "response":["pingdom"] 111 | }, 112 | { 113 | "name":"tilda", 114 | "cname":["tilda.ws"], 115 | "response":["Domain has been assigned"] 116 | }, 117 | { 118 | "name":"wordpress", 119 | "cname":["wordpress.com"], 120 | "response":["Do you want to register"] 121 | }, 122 | { 123 | "name":"teamwork", 124 | "cname":["teamwork.com"], 125 | "response":["Oops - We didn't find your site."] 126 | }, 127 | { 128 | "name":"helpjuice", 129 | "cname":["helpjuice.com"], 130 | "response":["We could not find what you're looking for."] 131 | }, 132 | { 133 | "name":"helpscout", 134 | "cname":["helpscoutdocs.com"], 135 | "response":["No settings were found for this company:"] 136 | }, 137 | { 138 | "name":"cargo", 139 | "cname":["cargocollective.com"], 140 | "response":["If you're moving your domain away from Cargo you must make this configuration through your registrar's DNS control panel."] 141 | }, 142 | { 143 | "name":"feedpress", 144 | "cname":["redirect.feedpress.me"], 145 | "response":["The feed has not been found."] 146 | }, 147 | { 148 | "name":"surge", 149 | "cname":["surge.sh"], 150 | "response":["project not found"] 151 | }, 152 | { 153 | "name":"surveygizmo", 154 | "cname":["privatedomain.sgizmo.com", "privatedomain.surveygizmo.eu", "privatedomain.sgizmoca.com"], 155 | "response":["data-html-name"] 156 | }, 157 | { 158 | "name":"mashery", 159 | "cname":["mashery.com"], 160 | "response":["Unrecognized domain "] 161 | }, 162 | { 163 | "name":"intercom", 164 | "cname":["custom.intercom.help"], 165 | "response":["This page is reserved for artistic dogs.","

Uh oh. That page doesn’t exist.

"] 166 | }, 167 | { 168 | "name":"webflow", 169 | "cname":["proxy.webflow.io"], 170 | "response":["

The page you are looking for doesn't exist or has been moved.

"] 171 | }, 172 | { 173 | "name":"kajabi", 174 | "cname":["endpoint.mykajabi.com"], 175 | "response":["

The page you were looking for doesn't exist.

"] 176 | }, 177 | { 178 | "name":"thinkific", 179 | "cname":["thinkific.com"], 180 | "response":["You may have mistyped the address or the page may have moved."] 181 | }, 182 | { 183 | "name":"tave", 184 | "cname":["clientaccess.tave.com"], 185 | "response":["

Error 404: Page Not Found

"] 186 | }, 187 | { 188 | "name":"wishpond", 189 | "cname":["wishpond.com"], 190 | "response":["https://www.wishpond.com/404?campaign=true"] 191 | }, 192 | { 193 | "name":"aftership", 194 | "cname":["aftership.com"], 195 | "response":["Oops.

The page you're looking for doesn't exist."] 196 | }, 197 | { 198 | "name":"aha", 199 | "cname":["ideas.aha.io"], 200 | "response":["There is no portal here ... sending you back to Aha!"] 201 | }, 202 | { 203 | "name":"brightcove", 204 | "cname":["brightcovegallery.com", "gallery.video", "bcvp0rtal.com"], 205 | "response":["

"] 206 | }, 207 | { 208 | "name":"bigcartel", 209 | "cname":["bigcartel.com"], 210 | "response":["

Oops! We couldn’t find that page.

"] 211 | }, 212 | { 213 | "name":"activecompaign", 214 | "cname":["activehosted.com"], 215 | "response":["alt=\"LIGHTTPD - fly light.\""] 216 | }, 217 | { 218 | "name":"compaignmonitor", 219 | "cname":["createsend.com"], 220 | "response":["Double check the URL or