├── README.md ├── requirements.txt └── source-founder.py /README.md: -------------------------------------------------------------------------------- 1 | # source-founder 2 | check if the source code compressed and uploaded to the server by mistake 3 | # Discription 4 | - Some times the developer (by mistake) upload the source code of the subdomain to the server and it is accessible by anyone ( information disclosure vulnerability ) 5 | - So i decided not to waste time on this step of recon and automate it with this tool 6 | - This tool take a list of subdomains and check for the source code with multiple compressed extensions ( "zip","bak","tar","gizp","rar","7z","iso","bz2","gz","apk","cab","jar","bzip2","deb","ace") and you could add any other extension to this list and check for the response code for each file like this http://www.example.com ==> http://www.example.com/www.example.com.zip , http://www.example.com/www.example.com.rar ... etc 7 | - Some server respond with 200 response code even the file doesn't exist so to avoid false positive i have added that if the response code is 200 the tool get the content length and you could check if all extension give the same content length so this is a false positive 8 | - Also i made the output colorized so it is easy for your eyes to get the response code just by color 9 | 10 | # Install 11 | 12 | git clone https://github.com/smackerdodi/source-founder.git 13 | 14 | cd source-founder 15 | 16 | pip3 install -r requirements.txt 17 | 18 | # Usage 19 | 20 | python3 source-founder.py sub.txt output.txt 21 | 22 | sub.txt : File contain subdomains begin with http or https 23 | 24 | output.txt : File contain the output of the tool 25 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | futures 2 | requests 3 | thread6 4 | sys 5 | time 6 | colorama 7 | urllib3 8 | -------------------------------------------------------------------------------- /source-founder.py: -------------------------------------------------------------------------------- 1 | import concurrent.futures 2 | import requests 3 | import threading 4 | import sys 5 | import time 6 | from colorama import Fore, Style 7 | from urllib.parse import urlparse 8 | extensions = ["zip","bak","tar","gizp","rar","7z","iso","bz2","gz","apk","cab","jar","bzip2","deb","ace"] 9 | inputfile=sys.argv[1] 10 | outputfile=sys.argv[2] 11 | output=open(outputfile, "a") 12 | with open(inputfile, "r") as f: 13 | inputurl = [line.rstrip() for line in f] 14 | threadLocal = threading.local() 15 | count = len(inputurl) 16 | print("number of urls = " + str(count)) 17 | def get_session(): 18 | if not hasattr(threadLocal, "session"): 19 | threadLocal.session = requests.Session() 20 | return threadLocal.session 21 | def check_sub(url): 22 | try : 23 | session=get_session() 24 | subd = urlparse(url.strip()).netloc 25 | url2 = url.strip() + "/" + subd 26 | for ext in extensions : 27 | url3 = url2 + "." + ext 28 | res=session.get(url3, timeout=1, allow_redirects=False) 29 | if str(res.status_code)[0] == "3": 30 | res3=url3 + " : " + str(res.status_code) 31 | print(Style.BRIGHT + Fore.WHITE + (url3)+ " : " + Fore.BLUE + str(res.status_code)) 32 | output.write(res3 +"\n") 33 | elif str(res.status_code)[0] == "2": 34 | res2=url3 + " : " + str(res.status_code) + " : " + res.headers['Content-Length'] 35 | print(Style.BRIGHT + Fore.GREEN + (url3)+ " : " + str(res.status_code) + " : " + res.headers['Content-Length'] + " bytes") 36 | output.write(res2 +"\n") 37 | elif str(res.status_code)[0] == "4": 38 | res4=url3 + " : " + str(res.status_code) 39 | print(Style.BRIGHT + Fore.WHITE + (url3)+ " : " + Fore.YELLOW + str(res.status_code)) 40 | output.write(res4 +"\n") 41 | elif str(res.status_code)[0] == "5": 42 | res5=url3 + " : " + str(res.status_code) 43 | print(Style.BRIGHT + Fore.WHITE + (url3)+ " : " + Fore.RED + str(res.status_code)) 44 | output.write(res5 +"\n") 45 | else : 46 | res6=url3 + " : " + str(res.status_code) 47 | print(Style.BRIGHT + Fore.WHITE + (url3)+ " : " + Fore.RED + str(res.status_code)) 48 | output.write(res6 +"\n") 49 | except: 50 | print(Style.BRIGHT + Fore.WHITE + (url3)+ " : " + Fore.RED+ " : is unreachable") 51 | def itterate_url(inputurl): 52 | url=inputurl 53 | check_sub(url) 54 | 55 | if __name__ == "__main__": 56 | start_time = time.time() 57 | with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: 58 | executor.map(itterate_url, inputurl) 59 | duration = time.time() - start_time 60 | print("finished in : " + str(duration) + " sec") 61 | --------------------------------------------------------------------------------