Repository: Warflop/CloudBunny Branch: master Commit: 5cf385ab93c9 Files: 8 Total size: 12.9 KB Directory structure: gitextract_powpurr8/ ├── LICENSE ├── README.md ├── api.conf ├── censys_search.py ├── cloudbunny.py ├── requirements.txt ├── shodan_search.py └── zoomeye_search.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Eddy Oliveira Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # CloudBunny CloudBunny is a tool to capture the origin server that uses a WAF as a proxy or protection. You can read more about the tool here: https://tinyurl.com/y8p48wb3

# How works In this tool we used three search engines to search domain information: Shodan, Censys and Zoomeye. To use the tools you need the API Keys, you can pick up the following links:
Shodan - https://account.shodan.io/
Censys - https://censys.io/account/api
ZoomEye - https://www.zoomeye.org/profile
NOTE: In Zoomeye you need to enter the login and password, it generates a dynamic api key and I already do this work for you. Just enter your login and password. After that you need to put the credentials in the api.conf file. Install the requirements:
$ pip3 install -r requirements.txt
# Usage By default the tool searches on all search engines (you can set this up by arguments), but you need to put the credentials as stated above. After you have loaded the credentials and installed the requirements, execute:
$ python3 cloudbunny.py -u securityattack.com.br
Check our help area:
$ python3 cloudbunny.py -h
Change securityattack.com.br for the domain of your choice. # Example

