├── README.md └── cloudhunter /README.md: -------------------------------------------------------------------------------- 1 | # CloudHunter 2 | -------------------------------------------------------------------------------- /cloudhunter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import requests, sys, optparse, os 4 | 5 | OKBLUE='\033[94m' 6 | OKRED='\033[91m' 7 | OKGREEN='\033[92m' 8 | OKORANGE='\033[93m' 9 | COLOR1='\033[95m' 10 | COLOR2='\033[96m' 11 | RESET='\x1b[0m' 12 | 13 | def logo(): 14 | version = "1.0" 15 | print ('') 16 | print (' _/ _/ _/ _/ ') 17 | print (' _/_/_/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ _/ _/ _/_/_/ _/_/_/_/ _/_/ _/ _/_/ ') 18 | print (' _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/ ') 19 | print ('_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ ') 20 | print (' _/_/_/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ _/_/_/ _/ _/ _/_/ _/_/_/ _/ ') 21 | print ('') 22 | print (OKORANGE + " + -- --=[CloudHunter by 1N3 - https://crowdshield.com" + RESET) 23 | print (RESET) 24 | 25 | logo() 26 | if len(sys.argv) < 2: 27 | print ("You need to specify a domain to check. Use --help for all options.") 28 | quit() 29 | else: 30 | parser = optparse.OptionParser() 31 | parser.add_option('-d', '--domain', 32 | action="store", dest="domain", 33 | help="Domain name to test", default="") 34 | 35 | parser.add_option('-w', '--wordlist', 36 | action="store", dest="wordlist", 37 | help="Wordlist of domains to test", default="") 38 | 39 | parser.add_option('-v', '--verbose', 40 | action="store", dest="verbose", 41 | help="Turn on verbose logging", default="") 42 | 43 | options, args = parser.parse_args() 44 | target = str(options.domain) 45 | wordlist = str(options.wordlist) 46 | verbose = str(options.verbose) 47 | cloudfronturl = 'http://coach.fitbit.com' 48 | 49 | if (len(wordlist) > 4): 50 | with open(wordlist) as f: 51 | urls = f.read().splitlines() 52 | for url in urls: 53 | 54 | 55 | if verbose == 'y': 56 | print(url) 57 | 58 | # LOOKING FOR CNAME S3 BUCKETS ON TARGET URL ########################################################### 59 | try: 60 | if verbose == 'y': 61 | print ("Looking for CloudFront CNAME's pointing to " + url) 62 | headers = {'Host':'%s' % url} 63 | params = '' 64 | r = requests.get(cloudfronturl, params=params, headers=headers) 65 | resp = r.text 66 | 67 | if "ListBucketResult" in str(resp): 68 | print(OKRED + '[+] 1 Host ' + url + ' has a CloudFront CNAME record pointing to a public S3 bucket!' + RESET) 69 | if verbose == 'y': 70 | print(resp) 71 | 72 | except: 73 | pass 74 | 75 | # LOOKING FOR TOP LEVEL S3 BUCKETS ON TARGET URL ######################################################## 76 | try: 77 | if verbose == 'y': 78 | print ('Checking for public S3 bucket on https://' + url + '.s3.amazonaws.com') 79 | r2 = requests.get('https://' + url + '.s3.amazonaws.com', timeout=2) 80 | resp2 = r2.text 81 | 82 | if "ListBucketResult" in str(resp2): 83 | print(OKRED + '[+] 2 Host ' + url + ' has a public S3 bucket registered to the url https://' + url + '.s3.amazonaws.com!' + RESET) 84 | if verbose == 'y': 85 | print(resp2) 86 | 87 | except: 88 | pass 89 | 90 | # LOOKING FOR TOP LEVEL S3 BUCKETS ON TARGET URL ######################################################## 91 | try: 92 | keyword = url.split(".")[-2] 93 | url3 = 'https://' + keyword + '.s3.amazonaws.com' 94 | if verbose == 'y': 95 | print ('Checking for public S3 bucket on ' + url3) 96 | r3 = requests.get('https://' + keyword + '.s3.amazonaws.com', timeout=2) 97 | resp3 = r3.text 98 | 99 | 100 | if "ListBucketResult" in str(resp3): 101 | print(OKRED + '[+] 3 Host ' + url + ' has a public S3 bucket registered to the url https://' + keyword + '.s3.amazonaws.com!' + RESET) 102 | if verbose == 'y': 103 | print(resp3) 104 | 105 | except: 106 | pass 107 | 108 | # LOOKING FOR DIRECT S3 BUCKETS ON TARGET URL ############################################################ 109 | try: 110 | r4 = requests.get('https://' + url, timeout=2) 111 | resp4 = r3.text 112 | if verbose == 'y': 113 | print ('Checking for public S3 bucket on https://' + url) 114 | 115 | if "ListBucketResult" in str(resp4): 116 | print(OKRED + '[+] 4 Host ' + url + ' has a public S3 bucket registered to the url https://' + url + '.s3.amazonaws.com!' + RESET) 117 | if verbose == 'y': 118 | print(resp4) 119 | 120 | except Exception as ex: 121 | pass 122 | 123 | else: 124 | 125 | if verbose == 'y': 126 | print(target) 127 | 128 | # LOOKING FOR CNAME S3 BUCKETS ON TARGET URL ########################################################### 129 | try: 130 | if verbose == 'y': 131 | print ("Looking for CloudFront CNAME's on " + target) 132 | headers = {'Host':'%s' % target} 133 | params = '' 134 | r = requests.get(cloudfronturl, params=params, headers=headers) 135 | resp = r.text 136 | 137 | if "ListBucketResult" in str(resp): 138 | print(OKRED + '[+] Host ' + target + ' has a CloudFront CNAME record pointing to a public S3 bucket!' + RESET) 139 | if verbose == 'y': 140 | print(resp) 141 | 142 | except: 143 | pass 144 | 145 | # LOOKING FOR TOP LEVEL S3 BUCKETS ON TARGET URL ######################################################## 146 | try: 147 | if verbose == 'y': 148 | print ('Checking for public S3 bucket on https://' + target + '.s3.amazonaws.com') 149 | r2 = requests.get('https://' + target + '.s3.amazonaws.com', timeout=2) 150 | resp2 = r2.text 151 | 152 | if "ListBucketResult" in str(resp2): 153 | print(OKRED + '[+] Host ' + target + ' has a public S3 bucket registered to the target https://' + target + '.s3.amazonaws.com!' + RESET) 154 | if verbose == 'y': 155 | print(resp2) 156 | 157 | except: 158 | pass 159 | 160 | # LOOKING FOR TOP LEVEL S3 BUCKETS ON TARGET URL ########################################################## 161 | try: 162 | keyword = target.split(".")[-2] 163 | target3 = 'https://' + keyword + '.s3.amazonaws.com' 164 | if verbose == 'y': 165 | print ('Checking for public S3 bucket on ' + target3) 166 | r3 = requests.get('https://' + keyword + '.s3.amazonaws.com', timeout=2) 167 | resp3 = r3.text 168 | 169 | 170 | if "ListBucketResult" in str(resp3): 171 | print(OKRED + '[+] Host ' + target + ' has a public S3 bucket registered to the url https://' + keyword + '.s3.amazonaws.com!' + RESET) 172 | if verbose == 'y': 173 | print(resp3) 174 | 175 | except: 176 | pass 177 | 178 | # LOOKING FOR DIRECT S3 BUCKETS ON TARGET URL ############################################################ 179 | try: 180 | r4 = requests.get('https://' + target, timeout=2) 181 | resp4 = r3.text 182 | if verbose == 'y': 183 | print ('Checking for public S3 bucket on https://' + target) 184 | 185 | if "ListBucketResult" in str(resp4): 186 | print(OKRED + '[+] Host ' + target + ' has a public S3 bucket registered to the url https://' + target + '!' + RESET) 187 | if verbose == 'y': 188 | print(resp4) 189 | 190 | except Exception as ex: 191 | pass --------------------------------------------------------------------------------