[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Eddy Oliveira\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# CloudBunny\n\nCloudBunny is a tool to capture the origin server that uses a WAF as a proxy or protection.\n\nYou can read more about the tool here: https://tinyurl.com/y8p48wb3\n\n<p align=\"center\">\n<img src=\"https://i.imgur.com/CyGo02V.gif\">\n</p>\n\n# How works\n\nIn 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:\n\n<pre>\n<b>Shodan</b> - https://account.shodan.io/\n<b>Censys</b> - https://censys.io/account/api\n<b>ZoomEye</b> - https://www.zoomeye.org/profile\n</pre>\n\n<b>NOTE</b>: 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.\n\nAfter that you need to put the credentials in the <b>api.conf</b> file.\n\nInstall the requirements:\n\n<pre>\n$ pip3 install -r requirements.txt\n</pre>\n\n# Usage\n\nBy 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:\n\n<pre>\n$ python3 cloudbunny.py -u securityattack.com.br\n</pre>\n\nCheck our help area:\n\n<pre>\n$ python3 cloudbunny.py -h\n</pre>\n\nChange <b>securityattack.com.br</b> for the domain of your choice.\n\n# Example\n\n<pre>\n\n$ python3 cloudbunny.py -u site_example.com.br\n\n\t            /|      __  \n\t           / |   ,-~ /  \n\t          Y :|  //  /    \n\t          | jj /( .^  \n\t          >-\"~\"-v\"  \n\t         /       Y    \n\t        jo  o    |  \n\t       ( ~T~     j   \n\t        >._-' _./   \n\t       /   \"~\"  |    \n\t      Y     _,  |      \n\t     /| ;-\"~ _  l    \n\t    / l/ ,-\"~    \\  \n\t    \\//\\/      .- \\  \n\t     Y        /    Y*  \n\t     l       I     ! \n\t     ]\\      _\\    /\"\\ \n\t    (\" ~----( ~   Y.  )   \n\t~~~~~~~~~~~~~~~~~~~~~~~~~~    \nCloudBunny - Bypass WAF with Search Engines \nAuthor: Eddy Oliveira (@Warflop)\nhttps://github.com/Warflop \n    \n[+] Looking for target on Shodan...\n[+] Looking for target on Censys...\n[+] Looking for certificates on Censys...\n[+] Looking for target on ZoomEye...\n[-] Just more some seconds...\n\n\n+---------------+------------+-----------+----------------------------+\n|   IP Address  |    ISP     |   Ports   |        Last Update         |\n+---------------+------------+-----------+----------------------------+\n|  55.14.232.4  | Amazon.com | [80, 443] | 2018-11-02T16:02:51.074543 |\n| 54.222.146.40 | Amazon.com |    [80]   | 2018-11-02T10:16:38.166829 |\n| 18.235.52.237 | Amazon.com | [443, 80] | 2018-11-08T01:22:11.323980 |\n| 54.237.93.127 | Amazon.com | [443, 80] | 2018-11-05T15:54:40.248599 |\n| 53.222.94.157 | Amazon.com | [443, 80] | 2018-11-06T08:46:03.377082 |\n+---------------+------------+-----------+----------------------------+\n    We may have some false positives :)\n</pre>\n"
  },
  {
    "path": "api.conf",
    "content": "[shodan]\n\ntoken =\n\n[censys]\n\ntoken =\nuid =\n\n[zoomeye]\n\nusername =\npassword ="
  },
  {
    "path": "censys_search.py",
    "content": "from __future__ import print_function\nfrom urllib.parse import urlsplit \nimport censys.certificates\nimport configparser\nimport censys.ipv4\nimport re\n\nconfig = configparser.ConfigParser()\nconfig.read(\"api.conf\")\nTOKEN = config.get('censys', 'token')\nUID = config.get('censys', 'uid')\n\ndef split_url(url):\n    if re.match(r'http(s?)\\:', url):\n        parsed = urlsplit(url)\n        return parsed.netloc\n    else:\n        return url\n\ndef censys_search(title):\n    try:\n        api = censys.ipv4.CensysIPv4(api_id=UID, api_secret=TOKEN)\n        query = api.search('80.http.get.title: \"{0}\"'.format(title))\n        title_result = set([host['ip'] for host in query])\n        if title_result:\n            return title_result\n    except:\n        print(\"[-] We got an error here, maybe with your credentials!\")\n        exit(1)\n\n\ndef censys_search_certs(host):\n    try:\n        certificates = censys.certificates.CensysCertificates(api_id=UID, api_secret=TOKEN)\n\n        cert_query = certificates.search(\"parsed.names: {0} AND tags.raw: trusted AND NOT parsed.names: cloudflaressl.com\".format(host))        \n        result = set([cert['parsed.fingerprint_sha256'] for cert in cert_query])        \n        hosts_query = censys.ipv4.CensysIPv4(api_id=UID, api_secret=TOKEN)\n        hosts = ' OR '.join(result)\n        if hosts:\n            searching = hosts_query.search(hosts)\n            host_result = set([ search_result['ip'] for search_result in searching ])\n            return host_result\n    except:\n        print(\"[-] We got an error here, maybe with your credentials!\")\n        exit(1)"
  },
  {
    "path": "cloudbunny.py",
    "content": "from __future__ import print_function\nfrom bs4 import BeautifulSoup\nfrom zoomeye_search import *\nfrom shodan_search import *\nfrom censys_search import *\nfrom random import choice\nimport cfscrape\nimport argparse\nimport re\n\ndef banner():\n\n\tcolor = ['\\033[95m' , '\\033[96m', '\\033[36m' , '\\033[94m' , '\\033[92m' , '\\033[93m' , '\\033[91m']\n\n\tprint(choice(color) + ''' \n               _                                  \n              (`  ).                   _           \n             (     ).              .:(`  )`.       \n)           _(       '`.          :(   .    )      \n        .=(`(      .   )     .--  `.  (    ) )      \n       ((    (..__.:'-'   .+(   )   ` _`  ) )                 \n`.     `(       ) )       (   .  )     (   )  ._   \n  )      ` __.:'   )     (   (   ))     `-'.-(`  ) \n)  )  ( )       --'       `- __.'         :(      )) \n.-'  (_.'          .')                    `(    )  ))\n                  (_  )                     ` __.:'    \n\n\t            /|      __  \n\t           / |   ,-~ /  \n\t          Y :|  //  /    \n\t          | jj /( .^  \n\t          >-\"~\"-v\"  \n\t         /       Y    \n\t        jo  o    |  \n\t       ( ~T~     j   \n\t        >._-' _./   \n\t       /   \"~\"  |    \n\t      Y     _,  |      \n\t     /| ;-\"~ _  l    \n\t    / l/ ,-\"~    \\  \n\t    \\//\\/      .- \\  \n\t     Y        /    Y*  \n\t     l       I     ! \n\t     ]\\      _\\    /\"\\ \n\t    (\" ~----( ~   Y.  )   \n\t~~~~~~~~~~~~~~~~~~~~~~~~~~    \nCloudBunny - Bypass WAF with Search Engines \nAuthor: Eddy Oliveira (@Warflop)\nhttps://github.com/Warflop \\033[0m\n    ''')\n\ndef banner_footer():\n\n\tcolor = ['\\033[95m' , '\\033[96m', '\\033[36m' , '\\033[94m' , '\\033[92m' , '\\033[93m' , '\\033[91m']\n\n\tprint(choice(color) + ''' \n\n  /\\\\=//\\-\"\"\"-.        \n / /6 6\\ \\     \\        \n  =\\_Y_/=  (_  ;{}     \n    /^//_/-/__/      \n    \"\" \"\"  \"\"\"       \n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    We may have some false positives :)\n\\033[0m\n\t''')\n\ndef search(url):\n\n\theaders = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'}\n\n\ttry:\n\t\t\n\t\tif not re.match(r'http(s?)\\:', url):\n\t\t\turl = 'http://' + url\n\t\t\tscraper = cfscrape.create_scraper()\n\t\t\tdata  = scraper.get(url,headers=headers)\n\t\telse:\n\t\t\tscraper = cfscrape.create_scraper()\n\t\t\tdata  = scraper.get(url,headers=headers)\n\t\t\n\texcept:\n\n\t\tprint(\"Hey buddy, pass a real address please!\")\n\t\texit(1)\n\t\n\tif data.status_code == 200:\n\t\tsoup = BeautifulSoup(data.text,'html.parser')\n\t\tfor link in soup.title:\n\t\t\treturn link\n\telse:\n\t\tprint(\"We had a problem with the URL!\")\n\t\texit(1)\n\ndef main():\n\n\tresolver = []\n\tparser = argparse.ArgumentParser()\n\tparser.add_argument(\"-u\", '--url', help=\"Hey buddy, can you give me the URL to test?\")\n\tparser.add_argument(\"-s\", '--shodan', action=\"store_true\", help=\"Use Shodan\")\n\tparser.add_argument(\"-c\", '--censys', action=\"store_true\", help=\"Use Censys\")\n\tparser.add_argument(\"-z\", '--zoomeye', action=\"store_true\", help=\"Use ZoomEye\")\n\targs = parser.parse_args()\n\ttitle =\tsearch(args.url).encode('utf-8')\n\thost = split_url(args.url)\n\n\tif args.shodan or args.censys or args.zoomeye:\n\n\t\tif args.shodan:\n\t\t\tbanner()\n\t\t\tprint(\"[+] Looking for target on Shodan...\")\n\t\t\tif not shodan_search(title) is None:\n\t\t\t\tfor shodan_target in shodan_search(title):\n\t\t\t\t\tif not shodan_target in resolver:\n\t\t\t\t\t\tresolver.append(shodan_target)\n\n\t\tif args.censys:\n\t\t\tprint(\"[+] Looking for target on Censys...\")\n\t\t\tif not censys_search(title) is None:\n\t\t\t\tfor censys_target in censys_search(title):\n\t\t\t\t\tif not censys_target in resolver:\n\t\t\t\t\t\tresolver.append(censys_target)\n\t\t\n\t\t\tprint(\"[+] Looking for certificates on Censys...\")\n\t\t\tif not censys_search_certs(host) is None:\n\t\t\t\tfor censys_target_cert in censys_search_certs(host):\n\t\t\t\t\tif not censys_target_cert in resolver:\n\t\t\t\t\t\tresolver.append(censys_target_cert)\n\n\t\tif args.zoomeye:\n\t\t\tprint(\"[+] Looking for target on ZoomEye...\")\n\t\t\tif not zoomeye_search(title) is None:\n\t\t\t\tfor zoomeye_target in zoomeye_search(title):\n\t\t\t\t\tif not zoomeye_target in resolver:\n\t\t\t\t\t\tresolver.append(zoomeye_target)\n\n\t\tif resolver:\n\t\t\tprint(\"[*] We found some data wait just one more second...\")\n\t\t\tprint(\"\\n\")\n\t\t\tresult_search(resolver)\n\t\telse:\n\t\t\tprint(\"\\n\")\n\t\t\tprint(\"[-] Looks like our rabbit has not gotten so deep. :(\")\n\n\t\tbanner_footer()\n\n\telse:\n\t\t\tbanner()\n\t\t\tprint(\"[+] Looking for target on Shodan...\")\n\t\t\tif not shodan_search(title) is None:\n\t\t\t\tfor shodan_target in shodan_search(title):\n\t\t\t\t\tif not shodan_target in resolver:\n\t\t\t\t\t\tresolver.append(shodan_target)\n\n\t\t\tprint(\"[+] Looking for target on Censys...\")\n\t\t\tif not censys_search(title) is None:\n\t\t\t\tfor censys_target in censys_search(title):\n\t\t\t\t\tif not censys_target in resolver:\n\t\t\t\t\t\tresolver.append(censys_target)\n\t\t\n\t\t\tprint(\"[+] Looking for certificates on Censys...\")\n\t\t\tif not censys_search_certs(host) is None:\n\t\t\t\tfor censys_target_cert in censys_search_certs(host):\n\t\t\t\t\tif not censys_target_cert in resolver:\n\t\t\t\t\t\tresolver.append(censys_target_cert)\n\n\t\t\tprint(\"[+] Looking for target on ZoomEye...\")\n\t\t\tif not zoomeye_search(title) is None:\n\t\t\t\tfor zoomeye_target in zoomeye_search(title):\n\t\t\t\t\tif not zoomeye_target in resolver:\n\t\t\t\t\t\tresolver.append(zoomeye_target)\n\n\t\t\tif resolver:\n\t\t\t\tprint(\"[-] Just more some seconds...\")\n\t\t\t\tprint(\"\\n\")\n\t\t\t\tresult_search(resolver)\n\t\t\telse:\n\t\t\t\tprint(\"\\n\")\n\t\t\t\tprint(\"[-] Looks like our rabbit has not gotten so deep. :(\")\n\n\t\t\tbanner_footer()\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "requirements.txt",
    "content": "beautifulsoup4\nconfigparser\nPrettyTable\ncfscrape\nargparse\nrequests\ncensys\nshodan\nurllib\nzoomeye"
  },
  {
    "path": "shodan_search.py",
    "content": "from __future__ import print_function\nfrom prettytable import PrettyTable\nfrom shodan import Shodan\nimport configparser\nimport requests\n\nconfig = configparser.ConfigParser()\nconfig.read(\"api.conf\")\ntoken = config.get('shodan', 'token')\napi = Shodan(token)\n\ndef test_api_shodan(token):\n\n\tresponse = requests.get(\"https://api.shodan.io/api-info?key={0}\".format(token))\n\tif response.status_code != 200:\n\t\tprint(\"[-] We got an error with your shodan credentials.\")\n\t\texit(1)\t\t\n\ndef shodan_search(word):\n\n\ttest_api_shodan(token)\n\n\ttry:\n\n\t\tbanner = api.search_cursor('http.title:\"{0}\"'.format(word))\n\t\ttitle_result = set([host['ip_str'] for host in banner])\n\t\tif title_result:\n\t\t\treturn title_result\n\n\texcept:\n\n\t\tprint(\"[-] We got an error here!\")\n\t\texit(1)\n\ndef result_search(list_host):\n\n\ttable = PrettyTable(['IP Address','ISP','Ports','Last Update'])\n\n\tfor check in list_host:\n\t\ttry:\n\t\t\thost_result = api.host(check)\n\t\t\ttable.add_row([host_result['ip_str'], host_result['isp'], host_result['ports'], host_result['last_update']])\n\t\texcept:\n\t\t\tprint(\"[-] We got an error here!\")\n\t\t\texit(1)\t\t\t\n\n\tprint(table)\n"
  },
  {
    "path": "zoomeye_search.py",
    "content": "from __future__ import print_function\nimport requests\nimport configparser\n\nconfig = configparser.ConfigParser()\nconfig.read(\"api.conf\")\nusername = config.get('zoomeye', 'username')\npassword = config.get('zoomeye', 'password')\n\ndef zoomeye_search(word):\n\n\ttry:\n\n\t\tdata = '{ \"username\": \"'+username+'\", \"password\": \"'+password+'\" }'\n\t\tresponse = requests.post('https://api.zoomeye.org/user/login', data=data)\n\t\ttoken = response.json()['access_token']\n\n\texcept:\n\n\t\tprint(\"[-] We got an error with your zoomeye credentials. (Check if zoomeye is down ¯\\_(ツ)_/¯)\")\n\t\texit(1)\n\n\n\ttry:\n\n\t\theaders = {\n\t\t    'Authorization': 'JWT {0}'.format(token),\n\t\t}\n\n\t\tparams = {\n\t\t    ('query', 'title: \"{0}\"'.format(word))\n\t\t}\n\n\t\tresponse = requests.get('https://api.zoomeye.org/host/search', headers=headers, params=params)\n\t\tfinal = response.json()['matches']\n\t\ttitle_result = set([host['ip'] for host in final])\n\t\tif title_result:\n\t\t\treturn title_result\n\n\texcept:\n\n\t\tprint(\"[-] We got an error here!\")\n\t\texit(1)\n\t\t\n"
  }
]