$ python3 cloudbunny.py -u site_example.com.br

	            /|      __  
	           / |   ,-~ /  
	          Y :|  //  /    
	          | jj /( .^  
	          >-"~"-v"  
	         /       Y    
	        jo  o    |  
	       ( ~T~     j   
	        >._-' _./   
	       /   "~"  |    
	      Y     _,  |      
	     /| ;-"~ _  l    
	    / l/ ,-"~    \  
	    \//\/      .- \  
	     Y        /    Y*  
	     l       I     ! 
	     ]\      _\    /"\ 
	    (" ~----( ~   Y.  )   
	~~~~~~~~~~~~~~~~~~~~~~~~~~    
CloudBunny - Bypass WAF with Search Engines 
Author: Eddy Oliveira (@Warflop)
https://github.com/Warflop 
    
[+] Looking for target on Shodan...
[+] Looking for target on Censys...
[+] Looking for certificates on Censys...
[+] Looking for target on ZoomEye...
[-] Just more some seconds...


+---------------+------------+-----------+----------------------------+
|   IP Address  |    ISP     |   Ports   |        Last Update         |
+---------------+------------+-----------+----------------------------+
|  55.14.232.4  | Amazon.com | [80, 443] | 2018-11-02T16:02:51.074543 |
| 54.222.146.40 | Amazon.com |    [80]   | 2018-11-02T10:16:38.166829 |
| 18.235.52.237 | Amazon.com | [443, 80] | 2018-11-08T01:22:11.323980 |
| 54.237.93.127 | Amazon.com | [443, 80] | 2018-11-05T15:54:40.248599 |
| 53.222.94.157 | Amazon.com | [443, 80] | 2018-11-06T08:46:03.377082 |
+---------------+------------+-----------+----------------------------+
    We may have some false positives :)
================================================ FILE: api.conf ================================================ [shodan] token = [censys] token = uid = [zoomeye] username = password = ================================================ FILE: censys_search.py ================================================ from __future__ import print_function from urllib.parse import urlsplit import censys.certificates import configparser import censys.ipv4 import re config = configparser.ConfigParser() config.read("api.conf") TOKEN = config.get('censys', 'token') UID = config.get('censys', 'uid') def split_url(url): if re.match(r'http(s?)\:', url): parsed = urlsplit(url) return parsed.netloc else: return url def censys_search(title): try: api = censys.ipv4.CensysIPv4(api_id=UID, api_secret=TOKEN) query = api.search('80.http.get.title: "{0}"'.format(title)) title_result = set([host['ip'] for host in query]) if title_result: return title_result except: print("[-] We got an error here, maybe with your credentials!") exit(1) def censys_search_certs(host): try: certificates = censys.certificates.CensysCertificates(api_id=UID, api_secret=TOKEN) cert_query = certificates.search("parsed.names: {0} AND tags.raw: trusted AND NOT parsed.names: cloudflaressl.com".format(host)) result = set([cert['parsed.fingerprint_sha256'] for cert in cert_query]) hosts_query = censys.ipv4.CensysIPv4(api_id=UID, api_secret=TOKEN) hosts = ' OR '.join(result) if hosts: searching = hosts_query.search(hosts) host_result = set([ search_result['ip'] for search_result in searching ]) return host_result except: print("[-] We got an error here, maybe with your credentials!") exit(1) ================================================ FILE: cloudbunny.py ================================================ from __future__ import print_function from bs4 import BeautifulSoup from zoomeye_search import * from shodan_search import * from censys_search import * from random import choice import cfscrape import argparse import re def banner(): color = ['\033[95m' , '\033[96m', '\033[36m' , '\033[94m' , '\033[92m' , '\033[93m' , '\033[91m'] print(choice(color) + ''' _ (` ). _ ( ). .:(` )`. ) _( '`. :( . ) .=(`( . ) .-- `. ( ) ) (( (..__.:'-' .+( ) ` _` ) ) `. `( ) ) ( . ) ( ) ._ ) ` __.:' ) ( ( )) `-'.-(` ) ) ) ( ) --' `- __.' :( )) .-' (_.' .') `( ) )) (_ ) ` __.:' /| __ / | ,-~ / Y :| // / | jj /( .^ >-"~"-v" / Y jo o | ( ~T~ j >._-' _./ / "~" | Y _, | /| ;-"~ _ l / l/ ,-"~ \ \//\/ .- \ Y / Y* l I ! ]\ _\ /"\ (" ~----( ~ Y. ) ~~~~~~~~~~~~~~~~~~~~~~~~~~ CloudBunny - Bypass WAF with Search Engines Author: Eddy Oliveira (@Warflop) https://github.com/Warflop \033[0m ''') def banner_footer(): color = ['\033[95m' , '\033[96m', '\033[36m' , '\033[94m' , '\033[92m' , '\033[93m' , '\033[91m'] print(choice(color) + ''' /\\=//\-"""-. / /6 6\ \ \ =\_Y_/= (_ ;{} /^//_/-/__/ "" "" """ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We may have some false positives :) \033[0m ''') def search(url): headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'} try: if not re.match(r'http(s?)\:', url): url = 'http://' + url scraper = cfscrape.create_scraper() data = scraper.get(url,headers=headers) else: scraper = cfscrape.create_scraper() data = scraper.get(url,headers=headers) except: print("Hey buddy, pass a real address please!") exit(1) if data.status_code == 200: soup = BeautifulSoup(data.text,'html.parser') for link in soup.title: return link else: print("We had a problem with the URL!") exit(1) def main(): resolver = [] parser = argparse.ArgumentParser() parser.add_argument("-u", '--url', help="Hey buddy, can you give me the URL to test?") parser.add_argument("-s", '--shodan', action="store_true", help="Use Shodan") parser.add_argument("-c", '--censys', action="store_true", help="Use Censys") parser.add_argument("-z", '--zoomeye', action="store_true", help="Use ZoomEye") args = parser.parse_args() title = search(args.url).encode('utf-8') host = split_url(args.url) if args.shodan or args.censys or args.zoomeye: if args.shodan: banner() print("[+] Looking for target on Shodan...") if not shodan_search(title) is None: for shodan_target in shodan_search(title): if not shodan_target in resolver: resolver.append(shodan_target) if args.censys: print("[+] Looking for target on Censys...") if not censys_search(title) is None: for censys_target in censys_search(title): if not censys_target in resolver: resolver.append(censys_target) print("[+] Looking for certificates on Censys...") if not censys_search_certs(host) is None: for censys_target_cert in censys_search_certs(host): if not censys_target_cert in resolver: resolver.append(censys_target_cert) if args.zoomeye: print("[+] Looking for target on ZoomEye...") if not zoomeye_search(title) is None: for zoomeye_target in zoomeye_search(title): if not zoomeye_target in resolver: resolver.append(zoomeye_target) if resolver: print("[*] We found some data wait just one more second...") print("\n") result_search(resolver) else: print("\n") print("[-] Looks like our rabbit has not gotten so deep. :(") banner_footer() else: banner() print("[+] Looking for target on Shodan...") if not shodan_search(title) is None: for shodan_target in shodan_search(title): if not shodan_target in resolver: resolver.append(shodan_target) print("[+] Looking for target on Censys...") if not censys_search(title) is None: for censys_target in censys_search(title): if not censys_target in resolver: resolver.append(censys_target) print("[+] Looking for certificates on Censys...") if not censys_search_certs(host) is None: for censys_target_cert in censys_search_certs(host): if not censys_target_cert in resolver: resolver.append(censys_target_cert) print("[+] Looking for target on ZoomEye...") if not zoomeye_search(title) is None: for zoomeye_target in zoomeye_search(title): if not zoomeye_target in resolver: resolver.append(zoomeye_target) if resolver: print("[-] Just more some seconds...") print("\n") result_search(resolver) else: print("\n") print("[-] Looks like our rabbit has not gotten so deep. :(") banner_footer() if __name__ == '__main__': main() ================================================ FILE: requirements.txt ================================================ beautifulsoup4 configparser PrettyTable cfscrape argparse requests censys shodan urllib zoomeye ================================================ FILE: shodan_search.py ================================================ from __future__ import print_function from prettytable import PrettyTable from shodan import Shodan import configparser import requests config = configparser.ConfigParser() config.read("api.conf") token = config.get('shodan', 'token') api = Shodan(token) def test_api_shodan(token): response = requests.get("https://api.shodan.io/api-info?key={0}".format(token)) if response.status_code != 200: print("[-] We got an error with your shodan credentials.") exit(1) def shodan_search(word): test_api_shodan(token) try: banner = api.search_cursor('http.title:"{0}"'.format(word)) title_result = set([host['ip_str'] for host in banner]) if title_result: return title_result except: print("[-] We got an error here!") exit(1) def result_search(list_host): table = PrettyTable(['IP Address','ISP','Ports','Last Update']) for check in list_host: try: host_result = api.host(check) table.add_row([host_result['ip_str'], host_result['isp'], host_result['ports'], host_result['last_update']]) except: print("[-] We got an error here!") exit(1) print(table) ================================================ FILE: zoomeye_search.py ================================================ from __future__ import print_function import requests import configparser config = configparser.ConfigParser() config.read("api.conf") username = config.get('zoomeye', 'username') password = config.get('zoomeye', 'password') def zoomeye_search(word): try: data = '{ "username": "'+username+'", "password": "'+password+'" }' response = requests.post('https://api.zoomeye.org/user/login', data=data) token = response.json()['access_token'] except: print("[-] We got an error with your zoomeye credentials. (Check if zoomeye is down ¯\_(ツ)_/¯)") exit(1) try: headers = { 'Authorization': 'JWT {0}'.format(token), } params = { ('query', 'title: "{0}"'.format(word)) } response = requests.get('https://api.zoomeye.org/host/search', headers=headers, params=params) final = response.json()['matches'] title_result = set([host['ip'] for host in final]) if title_result: return title_result except: print("[-] We got an error here!") exit(1)