Compare commits

...

47 commits
v1.4 ... master

Author SHA1 Message Date
Ekultek
21b8756306
Merge pull request #739 from sylwit/master
Dockerize
2019-05-10 08:46:38 -05:00
sylwit
d75169e401 Dockerize 2019-04-08 00:58:22 -04:00
Ekultek
f6a3ada2f0
Merge pull request #552 from TimVerheul/patch-1
Fixed Issue #551
2019-02-26 11:59:21 -06:00
TimV01
ac83743b4d
Fixed Issue #551
I implemented the function so it won't shutdown the script when a dork gave 0 urls.
@Ekultek Please take a look at this, might add it to your next release ;)

FYI: I am interested in further contribution.
2018-10-19 20:07:46 +02:00
Ekultek
910c3e434a
Update README.md 2018-08-06 15:06:57 -05:00
Ekultek
f512423c4e
Update README.md 2018-08-06 15:06:17 -05:00
Ekultek
2ca5c5ac3f
Update README.md 2018-08-06 15:05:53 -05:00
ekultek
55ba7ca7fe quick little fix for an issue with the new animation message 2018-02-10 20:03:57 -06:00
ekultek
caa7a4a564 updated md5sums 2018-02-10 19:33:39 -06:00
ekultek
3d8cf0e9f8 added a output option in getting the browser version, also bumped version number 2018-02-10 19:31:58 -06:00
ekultek
9dae61919d leaving a to do not for myself 2018-02-10 19:30:39 -06:00
ekultek
fe9c0abb76 lots of updates to the installation method 2018-02-10 19:24:56 -06:00
ekultek
443c0d94d1 changed firefox compatibility from version 52-58 2018-02-10 18:37:40 -06:00
ekultek
cfc348f03f created a script for installing xvfb 2018-02-10 18:37:12 -06:00
ekultek
6cecf4f6d1 created a way to make sure the arguments that you pass are implemented into Zeus production and are not still in the testing phase 2018-02-07 11:55:38 -06:00
ekultek
69a9305e11 added new checksums for the files 2018-02-07 11:32:40 -06:00
ekultek
f14bbe5645 changed the identifier from random chars to the hash of the stacktrace, this will help for a furture update where it will check if the issue is already on the bug tracker 2018-02-07 11:29:56 -06:00
ekultek
51905bbc82 removed a redundant '|' from the usage 2018-02-07 11:28:46 -06:00
ekultek
b857e6b120 added the new release for the newest version 2018-02-07 11:28:20 -06:00
ekultek
ae134c3989 removes the old profile of firefox from /usr/lib now (issue #353) 2018-02-07 11:28:02 -06:00
ekultek
e5ac6316d3 patches an issue where the present alert would cause an issue (issue #312) 2017-12-19 10:07:36 -06:00
ekultek
cadc40b81a patches an issue where the XSS scan fails if it does not have a protocol (issue #314) 2017-12-19 10:01:04 -06:00
ekultek
b0ea074e4e patches an issue where it will keep running if the file does not exist instead of shutting down (issue #306) 2017-12-15 10:03:45 -06:00
ekultek
14f2506ef5 patches an issue where a malformed URL would cause the program to fail (issue #286) 2017-12-15 09:59:01 -06:00
ekultek
1bfac89266 removed the gist lookup, it will be reimplemented in the furture, but for now there's to many problems with it (issue #285) 2017-12-15 09:46:36 -06:00
ekultek
f0056a0133 removed failing queries from the dorks.txt file 2017-12-15 09:44:46 -06:00
Thomas
31c530cc9f
updated the Firefox link, also added a 32bit install script. Should work all around now. 2017-12-14 19:23:55 -06:00
Thomas
1423e420d5
Updated the installation method for backbox, should actually work now 2017-12-14 19:18:34 -06:00
Thomas
f7a7b436f8
updated the link for installation 2017-12-14 15:20:48 -06:00
Thomas
05d88eaec8
Read somewhere that this is a pain in the ass to install on backbox, so here’s how you do it 2017-12-14 15:19:19 -06:00
ekultek
73a6458fb8 new checksums for the changed files 2017-12-09 22:22:10 -06:00
ekultek
aab81e892e bumped the version number for the new updates 2017-12-09 22:21:55 -06:00
ekultek
6e2e13a2c7 moved the sys calls to the main zeus.py file so they will be set at the start of the program 2017-12-09 22:21:31 -06:00
ekultek
a302562893 moved the encoding declaration to the main file, it will now be started at the beginning of the program, also removed the call to dict the proxy (issue #287) 2017-12-09 22:20:48 -06:00
ekultek
c83f745f84 moved the recursion limit to the main file so that it will load at the start of the program (issue #285) 2017-12-09 22:19:26 -06:00
ekultek
301461bf71 removed the duplicates from the dork file list, there was around 400+ dupes 2017-12-09 22:18:09 -06:00
ekultek
14a7204e88 created a new tamper script, this will obfuscate the script by it's HTML entity IE < == &lt; > == &gt; 2017-12-08 12:25:29 -06:00
ekultek
e5b52d7b45 bumped version number, Tor timesec warning will be output during header configuration 2017-12-07 16:29:18 -06:00
ekultek
362753d57c minor update for a new feature that will be implemented soon (preparing for it) 2017-12-07 16:28:12 -06:00
ekultek
27701e6660 minor update to the output of Tor timesec 2017-12-07 16:27:15 -06:00
ekultek
82f0c1f1ec this completely fixes issue #256 issue was that the catch was in the wrong spot 2017-12-07 07:46:12 -06:00
ekultek
b16a9c184a getting rid of the '...' at the end of the output string, got sick of typing it os now it won't be there anymore 2017-12-07 07:27:20 -06:00
ekultek
43199d690d this should patch issue #256 this seems to happen when the URL is malformed 2017-12-07 07:26:40 -06:00
ekultek
0349835951 created a new plugin identifier for moodle 2017-12-07 07:25:48 -06:00
ekultek
6e3d4b98f8 these updates should patch issue #245 and issue #252, seems that the error just wasn't being caught 2017-12-06 21:13:12 -06:00
ekultek
4e0945b842 patches an issue where any connection problem (timeout, disconnect, etc) would cause a unexpected exception (issue #239). also patches an issue where XSS was stuck in a loop (issue #240). added two new plugin detection scripts 2017-12-06 17:14:13 -06:00
ekultek
b86db8008f update for an issue #233, #234, #235 and #237. issue was with Tor (proxy 127.0.0.1:9050) needed a higher timeout for it 2017-12-06 10:48:58 -06:00
34 changed files with 5169 additions and 5768 deletions

34
Dockerfile Normal file
View file

@ -0,0 +1,34 @@
FROM ubuntu:18.10
WORKDIR /app
RUN apt update && \
apt install -y \
libxml2-dev \
libxslt1-dev \
libgtk-3-dev \
libdbus-glib-1-2 \
python-dev \
python-pip \
git \
curl \
nmap \
sqlmap \
xvfb \
&& rm -rf /var/lib/apt/lists/*
ARG GECKO_DRIVER_VERSION=0.23.0
ARG FIREFOX_VERSION=58.0.2
RUN git clone https://github.com/ekultek/zeus-scanner.git . && \
pip install -r requirements.txt
RUN curl -L https://github.com/mozilla/geckodriver/releases/download/v${GECKO_DRIVER_VERSION}/geckodriver-v${GECKO_DRIVER_VERSION}-linux64.tar.gz | tar xz -C /usr/bin
RUN curl -L https://ftp.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/linux-$(uname -m)/en-US/firefox-${FIREFOX_VERSION}.tar.bz2 -o firefox.tar.bz2 && \
tar xjf firefox.tar.bz2 -C /opt && \
rm firefox.tar.bz2 && \
ln -s /opt/firefox/firefox /usr/bin/firefox
CMD ["python", "zeus.py"]

View file

@ -1,8 +1,12 @@
**_NOTE: due to dumbass people, automatic issue creation has been turned off until further notice_**
----
[![GitHub stars](https://img.shields.io/github/stars/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/stargazers) [![GitHub stars](https://img.shields.io/github/stars/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/network) [![GitHub forks](https://img.shields.io/github/forks/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/network)
[![GitHub issues](https://img.shields.io/github/issues/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/issues) [![GitHub issues](https://img.shields.io/github/issues/ekultek/zeus-scanner.svg?style=flat-square)](https://github.com/ekultek/zeus-scanner/issues)
[![GitHub license](https://img.shields.io/badge/license-GPL-blue.svg?style=flat-square)](https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/master/.github/LICENSE.md) [![GitHub license](https://img.shields.io/badge/license-GPL-blue.svg?style=flat-square)](https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/master/.github/LICENSE.md)
[![Twitter](https://img.shields.io/twitter/url/https/github.com/ekultek/zeus-scanner.svg?style=social)](https://twitter.com/Zeus_Scanner) [![Twitter](https://img.shields.io/twitter/url/https/github.com/ekultek/zeus-scanner.svg?style=social)](https://twitter.com/stay__salty)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://github.com/Ekultek/Zeus-Scanner#donations) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://github.com/Ekultek/Zeus-Scanner#donations)
# Helpful links directory # Helpful links directory
@ -13,6 +17,7 @@
- [Requirements and installation](https://github.com/Ekultek/Zeus-Scanner#requirements) - [Requirements and installation](https://github.com/Ekultek/Zeus-Scanner#requirements)
- [Ubuntu/Debian](https://github.com/Ekultek/Zeus-Scanner#ubuntudebian) - [Ubuntu/Debian](https://github.com/Ekultek/Zeus-Scanner#ubuntudebian)
- [centOS](https://github.com/Ekultek/Zeus-Scanner#centos) - [centOS](https://github.com/Ekultek/Zeus-Scanner#centos)
- [Backbox](https://github.com/Ekultek/Zeus-Scanner#backbox)
- [other](https://github.com/Ekultek/Zeus-Scanner#others) - [other](https://github.com/Ekultek/Zeus-Scanner#others)
- [Screenshots](https://github.com/Ekultek/Zeus-Scanner#screenshots) - [Screenshots](https://github.com/Ekultek/Zeus-Scanner#screenshots)
- [Demo video](https://vimeo.com/239885768) - [Demo video](https://vimeo.com/239885768)
@ -79,7 +84,7 @@ There are some requirements for this to be run successfully.
##### Basic requirements ##### Basic requirements
- `libxml2-dev`, `libxslt1-dev`, `python-dev` are required for the installation process - `libxml2-dev`, `libxslt1-dev`, `python-dev` are required for the installation process
- Firefox web browser is required as of now, you will need Firefox version `<=57 >=51` (between 51 and 57). Full functionality for other browsers will eventually be added. - Firefox web browser is required as of now, you will need Firefox version `<=58 >=52` (between 52 and 58). Full functionality for other browsers will eventually be added.
- If you want to run sqlmap through the URL's you will need sqlmap somewhere on your system. - If you want to run sqlmap through the URL's you will need sqlmap somewhere on your system.
- If you want to run a port scan using nmap on the URL's IP addresses. You will need nmap on your system. - If you want to run a port scan using nmap on the URL's IP addresses. You will need nmap on your system.
- [Geckodriver](https://github.com/mozilla/geckodriver) is required to run the firefox web browser and will be installed the first time you run. It will be added to your `/usr/bin` so that it can be run in your ENV PATH. - [Geckodriver](https://github.com/mozilla/geckodriver) is required to run the firefox web browser and will be installed the first time you run. It will be added to your `/usr/bin` so that it can be run in your ENV PATH.
@ -99,7 +104,7 @@ There are some requirements for this to be run successfully.
### Installation ### Installation
You can download the latest [tar.gz](https://github.com/ekultek/zeus-scanner/tarball/master), the latest [zip](https://github.com/ekultek/zeus-scanner/zipball/master), or you can find the current stable release [here](https://github.com/Ekultek/Zeus-Scanner/releases/tag/v1.4). Alternatively you can install the latest development version by following the instructions that best match your operating system: You can download the latest [tar.gz](https://github.com/ekultek/zeus-scanner/tarball/master), the latest [zip](https://github.com/ekultek/zeus-scanner/zipball/master), or you can find the current stable release [here](https://github.com/Ekultek/Zeus-Scanner/releases/tag/v1.5). Alternatively you can install the latest development version by following the instructions that best match your operating system:
**_NOTE: (optional but highly advised)_** add sqlmap and nmap to your environment PATH by moving them to `/usr/bin` or by adding them to the PATH via terminal **_NOTE: (optional but highly advised)_** add sqlmap and nmap to your environment PATH by moving them to `/usr/bin` or by adding them to the PATH via terminal
@ -115,6 +120,36 @@ sudo apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://g
sudo apt-get install gcc python-devel libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && sudo pip2 install -r requirements.txt && sudo python zeus.py sudo apt-get install gcc python-devel libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && sudo pip2 install -r requirements.txt && sudo python zeus.py
``` ```
#### Backbox
64 bit installation:
```
sudo -s << EOF
aptitude purge firefox
wget https://ftp.mozilla.org/pub/firefox/releases/57.0/linux-x86_64/en-US/firefox-57.0.tar.bz2
tar -xjf firefox-57.0.tar.bz2
rm -rf /opt/firefox*
mv firefox /opt/firefox57
mv /usr/bin/firefox /usr/bin/firefoxold
ln -s /opt/firefox57/firefox-bin /usr/bin/firefox
apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && pip2 install -r requirements.txt && python zeus.py
EOF
```
32 bit installation:
```
sudo -s << EOF
aptitude purge firefox
wget https://ftp.mozilla.org/pub/firefox/releases/57.0/linux-i686/en-US/firefox-57.0.tar.bz2
tar -xjf firefox-57.0.tar.bz2
rm -rf /opt/firefox*
mv firefox /opt/firefox57
mv /usr/bin/firefox /usr/bin/firefoxold
ln -s /opt/firefox57/firefox-bin /usr/bin/firefox
apt-get install libxml2-dev libxslt1-dev python-dev && git clone https://github.com/ekultek/zeus-scanner.git && cd zeus-scanner && pip2 install -r requirements.txt && python zeus.py
EOF
```
##### Others ##### Others
``` ```
@ -145,4 +180,4 @@ OpenSource Projects is a Facebook community page who's goal is to give developer
- [Spanish](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-spanish.md) - [Spanish](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-spanish.md)
- [Russian](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-russian.md) - [Russian](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-russian.md)
- [French](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-french.md) - [French](https://github.com/Ekultek/Zeus-Scanner/blob/master/.github/translations/README-french.md)

View file

@ -1,5 +1,9 @@
import os import os
import sys
import time
import shlex
import platform import platform
import threading
import subprocess import subprocess
import tarfile import tarfile
try: try:
@ -13,6 +17,27 @@ import lib.core.common
import lib.core.settings import lib.core.settings
stop_animation = False
xvfb_path = "{}/etc/scripts/install_xvfb.sh".format(os.getcwd())
def animation(text):
global stop_animation
i = 0
while not stop_animation:
temp_text = list(text)
if i >= len(temp_text):
i = 0
temp_text[i] = temp_text[i].upper()
temp_text = ''.join(temp_text)
sys.stdout.write("\033[92m{}\r\033[0m".format(temp_text))
sys.stdout.flush()
i += 1
time.sleep(0.1)
else:
pass
def disclaimer(): def disclaimer():
question = raw_input( question = raw_input(
"\033[91mAttacking targets without consent is not only illegal, but it " "\033[91mAttacking targets without consent is not only illegal, but it "
@ -28,7 +53,7 @@ def disclaimer():
else: else:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"you have not agreed with the terms of service, so " "you have not agreed with the terms of service, so "
"Zeus will shut down now...", level=50 "Zeus will shut down now", level=50
)) ))
return False return False
@ -46,6 +71,8 @@ def parse_hosts(filepath="/etc/hosts"):
def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"): def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename="path_config.ini"):
global stop_animation
lib.core.settings.create_dir(directory.format(os.getcwd())) lib.core.settings.create_dir(directory.format(os.getcwd()))
full_path = "{}/{}".format( full_path = "{}/{}".format(
directory.format(os.getcwd()), directory.format(os.getcwd()),
@ -62,6 +89,8 @@ def find_tools(to_search=("sqlmap", "nmap"), directory="{}/bin/paths", filename=
path_schema[item] = None path_schema[item] = None
for key, value in path_schema.iteritems(): for key, value in path_schema.iteritems():
if value is None: if value is None:
stop_animation = True
print("\n")
provided_path = lib.core.common.prompt( provided_path = lib.core.common.prompt(
"what is the full path to {} on your system".format(key) "what is the full path to {} on your system".format(key)
) )
@ -78,9 +107,9 @@ def config_gecko_version(browser_version):
figure out which gecko version you need figure out which gecko version you need
""" """
version_specs = { version_specs = {
(56, 57): 19, (57, 58): 19,
(55, 54): 18, (56, 55, 54): 18,
(53, 52, 51): 17 (53, 52): 17
} }
if isinstance(browser_version, (tuple, list, set)): if isinstance(browser_version, (tuple, list, set)):
major = browser_version[0] major = browser_version[0]
@ -112,11 +141,13 @@ def check_xvfb(exc="Xvfb"):
""" """
test for xvfb on the users system test for xvfb on the users system
""" """
global xvfb_path
global stop_animation
if whichcraft.which(exc) is None: if whichcraft.which(exc) is None:
lib.core.settings.logger.info(lib.core.settings.set_color( cmd = shlex.split("sudo sh {}".format(xvfb_path))
"installing Xvfb, required by pyvirutaldisplay..." subprocess.call(cmd)
)) stop_animation = True
subprocess.call(["sudo", "apt-get", "install", "xvfb"])
else: else:
return True return True
@ -136,53 +167,45 @@ def check_if_run(file_check="{}/bin/executed.txt"):
return True return True
def untar_gecko(filename="{}/bin/drivers/geckodriver-v0.{}.0-linux{}.tar.gz", verbose=False): def untar_gecko(filename="{}/bin/drivers/geckodriver-v0.{}.0-linux{}.tar.gz"):
""" """
untar the correct gecko driver for your computer architecture untar the correct gecko driver for your computer architecture
""" """
global stop_animation
arch_info = {"64bit": "64", "32bit": "32"} arch_info = {"64bit": "64", "32bit": "32"}
file_arch = arch_info[platform.architecture()[0]] file_arch = arch_info[platform.architecture()[0]]
ff_version = lib.core.settings.get_browser_version() ff_version = lib.core.settings.get_browser_version(output=False)
if isinstance(ff_version, str) or ff_version is None: if isinstance(ff_version, str) or ff_version is None:
stop_animation = True
ff_version = lib.core.common.prompt( ff_version = lib.core.common.prompt(
"enter your firefox browser version (if you don't know it run firefox --version" "enter your firefox browser version (if you don't know it run firefox --version)"
) )
gecko_version = config_gecko_version(ff_version) gecko_version = config_gecko_version(ff_version)
if gecko_version is None: if gecko_version is None:
stop_animation = True
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"your current firefox version is not supported by Zeus...", level=50 "your current firefox version is not supported by Zeus", level=50
)) ))
lib.core.common.shutdown() lib.core.common.shutdown()
gecko_full_filename = filename.format(os.getcwd(), gecko_version, file_arch) gecko_full_filename = filename.format(os.getcwd(), gecko_version, file_arch)
with open(lib.core.settings.GECKO_VERSION_INFO_PATH, "a+") as log: with open(lib.core.settings.GECKO_VERSION_INFO_PATH, "a+") as log:
log.write(gecko_full_filename.split("/")[-1]) log.write(gecko_full_filename.split("/")[-1])
tar = tarfile.open(filename.format(os.getcwd(), gecko_version, file_arch), "r:gz") tar = tarfile.open(filename.format(os.getcwd(), gecko_version, file_arch), "r:gz")
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"extracting the correct driver for your architecture...", level=10
))
try: try:
tar.extractall("/usr/bin") tar.extractall("/usr/bin")
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"driver extracted into /usr/bin (you may change this, but ensure that it "
"is in your PATH)...", level=10
))
except IOError as e: except IOError as e:
if "Text file busy" in str(e): if "Text file busy" in str(e):
lib.core.settings.logger.info(lib.core.settings.set_color(
"the driver is already installed..."
))
tar.close() tar.close()
pass pass
except Exception as e: except Exception as e:
if "[Errno 13] Permission denied: '/usr/bin/geckodriver'" in str(e): if "[Errno 13] Permission denied: '/usr/bin/geckodriver'" in str(e):
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"first run must be ran as root (sudo python zeus.py)...", level=50 "first run must be ran as root (sudo python zeus.py)", level=50
)) ))
else: else:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"ran into exception '{}', logged to current log file...".format(e), level=50 "ran into exception '{}', logged to current log file".format(e), level=50
)) ))
exit(-1) exit(-1)
tar.close() tar.close()
@ -192,10 +215,6 @@ def ensure_placed(item="geckodriver", verbose=False):
""" """
use whichcraft to ensure that the driver has been placed in your PATH variable use whichcraft to ensure that the driver has been placed in your PATH variable
""" """
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"ensuring that the driver exists in your system path...", level=10
))
if not whichcraft.which(item): if not whichcraft.which(item):
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"the executable '{}' does not appear to be in your /usr/bin PATH. " "the executable '{}' does not appear to be in your /usr/bin PATH. "
@ -204,10 +223,6 @@ def ensure_placed(item="geckodriver", verbose=False):
)) ))
exit(-1) exit(-1)
else: else:
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"driver exists, continuing...", level=10
))
return True return True
@ -215,39 +230,28 @@ def main(rewrite="{}/bin/executed.txt", verbose=False):
""" """
main method main method
""" """
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"verifying operating system...", level=10
))
if not check_os(): if not check_os():
raise NotImplementedError(lib.core.settings.set_color( raise NotImplementedError(lib.core.settings.set_color(
"as of now, Zeus requires Linux to run successfully " "as of now, Zeus requires Linux to run successfully "
"your current operating system '{}' is not implemented " "your current operating system '{}' is not implemented "
"yet...".format(platform.platform()), level=50 "yet".format(platform.platform()), level=50
)) ))
if check_if_run(): if check_if_run():
if not disclaimer(): if not disclaimer():
exit(1) exit(1)
lib.core.settings.logger.info(lib.core.settings.set_color( t = threading.Thread(target=animation, args=(
"seems this is your first time running the application, " "seems this is your first time running the application, doing setup please wait..",))
"doing setup please wait..." t.daemon = True
)) t.start()
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"checking if xvfb is on your system...", level=10
))
find_tools() find_tools()
check_xvfb() check_xvfb()
untar_gecko(verbose=verbose) untar_gecko()
parse_hosts() parse_hosts()
if ensure_placed(verbose=verbose): if ensure_placed(verbose=verbose):
with open(rewrite.format(os.getcwd()), "w") as rw: with open(rewrite.format(os.getcwd()), "w") as rw:
rw.write("TRUE") rw.write("TRUE")
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"done, continuing process..." "done, continuing process"
)) ))
else: else:
if verbose: pass
lib.core.settings.logger.debug(lib.core.settings.set_color(
"already ran, skipping...", level=10
))

View file

@ -1,111 +1,119 @@
1caf80ae9a944960ef67773c2bbdd6b2 ./zeus.py 685a20fa3fc7652b5c3e39821cdc6f25 ./zeus.py
4b32db388e8acda35570c734d27c950c ./etc/scripts/launch_sqlmap.sh 4b32db388e8acda35570c734d27c950c ./etc/scripts/launch_sqlmap.sh
6ad5f22ec4a6f8324bfb1b01ab6d51ec ./etc/scripts/cleanup.sh 6ad5f22ec4a6f8324bfb1b01ab6d51ec ./etc/scripts/cleanup.sh
74d7bee13890a9dd279bb857591647ce ./etc/scripts/reinstall.sh 869025acb457dc881e53e440aa11dd7b ./etc/scripts/reinstall.sh
155c9482f690f1482f324a7ffd8b8098 ./etc/scripts/fix_pie.sh 155c9482f690f1482f324a7ffd8b8098 ./etc/scripts/fix_pie.sh
0e435c641bc636ac0b3d54e032d9cf6a ./etc/scripts/install_nmap.sh 0e435c641bc636ac0b3d54e032d9cf6a ./etc/scripts/install_nmap.sh
440431165b2db8a537c1a93cb2232f16 ./etc/scripts/install_xvfb.sh
66b11aa388ea909de7b212341259a318 ./etc/auths/git_auth 66b11aa388ea909de7b212341259a318 ./etc/auths/git_auth
8f686b05c5c5dfc02f0fcaa7ebc8677c ./etc/auths/whois_auth 8f686b05c5c5dfc02f0fcaa7ebc8677c ./etc/auths/whois_auth
d3ad89703575a712a0aeead2b176d8c5 ./etc/html/clickjacking_test_page.html d3ad89703575a712a0aeead2b176d8c5 ./etc/html/clickjacking_test_page.html
642a77905d8bb4e5533e0e9c2137c0fa ./etc/text_files/agents.txt 642a77905d8bb4e5533e0e9c2137c0fa ./etc/text_files/agents.txt
82cc68f46539d0255f7ce14cd86cd49b ./etc/text_files/link_ext.txt 82cc68f46539d0255f7ce14cd86cd49b ./etc/text_files/link_ext.txt
9659c647c725773e82d130e0f5c73c57 ./etc/text_files/dorks.txt c57ac34fe965961917ac8a207df256d5 ./etc/text_files/dorks.txt
dc7bfc3d7b9b23340ee37806316bd770 ./etc/text_files/xss_payloads.txt cf85d83da34d70720193d83950c31fdc ./etc/text_files/xss_payloads.txt
6cabeb9919d2301efc4ba3d8869282d6 ./etc/checksum/md5sum.md5
5250f0aa13b8af4775efa506e77de1ce ./etc/xml/headers.xml 5250f0aa13b8af4775efa506e77de1ce ./etc/xml/headers.xml
d41d8cd98f00b204e9800998ecf8427e ./bin/__init__.py d41d8cd98f00b204e9800998ecf8427e ./bin/__init__.py
ebd255c3ab49efde3155338e5d596b63 ./bin/unzip_gecko.py 3be7ee6f4267e0d0cf2143b58792527b ./bin/paths/path_config.ini
fa5084cc7ee56ff2df8631b76be5be4d ./bin/unzip_gecko.py
c0d83f0b82a6b30de8811e69e6d95c61 ./bin/executed.txt
dc1eb4ebe0f372af48b5a9c107ebc68d ./bin/drivers/geckodriver-v0.18.0-linux32.tar.gz dc1eb4ebe0f372af48b5a9c107ebc68d ./bin/drivers/geckodriver-v0.18.0-linux32.tar.gz
be18faeea6e7db9db6990d8667e2298f ./bin/drivers/geckodriver-v0.17.0-linux64.tar.gz be18faeea6e7db9db6990d8667e2298f ./bin/drivers/geckodriver-v0.17.0-linux64.tar.gz
79b1a158f96d29942a111c0905f1c807 ./bin/drivers/geckodriver-v0.17.0-linux32.tar.gz 79b1a158f96d29942a111c0905f1c807 ./bin/drivers/geckodriver-v0.17.0-linux32.tar.gz
ca6935a72fd0527d15a78a17a35e56e8 ./bin/drivers/geckodriver-v0.19.0-linux64.tar.gz ca6935a72fd0527d15a78a17a35e56e8 ./bin/drivers/geckodriver-v0.19.0-linux64.tar.gz
4ccb56fb3700005c9f9188f84152f21a ./bin/drivers/geckodriver-v0.18.0-linux64.tar.gz 4ccb56fb3700005c9f9188f84152f21a ./bin/drivers/geckodriver-v0.18.0-linux64.tar.gz
07cd383c8aef8ea5ef194a506141afd6 ./bin/drivers/geckodriver-v0.19.0-linux32.tar.gz 07cd383c8aef8ea5ef194a506141afd6 ./bin/drivers/geckodriver-v0.19.0-linux32.tar.gz
785c28da8b681a7e23964f99118b5aab ./lib/tamper_scripts/obfuscateordinal_encode.py 145e4a7dc985e99962dabe3b221fc51e ./lib/tamper_scripts/obfuscateordinal_encode.py
10bf1bc4ef0287d31633148fab557e8a ./lib/tamper_scripts/uppercase_encode.py 10bf1bc4ef0287d31633148fab557e8a ./lib/tamper_scripts/uppercase_encode.py
5b68de0ce3a783b870921b09b5222146 ./lib/tamper_scripts/hex_encode.py fcef22874b6732fd1b1bd062e18e65db ./lib/tamper_scripts/hex_encode.py
1537b3b94566aebf0f89bed074e96581 ./lib/tamper_scripts/url_encode.py 1537b3b94566aebf0f89bed074e96581 ./lib/tamper_scripts/url_encode.py
d41d8cd98f00b204e9800998ecf8427e ./lib/tamper_scripts/__init__.py d41d8cd98f00b204e9800998ecf8427e ./lib/tamper_scripts/__init__.py
7b636a332b2e99547ec9565d8e094308 ./lib/tamper_scripts/unicode_encode.py 7b636a332b2e99547ec9565d8e094308 ./lib/tamper_scripts/unicode_encode.py
07a792bccd13f64873a27aee4aaa8ea6 ./lib/tamper_scripts/space2comment_encode.py 07a792bccd13f64873a27aee4aaa8ea6 ./lib/tamper_scripts/space2comment_encode.py
1053a0c89e514d2c94bc822d34715896 ./lib/tamper_scripts/randomcase_encode.py 1053a0c89e514d2c94bc822d34715896 ./lib/tamper_scripts/randomcase_encode.py
349c30cbab4308bd94829d92b4e34f9d ./lib/tamper_scripts/lowercase_encode.py 349c30cbab4308bd94829d92b4e34f9d ./lib/tamper_scripts/lowercase_encode.py
6e1d6276a295f6c5d41b6f6f0e1316b0 ./lib/tamper_scripts/enclosebrackets_encode.py 0c5e78674a8d27e7c20af1dca8656789 ./lib/tamper_scripts/enclosebrackets_encode.py
694231b4c2f99406481c34ced85ddfe1 ./lib/tamper_scripts/base64_encode.py
6ac38bec8c32eab57efa01f7a06dff14 ./lib/tamper_scripts/space2null_encode.py
3b8c95a6a3b7cecce5118f2fb1ccc6b8 ./lib/tamper_scripts/appendnull_encode.py
5824916df46428a8304ee0156bcee989 ./lib/tamper_scripts/multispace2comment_encode.py 5824916df46428a8304ee0156bcee989 ./lib/tamper_scripts/multispace2comment_encode.py
9fd42d65993aa20d1bf5acbc4d042d2e ./lib/tamper_scripts/base64_encode.py
f77b7a9a19b94e26903eeecf5a787ea3 ./lib/tamper_scripts/space2null_encode.py
3b8c95a6a3b7cecce5118f2fb1ccc6b8 ./lib/tamper_scripts/appendnull_encode.py
8e8792e38649f18d90bb0084202bb59e ./lib/tamper_scripts/obfuscateentity_encode.py
d41d8cd98f00b204e9800998ecf8427e ./lib/__init__.py
6299b188a730844954044887f528435a ./lib/firewall/cloudfront.py 6299b188a730844954044887f528435a ./lib/firewall/cloudfront.py
d41d8cd98f00b204e9800998ecf8427e ./lib/firewall/__init__.py d41d8cd98f00b204e9800998ecf8427e ./lib/firewall/__init__.py
eb3a3066efbcf87dbc10a49be445cb8f ./lib/firewall/urlscan.py 81a29a14d72980a306fbaec0dc772048 ./lib/firewall/fortigate.py
d4986f3d95a773d7c3585b07bcd6310e ./lib/firewall/sucuri.py d4986f3d95a773d7c3585b07bcd6310e ./lib/firewall/sucuri.py
763af6773e920d6bdc185f5bd4df6084 ./lib/firewall/dw.py
e4514021485dbb94c3f0023b04af01ad ./lib/firewall/aws.py e4514021485dbb94c3f0023b04af01ad ./lib/firewall/aws.py
eb3a3066efbcf87dbc10a49be445cb8f ./lib/firewall/urlscan.py
71744d7a95f42063a8fb6e720932cd3d ./lib/firewall/sonicwall.py
7af3ee8615c7dc761f050e0ba638eaef ./lib/firewall/armor.py
1f303641d59686d544f2986ff74c6b31 ./lib/firewall/webseal.py 1f303641d59686d544f2986ff74c6b31 ./lib/firewall/webseal.py
78e6b01feb9bad68c2fc8a79e75930fd ./lib/firewall/yundun.py
e4eef006dd909c222b1b9f48826c3ef5 ./lib/firewall/pk.py e4eef006dd909c222b1b9f48826c3ef5 ./lib/firewall/pk.py
bf5285dc059c761e1719bc734ae8504f ./lib/firewall/varnish.py
6b370050b40d8c1d2221424f756c7842 ./lib/firewall/paloalto.py 6b370050b40d8c1d2221424f756c7842 ./lib/firewall/paloalto.py
73c1727e604ec6e00541687bfc64c0d6 ./lib/firewall/akamai.py
6bbe2f6f6a2a1ddf0e416e94ec1f0763 ./lib/firewall/siteguard.py 6bbe2f6f6a2a1ddf0e416e94ec1f0763 ./lib/firewall/siteguard.py
787e21ed577ff05b095aa0f0e5e5e9bf ./lib/firewall/cloudflare.py 787e21ed577ff05b095aa0f0e5e5e9bf ./lib/firewall/cloudflare.py
c3f01fc8ff7dfe7759f63bf16b00f127 ./lib/firewall/wordfence.py c3f01fc8ff7dfe7759f63bf16b00f127 ./lib/firewall/wordfence.py
6ccf3a1df5aa6429cd3365b7b8ded8f4 ./lib/firewall/powerful.py 2f0a935d2bb9b8aa711e511f48595a81 ./lib/firewall/powerful.py
54815706261c32b57fbbdc99244b5cdd ./lib/firewall/modsecurity.py
5ee20e2c158d0734b4dd5a8eb47f8ea5 ./lib/firewall/squid.py
71744d7a95f42063a8fb6e720932cd3d ./lib/firewall/sonicwall.py
9070b43428bd17fd5faf86995cb559a2 ./lib/firewall/stringray.py
bf5285dc059c761e1719bc734ae8504f ./lib/firewall/varnish.py
78e6b01feb9bad68c2fc8a79e75930fd ./lib/firewall/yundun.py
cb45428e92485b759ff5cb46a0be9c73 ./lib/firewall/yunsuo.py
bbd8b4c6100070d420d48dc7dfc297eb ./lib/firewall/webknight.py bbd8b4c6100070d420d48dc7dfc297eb ./lib/firewall/webknight.py
54815706261c32b57fbbdc99244b5cdd ./lib/firewall/modsecurity.py
9070b43428bd17fd5faf86995cb559a2 ./lib/firewall/stringray.py
5ee20e2c158d0734b4dd5a8eb47f8ea5 ./lib/firewall/squid.py
95b908a21c0ff456ae59df4c6c189c54 ./lib/firewall/wallarm.py 95b908a21c0ff456ae59df4c6c189c54 ./lib/firewall/wallarm.py
cb45428e92485b759ff5cb46a0be9c73 ./lib/firewall/yunsuo.py
8fc8d62377bebbfa7ca4d70a79eab115 ./lib/firewall/bigip.py 8fc8d62377bebbfa7ca4d70a79eab115 ./lib/firewall/bigip.py
73c1727e604ec6e00541687bfc64c0d6 ./lib/firewall/akamai.py
7af3ee8615c7dc761f050e0ba638eaef ./lib/firewall/armor.py
763af6773e920d6bdc185f5bd4df6084 ./lib/firewall/dw.py
81a29a14d72980a306fbaec0dc772048 ./lib/firewall/fortigate.py
6ea65a0160c21e144e92334acc2e3667 ./lib/firewall/anquanbao.py 6ea65a0160c21e144e92334acc2e3667 ./lib/firewall/anquanbao.py
22a0ad8f2fa1a16b651cb5ae37ca9b0d ./lib/firewall/generic.py 22a0ad8f2fa1a16b651cb5ae37ca9b0d ./lib/firewall/generic.py
ed18ed1f72f3887e63fa7ce060841e4a ./lib/plugins/aardvark.py ed18ed1f72f3887e63fa7ce060841e4a ./lib/plugins/aardvark.py
a8b3e6924bab72607b1d1c1a8dcb561d ./lib/plugins/4d.py a8b3e6924bab72607b1d1c1a8dcb561d ./lib/plugins/4d.py
03355a122c047dc598fc271620119978 ./lib/plugins/jquery.py 03355a122c047dc598fc271620119978 ./lib/plugins/jquery.py
d41d8cd98f00b204e9800998ecf8427e ./lib/plugins/__init__.py d41d8cd98f00b204e9800998ecf8427e ./lib/plugins/__init__.py
353db8b22c031433ea73a12943927557 ./lib/plugins/clipbucket.py
5908a81cc9b332348b26a3ccd5ddb798 ./lib/plugins/ihtml.py 5908a81cc9b332348b26a3ccd5ddb798 ./lib/plugins/ihtml.py
d76d2839ed8875739328bb5f2a838ba6 ./lib/plugins/360.py d76d2839ed8875739328bb5f2a838ba6 ./lib/plugins/360.py
16e4708c510811760129f6fb4842e92e ./lib/plugins/3dcart.py 16e4708c510811760129f6fb4842e92e ./lib/plugins/3dcart.py
2ce0a2101bb5706a136de83a729965f3 ./lib/plugins/b2evolution.py 2ce0a2101bb5706a136de83a729965f3 ./lib/plugins/b2evolution.py
b4ab6d1e0d3582fc66111988b246acc0 ./lib/plugins/bmcremedy.py 497facc7b12e6e691aab65980d8f5026 ./lib/plugins/bmcremedy.py
2dcee5bc924732dd21f16983eef9a99d ./lib/plugins/abyss.py 2dcee5bc924732dd21f16983eef9a99d ./lib/plugins/abyss.py
d2c100e6e6f7fbda8448d36a6928c979 ./lib/plugins/68classified.py d2c100e6e6f7fbda8448d36a6928c979 ./lib/plugins/68classified.py
f1eb201cce16853049a615805b01bc60 ./lib/plugins/bomgar.py f1eb201cce16853049a615805b01bc60 ./lib/plugins/bomgar.py
ce3b79dc80e369ffd55d2cbe90e6a0ab ./lib/plugins/mssqlreportmanager.py
55ec8cde9d438a90327911910164abf2 ./lib/plugins/opengraph.py 55ec8cde9d438a90327911910164abf2 ./lib/plugins/opengraph.py
8658f8a185499ec6d10b1d2da6104c27 ./lib/plugins/atomfeed.py 8658f8a185499ec6d10b1d2da6104c27 ./lib/plugins/atomfeed.py
c2533d4a8dc5fdaa4b8d584588b32ec2 ./lib/plugins/html5.py c2533d4a8dc5fdaa4b8d584588b32ec2 ./lib/plugins/html5.py
a3ed012f11ff2bffbc143fbef63d0c12 ./lib/plugins/3com.py a3ed012f11ff2bffbc143fbef63d0c12 ./lib/plugins/3com.py
55d834ae87e96787807e21b65ec68bca ./lib/plugins/moodle.py
44019a327ec1db91851d652630788742 ./lib/plugins/googleapi.py 44019a327ec1db91851d652630788742 ./lib/plugins/googleapi.py
c4ac50a3f3550c62219e7e4f38d4b496 ./lib/plugins/1024.py c4ac50a3f3550c62219e7e4f38d4b496 ./lib/plugins/1024.py
0b63885649f369ea410c8169e947fdab ./lib/plugins/accellion.py 0b63885649f369ea410c8169e947fdab ./lib/plugins/accellion.py
76a1d1decfb872bfafdf510c656f113a ./lib/plugins/rssfeed.py 76a1d1decfb872bfafdf510c656f113a ./lib/plugins/rssfeed.py
320f0db977c85b477ba1ea78b140cb8a ./lib/plugins/4images.py 320f0db977c85b477ba1ea78b140cb8a ./lib/plugins/4images.py
35dc8b7da4becb60662aab3c48a9210b ./lib/plugins/openxchange.py 35dc8b7da4becb60662aab3c48a9210b ./lib/plugins/openxchange.py
b5ff3286060c0bbc0fe1f0f591131c9c ./lib/attacks/gist_lookup/__init__.py bdb7ff546787d38bbbd0aac9d4a4cdf8 ./lib/attacks/clickjacking_scan/__init__.py
86224bd899c2a2438042cbdc077dc4cc ./lib/attacks/clickjacking_scan/__init__.py
d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/__init__.py d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/__init__.py
4c644b0e3a62b6c1528d34a04837aa35 ./lib/attacks/sqlmap_scan/__init__.py 6e9e0a9e2c72e00d8690c0177b695d56 ./lib/attacks/sqlmap_scan/__init__.py
5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py 5e5bb575014ebe613db6bf671d008cf8 ./lib/attacks/sqlmap_scan/sqlmap_opts.py
7bc7a6f3e85651aab3588f087563eded ./lib/attacks/whois_lookup/__init__.py d41d8cd98f00b204e9800998ecf8427e ./lib/attacks/whois_lookup/__init__.py
8ec72bb33df998e32b925e3060d9d17a ./lib/attacks/whois_lookup/whois.py c5b69617f040fef1d5930948905aa8d0 ./lib/attacks/whois_lookup/whois.py
916b768e783ff771bce80bd6f5112d4f ./lib/attacks/admin_panel_finder/__init__.py 4fd96bb3002e949687d7ae863ee87264 ./lib/attacks/admin_panel_finder/__init__.py
52942c7b33ff696901f5a4201ba4507f ./lib/attacks/xss_scan/__init__.py 2017e69c3420c9e240fccb310f086da7 ./lib/attacks/xss_scan/__init__.py
7642d078fe304a7ca8bfaaa070a0cb31 ./lib/attacks/nmap_scan/__init__.py 40ba04fb18dcbb81cb42376a825c238f ./lib/attacks/nmap_scan/__init__.py
216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py 216999fa0e84866d5c1d96d5676034e4 ./lib/attacks/nmap_scan/nmap_opts.py
c01ef6dc27a2d3ff99e282ccc89d7d45 ./lib/header_check/__init__.py 0114ebe3d45612ef143f2777f027374c ./lib/header_check/__init__.py
cd8e35cfd995d0a93892cfc83f01dea7 ./lib/core/common.py 2a8acb2191d80da75f0e4d09c00df9f6 ./lib/core/common.py
4433353fb5c55578391d8b4006191ee8 ./lib/core/errors.py
38d8ce4aec42ec147b44a36c69b15ea8 ./lib/core/parse.py
d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py
0112338e057d62d4580c86033c18df05 ./lib/core/settings.py
de4254c5e40f7aa4fb81e0608f758a2c ./lib/core/decorators.py de4254c5e40f7aa4fb81e0608f758a2c ./lib/core/decorators.py
9a02e5b913d210350545ac26510a63c9 ./var/search/__init__.py 3f045c64ef155a517b7a3f3b66905325 ./lib/core/errors.py
83928f6c090722d87a905a447cb51aed ./var/search/selenium_search.py d41d8cd98f00b204e9800998ecf8427e ./lib/core/__init__.py
cfcce04aac694eee7a6c73969861ce43 ./var/search/pgp_search.py 0faeed8eac30526f3751dd67fe5c9f7e ./lib/core/settings.py
27bce5d5d1e7d01788c5273016b19370 ./lib/core/parse.py
d41d8cd98f00b204e9800998ecf8427e ./var/__init__.py d41d8cd98f00b204e9800998ecf8427e ./var/__init__.py
d41d8cd98f00b204e9800998ecf8427e ./var/auto_issue/__init__.py d41d8cd98f00b204e9800998ecf8427e ./var/auto_issue/__init__.py
0c11c16126baf789388a661bbbefb149 ./var/auto_issue/github.py c58e73857e42a07fa6eb559433b32c1a ./var/auto_issue/github.py
222102e56b3f4b9facda7ed28690d3f7 ./var/blackwidow/__init__.py 503e44b36f0bcd81e20840be5b73320e ./var/search/__init__.py
c52867e57beeeeac2da57f597b644faf ./var/search/selenium_search.py
12340de27a75273cd444f7257d354311 ./var/search/pgp_search.py
0af5ab455a535a2f141cfae4758a4bb4 ./var/blackwidow/__init__.py

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
sudo apt-get install xvfb --yes > /dev/null 2>&1

View file

@ -2,6 +2,7 @@
for pid in $(ps -ef | grep "firefox" | awk '{print $2}'); do kill -9 ${pid}; done > /dev/null 2>&1 for pid in $(ps -ef | grep "firefox" | awk '{print $2}'); do kill -9 ${pid}; done > /dev/null 2>&1
mv ~/.mozilla ~/.mozilla.old > /dev/null 2>&1 mv ~/.mozilla ~/.mozilla.old > /dev/null 2>&1
rm /usr/lib/firefox* > /dev/null 2>&1
sudo apt-get update > /dev/null 2>&1 sudo apt-get update > /dev/null 2>&1
sudo apt-get --purge --reinstall --assume-yes install firefox=56.0 > /dev/null 2>&1 sudo apt-get --purge --reinstall --assume-yes install firefox=56.0 > /dev/null 2>&1
sudo pip2 install selenium -U sudo pip2 install selenium -U > /dev/null 2>&1

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
currently_searching = ext[robots if robots else sitemap] currently_searching = ext[robots if robots else sitemap]
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"currently searching for a '{}'...".format(currently_searching), level=10 "currently searching for a '{}'".format(currently_searching), level=10
)) ))
try: try:
@ -44,13 +44,13 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
_, code, data, _ = lib.core.common.get_page(full_url) _, code, data, _ = lib.core.common.get_page(full_url)
except (TooManyRedirects, ConnectionError, ReadTimeout): except (TooManyRedirects, ConnectionError, ReadTimeout):
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"connection to '{}' failed, assuming does not exist and continuing...".format(full_url), level=40 "connection to '{}' failed, assuming does not exist and continuing".format(full_url), level=40
)) ))
return False return False
if code == 404: if code == 404:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"unable to connect to '{}', assuming does not exist and continuing...".format( "unable to connect to '{}', assuming does not exist and continuing".format(
full_url full_url
), level=40 ), level=40
)) ))
@ -80,7 +80,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
) )
) )
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"robots.txt page will be saved into a file...", level=25 "robots.txt page will be saved into a file", level=25
)) ))
return lib.core.common.write_to_log_file( return lib.core.common.write_to_log_file(
data, lib.core.settings.ROBOTS_PAGE_PATH, lib.core.settings.ROBOTS_TXT_FILENAME.format( data, lib.core.settings.ROBOTS_PAGE_PATH, lib.core.settings.ROBOTS_TXT_FILENAME.format(
@ -89,7 +89,7 @@ def check_for_externals(url, data_sep="-" * 30, **kwargs):
) )
elif sitemap: elif sitemap:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"found a sitemap, saving to file...", level=25 "found a sitemap, saving to file", level=25
)) ))
return lib.core.common.write_to_log_file( return lib.core.common.write_to_log_file(
data, lib.core.settings.SITEMAP_FILE_LOG_PATH, lib.core.settings.SITEMAP_FILENAME.format( data, lib.core.settings.SITEMAP_FILE_LOG_PATH, lib.core.settings.SITEMAP_FILENAME.format(
@ -114,12 +114,12 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
true_url = "{}{}{}".format(protocol, stripped_url, ext) true_url = "{}{}{}".format(protocol, stripped_url, ext)
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"trying '{}'...".format(true_url), level=10 "trying '{}'".format(true_url), level=10
)) ))
try: try:
urlopen(true_url, timeout=5) urlopen(true_url, timeout=5)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"connected successfully to '{}'...".format(true_url), level=25 "connected successfully to '{}'".format(true_url), level=25
)) ))
connections.add(true_url) connections.add(true_url)
except HTTPError as e: except HTTPError as e:
@ -127,7 +127,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
if verbose: if verbose:
if "Access Denied" in str(e): if "Access Denied" in str(e):
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"got access denied, possible control panel found without external access on '{}'...".format( "got access denied, possible control panel found without external access on '{}'".format(
true_url true_url
), ),
level=30 level=30
@ -137,7 +137,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
for error_code in lib.core.common.STATUS_CODES.iterkeys(): for error_code in lib.core.common.STATUS_CODES.iterkeys():
if int(data[2].split(":")[0]) == error_code: if int(data[2].split(":")[0]) == error_code:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"failed to connect got error code {} (reason: {})...".format( "failed to connect got error code {} (reason: {})".format(
data[2], lib.core.common.STATUS_CODES[error_code] data[2], lib.core.common.STATUS_CODES[error_code]
), level=40 ), level=40
)) ))
@ -145,33 +145,33 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
if verbose: if verbose:
if "<urlopen error timed out>" or "timeout: timed out" in str(e): if "<urlopen error timed out>" or "timeout: timed out" in str(e):
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"connection timed out assuming won't connect and skipping...", level=30 "connection timed out assuming won't connect and skipping", level=30
)) ))
else: else:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"failed to connect with unexpected error '{}'...".format(str(e)), level=50 "failed to connect with unexpected error '{}'".format(str(e)), level=50
)) ))
request_issue_creation() request_issue_creation()
possible_connections, connections = list(possible_connections), list(connections) possible_connections, connections = list(possible_connections), list(connections)
data_msg = "found {} possible connections(s) and {} successful connection(s)..." data_msg = "found {} possible connections(s) and {} successful connection(s)"
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
data_msg.format(len(possible_connections), len(connections)) data_msg.format(len(possible_connections), len(connections))
)) ))
if len(connections) > 0: if len(connections) > 0:
# create the connection tree if we got some connections # create the connection tree if we got some connections
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"creating connection tree..." "creating connection tree"
)) ))
lib.core.settings.create_tree(url, connections) lib.core.settings.create_tree(url, connections)
else: else:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"did not receive any successful connections to the admin page of " "did not receive any successful connections to the admin page of "
"{}...".format(url), level=50 "{}".format(url), level=50
)) ))
if show_possibles: if show_possibles:
if len(possible_connections) > 0: if len(possible_connections) > 0:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"creating possible connection tree..." "creating possible connection tree"
)) ))
lib.core.settings.create_tree(url, possible_connections) lib.core.settings.create_tree(url, possible_connections)
else: else:
@ -181,7 +181,7 @@ def check_for_admin_page(url, exts, protocol="http://", **kwargs):
)) ))
if len(connections) > 0: if len(connections) > 0:
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"only writing successful connections to log file...", level=30 "only writing successful connections to log file", level=30
)) ))
lib.core.common.write_to_log_file( lib.core.common.write_to_log_file(
list(connections), list(connections),
@ -211,32 +211,32 @@ def main(url, show=False, verbose=False, **kwargs):
try: try:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"parsing robots.txt..." "parsing robots.txt"
)) ))
results = check_for_externals(url, robots=True, batch=batch) results = check_for_externals(url, robots=True, batch=batch)
if not results: if not results:
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"seems like this page is either blocking access to robots.txt or it does not exist...", level=30 "seems like this page is either blocking access to robots.txt or it does not exist", level=30
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"checking for a sitemap..." "checking for a sitemap"
)) ))
check_for_externals(url, sitemap=True) check_for_externals(url, sitemap=True)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"loading extensions..." "loading extensions"
)) ))
extensions = __load_extensions() extensions = __load_extensions()
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"loaded a total of {} extensions...".format(len(extensions)), level=10 "loaded a total of {} extensions".format(len(extensions)), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"attempting to bruteforce admin panel..." "attempting to bruteforce admin panel"
)) ))
if do_threading: if do_threading:
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"starting {} threads, you will not be able to end the process until " "starting {} threads, you will not be able to end the process until "
"it is completed...".format(proc_num), level=30 "it is completed".format(proc_num), level=30
)) ))
tasks = [] tasks = []
for _ in range(0, proc_num): for _ in range(0, proc_num):

View file

@ -65,7 +65,7 @@ def clickjacking_main(url, **kwargs):
) )
if question.lower().startswith("n"): if question.lower().startswith("n"):
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"automatically removing all queries from URL..." "automatically removing all queries from URL"
)) ))
url = "http://{}".format(lib.core.settings.replace_http(url, complete=True)) url = "http://{}".format(lib.core.settings.replace_http(url, complete=True))
@ -73,14 +73,14 @@ def clickjacking_main(url, **kwargs):
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"generating HTML...", level=10 "generating HTML", level=10
)) ))
data = scanner.generate_html() data = scanner.generate_html()
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"HTML generated successfully...", level=10 "HTML generated successfully", level=10
)) ))
print("{}\n{}\n{}".format("-" * 30, data, "-" * 30)) print("{}\n{}\n{}".format("-" * 30, data, "-" * 30))
@ -90,7 +90,7 @@ def clickjacking_main(url, **kwargs):
if results: if results:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"it appears that provided URL '{}' is vulnerable to clickjacking, writing " "it appears that provided URL '{}' is vulnerable to clickjacking, writing "
"to HTML file...".format(url), level=25 "to HTML file".format(url), level=25
)) ))
lib.core.common.write_to_log_file( lib.core.common.write_to_log_file(
data, data,
@ -99,7 +99,7 @@ def clickjacking_main(url, **kwargs):
) )
else: else:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"provided URL '{}' seems to have the correct protection from clickjacking...".format( "provided URL '{}' seems to have the correct protection from clickjacking".format(
url url
), level=40 ), level=40
)) ))
@ -109,6 +109,6 @@ def clickjacking_main(url, **kwargs):
except Exception as e: # until I figure out the errors, we'll just make issues about them except Exception as e: # until I figure out the errors, we'll just make issues about them
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"Zeus failed to process the clickjacking test and received " "Zeus failed to process the clickjacking test and received "
"error code '{}'...".format(e), level=50 "error code '{}'".format(e), level=50
)) ))
var.auto_issue.github.request_issue_creation() var.auto_issue.github.request_issue_creation()

View file

@ -1,158 +0,0 @@
import re
import sys
from bs4 import BeautifulSoup
import lib.core.common
import lib.core.settings
def __create_url(redirect, template="https://gist.github.com{}"):
"""
create the URL for the Gists
"""
return template.format(redirect)
def get_raw_html(redirect, verbose=False):
"""
get the raw HTML of the Gist plus the URL for it
"""
tag, descriptor = "a", "href"
raw_gist_regex = re.compile(r".raw.[a-z0-9]{40}", re.I)
_, status, html, _ = lib.core.common.get_page(redirect)
if status == 200:
soup = BeautifulSoup(html, "html.parser")
for link in soup.findAll(tag):
raw_gist_redirect = link.get(descriptor)
if raw_gist_regex.search(str(raw_gist_redirect)) is not None:
url = __create_url(raw_gist_redirect)
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"found raw Gist URL '{}'...".format(url), level=10
))
_, _, html, _ = lib.core.common.get_page(url)
raw_soup = BeautifulSoup(html, "html.parser")
return raw_soup, url
else:
return None, None
def get_links(page_set, proxy=None, agent=None):
"""
parse 10 pages of Github gists and use them
"""
redirects, retval = set(), set()
gist_search_url = "https://gist.github.com/discover?page={}"
tag, descriptor = "a", "href"
gist_regex = re.compile(r"[a-f0-9]{32}", re.I)
gist_skip_schema = ("stargazers", "forks", "#comments")
for i in range(page_set):
lib.core.settings.logger.info(lib.core.settings.set_color(
"fetching all Gists on page #{}...".format(i+1)
))
_, status, html, _ = lib.core.common.get_page(
gist_search_url.format(i+1), proxy=proxy, agent=agent
)
if status == 200:
soup = BeautifulSoup(html, "html.parser")
for link in soup.findAll(tag):
redirect = link.get(descriptor)
if not any(s in redirect for s in gist_skip_schema):
if gist_regex.search(redirect) is not None:
if not any(protocol in redirect for protocol in ["https://", "http://"]):
redirects.add(__create_url(redirect))
else:
redirects.add(redirect)
else:
lib.core.settings.logger.warning(lib.core.settings.set_color(
"page #{} failed to load with status code {} (reason '{}')...".format(
i+1, status, lib.core.common.STATUS_CODES[int(status)]
), level=30
))
continue
return redirects
def check_files_for_information(data_to_search, query):
"""
check the files to see if they contain any of the information that was specified
"""
# create multiple regex types to ensure that we cover all our
# bases while we do the searching.
# this will make it so that if there is a match anywhere
# in anything, we'll find it.
data_to_search = str(data_to_search)
data_regex_schema = (
# match a URL with or without www
re.compile(r"(http(s)?)?(.//)?(www.)?{}".format(query), re.I),
# match our string and any random character around it (I like to call it the tittyex)
re.compile(r"(.)?{}(.)?".format(query), re.I),
# single boundary match, checks if it's inside of something else
re.compile(r"\b{}".format(query), re.I),
# double boundary, same as above but with another boundary
re.compile(r"\b{}\b".format(query), re.I),
# wildcard match
re.compile(r"{}*".format(query), re.I),
# normal match
re.compile(r"{}".format(query), re.I)
)
for regex in list(data_regex_schema):
if regex.search(data_to_search) is not None:
lib.core.settings.logger.info(lib.core.settings.set_color(
"found match with given specifics ('{}'), saving Gist to file...".format(
regex.pattern
), level=25
))
lib.core.common.write_to_log_file(
data_to_search,
lib.core.settings.GIST_MATCH_LOG,
lib.core.settings.GIST_FILENAME.format(query)
)
# @lib.core.decorators.tail_call_optimized
def github_gist_search_main(query, **kwargs):
"""
main function for searching Gists
"""
proxy = kwargs.get("proxy", None)
agent = kwargs.get("agent", None)
verbose = kwargs.get("verbose", False)
page_set = kwargs.get("page_set", 10)
# there seems to be a recursion issue in this function,
# so until I get this figured out, we're going to change
# the maximum recursion of the system when we get here
sys.setrecursionlimit(1500)
try:
lib.core.settings.logger.info(lib.core.settings.set_color(
"searching a total of {} pages of Gists for '{}'...".format(
page_set, query
)
))
if "www." in query:
query = query.split(".")[1]
links = get_links(page_set, proxy=proxy, agent=agent)
if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color(
"found a total of {} links to search...".format(
len(links)
), level=15
))
for link in list(links):
if link is not None:
gist, gist_link = get_raw_html(link, verbose=verbose)
check_files_for_information(gist, query)
except KeyboardInterrupt:
if not lib.core.common.pause():
lib.core.common.shutdown()
except Exception as e:
lib.core.settings.logger.exception(lib.core.settings.set_color(
"Gist search has failed with error '{}'...".format(str(e)), level=50
))

View file

@ -41,7 +41,7 @@ class NmapHook(object):
""" """
send all the information to a JSON file for further use send all the information to a JSON file for further use
""" """
lib.core.common.write_to_log_file( return lib.core.common.write_to_log_file(
data, lib.core.settings.NMAP_LOG_FILE_PATH, data, lib.core.settings.NMAP_LOG_FILE_PATH,
lib.core.settings.NMAP_FILENAME.format(self.ip) lib.core.settings.NMAP_FILENAME.format(self.ip)
) )
@ -52,13 +52,14 @@ class NmapHook(object):
""" """
# have to create a spacer or the output comes out funky.. # have to create a spacer or the output comes out funky..
spacer_data = {4: " " * 8, 6: " " * 6, 8: " " * 4} spacer_data = {4: " " * 8, 6: " " * 6, 8: " " * 4}
lib.core.settings.logger.info(lib.core.settings.set_color("finding data for IP '{}'...".format(self.ip))) lib.core.settings.logger.info(lib.core.settings.set_color("finding data for IP '{}'".format(self.ip)))
json_data = json.loads(json_data)["scan"] json_data = json.loads(json_data)["scan"]
host = json_data[self.ip]["hostnames"][0]["name"] host = json_data[self.ip]["hostnames"][0]["name"]
host_skip = (not len(host) == 0, " ", "", None)
print( print(
"{}\nScanned: {} ({})\tStatus: {}\nProtocol: {}\n".format( "{}\nScanned: {} ({})\tStatus: {}\nProtocol: {}\n".format(
sep, self.ip, sep, self.ip,
host if host is not "" or None or not len(host) == 0 else "unknown", host if host != any(s for s in list(host_skip)) else "unknown",
json_data[self.ip]["status"]["state"], json_data[self.ip]["status"]["state"],
"TCP" "TCP"
) )
@ -98,35 +99,35 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
with lib.core.decorators.TimeOut(seconds=timeout_time): with lib.core.decorators.TimeOut(seconds=timeout_time):
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"if the port scan is not completed in {}(m) it will timeout...".format( "if the port scan is not completed in {}(m) it will timeout".format(
lib.core.settings.convert_to_minutes(timeout_time) lib.core.settings.convert_to_minutes(timeout_time)
), level=30 ), level=30
)) ))
url = url.strip() url = url.strip()
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"attempting to find IP address for hostname '{}'...".format(url) "attempting to find IP address for hostname '{}'".format(url)
)) ))
try: try:
found_ip_address = socket.gethostbyname(url) found_ip_address = socket.gethostbyname(url)
except socket.gaierror: except socket.gaierror:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"failed to gather IP address for URL '{}'...".format(url) "failed to gather IP address for URL '{}'".format(url)
)) ))
return return
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"checking for nmap on your system...", level=10 "checking for nmap on your system", level=10
)) ))
nmap_exists = "".join(find_nmap()) nmap_exists = "".join(find_nmap())
if nmap_exists: if nmap_exists:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"nmap has been found under '{}'...".format(nmap_exists), level=10 "nmap has been found under '{}'".format(nmap_exists), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"starting port scan on IP address '{}'...".format(found_ip_address) "starting port scan on IP address '{}'".format(found_ip_address)
)) ))
try: try:
data = scanner(found_ip_address, opts=opts) data = scanner(found_ip_address, opts=opts)
@ -134,11 +135,11 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
data.show_open_ports(json_data) data.show_open_ports(json_data)
file_path = data.send_to_file(json_data) file_path = data.send_to_file(json_data)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"port scan completed, all data saved to JSON file under '{}'...".format(file_path) "port scan completed, all data saved to JSON file under '{}'".format(file_path)
)) ))
except KeyError: except KeyError:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"no port information found for '{}({})'...".format( "no port information found for '{}({})'".format(
url, found_ip_address url, found_ip_address
), level=50 ), level=50
)) ))
@ -149,20 +150,20 @@ def perform_port_scan(url, scanner=NmapHook, **kwargs):
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"port scan is taking to long and has hit the timeout, you " "port scan is taking to long and has hit the timeout, you "
"can increase this time by passing the --time-sec flag (IE " "can increase this time by passing the --time-sec flag (IE "
"--time-sec 300)...", level=40 "--time-sec 300)", level=40
)) ))
except Exception as e: except Exception as e:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"ran into exception '{}', cannot continue quitting...".format(e), level=50 "ran into exception '{}', cannot continue quitting".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
pass pass
else: else:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"nmap was not found on your system...", level=50 "nmap was not found on your system", level=50
)) ))
lib.core.common.run_fix( lib.core.common.run_fix(
"would you like to automatically install it", "would you like to automatically install it",
"sudo sh {}".format(lib.core.settings.NMAP_INSTALLER_TOOL), "sudo sh {}".format(lib.core.settings.NMAP_INSTALLER_TOOL),
"nmap is not installed, please install it in order to continue..." "nmap is not installed, please install it in order to continue"
) )

View file

@ -111,7 +111,7 @@ class SqlmapHook(object):
if current_status != "running": if current_status != "running":
raise lib.core.errors.SqlmapFailedStart( raise lib.core.errors.SqlmapFailedStart(
"sqlmap API failed to start the run, check the client and see what " "sqlmap API failed to start the run, check the client and see what "
"the problem is and try again..." "the problem is and try again"
) )
already_displayed = set() already_displayed = set()
while current_status == "running": while current_status == "running":
@ -156,7 +156,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
if auto_start: if auto_start:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"attempting to launch sqlmap API..." "attempting to launch sqlmap API"
)) ))
sqlmap_api_command = shlex.split("sudo sh {} p {}".format( sqlmap_api_command = shlex.split("sudo sh {} p {}".format(
lib.core.settings.LAUNCH_SQLMAP_API_TOOL, "".join(found_path) lib.core.settings.LAUNCH_SQLMAP_API_TOOL, "".join(found_path)
@ -164,58 +164,58 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
subprocess.Popen(sqlmap_api_command, stdout=subprocess.PIPE) subprocess.Popen(sqlmap_api_command, stdout=subprocess.PIPE)
if is_started: if is_started:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"sqlmap API is up and running, continuing process..." "sqlmap API is up and running, continuing process"
)) ))
else: else:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"there was a problem starting sqlmap API...", level=40 "there was a problem starting sqlmap API", level=40
)) ))
lib.core.common.prompt( lib.core.common.prompt(
"manually start the API and press enter when ready..." "manually start the API and press enter when ready"
) )
else: else:
if not is_started: if not is_started:
lib.core.common.prompt( lib.core.common.prompt(
"sqlmap API is not started, start it and press enter to continue..." "sqlmap API is not started, start it and press enter to continue"
) )
try: try:
sqlmap_scan = SqlmapHook(url, port=port) sqlmap_scan = SqlmapHook(url, port=port)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"initializing new sqlmap scan with given URL '{}'...".format(url) "initializing new sqlmap scan with given URL '{}'".format(url)
)) ))
sqlmap_scan.init_new_scan() sqlmap_scan.init_new_scan()
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"scan initialized...", level=10 "scan initialized", level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"gathering sqlmap API scan ID..." "gathering sqlmap API scan ID"
)) ))
api_id = sqlmap_scan.get_scan_id() api_id = sqlmap_scan.get_scan_id()
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"current sqlmap scan ID: '{}'...".format(api_id), level=10 "current sqlmap scan ID: '{}'".format(api_id), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"starting sqlmap scan on url: '{}'...".format(url), level=25 "starting sqlmap scan on url: '{}'".format(url), level=25
)) ))
if opts: if opts:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"using arguments: '{}'...".format(opts), level=10 "using arguments: '{}'".format(opts), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"adding arguments to sqlmap API..." "adding arguments to sqlmap API"
)) ))
else: else:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"no arguments passed, skipping...", level=10 "no arguments passed, skipping", level=10
)) ))
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"please keep in mind that this is the API, output will " "please keep in mind that this is the API, output will "
"not be saved to log file, it may take a little longer " "not be saved to log file, it may take a little longer "
"to finish processing, launching sqlmap...", level=30 "to finish processing, launching sqlmap", level=30
)) ))
sqlmap_scan.start_scan(api_id, opts=opts) sqlmap_scan.start_scan(api_id, opts=opts)
print("-" * 30) print("-" * 30)
@ -224,7 +224,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
except requests.exceptions.HTTPError as e: except requests.exceptions.HTTPError as e:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"ran into error '{}', seems you didn't start the server, check " "ran into error '{}', seems you didn't start the server, check "
"the server port and try again...".format(e), level=50 "the server port and try again".format(e), level=50
)) ))
pass pass
except KeyboardInterrupt: except KeyboardInterrupt:
@ -236,7 +236,7 @@ def sqlmap_scan_main(url, port=None, verbose=None, opts=None, auto_start=False):
"sqlmap API is not started, did you forget to start it? " "sqlmap API is not started, did you forget to start it? "
"You will need to open a new terminal, cd into sqlmap, and " "You will need to open a new terminal, cd into sqlmap, and "
"run `python sqlmapapi.py -s` otherwise pass the correct flags " "run `python sqlmapapi.py -s` otherwise pass the correct flags "
"to auto start the API...", level=40 "to auto start the API", level=40
)) ))
pass pass
else: else:

View file

@ -74,7 +74,7 @@ def whois_lookup_main(domain, **kwargs):
try: try:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"performing WhoIs lookup on given domain '{}'...".format(domain) "performing WhoIs lookup on given domain '{}'".format(domain)
)) ))
if timeout is not None: if timeout is not None:
time.sleep(timeout) time.sleep(timeout)
@ -82,14 +82,14 @@ def whois_lookup_main(domain, **kwargs):
raw_information = gather_raw_whois_info(domain) raw_information = gather_raw_whois_info(domain)
except Exception: except Exception:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"unable to produce information from WhoIs lookup...", level=40 "unable to produce information from WhoIs lookup", level=40
)) ))
return None return None
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"discovered raw information...", level=25 "discovered raw information", level=25
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"gathering interesting information..." "gathering interesting information"
)) ))
interesting_data = get_interesting(raw_information) interesting_data = get_interesting(raw_information)
if verbose: if verbose:
@ -97,7 +97,7 @@ def whois_lookup_main(domain, **kwargs):
human_readable_display(domain, interesting_data) human_readable_display(domain, interesting_data)
except (ValueError, Exception): except (ValueError, Exception):
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"unable to display any information from WhoIs lookup on domain '{}'...".format(domain), level=50 "unable to display any information from WhoIs lookup on domain '{}'".format(domain), level=50
)) ))
return None return None
lib.core.common.write_to_log_file( lib.core.common.write_to_log_file(

View file

@ -29,6 +29,19 @@ def list_tamper_scripts(path="{}/lib/tamper_scripts"):
return retval return retval
def assign_protocol(url, force=False):
auto_assign = ("http://{}", "https://{}")
url_verification = re.compile(r"http(s)?", re.I)
if url_verification.search(url) is None:
if not force:
return auto_assign[0].format(url)
else:
return auto_assign[1].format(url)
else:
return url
def __tamper_payload(payload, tamper_type, warning=True, **kwargs): def __tamper_payload(payload, tamper_type, warning=True, **kwargs):
""" """
add the tamper to the payload from the given tamper type add the tamper to the payload from the given tamper type
@ -40,7 +53,7 @@ def __tamper_payload(payload, tamper_type, warning=True, **kwargs):
if warning: if warning:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"tampering payload with '{}'...".format(tamper), level=10 "tampering payload with '{}'".format(tamper), level=10
)) ))
if tamper in acceptable: if tamper in acceptable:
tamper_name = "lib.tamper_scripts.{}_encode" tamper_name = "lib.tamper_scripts.{}_encode"
@ -58,7 +71,7 @@ def __load_payloads(filename="{}/etc/text_files/xss_payloads.txt"):
with open(filename.format(os.getcwd())) as payloads: return payloads.readlines() with open(filename.format(os.getcwd())) as payloads: return payloads.readlines()
def create_urls(url, payload_list, tamper=None, verbose=False): def create_urls(url, payload_list, tamper=None, verbose=False, force=False):
""" """
create the tampered URL's, write them to a temporary file and read them from there create the tampered URL's, write them to a temporary file and read them from there
""" """
@ -73,13 +86,12 @@ def create_urls(url, payload_list, tamper=None, verbose=False):
else: else:
payload = __tamper_payload(payload, tamper_type=tamper, warning=False, verbose=verbose) payload = __tamper_payload(payload, tamper_type=tamper, warning=False, verbose=verbose)
except InvalidTamperProvided: except InvalidTamperProvided:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"you provided and invalid tamper script, acceptable tamper scripts are: {}...".format( "you provided and invalid tamper script, acceptable tamper scripts are: {}".format(
" | ".join(list_tamper_scripts()), level=40 " | ".join(list_tamper_scripts()), level=40
) )
)) ))
lib.core.common.shutdown() loaded_url = "{}{}\n".format(assign_protocol(url.strip(), force=force), payload.strip())
loaded_url = "{}{}\n".format(url.strip(), payload.strip())
tmp.write(loaded_url) tmp.write(loaded_url)
return tf_name return tf_name
@ -97,7 +109,7 @@ def find_xss_script(url, **kwargs):
else: else:
retval = data[payload_parser["query"]] retval = data[payload_parser["query"]]
# just double checking... # just double checking
if retval == "" or None: if retval == "" or None:
retval = data[payload_parser["path"]] retval = data[payload_parser["path"]]
return retval return retval
@ -110,35 +122,19 @@ def scan_xss(url, agent=None, proxy=None):
be tampered or encoded if the site is not vulnerable be tampered or encoded if the site is not vulnerable
""" """
retry_flags = 3 try:
auto_assign = "http://{}" _, status, html_data, _ = lib.core.common.get_page(url, agent=agent, proxy=proxy)
url_verification = re.compile(r"http(s)?", re.I) query = find_xss_script(url)
for db in lib.core.settings.DBMS_ERRORS.keys():
if url_verification.search(url) is None: for item in lib.core.settings.DBMS_ERRORS[db]:
lib.core.settings.logger.warning(lib.core.settings.set_color( if re.findall(item, html_data):
"protocol missing from URL, automatically assigning protocol...", level=30 return "sqli", db
)) if status != 404:
url = auto_assign.format(url) if query in html_data:
return True, None
while retry_flags > 0: return False, None
try: except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError):
_, status, html_data, _ = lib.core.common.get_page(url, agent=agent, proxy=proxy) return False, None
query = find_xss_script(url)
for db in lib.core.settings.DBMS_ERRORS.keys():
for item in lib.core.settings.DBMS_ERRORS[db]:
if re.findall(item, html_data):
return "sqli", db
if status != 404:
if query in html_data:
return True, None
retry_flags -= 1
except requests.exceptions.ChunkedEncodingError:
lib.core.settings.logger.warning(lib.core.settings.set_color(
"encoding seems to be messed up, retrying request...", level=30
))
retry_flags -= 1
return False, None
def main_xss(start_url, proxy=None, agent=None, **kwargs): def main_xss(start_url, proxy=None, agent=None, **kwargs):
@ -148,6 +144,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
tamper = kwargs.get("tamper", None) tamper = kwargs.get("tamper", None)
verbose = kwargs.get("verbose", False) verbose = kwargs.get("verbose", False)
batch = kwargs.get("batch", False) batch = kwargs.get("batch", False)
force = kwargs.get("force_ssl", False)
question_msg = ( question_msg = (
"it appears that heuristic tests have shown this URL may not be a good " "it appears that heuristic tests have shown this URL may not be a good "
@ -168,30 +165,30 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
try: try:
if tamper: if tamper:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"tampering payloads with '{}'...".format(tamper) "tampering payloads with '{}'".format(tamper)
)) ))
find_xss_script(start_url) find_xss_script(start_url)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"loading payloads..." "loading payloads"
)) ))
payloads = __load_payloads() payloads = __load_payloads()
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"a total of {} payloads loaded...".format(len(payloads)), level=10 "a total of {} payloads loaded".format(len(payloads)), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"payloads will be written to a temporary file and read from there..." "payloads will be written to a temporary file and read from there"
)) ))
filename = create_urls(start_url, payloads, tamper=tamper, verbose=verbose) filename = create_urls(start_url, payloads, tamper=tamper, verbose=verbose, force=force)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"loaded URL's have been saved to '{}'...".format(filename), level=25 "loaded URL's have been saved to '{}'".format(filename), level=25
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"testing for XSS vulnerabilities on host '{}'...".format(start_url) "testing for XSS vulnerabilities on host '{}'".format(start_url)
)) ))
if proxy is not None: if proxy is not None:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"using proxy '{}'...".format(proxy) "using proxy '{}'".format(proxy)
)) ))
success = set() success = set()
with open(filename) as urls: with open(filename) as urls:
@ -202,42 +199,44 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
result = scan_xss(url, proxy=proxy, agent=agent) result = scan_xss(url, proxy=proxy, agent=agent)
if verbose: if verbose:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"trying payload '{}'...".format(payload) "trying payload '{}'".format(payload)
)) ))
if result[0] != "sqli" and result[0] is True: if result[0] != "sqli" and result[0] is True:
success.add(url) success.add(url)
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"payload '{}' appears to be usable...".format(payload), level=15 "payload '{}' appears to be usable".format(payload), level=15
)) ))
elif result[0] is "sqli": elif result[0] is "sqli":
if i <= 1: if i <= 1:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"loaded URL '{}' threw a DBMS error and appears to be injectable, test for " "loaded URL '{}' threw a DBMS error and appears to be injectable, test for "
"SQL injection, backend DBMS appears to be '{}'...".format( "SQL injection, backend DBMS appears to be '{}'".format(
url, result[1] url, result[1]
), level=40 ), level=40
)) ))
else: else:
if verbose: if verbose:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"SQL error discovered...", level=40 "SQL error discovered", level=40
)) ))
else: else:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"host '{}' does not appear to be vulnerable to XSS attacks with payload '{}'...".format( "host '{}' does not appear to be vulnerable to XSS attacks with payload '{}'".format(
start_url, payload start_url, payload
), level=10 ), level=10
)) ))
except ( except (
requests.exceptions.ConnectionError, requests.exceptions.ConnectionError,
requests.exceptions.TooManyRedirects, requests.exceptions.TooManyRedirects,
requests.exceptions.ReadTimeout requests.exceptions.ReadTimeout,
requests.exceptions.InvalidURL
): ):
lib.core.settings.logger.error(lib.core.settings.set_color( if not payload == "":
"payload '{}' caused a connection error, assuming no good and continuing...".format(payload), level=40 lib.core.settings.logger.error(lib.core.settings.set_color(
)) "payload '{}' caused a connection error, assuming no good and continuing".format(payload), level=40
))
if len(success) != 0: if len(success) != 0:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
@ -246,7 +245,7 @@ def main_xss(start_url, proxy=None, agent=None, **kwargs):
lib.core.settings.create_tree(start_url, list(success)) lib.core.settings.create_tree(start_url, list(success))
else: else:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"host '{}' does not appear to be vulnerable to XSS attacks...".format(start_url), level=40 "host '{}' does not appear to be vulnerable to XSS attacks".format(start_url), level=40
)) ))
question_msg = "would you like to keep the created URLs saved for further testing" question_msg = "would you like to keep the created URLs saved for further testing"
if not batch: if not batch:

View file

@ -24,7 +24,7 @@ STATUS_CODES = {
200: "OK", 201: "created", 202: "accepted", 203: "non-authoritative information", 200: "OK", 201: "created", 202: "accepted", 203: "non-authoritative information",
204: "no content", 205: "reset content", 206: "partial content", 204: "no content", 205: "reset content", 206: "partial content",
207: "multi-status", 208: "already reported", 226: "IM used", 207: "multi-status", 208: "already reported", 226: "IM used",
300: "multiple choices", 301: "moved permanently", 302: "not found", 300: "multiple choices", 301: "moved permanently", 302: "found redirect",
303: "see other", 304: "not modified", 305: "use proxy", 303: "see other", 304: "not modified", 305: "use proxy",
306: "switch proxy", 308: "permanent redirect", 306: "switch proxy", 308: "permanent redirect",
400: "bad request", 401: "unauthorized", 402: "payment required", 400: "bad request", 401: "unauthorized", 402: "payment required",
@ -162,7 +162,7 @@ def write_to_log_file(data_to_write, path, filename, blacklist=False):
items = log.readlines() items = log.readlines()
if any(d.strip() == data_to_write for d in items): if any(d.strip() == data_to_write for d in items):
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"query already in blacklist..." "query already in blacklist"
)) ))
return full_file_path return full_file_path
else: else:
@ -181,7 +181,7 @@ def write_to_log_file(data_to_write, path, filename, blacklist=False):
else: else:
log.write(data_to_write + "\n") log.write(data_to_write + "\n")
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"successfully wrote found items to '{}'...".format(full_file_path) "successfully wrote found items to '{}'".format(full_file_path)
)) ))
return full_file_path return full_file_path
@ -276,7 +276,7 @@ def run_fix(message, command, fail_message, exit_process=False):
subprocess.call(cmd) subprocess.call(cmd)
if exit_process: if exit_process:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"command completed successfully, should be safe to re-run Zeus..." "command completed successfully, should be safe to re-run Zeus"
)) ))
else: else:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
@ -329,7 +329,11 @@ def get_page(url, **kwargs):
else: else:
proxies = {} proxies = {}
req = requests.get(url, params=headers, proxies=proxies, verify=False if skip_verf else True, timeout=20) if proxy is not None and "127.0.0.1" in proxy:
req = requests.get(url, params=headers, proxies=proxies, verify=False, timeout=40)
else:
req = requests.get(url, params=headers, proxies=proxies, verify=False, timeout=20)
status = req.status_code status = req.status_code
html = req.content html = req.content
headers = req.headers headers = req.headers

View file

@ -19,4 +19,7 @@ class InvalidInputProvided(Exception): pass
class InvalidTamperProvided(Exception): pass class InvalidTamperProvided(Exception): pass
class PortScanTimeOutException(Exception): pass class PortScanTimeOutException(Exception): pass
class ZeusArgumentException(Exception): pass

View file

@ -1,3 +1,4 @@
import sys
from optparse import ( from optparse import (
OptionParser, OptionParser,
OptionGroup, OptionGroup,
@ -6,6 +7,7 @@ from optparse import (
import lib.core.settings import lib.core.settings
import lib.core.common import lib.core.common
import lib.core.errors
import lib.attacks.nmap_scan.nmap_opts import lib.attacks.nmap_scan.nmap_opts
import lib.attacks.sqlmap_scan.sqlmap_opts import lib.attacks.sqlmap_scan.sqlmap_opts
@ -24,7 +26,7 @@ class ZeusParser(OptionParser):
""" """
command line parser, parses all of Zeus's arguments and flags command line parser, parses all of Zeus's arguments and flags
""" """
parser = OptionParser(usage="./zeus.py -d|r|l|f|b| DORK|FILE|URL [ATTACKS] [--OPTS]") parser = OptionParser(usage="./zeus.py -d|r|l|f|b DORK|FILE|URL [ATTACKS] [--OPTS]")
# mandatory options # mandatory options
mandatory = OptionGroup(parser, "Mandatory Options", mandatory = OptionGroup(parser, "Mandatory Options",
@ -45,6 +47,11 @@ class ZeusParser(OptionParser):
mandatory.add_option("-f", "--url-file", dest="fileToEnumerate", metavar="FILE-PATH", mandatory.add_option("-f", "--url-file", dest="fileToEnumerate", metavar="FILE-PATH",
help="Run an attack on URL's in a given file") help="Run an attack on URL's in a given file")
# being worked on
# TODO:/
mandatory.add_option("-u", "--url", dest="singleTargetRecon", metavar="URL",
help=SUPPRESS_HELP)
# attack options # attack options
attacks = OptionGroup(parser, "Attack arguments", attacks = OptionGroup(parser, "Attack arguments",
"These arguments will give you the choice on how you want to check the websites") "These arguments will give you the choice on how you want to check the websites")
@ -67,8 +74,10 @@ class ZeusParser(OptionParser):
attacks.add_option("-c", "--clickjacking", dest="performClickjackingScan", action="store_true", attacks.add_option("-c", "--clickjacking", dest="performClickjackingScan", action="store_true",
help="Perform a clickjacking scan on a provided URL") help="Perform a clickjacking scan on a provided URL")
# being worked on
# TODO:/
attacks.add_option("-g", "--github-search", dest="searchGithub", action="store_true", attacks.add_option("-g", "--github-search", dest="searchGithub", action="store_true",
help="Perform a Github Gist search for any information on the found websites") help=SUPPRESS_HELP)
attacks.add_option("-P", "--pgp", dest="pgpLookup", action="store_true", attacks.add_option("-P", "--pgp", dest="pgpLookup", action="store_true",
help="Perform a PGP public key lookup on the found URLs") help="Perform a PGP public key lookup on the found URLs")
@ -96,6 +105,8 @@ class ZeusParser(OptionParser):
attacks.add_option("--tamper", dest="tamperXssPayloads", metavar="TAMPER-SCRIPT", attacks.add_option("--tamper", dest="tamperXssPayloads", metavar="TAMPER-SCRIPT",
help="Send the XSS payloads through tampering before sending to the target") help="Send the XSS payloads through tampering before sending to the target")
# being worked on
# TODO:/
attacks.add_option("--thread", dest="threadPanels", action="store_true", attacks.add_option("--thread", dest="threadPanels", action="store_true",
help=SUPPRESS_HELP) help=SUPPRESS_HELP)
@ -141,6 +152,11 @@ class ZeusParser(OptionParser):
help="Attempt to identify if the target is protected by some kind of " help="Attempt to identify if the target is protected by some kind of "
"WAF/IDS/IPS") "WAF/IDS/IPS")
# being worked on
# TODO:/
search_items.add_option("--force-ssl", dest="forceSSL", action="store_true",
help=SUPPRESS_HELP)
search_items.add_option("--identify-plugins", dest="identifyPlugin", action="store_true", search_items.add_option("--identify-plugins", dest="identifyPlugin", action="store_true",
help="Attempt to identify what plugins the target is using") help="Attempt to identify what plugins the target is using")
@ -182,6 +198,8 @@ class ZeusParser(OptionParser):
misc.add_option("--version", dest="showCurrentVersion", action="store_true", misc.add_option("--version", dest="showCurrentVersion", action="store_true",
help="Show the current version and exit") help="Show the current version and exit")
# being worked on
# TODO:/
misc.add_option("-T", "--x-threads", dest="amountOfThreads", metavar="THREAD-AMOUNT", type=int, misc.add_option("-T", "--x-threads", dest="amountOfThreads", metavar="THREAD-AMOUNT", type=int,
help=SUPPRESS_HELP) help=SUPPRESS_HELP)
@ -221,7 +239,7 @@ class ZeusParser(OptionParser):
) )
print("\n") print("\n")
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"for more information about sqlmap arguments, see here '{}'...".format( "for more information about sqlmap arguments, see here '{}'".format(
lib.core.settings.SQLMAP_MAN_PAGE_URL lib.core.settings.SQLMAP_MAN_PAGE_URL
) )
)) ))
@ -240,7 +258,7 @@ class ZeusParser(OptionParser):
) )
print("\n") print("\n")
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"for more information on what the arguments do please see here '{}'...".format( "for more information on what the arguments do please see here '{}'".format(
lib.core.settings.NMAP_MAN_PAGE_URL lib.core.settings.NMAP_MAN_PAGE_URL
) )
)) ))
@ -249,7 +267,29 @@ class ZeusParser(OptionParser):
# update the program # update the program
if opt.updateZeus: if opt.updateZeus:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"update in progress..." "update in progress"
)) ))
lib.core.settings.update_zeus() lib.core.settings.update_zeus()
lib.core.common.shutdown() lib.core.common.shutdown()
@staticmethod
def verify_args(args=sys.argv):
not_implemented_args = (
"-T", "--x-threads", "--force-ssl", "--thread",
"-g", "--github-search", "-u", "--url"
)
# check if any of the arguments are not implemented that have been passed
# via the command line
# TODO:/
# need to create a way to parse all arguments for compatibility with one another
for arg in args:
for nia in not_implemented_args:
if arg == nia:
raise lib.core.errors.ZeusArgumentException(
"\n\nit appears that one of the arguments you have passed ('{}'), "
"has not been implemented into Zeus production yet. This usually means "
"that the option is still in testing and is not ready for use. Arguments "
"that are still in testing are: {}\n".format(
nia, ", ".join(["'{}'".format(a) for a in not_implemented_args])
)
)

View file

@ -8,7 +8,6 @@ import shlex
import difflib import difflib
import logging import logging
import base64 import base64
import string
import random import random
import socket import socket
import struct import struct
@ -45,7 +44,7 @@ CLONE = "https://github.com/ekultek/zeus-scanner.git"
ISSUE_LINK = "https://github.com/ekultek/zeus-scanner/issues" ISSUE_LINK = "https://github.com/ekultek/zeus-scanner/issues"
# current version <major.minor.commit.patch ID> # current version <major.minor.commit.patch ID>
VERSION = "1.4".format(PATCH_ID) VERSION = "1.5.2.{}".format(PATCH_ID)
# colors to output depending on the version # colors to output depending on the version
VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30} VERSION_TYPE_COLORS = {"dev": 33, "stable": 92, "other": 30}
@ -284,13 +283,6 @@ AUTHORIZED_SEARCH_ENGINES = {
"pgp": "https://pgp.mit.edu/pks/lookup?search={}&op=index" "pgp": "https://pgp.mit.edu/pks/lookup?search={}&op=index"
} }
# search page for Gists and rate checking URL
GITHUB_GIST_SEARCH_URLS = {
"search": "https://api.github.com/gists/public?page={}&per_page=100",
"check_rate": "https://api.github.com/users/ZeusIssueReporter"
}
# extensions to exclude from the spider # extensions to exclude from the spider
SPIDER_EXT_EXCLUDE = ( SPIDER_EXT_EXCLUDE = (
"3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff", "3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff",
@ -320,7 +312,7 @@ URL_EXCLUDES = (
"torproject.org", "search-results.com", "index.com", "torproject.org", "search-results.com", "index.com",
"gov", ".gov", "facebook.com", "instagram.com", "snapchat", "gov", ".gov", "facebook.com", "instagram.com", "snapchat",
"stackoverflow", "stackexchange", "github.com", "apple.com", "stackoverflow", "stackexchange", "github.com", "apple.com",
"http://my." "http://my.", "root.cern"
) )
# regular expressions used for DBMS recognition based on error message response # regular expressions used for DBMS recognition based on error message response
@ -465,7 +457,7 @@ def setup(verbose=False):
""" """
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"checking if the application has been run before...", level=10 "checking if the application has been run before", level=10
)) ))
bin.unzip_gecko.main(verbose=verbose) bin.unzip_gecko.main(verbose=verbose)
@ -513,12 +505,12 @@ def grab_random_agent(agent_path="{}/etc/text_files/agents.txt", verbose=False):
""" """
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"grabbing random user-agent from '{}'...".format(agent_path.format(os.getcwd())), level=10 "grabbing random user-agent from '{}'".format(agent_path.format(os.getcwd())), level=10
)) ))
with open(agent_path.format(os.getcwd())) as agents: with open(agent_path.format(os.getcwd())) as agents:
retval = random.choice(agents.readlines()) retval = random.choice(agents.readlines())
logger.info(set_color( logger.info(set_color(
"random agent being used '{}'...".format(retval.strip()) "random agent being used '{}'".format(retval.strip())
)) ))
return retval.strip() return retval.strip()
@ -555,7 +547,7 @@ def update_zeus():
return os.system("git pull origin master") return os.system("git pull origin master")
else: else:
logger.fatal(set_color( logger.fatal(set_color(
"no git repository found in directory, unable to update automatically..." "no git repository found in directory, unable to update automatically"
)) ))
@ -608,28 +600,34 @@ def search_for_process(name):
return False if not any(name in proc for proc in list(all_process_names)) else True return False if not any(name in proc for proc in list(all_process_names)) else True
def get_browser_version(): def get_browser_version(output=True):
""" """
obtain the firefox browser version, this is necessary because zeus can only handle certain versions. obtain the firefox browser version, this is necessary because zeus can only handle certain versions.
""" """
logger.info(set_color( if output:
"attempting to get firefox browser version..." logger.info(set_color(
)) "attempting to get firefox browser version"
))
try: try:
firefox_version_command = shlex.split("firefox --version") firefox_version_command = shlex.split("firefox --version")
output = subprocess.check_output(firefox_version_command) output = subprocess.check_output(firefox_version_command)
except (OSError, Exception): except OSError:
logger.error(set_color( logger.error(set_color(
"failed to run firefox...", level=50 "failed to run firefox", level=50
)) ))
return "failed to start" return "failed to start"
try: try:
major, minor = map(int, re.search(r"(\d+).(\d+)", output).groups()) major, minor = map(int, re.search(r"(\d+).(\d+)", output).groups())
except (ValueError, Exception): except ValueError:
logger.error(set_color( logger.error(set_color(
"failed to parse '{}' for version number...".format(output), level=50 "failed to parse '{}' for version number".format(output), level=50
)) ))
return "failed to gather" return output
except Exception as e:
logger.error(set_color(
"received and exception from firefox '{}'".format(str(e), level=50)
))
return str(e)
return major, minor return major, minor
@ -643,11 +641,15 @@ def config_headers(**kwargs):
rand_agent = kwargs.get("rand_agent", None) rand_agent = kwargs.get("rand_agent", None)
verbose = kwargs.get("verbose", False) verbose = kwargs.get("verbose", False)
if proxy is not None: if proxy is not None:
if "127.0.0.1" in proxy:
logger.warning(set_color(
"timeout will be increased to 40s due to Tor being used", level=30
))
proxy_retval = proxy proxy_retval = proxy
elif rand_proxy is not None: elif rand_proxy is not None:
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"loading random proxy from '{}'...".format(rand_proxy), level=10 "loading random proxy from '{}'".format(rand_proxy), level=10
)) ))
with open(rand_proxy) as proxies: with open(rand_proxy) as proxies:
possible = proxies.readlines() possible = proxies.readlines()
@ -673,14 +675,14 @@ def get_md5sum(url="https://raw.githubusercontent.com/Ekultek/Zeus-Scanner/maste
return True return True
def create_identifier(chars=string.ascii_letters): def create_identifier(st):
""" """
create the identifier for your Github issue create the identifier for your Github issue
""" """
retval = [] import hashlib
for _ in range(0, 7): obj = hashlib.md5()
retval.append(random.choice(chars)) obj.update(st)
return "".join(retval) return obj.hexdigest()[1:9]
def config_search_engine(**kwargs): def config_search_engine(**kwargs):
@ -693,8 +695,8 @@ def config_search_engine(**kwargs):
ddg = kwargs.get("ddg", False) ddg = kwargs.get("ddg", False)
enum = kwargs.get("enum", None) enum = kwargs.get("enum", None)
non_default_msg = "specified to use non-default search engine..." non_default_msg = "specified to use non-default search engine"
se_message = "using '{}' as the search engine..." se_message = "using '{}' as the search engine"
if ddg: if ddg:
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
@ -706,7 +708,7 @@ def config_search_engine(**kwargs):
se = AUTHORIZED_SEARCH_ENGINES["duckduckgo"] se = AUTHORIZED_SEARCH_ENGINES["duckduckgo"]
elif aol: elif aol:
logger.warning(set_color( logger.warning(set_color(
"AOL will take a little longer due to pop-ups...", level=30 "AOL will take a little longer due to pop-ups", level=30
)) ))
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
@ -727,16 +729,16 @@ def config_search_engine(**kwargs):
se = AUTHORIZED_SEARCH_ENGINES["bing"] se = AUTHORIZED_SEARCH_ENGINES["bing"]
elif enum is not None: elif enum is not None:
logger.info(set_color( logger.info(set_color(
"running enumeration on given file '{}'...".format(enum) "running enumeration on given file '{}'".format(enum)
)) ))
se = None se = None
else: else:
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"using default search engine (Google)...", level=10 "using default search engine (Google)", level=10
)) ))
logger.info(set_color( logger.info(set_color(
"using default search engine..." "using default search engine"
)) ))
se = AUTHORIZED_SEARCH_ENGINES["google"] se = AUTHORIZED_SEARCH_ENGINES["google"]
return se return se
@ -753,7 +755,7 @@ def create_arguments(**kwargs):
conf_file = kwargs.get("conf", None) conf_file = kwargs.get("conf", None)
logger.info(set_color( logger.info(set_color(
"creating arguments for {}...".format("sqlmap" if sqlmap else "nmap") "creating arguments for {}".format("sqlmap" if sqlmap else "nmap")
)) ))
retval = [] retval = []
splitter = {"sqlmap": ",", "nmap": "|"} splitter = {"sqlmap": ",", "nmap": "|"}
@ -765,7 +767,7 @@ def create_arguments(**kwargs):
if o.lower() == opt[0]: if o.lower() == opt[0]:
retval.append((o, opt[1])) retval.append((o, opt[1]))
elif sqlmap: elif sqlmap:
warn_msg = "option '{}' is not recognized by sqlmap API, skipping..." warn_msg = "option '{}' is not recognized by sqlmap API, skipping"
if sqlmap_args is not None: if sqlmap_args is not None:
for line in sqlmap_args.split(splitter["sqlmap"]): for line in sqlmap_args.split(splitter["sqlmap"]):
try: try:
@ -788,7 +790,7 @@ def create_arguments(**kwargs):
)) ))
elif nmap: elif nmap:
warning_msg = "option {} is not known by the nmap api, skipping..." warning_msg = "option {} is not known by the nmap api, skipping"
if nmap_args is not None: if nmap_args is not None:
for line in nmap_args.split(splitter["nmap"]): for line in nmap_args.split(splitter["nmap"]):
try: try:
@ -826,7 +828,7 @@ def create_random_ip():
if generated == "0.0.0.0" or "255.255.255.255": if generated == "0.0.0.0" or "255.255.255.255":
generated = __get_nodes() # if it isn't a real IP regenerate it generated = __get_nodes() # if it isn't a real IP regenerate it
logger.info(set_color( logger.info(set_color(
"random IP address generated for header '{}'...".format(generated) "random IP address generated for header '{}'".format(generated)
)) ))
return generated return generated
@ -854,7 +856,7 @@ def check_for_protection(protected, attack_type):
if attack_type in items or "all" in items: if attack_type in items or "all" in items:
logger.warning(set_color( logger.warning(set_color(
"provided target seems to have protection against this attack type...", level=30 "provided target seems to have protection against this attack type", level=30
)) ))
protected.clear() # clear the set protected.clear() # clear the set
return True return True
@ -868,7 +870,7 @@ def deprecation(target_version, method, connect=True, *args, **kwargs):
print( print(
"[{} DEPRECATION] {}".format( "[{} DEPRECATION] {}".format(
time.strftime("%H:%M:%S"), set_color( time.strftime("%H:%M:%S"), set_color(
"{} will be deprecated by version {}...".format( "{} will be deprecated by version {}".format(
method.__name__, target_version method.__name__, target_version
), level=35 ), level=35
) )
@ -880,7 +882,7 @@ def deprecation(target_version, method, connect=True, *args, **kwargs):
"[{} DEPRECATION] {}".format( "[{} DEPRECATION] {}".format(
time.strftime("%H:%M:%S"), set_color( time.strftime("%H:%M:%S"), set_color(
"{} has been deprecated and will no longer work, " "{} has been deprecated and will no longer work, "
"this attack type will be completely removed by v{}...".format( "this attack type will be completely removed by v{}".format(
method.__name__, target_version method.__name__, target_version
), level=35 ), level=35
) )
@ -896,10 +898,10 @@ def check_thread_num(number, batch=False, default=5):
logger.warning(set_color( logger.warning(set_color(
"you have specified {} threads, it is highly advised to not go over {} threads, " "you have specified {} threads, it is highly advised to not go over {} threads, "
"doing so will most likely not give a significant performance increase and also " "doing so will most likely not give a significant performance increase and also "
"will most likely cause unforeseen issues...".format(number, MAX_THREADS), level=30 "will most likely cause unforeseen issues".format(number, MAX_THREADS), level=30
)) ))
question_msg = "would you like to continue anyways" question_msg = "would you like to continue anyways"
default_msg = "defaulting to 5 threads..." default_msg = "defaulting to 5 threads"
if not batch: if not batch:
question = lib.core.common.prompt( question = lib.core.common.prompt(
question_msg, opts="yN" question_msg, opts="yN"
@ -931,7 +933,7 @@ def run_attacks(url, **kwargs):
verbose = kwargs.get("verbose", False) verbose = kwargs.get("verbose", False)
whois = kwargs.get("whois", False) whois = kwargs.get("whois", False)
clickjacking = kwargs.get("clickjacking", False) clickjacking = kwargs.get("clickjacking", False)
github = kwargs.get("github", False) # github = kwargs.get("github", False)
pgp = kwargs.get("pgp", False) pgp = kwargs.get("pgp", False)
auto_start = kwargs.get("auto_start", False) auto_start = kwargs.get("auto_start", False)
sqlmap_arguments = kwargs.get("sqlmap_args", None) sqlmap_arguments = kwargs.get("sqlmap_args", None)
@ -946,6 +948,7 @@ def run_attacks(url, **kwargs):
agent = kwargs.get("agent", None) agent = kwargs.get("agent", None)
conf_file = kwargs.get("conf_file", None) conf_file = kwargs.get("conf_file", None)
threads = kwargs.get("threads", None) threads = kwargs.get("threads", None)
force_ssl = kwargs.get("ssl", False)
if threads > MAX_THREADS: if threads > MAX_THREADS:
threads = check_thread_num(threads, batch=batch) threads = check_thread_num(threads, batch=batch)
@ -969,7 +972,7 @@ def run_attacks(url, **kwargs):
"as of now only 1 attack is supported at a time, choose " "as of now only 1 attack is supported at a time, choose "
"your attack and try again. You can use the -f flag if " "your attack and try again. You can use the -f flag if "
"you do not want to complete an entire search again " "you do not want to complete an entire search again "
"(IE -f /home/me/zeus-scanner/log/url-log/url-log-1.log)...", level=40 "(IE -f /home/me/zeus-scanner/log/url-log/url-log-1.log)", level=40
)) ))
lib.core.common.shutdown() lib.core.common.shutdown()
@ -1008,6 +1011,7 @@ def run_attacks(url, **kwargs):
main_xss( main_xss(
url, verbose=verbose, proxy=proxy, url, verbose=verbose, proxy=proxy,
agent=agent, tamper=tamper_script, batch=batch, agent=agent, tamper=tamper_script, batch=batch,
force_ssl=force_ssl
) )
elif whois: elif whois:
from lib.attacks.whois_lookup.whois import whois_lookup_main from lib.attacks.whois_lookup.whois import whois_lookup_main
@ -1019,10 +1023,10 @@ def run_attacks(url, **kwargs):
if check_for_protection(PROTECTED, "clickjacking"): if check_for_protection(PROTECTED, "clickjacking"):
clickjacking_main(url, agent=agent, proxy=proxy, clickjacking_main(url, agent=agent, proxy=proxy,
forward=forwarded, batch=batch) forward=forwarded, batch=batch)
elif github: # elif github:
from lib.attacks.gist_lookup import github_gist_search_main # from lib.attacks.gist_lookup import github_gist_search_main
query = replace_http(url) # query = replace_http(url)
github_gist_search_main(query, agent=agent, proxy=proxy, verbose=verbose) # github_gist_search_main(query, agent=agent, proxy=proxy, verbose=verbose)
elif pgp: elif pgp:
from var.search.pgp_search import pgp_main from var.search.pgp_search import pgp_main
pgp_main(url, verbose=verbose) pgp_main(url, verbose=verbose)
@ -1030,7 +1034,7 @@ def run_attacks(url, **kwargs):
pass pass
else: else:
logger.warning(set_color( logger.warning(set_color(
"skipping '{}'...".format(url), level=30 "skipping '{}'".format(url), level=30
)) ))

View file

@ -1,10 +1,14 @@
import os import os
import re import re
import time
import importlib import importlib
import unicodedata import unicodedata
from xml.dom import minidom from xml.dom import minidom
from requests.exceptions import ConnectionError from requests.exceptions import (
ConnectionError,
ReadTimeout
)
from var.auto_issue.github import request_issue_creation from var.auto_issue.github import request_issue_creation
from lib.core.common import ( from lib.core.common import (
@ -12,7 +16,7 @@ from lib.core.common import (
shutdown, shutdown,
pause, pause,
get_page, get_page,
HTTP_HEADER HTTP_HEADER,
) )
from lib.core.settings import ( from lib.core.settings import (
logger, set_color, logger, set_color,
@ -46,17 +50,12 @@ def get_charset(html, headers, **kwargs):
content = headers.get(HTTP_HEADER.CONTENT_TYPE, "") content = headers.get(HTTP_HEADER.CONTENT_TYPE, "")
charset = charset_regex.search(content) charset = charset_regex.search(content)
if charset is not None: if charset is not None:
return charset return charset.group(1)
return None return None
def detect_protection(url, status, html, headers, **kwargs): def detect_protection(url, status, html, headers, **kwargs):
verbose = kwargs.get("verbose", False) verbose = kwargs.get("verbose", False)
if verbose:
logger.debug(set_color(
"attempting connection to '{}'...".format(url), level=10
))
try: try:
# make sure there are no DBMS errors in the HTML # make sure there are no DBMS errors in the HTML
for dbms in DBMS_ERRORS: for dbms in DBMS_ERRORS:
@ -65,7 +64,7 @@ def detect_protection(url, status, html, headers, **kwargs):
logger.warning(set_color( logger.warning(set_color(
"it appears that the WAF/IDS/IPS check threw a DBMS error and may be vulnerable " "it appears that the WAF/IDS/IPS check threw a DBMS error and may be vulnerable "
"to SQL injection attacks. it appears the backend DBMS is '{}', site will be " "to SQL injection attacks. it appears the backend DBMS is '{}', site will be "
"saved for further processing...".format(dbms), level=30 "saved for further processing".format(dbms), level=30
)) ))
write_to_log_file(url, SQLI_SITES_FILEPATH, SQLI_FOUND_FILENAME) write_to_log_file(url, SQLI_SITES_FILEPATH, SQLI_FOUND_FILENAME)
return None return None
@ -76,7 +75,7 @@ def detect_protection(url, status, html, headers, **kwargs):
item = item[:-3] item = item[:-3]
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"loading script '{}'...".format(item), level=10 "loading script '{}'".format(item), level=10
)) ))
detection_name = "lib.firewall.{}" detection_name = "lib.firewall.{}"
detection_name = detection_name.format(item) detection_name = detection_name.format(item)
@ -89,7 +88,7 @@ def detect_protection(url, status, html, headers, **kwargs):
del retval[retval.index("Generic (Unknown)")] del retval[retval.index("Generic (Unknown)")]
except (Exception, IndexError): except (Exception, IndexError):
logger.warning(set_color( logger.warning(set_color(
"multiple firewalls identified ({}), displaying most likely...".format( "multiple firewalls identified ({}), displaying most likely".format(
", ".join([item.split("(")[0] for item in retval]) ", ".join([item.split("(")[0] for item in retval])
), level=30 ), level=30
)) ))
@ -100,7 +99,7 @@ def detect_protection(url, status, html, headers, **kwargs):
logger.warning(set_color( logger.warning(set_color(
"discovered firewall is unknown to Zeus, saving fingerprint to file. " "discovered firewall is unknown to Zeus, saving fingerprint to file. "
"if you know the details or the context of the firewall please create " "if you know the details or the context of the firewall please create "
"an issue ({}) with the fingerprint, or a pull request with the script...".format( "an issue ({}) with the fingerprint, or a pull request with the script".format(
ISSUE_LINK ISSUE_LINK
), level=30 ), level=30
)) ))
@ -113,14 +112,14 @@ def detect_protection(url, status, html, headers, **kwargs):
return None return None
except Exception as e: except Exception as e:
if "Read timed out." or "Connection reset by peer" in str(e): if any(err in str(e) for err in ["Read timed out.", "Connection reset by peer"]):
logger.warning(set_color( logger.warning(set_color(
"detection request failed, assuming no protection and continuing...", level=30 "detection request failed, assuming no protection and continuing", level=30
)) ))
return None return None
else: else:
logger.exception(set_color( logger.exception(set_color(
"Zeus ran into an unexpected error '{}'...".format(e), level=50 "Zeus ran into an unexpected error '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
return None return None
@ -137,7 +136,7 @@ def detect_plugins(html, headers, **kwargs):
plugin = plugin[:-3] plugin = plugin[:-3]
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"loading script '{}'...".format(plugin), level=10 "loading script '{}'".format(plugin), level=10
)) ))
plugin_detection = "lib.plugins.{}" plugin_detection = "lib.plugins.{}"
plugin_detection = plugin_detection.format(plugin) plugin_detection = plugin_detection.format(plugin)
@ -151,12 +150,12 @@ def detect_plugins(html, headers, **kwargs):
logger.exception(str(e)) logger.exception(str(e))
if "Read timed out." or "Connection reset by peer" in str(e): if "Read timed out." or "Connection reset by peer" in str(e):
logger.warning(set_color( logger.warning(set_color(
"plugin request failed, assuming no plugins and continuing...", level=30 "plugin request failed, assuming no plugins and continuing", level=30
)) ))
return None return None
else: else:
logger.exception(set_color( logger.exception(set_color(
"plugin detection has failed with error {}...".format(str(e)) "plugin detection has failed with error {}".format(str(e))
)) ))
request_issue_creation() request_issue_creation()
@ -181,7 +180,7 @@ def load_headers(url, req, **kwargs):
if len(req.cookies) > 0: if len(req.cookies) > 0:
logger.info(set_color( logger.info(set_color(
"found a request cookie, saving to file...", level=25 "found a request cookie, saving to file", level=25
)) ))
try: try:
cookie_start = req.cookies.keys() cookie_start = req.cookies.keys()
@ -247,7 +246,9 @@ def main_header_check(url, **kwargs):
identify_waf = kwargs.get("identify_waf", True) identify_waf = kwargs.get("identify_waf", True)
identify_plugins = kwargs.get("identify_plugins", True) identify_plugins = kwargs.get("identify_plugins", True)
show_description = kwargs.get("show_description", False) show_description = kwargs.get("show_description", False)
attempts = kwargs.get("attempts", 3)
default_sleep_time = 5
protection = {"hostname": url} protection = {"hostname": url}
definition = { definition = {
"x-xss": ("protection against XSS attacks", "XSS"), "x-xss": ("protection against XSS attacks", "XSS"),
@ -260,69 +261,74 @@ def main_header_check(url, **kwargs):
"content-security": ("header protection against multiple attack types", "ALL") "content-security": ("header protection against multiple attack types", "ALL")
} }
req, status, html, headers = get_page(url, proxy=proxy, agent=agent, xforward=xforward)
try: try:
req, status, html, headers = get_page(url, proxy=proxy, agent=agent, xforward=xforward)
logger.info(set_color( logger.info(set_color(
"detecting target charset..." "detecting target charset"
)) ))
charset = get_charset(url, headers) charset = get_charset(html, headers)
if charset is not None: if charset is not None:
logger.info(set_color( logger.info(set_color(
"target charset appears to be '{}'...".format(charset), level=25 "target charset appears to be '{}'".format(charset), level=25
)) ))
else: else:
logger.warning(set_color( logger.warning(set_color(
"unable to detect target charset...", level=30 "unable to detect target charset", level=30
)) ))
if identify_waf: if identify_waf:
waf_url = "{} {}".format(url, PROTECTION_CHECK_PAYLOAD) waf_url = "{} {}".format(url.strip(), PROTECTION_CHECK_PAYLOAD)
_, waf_status, waf_html, waf_headers = get_page(waf_url, xforward=xforward, proxy=proxy, agent=agent) _, waf_status, waf_html, waf_headers = get_page(waf_url, xforward=xforward, proxy=proxy, agent=agent)
logger.info(set_color( logger.info(set_color(
"checking if target URL is protected by some kind of WAF/IPS/IDS..." "checking if target URL is protected by some kind of WAF/IPS/IDS"
)) ))
if verbose:
logger.debug(set_color(
"attempting connection to '{}'".format(waf_url), level=10
))
identified_waf = detect_protection(url, waf_status, waf_html, waf_headers, verbose=verbose) identified_waf = detect_protection(url, waf_status, waf_html, waf_headers, verbose=verbose)
if identified_waf is None: if identified_waf is None:
logger.info(set_color( logger.info(set_color(
"no WAF/IDS/IPS has been identified on target URL...", level=25 "no WAF/IDS/IPS has been identified on target URL", level=25
)) ))
else: else:
logger.warning(set_color( logger.warning(set_color(
"the target URL WAF/IDS/IPS has been identified as '{}'...".format(identified_waf), level=35 "the target URL WAF/IDS/IPS has been identified as '{}'".format(identified_waf), level=35
)) ))
if identify_plugins: if identify_plugins:
logger.info(set_color( logger.info(set_color(
"attempting to identify plugins..." "attempting to identify plugins"
)) ))
identified_plugin = detect_plugins(html, headers, verbose=verbose) identified_plugin = detect_plugins(html, headers, verbose=verbose)
if identified_plugin is not None: if identified_plugin is not None:
for plugin in identified_plugin: for plugin in identified_plugin:
if show_description: if show_description:
logger.info(set_color( logger.info(set_color(
"possible plugin identified as '{}' (description: '{}')...".format( "possible plugin identified as '{}' (description: '{}')".format(
plugin[0], plugin[1] plugin[0], plugin[1]
), level=25 ), level=25
)) ))
else: else:
logger.info(set_color( logger.info(set_color(
"possible plugin identified as '{}'...".format( "possible plugin identified as '{}'".format(
plugin[0] plugin[0]
), level=25 ), level=25
)) ))
else: else:
logger.warning(set_color( logger.warning(set_color(
"no known plugins identified on target...", level=30 "no known plugins identified on target", level=30
)) ))
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"loading XML data...", level=10 "loading XML data", level=10
)) ))
comparable_headers = load_xml_data(HEADER_XML_DATA) comparable_headers = load_xml_data(HEADER_XML_DATA)
logger.info(set_color( logger.info(set_color(
"attempting to get request headers for '{}'...".format(url.strip()) "attempting to get request headers for '{}'".format(url.strip())
)) ))
try: try:
found_headers = load_headers(url, req) found_headers = load_headers(url, req)
@ -331,31 +337,56 @@ def main_header_check(url, **kwargs):
found_headers = None found_headers = None
else: else:
logger.exception(set_color( logger.exception(set_color(
"Zeus has hit an unexpected error and cannot continue '{}'...".format(e), level=50 "Zeus has hit an unexpected error and cannot continue '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
if found_headers is not None: if found_headers is not None:
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"fetched {}...".format(found_headers), level=10 "fetched {}".format(found_headers), level=10
)) ))
headers_established = [str(h) for h in compare_headers(found_headers, comparable_headers)] headers_established = [str(h) for h in compare_headers(found_headers, comparable_headers)]
for key in definition.iterkeys(): for key in definition.iterkeys():
if any(key in h.lower() for h in headers_established): if any(key in h.lower() for h in headers_established):
logger.warning(set_color( logger.warning(set_color(
"provided target has {}...".format(definition[key][0]), level=30 "provided target has {}".format(definition[key][0]), level=30
)) ))
for key in found_headers.iterkeys(): for key in found_headers.iterkeys():
protection[key] = found_headers[key] protection[key] = found_headers[key]
logger.info(set_color( logger.info(set_color(
"writing found headers to log file...", level=25 "writing found headers to log file", level=25
)) ))
return write_to_log_file(protection, HEADER_RESULT_PATH, HEADERS_FILENAME.format(replace_http(url))) return write_to_log_file(protection, HEADER_RESULT_PATH, HEADERS_FILENAME.format(replace_http(url)))
else: else:
logger.error(set_color( logger.error(set_color(
"unable to retrieve headers for site '{}'...".format(url.strip()), level=40 "unable to retrieve headers for site '{}'".format(url.strip()), level=40
)) ))
except ConnectionError:
attempts = attempts - 1
if attempts == 0:
return False
logger.warning(set_color(
"target actively refused the connection, sleeping for {}s and retrying the request".format(
default_sleep_time
), level=30
))
time.sleep(default_sleep_time)
main_header_check(
url, proxy=proxy, agent=agent, xforward=xforward, show_description=show_description,
identify_plugins=identify_plugins, identify_waf=identify_waf, verbose=verbose,
attempts=attempts
)
except ReadTimeout:
logger.error(set_color(
"meta-data retrieval failed due to target URL timing out, skipping", level=40
))
except KeyboardInterrupt: except KeyboardInterrupt:
if not pause(): if not pause():
shutdown() shutdown()
except Exception as e:
logger.exception(set_color(
"meta-data retrieval failed with unexpected error '{}'".format(
str(e)
), level=50
))

21
lib/plugins/clipbucket.py Normal file
View file

@ -0,0 +1,21 @@
import re
__product__ = "ClipBucket"
__description__ = (
"ClipBucket is an Open Source and freely downloadable PHP "
"script that will let you start your own Video Sharing website"
)
def search(html, **kwargs):
html = str(html)
plugin_detection_schema = (
re.compile(r"<.\S+.clipbucket", re.I),
re.compile(r"content.[\'\"]clipbucket", re.I),
re.compile(r"http(s)?.//(www.)?clip.bucket.com", re.I),
re.compile(r"http(s)?.//(www.)?clipbucket.com", re.I),
)
for plugin in plugin_detection_schema:
if plugin.search(html) is not None:
return True

19
lib/plugins/moodle.py Normal file
View file

@ -0,0 +1,19 @@
import re
__product__ = "Moodle"
__description__ = (
"Moodle is an opensource educational software written in PHP"
)
def search(html, **kwargs):
html = str(html)
plugin_detection_schema = (
re.compile(r".moodle.", re.I),
re.compile(r".moodlesession.", re.I),
re.compile(r".php.moodlesession.(\w+)?(\d+)?", re.I)
)
for plugin in plugin_detection_schema:
if plugin.search(html) is not None:
return True

View file

@ -0,0 +1,18 @@
import re
__product__ = "Microsoft SQL Report Manager"
__description__ = (
"Microsoft SQL Server Report Manager - web-based report access and management tool"
)
def search(html, **kwargs):
html = str(html)
plugin_detection_schema = (
re.compile(r"content.[\'\"]?microsoft.sql.server.report", re.I),
re.compile(r"microsoft.sql.server.report.manager", re.I)
)
for plugin in plugin_detection_schema:
if plugin.search(html) is not None:
return True

View file

@ -11,6 +11,6 @@ def tamper(payload, **kwargs):
if warning: if warning:
logger.warning(set_color( logger.warning(set_color(
"base64 tamper scripts may increase the possibility of not finding vulnerabilities " "base64 tamper scripts may increase the possibility of not finding vulnerabilities "
"in otherwise vulnerable sites...", level=30 "in otherwise vulnerable sites", level=30
)) ))
return base64.b64encode(payload) return base64.b64encode(payload)

View file

@ -12,7 +12,7 @@ def tamper(payload, **kwargs):
if warning: if warning:
logger.warning(set_color( logger.warning(set_color(
"enclosing brackets is meant to be used as an obfuscation " "enclosing brackets is meant to be used as an obfuscation "
"against an already valid vulnerable site...", level=30 "against an already valid vulnerable site", level=30
)) ))
to_enclose = string.digits to_enclose = string.digits

View file

@ -8,7 +8,7 @@ def tamper(payload, **kwargs):
warning = kwargs.get("warning", True) warning = kwargs.get("warning", True)
if warning: if warning:
logger.warning(set_color( logger.warning(set_color(
"hex tamper scripts may increase the risk of false positives...", level=30 "hex tamper scripts may increase the risk of false positives", level=30
)) ))
retval = hex(hash(payload)) retval = hex(hash(payload))
if "-" in str(retval): if "-" in str(retval):

View file

@ -0,0 +1,29 @@
from lib.core.settings import (
logger,
set_color
)
def tamper(payload, **kwargs):
warning = kwargs.get("warning", True)
if warning:
logger.warning(set_color(
"obfuscating payloads by their entity encoding equivalent may increase the "
"risk of false positives", level=30
))
skip = ";"
encoding_schema = {
" ": "&nbsp;", "<": "&lt;", ">": "&gt;",
"&": "&amp;", '"': "&quot;", "'": "&apos;",
}
retval = ""
for char in str(payload):
if char in encoding_schema.iterkeys():
retval += encoding_schema[char]
elif char not in encoding_schema.iterkeys() and char != skip:
retval += char
else:
retval += char
return retval

View file

@ -10,7 +10,7 @@ def tamper(payload, **kwargs):
if warning: if warning:
logger.warning(set_color( logger.warning(set_color(
"obfuscating the payloads by ordinal equivalents may increase the risk " "obfuscating the payloads by ordinal equivalents may increase the risk "
"of false positives...", level=30 "of false positives", level=30
)) ))
retval = "" retval = ""

View file

@ -9,7 +9,7 @@ def tamper(payload, **kwargs):
if warning: if warning:
logger.warning(set_color( logger.warning(set_color(
"NULL encoding tamper scripts may increase the possibility of not finding vulnerabilities " "NULL encoding tamper scripts may increase the possibility of not finding vulnerabilities "
"in otherwise vulnerable sites...", level=30 "in otherwise vulnerable sites", level=30
)) ))
retval = "" retval = ""

View file

@ -40,7 +40,7 @@ def request_issue_creation():
if not lib.core.settings.get_md5sum(): if not lib.core.settings.get_md5sum():
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"it appears that your checksums did not match, therefore it is assumed " "it appears that your checksums did not match, therefore it is assumed "
"that you have edited some of the code, issue request denied...", level=50 "that you have edited some of the code, issue request denied", level=50
)) ))
lib.core.common.shutdown() lib.core.common.shutdown()
@ -49,18 +49,18 @@ def request_issue_creation():
) )
if question.lower().startswith("n"): if question.lower().startswith("n"):
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"Zeus has experienced an internal error and cannot continue, shutting down...", level=40 "Zeus has experienced an internal error and cannot continue, shutting down", level=40
)) ))
lib.core.common.shutdown() lib.core.common.shutdown()
lib.core.settings.fix_log_file() lib.core.settings.fix_log_file()
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"Zeus got an unexpected error and will automatically create an issue for this error, please wait..." "Zeus got an unexpected error and will automatically create an issue for this error, please wait"
)) ))
def __extract_stacktrace(file_data): def __extract_stacktrace(file_data):
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"extracting traceback from log file..." "extracting traceback from log file"
)) ))
retval, buff_mode, _buffer = [], False, "" retval, buff_mode, _buffer = [], False, ""
with open(file_data, "r+") as log: with open(file_data, "r+") as log:
@ -73,19 +73,19 @@ def request_issue_creation():
_buffer = "" _buffer = ""
if buff_mode: if buff_mode:
if len(line) > 400: if len(line) > 400:
line = line[:400] + "...\n" line = line[:400] + "\n"
_buffer += line _buffer += line
return "".join(retval) return "".join(retval)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"getting authorization..." "getting authorization"
)) ))
token = lib.core.settings.get_token(lib.core.settings.GITHUB_AUTH_PATH) token = lib.core.settings.get_token(lib.core.settings.GITHUB_AUTH_PATH)
current_log_file = lib.core.settings.get_latest_log_file(lib.core.settings.CURRENT_LOG_FILE_PATH) current_log_file = lib.core.settings.get_latest_log_file(lib.core.settings.CURRENT_LOG_FILE_PATH)
stacktrace = __extract_stacktrace(current_log_file) stacktrace = __extract_stacktrace(current_log_file)
identifier = lib.core.settings.create_identifier() identifier = lib.core.settings.create_identifier(stacktrace)
issue_title = "Unhandled exception ({})".format(identifier) issue_title = "Unhandled exception ({})".format(identifier)
ff_version = lib.core.settings.get_browser_version() ff_version = lib.core.settings.get_browser_version()
log_file_information = lib.core.settings.tails(current_log_file) log_file_information = lib.core.settings.tails(current_log_file)
@ -95,7 +95,7 @@ def request_issue_creation():
"body": "Zeus version:\n`{}`\n\n" "body": "Zeus version:\n`{}`\n\n"
"Firefox version:\n`{}`\n\n" "Firefox version:\n`{}`\n\n"
"Geckodriver version:\n`{}`\n\n" "Geckodriver version:\n`{}`\n\n"
"Error info:\n```{}````\n\n" "Error info:\n```{}```\n\n"
"Running details:\n`{}`\n\n" "Running details:\n`{}`\n\n"
"Commands used:\n`{}`\n\n" "Commands used:\n`{}`\n\n"
"Log file info:\n```{}```".format( "Log file info:\n```{}```".format(
@ -121,12 +121,12 @@ def request_issue_creation():
urllib2.urlopen(req, timeout=10).read() urllib2.urlopen(req, timeout=10).read()
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"issue has been created successfully with the following name '{}', your unique identifier " "issue has been created successfully with the following name '{}', your unique identifier "
"for this issue is '{}' and the URL to your issue is '{}'...".format( "for this issue is '{}' and the URL to your issue is '{}'".format(
issue_title, identifier, find_url(identifier) issue_title, identifier, find_url(identifier)
) )
)) ))
except Exception as e: except Exception as e:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"failed to auto create the issue, got exception '{}', " "failed to auto create the issue, got exception '{}', "
"you may manually create an issue...".format(e), level=50 "you may manually create an issue".format(e), level=50
)) ))

View file

@ -1,7 +1,4 @@
import os import os
import sys
reload(sys)
sys.setdefaultencoding("utf-8") # this will take care of most of the Unicode errors.
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
@ -20,7 +17,7 @@ class Blackwidow(object):
def __init__(self, url, user_agent=None, proxy=None, forward=None): def __init__(self, url, user_agent=None, proxy=None, forward=None):
self.url = url self.url = url
self.forward = forward or None self.forward = forward or None
self.proxy = lib.core.settings.proxy_string_to_dict(proxy) or None self.proxy = proxy
self.user_agent = user_agent or lib.core.settings.DEFAULT_USER_AGENT self.user_agent = user_agent or lib.core.settings.DEFAULT_USER_AGENT
@staticmethod @staticmethod
@ -39,7 +36,8 @@ class Blackwidow(object):
make sure the connection is good before you continue make sure the connection is good before you continue
""" """
try: try:
# verify=False will take care of SSLErrors # we'll skip SSL verification to avoid any SSLErrors that might
# arise, we won't really need it with this anyways
attempt, status, _, _ = lib.core.common.get_page( attempt, status, _, _ = lib.core.common.get_page(
self.url, agent=self.user_agent, xforward=self.forward, skip_verf=True, self.url, agent=self.user_agent, xforward=self.forward, skip_verf=True,
proxy=self.proxy proxy=self.proxy
@ -55,14 +53,14 @@ class Blackwidow(object):
else: else:
info_msg += "" info_msg += ""
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"provided website '{}' is refusing connection{}...".format( "provided website '{}' is refusing connection{}".format(
self.url, info_msg self.url, info_msg
), level=50 ), level=50
)) ))
lib.core.common.shutdown() lib.core.common.shutdown()
else: else:
lib.core.settings.logger.exception(lib.core.settings.set_color( lib.core.settings.logger.exception(lib.core.settings.set_color(
"failed to connect to '{}' received error '{}'...".format( "failed to connect to '{}' received error '{}'".format(
self.url, e self.url, e
), level=50 ), level=50
)) ))
@ -106,27 +104,27 @@ def blackwidow_main(url, **kwargs):
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"settings user-agent to '{}'...".format(agent), level=10 "settings user-agent to '{}'".format(agent), level=10
)) ))
if proxy is not None: if proxy is not None:
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"running behind proxy '{}'...".format(proxy), level=10 "running behind proxy '{}'".format(proxy), level=10
)) ))
lib.core.settings.create_dir("{}/{}".format(os.getcwd(), "log/blackwidow-log")) lib.core.settings.create_dir("{}/{}".format(os.getcwd(), "log/blackwidow-log"))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"starting blackwidow on '{}'...".format(url) "starting blackwidow on '{}'".format(url)
)) ))
crawler = Blackwidow(url, user_agent=agent, proxy=proxy, forward=forward) crawler = Blackwidow(url, user_agent=agent, proxy=proxy, forward=forward)
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"testing connection to the URL...", level=10 "testing connection to the URL", level=10
)) ))
test_code = crawler.test_connection() test_code = crawler.test_connection()
if not test_code[0] == "ok": if not test_code[0] == "ok":
error_msg = ( error_msg = (
"connection test failed with status code: {}, reason: '{}'. " "connection test failed with status code: {}, reason: '{}'. "
"test connection needs to pass, try a different link..." "test connection needs to pass, try a different link"
) )
for error_code in lib.core.common.STATUS_CODES.keys(): for error_code in lib.core.common.STATUS_CODES.keys():
if error_code == test_code[1]: if error_code == test_code[1]:
@ -144,15 +142,15 @@ def blackwidow_main(url, **kwargs):
lib.core.common.shutdown() lib.core.common.shutdown()
else: else:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"connection test succeeded, continuing...", level=25 "connection test succeeded, continuing", level=25
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"crawling given URL '{}' for links...".format(url) "crawling given URL '{}' for links".format(url)
)) ))
found = crawler.scrape_page_for_links(url) found = crawler.scrape_page_for_links(url)
if len(found) > 0: if len(found) > 0:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"found a total of {} links from given URL '{}'...".format( "found a total of {} links from given URL '{}'".format(
len(found), url len(found), url
), level=25 ), level=25
)) ))
@ -160,5 +158,5 @@ def blackwidow_main(url, **kwargs):
filename=lib.core.settings.BLACKWIDOW_FILENAME) filename=lib.core.settings.BLACKWIDOW_FILENAME)
else: else:
lib.core.settings.logger.fatal(lib.core.settings.set_color( lib.core.settings.logger.fatal(lib.core.settings.set_color(
"did not find any usable links from '{}'...".format(url), level=50 "did not find any usable links from '{}'".format(url), level=50
)) ))

View file

@ -128,7 +128,7 @@ class SetBrowser(object):
try: try:
if not self.tor: if not self.tor:
logger.info(set_color( logger.info(set_color(
"setting the browser..." "setting the browser"
)) ))
profile.set_preference("general.useragent.override", self.agent) profile.set_preference("general.useragent.override", self.agent)
browser = webdriver.Firefox(profile, proxy=self.__set_proxy()) browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
@ -137,7 +137,7 @@ class SetBrowser(object):
browser = webdriver.Firefox(profile, proxy=self.__set_proxy()) browser = webdriver.Firefox(profile, proxy=self.__set_proxy())
else: else:
logger.info(set_color( logger.info(set_color(
"setting the Tor browser emulation..." "setting the Tor browser emulation"
)) ))
profile = self.__tor_browser_emulation(profile) profile = self.__tor_browser_emulation(profile)
browser = webdriver.Firefox(profile) browser = webdriver.Firefox(profile)

View file

@ -109,18 +109,18 @@ def get_pgp_keys(url_list, query, attribute="pre", **kwargs):
identity_matcher = re.compile(r"\bbegin.pgp.public.key.block", re.I) identity_matcher = re.compile(r"\bbegin.pgp.public.key.block", re.I)
amount_left = len(url_list) amount_left = len(url_list)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"checking a maximum of {} PGP keys...".format(amount_to_search) "checking a maximum of {} PGP keys".format(amount_to_search)
)) ))
for i, url in enumerate(url_list, start=1): for i, url in enumerate(url_list, start=1):
if i >= amount_to_search: if i >= amount_to_search:
break break
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"checking '{}'...".format(url), level=10 "checking '{}'".format(url), level=10
)) ))
if i % 25 == 0: if i % 25 == 0:
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"currently checking PGP key #{}, {} left to check ({} total found)...".format( "currently checking PGP key #{}, {} left to check ({} total found)".format(
i, amount_to_search - i, amount_left i, amount_to_search - i, amount_left
) )
)) ))
@ -140,7 +140,7 @@ def get_pgp_keys(url_list, query, attribute="pre", **kwargs):
extracted_keys.add(context) extracted_keys.add(context)
except ReadTimeout: except ReadTimeout:
lib.core.settings.logger.error(lib.core.settings.set_color( lib.core.settings.logger.error(lib.core.settings.set_color(
"PGP key failed connection, assuming no good and skipping...", level=40 "PGP key failed connection, assuming no good and skipping", level=40
)) ))
for i, k in enumerate(extracted_keys): for i, k in enumerate(extracted_keys):
pgp_key = str(k).split("<{}>".format(attribute)) # split the string by the tag pgp_key = str(k).split("<{}>".format(attribute)) # split the string by the tag
@ -164,7 +164,7 @@ def pgp_main(query, verbose=False):
except Exception: except Exception:
query = query query = query
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"searching public PGP files with given query '{}'...".format(query) "searching public PGP files with given query '{}'".format(query)
)) ))
try: try:
html = obtain_html( html = obtain_html(
@ -172,25 +172,25 @@ def pgp_main(query, verbose=False):
) )
except (Exception, ReadTimeout): except (Exception, ReadTimeout):
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"connection failed, assuming no PGP keys...", level=30 "connection failed, assuming no PGP keys", level=30
)) ))
html = None html = None
if html is not None: if html is not None:
urls = gather_urls(html) urls = gather_urls(html)
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"found a total of {} URLs...".format(len(urls)) "found a total of {} URLs".format(len(urls))
)) ))
if verbose: if verbose:
lib.core.settings.logger.debug(lib.core.settings.set_color( lib.core.settings.logger.debug(lib.core.settings.set_color(
"found a '{}'...".format(urls), level=10 "found a '{}'".format(urls), level=10
)) ))
lib.core.settings.logger.info(lib.core.settings.set_color( lib.core.settings.logger.info(lib.core.settings.set_color(
"gathering PGP key(s) and writing to a file...", level=25 "gathering PGP key(s) and writing to a file", level=25
)) ))
return get_pgp_keys(urls, query, verbose=verbose) return get_pgp_keys(urls, query, verbose=verbose)
else: else:
lib.core.settings.logger.warning(lib.core.settings.set_color( lib.core.settings.logger.warning(lib.core.settings.set_color(
"did not find anything using query '{}'...".format(query), level=30 "did not find anything using query '{}'".format(query), level=30
)) ))
except KeyboardInterrupt: except KeyboardInterrupt:
if not lib.core.common.pause(): if not lib.core.common.pause():

View file

@ -75,20 +75,20 @@ def get_urls(query, url, verbose=False, **kwargs):
batch = kwargs.get("batch", False) batch = kwargs.get("batch", False)
xforward = kwargs.get("xforward", False) xforward = kwargs.get("xforward", False)
logger.info(set_color( logger.info(set_color(
"setting up virtual display to hide the browser..." "setting up virtual display to hide the browser"
)) ))
ff_display = Display(visible=0, size=(800, 600)) ff_display = Display(visible=0, size=(800, 600))
ff_display.start() ff_display.start()
browser = var.search.SetBrowser(agent=user_agent, proxy=proxy, tor=tor, xforward=xforward).set_browser() browser = var.search.SetBrowser(agent=user_agent, proxy=proxy, tor=tor, xforward=xforward).set_browser()
logger.info(set_color("browser will open shortly...", level=25)) logger.info(set_color("browser will open shortly", level=25))
browser.get(url) browser.get(url)
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"searching search engine for the 'q' element (search button)...", level=10 "searching search engine for the 'q' element (search button)", level=10
)) ))
search = browser.find_element_by_name('q') search = browser.find_element_by_name('q')
logger.info(set_color( logger.info(set_color(
"searching search engine using query '{}'...".format(query) "searching search engine using query '{}'".format(query)
)) ))
try: try:
# enter the text you want to search and hit enter # enter the text you want to search and hit enter
@ -98,31 +98,35 @@ def get_urls(query, url, verbose=False, **kwargs):
time.sleep(3) time.sleep(3)
else: else:
logger.warning(set_color( logger.warning(set_color(
"sleep time has been increased to 10 seconds due to tor being used...", level=30 "sleep time has been increased to 10 seconds due to tor being used", level=30
)) ))
time.sleep(10) time.sleep(10)
except ElementNotInteractableException: except ElementNotInteractableException:
# get rid of the popup box and hit enter after entering the text to search # get rid of the popup box and hit enter after entering the text to search
browser.execute_script("document.querySelectorAll('label.boxed')[1].click()") try:
search.send_keys(query) for _ in range(5):
search.send_keys(Keys.RETURN) browser.execute_script("document.querySelectorAll('label.boxed')[{}].click()".format(_))
time.sleep(3) search.send_keys(query)
search.send_keys(Keys.RETURN)
time.sleep(3)
except Exception:
pass
except UnicodeDecodeError: except UnicodeDecodeError:
logger.error(set_color( logger.error(set_color(
"your query '{}' appears to have unicode characters in it, selenium is not " "your query '{}' appears to have unicode characters in it, selenium is not "
"properly formatted to handle unicode characters, this dork will be skipped...".format( "properly formatted to handle unicode characters, this dork will be skipped".format(
query query
), level=40 ), level=40
)) ))
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"obtaining URL from selenium..." "obtaining URL from selenium"
)) ))
try: try:
retval = browser.current_url retval = browser.current_url
except UnexpectedAlertPresentException: except UnexpectedAlertPresentException:
logger.warning(set_color( logger.warning(set_color(
"alert present, closing...", level=30 "alert present, closing", level=30
)) ))
# discover the alert and close it before continuing # discover the alert and close it before continuing
alert = browser.switch_to.alert alert = browser.switch_to.alert
@ -131,7 +135,7 @@ def get_urls(query, url, verbose=False, **kwargs):
# if you have been IP banned, we'll extract the URL from it # if you have been IP banned, we'll extract the URL from it
if IP_BAN_REGEX.search(retval) is not None: if IP_BAN_REGEX.search(retval) is not None:
logger.warning(set_color( logger.warning(set_color(
"it appears that Google is attempting to block your IP address, attempting bypass...", level=30 "it appears that Google is attempting to block your IP address, attempting bypass", level=30
)) ))
try: try:
retval = URLParser(retval).extract_ip_ban_url() retval = URLParser(retval).extract_ip_ban_url()
@ -155,7 +159,7 @@ def get_urls(query, url, verbose=False, **kwargs):
write_to_log_file(retval, EXTRACTED_URL_LOG, EXTRACTED_URL_FILENAME) write_to_log_file(retval, EXTRACTED_URL_LOG, EXTRACTED_URL_FILENAME)
logger.info(set_color( logger.info(set_color(
"it is advised to extract the URL's from the produced URL written to the above " "it is advised to extract the URL's from the produced URL written to the above "
"(IE open the log, copy the url into firefox)...".format(retval) "(IE open the log, copy the url into firefox)".format(retval)
)) ))
shutdown() shutdown()
except Exception as e: except Exception as e:
@ -165,7 +169,7 @@ def get_urls(query, url, verbose=False, **kwargs):
ff_display.stop() ff_display.stop()
logger.exception(set_color( logger.exception(set_color(
"zeus was unable to extract the correct URL from the ban URL '{}', " "zeus was unable to extract the correct URL from the ban URL '{}', "
"got exception '{}'...".format( "got exception '{}'".format(
unquote(retval), e unquote(retval), e
), level=50 ), level=50
)) ))
@ -173,7 +177,7 @@ def get_urls(query, url, verbose=False, **kwargs):
shutdown() shutdown()
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"found current URL from selenium browser...", level=10 "found current URL from selenium browser", level=10
)) ))
logger.info(set_color( logger.info(set_color(
"closing the browser and continuing process.." "closing the browser and continuing process.."
@ -201,31 +205,31 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"parsing blacklist...", level=10 "parsing blacklist", level=10
)) ))
parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch) parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch)
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"checking for user-agent and proxy configuration...", level=10 "checking for user-agent and proxy configuration", level=10
)) ))
if not parse_webcache and "google" in url_to_search: if not parse_webcache and "google" in url_to_search:
logger.warning(set_color( logger.warning(set_color(
"will not parse webcache URL's (to parse webcache pass -W)...", level=30 "will not parse webcache URL's (to parse webcache pass -W)", level=30
)) ))
if not pull_all: if not pull_all:
logger.warning(set_color( logger.warning(set_color(
"only pulling URLs with GET(query) parameters (to pull all URL's pass -E)...", level=30 "only pulling URLs with GET(query) parameters (to pull all URL's pass -E)", level=30
)) ))
user_agent_info = "adjusting user-agent header to {}..." user_agent_info = "adjusting user-agent header to {}"
if user_agent is not DEFAULT_USER_AGENT: if user_agent is not DEFAULT_USER_AGENT:
user_agent_info = user_agent_info.format(user_agent.strip()) user_agent_info = user_agent_info.format(user_agent.strip())
else: else:
user_agent_info = user_agent_info.format("default user agent '{}'".format(DEFAULT_USER_AGENT)) user_agent_info = user_agent_info.format("default user agent '{}'".format(DEFAULT_USER_AGENT))
proxy_string_info = "setting proxy to {}..." proxy_string_info = "setting proxy to {}"
if proxy_string is not None: if proxy_string is not None:
proxy_string = proxy_string_to_dict(proxy_string) proxy_string = proxy_string_to_dict(proxy_string)
proxy_string_info = proxy_string_info.format( proxy_string_info = proxy_string_info.format(
@ -236,13 +240,13 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
"tor proxy settings" "tor proxy settings"
) )
else: else:
proxy_string_info = "no proxy configuration detected..." proxy_string_info = "no proxy configuration detected"
if forward_for: if forward_for:
ip_to_use = (create_random_ip(), create_random_ip(), create_random_ip()) ip_to_use = (create_random_ip(), create_random_ip(), create_random_ip())
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"random IP addresses generated for headers '{}'...".format(ip_to_use), level=10 "random IP addresses generated for headers '{}'".format(ip_to_use), level=10
)) ))
headers = { headers = {
@ -256,7 +260,7 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
HTTP_HEADER.USER_AGENT: user_agent HTTP_HEADER.USER_AGENT: user_agent
} }
logger.info(set_color( logger.info(set_color(
"attempting to gather query URL..." "attempting to gather query URL"
)) ))
try: try:
query_url = get_urls( query_url = get_urls(
@ -268,17 +272,17 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
logger.fatal(set_color( logger.fatal(set_color(
"firefox was not found in the default location on your system, " "firefox was not found in the default location on your system, "
"check your installation and make sure it is in /usr/lib, if you " "check your installation and make sure it is in /usr/lib, if you "
"find it there, restart your system and try again...", level=50 "find it there, restart your system and try again", level=50
)) ))
elif "connection refused" in str(e).lower(): elif "connection refused" in str(e).lower():
logger.fatal(set_color( logger.fatal(set_color(
"there are to many sessions of firefox opened and selenium cannot " "there are to many sessions of firefox opened and selenium cannot "
"create a new one...", level=50 "create a new one", level=50
)) ))
run_fix( run_fix(
"would you like to attempt to auto clean the open sessions", "would you like to attempt to auto clean the open sessions",
"sudo sh {}".format(CLEANUP_TOOL_PATH), "sudo sh {}".format(CLEANUP_TOOL_PATH),
"kill off the open sessions of firefox and re-run Zeus...", "kill off the open sessions of firefox and re-run Zeus",
exit_process=True exit_process=True
) )
elif "Program install error!" in str(e): elif "Program install error!" in str(e):
@ -289,50 +293,50 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
run_fix( run_fix(
"would you like to attempt to fix this issue automatically", "would you like to attempt to fix this issue automatically",
"sudo sh {}".format(FIX_PROGRAM_INSTALL_PATH), "sudo sh {}".format(FIX_PROGRAM_INSTALL_PATH),
"you can manually try and re-install Xvfb to fix the problem...", "you can manually try and re-install Xvfb to fix the problem",
exit_process=True exit_process=True
) )
elif "Message: Reached error page:" in str(e): elif "Message: Reached error page:" in str(e):
logger.fatal(set_color( logger.fatal(set_color(
"geckodriver has hit an error that usually means it needs to be reinstalled...", level=50 "geckodriver has hit an error that usually means it needs to be reinstalled", level=50
)) ))
question = prompt( question = prompt(
"would you like to attempt a reinstallation of the geckodriver", opts="yN" "would you like to attempt a reinstallation of the geckodriver", opts="yN"
) )
if question.lower().startswith("y"): if question.lower().startswith("y"):
logger.warning(set_color( logger.warning(set_color(
"rewriting all executed information, path information, and removing geckodriver...", level=30 "rewriting all executed information, path information, and removing geckodriver", level=30
)) ))
rewrite_all_paths() rewrite_all_paths()
logger.info(set_color( logger.info(set_color(
"all paths rewritten, you will be forced to re-install everything next run of Zeus..." "all paths rewritten, you will be forced to re-install everything next run of Zeus"
)) ))
else: else:
logger.fatal(set_color( logger.fatal(set_color(
"you will need to remove the geckodriver from /usr/bin and reinstall it...", level=50 "you will need to remove the geckodriver from /usr/bin and reinstall it", level=50
)) ))
shutdown() shutdown()
elif "Unable to find a matching set of capabilities" in str(e): elif "Unable to find a matching set of capabilities" in str(e):
logger.fatal(set_color( logger.fatal(set_color(
"it appears that firefox, selenium, and geckodriver are not playing nice with one another...", level=50 "it appears that firefox, selenium, and geckodriver are not playing nice with one another", level=50
)) ))
run_fix( run_fix(
"would you like to attempt to resolve this issue automatically", "would you like to attempt to resolve this issue automatically",
"sudo sh {}".format(REINSTALL_TOOL), "sudo sh {}".format(REINSTALL_TOOL),
("you will need to reinstall firefox to a later version, update selenium, and reinstall the " ("you will need to reinstall firefox to a later version, update selenium, and reinstall the "
"geckodriver to continue using Zeus..."), "geckodriver to continue using Zeus"),
exit_process=True exit_process=True
) )
else: else:
logger.exception(set_color( logger.exception(set_color(
"{} failed to gather the URL from search engine, caught exception '{}' " "{} failed to gather the URL from search engine, caught exception '{}' "
"exception has been logged to current log file...".format( "exception has been logged to current log file".format(
os.path.basename(__file__), str(e).strip()), level=50) os.path.basename(__file__), str(e).strip()), level=50)
) )
request_issue_creation() request_issue_creation()
shutdown() shutdown()
logger.info(set_color( logger.info(set_color(
"URL successfully gathered, searching for GET parameters..." "URL successfully gathered, searching for GET parameters"
)) ))
logger.info(set_color(proxy_string_info)) logger.info(set_color(proxy_string_info))
@ -341,7 +345,7 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
req = requests.get(query_url, proxies=proxy_string, params=headers) req = requests.get(query_url, proxies=proxy_string, params=headers)
except ConnectionError: except ConnectionError:
logger.warning(set_color( logger.warning(set_color(
"target machine refused connection, delaying and trying again...", level=30 "target machine refused connection, delaying and trying again", level=30
)) ))
time.sleep(3) time.sleep(3)
req = requests.get(query_url, proxies=proxy_string, params=headers) req = requests.get(query_url, proxies=proxy_string, params=headers)
@ -365,15 +369,15 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
if verbose: if verbose:
try: try:
logger.debug(set_color( logger.debug(set_color(
"found '{}'...".format(url.split(splitter)[0]), level=10 "found '{}'".format(url.split(splitter)[0]), level=10
)) ))
except TypeError: except TypeError:
logger.debug(set_color( logger.debug(set_color(
"found '{}'...".format(str(url).split(splitter)[0]), level=10 "found '{}'".format(str(url).split(splitter)[0]), level=10
)) ))
except AttributeError: except AttributeError:
logger.debug(set_color( logger.debug(set_color(
"found '{}...".format(str(url)), level=10 "found '{}".format(str(url)), level=10
)) ))
if url is not None: if url is not None:
retval.add(url.split(splitter)[0]) retval.add(url.split(splitter)[0])
@ -384,12 +388,12 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
if parse_webcache: if parse_webcache:
if "webcache" in url: if "webcache" in url:
logger.info(set_color( logger.info(set_color(
"found a webcache URL, extracting..." "found a webcache URL, extracting"
)) ))
url = URLParser(url).extract_webcache_url() url = URLParser(url).extract_webcache_url()
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"found '{}'...".format(url), level=15 "found '{}'".format(url), level=15
)) ))
true_retval.add(url) true_retval.add(url)
else: else:
@ -403,18 +407,18 @@ def parse_search_results(query, url_to_search, verbose=False, **kwargs):
amount_of_urls = len(open(file_path).readlines()) amount_of_urls = len(open(file_path).readlines())
success_rate = calculate_success(amount_of_urls) success_rate = calculate_success(amount_of_urls)
logger.info(set_color( logger.info(set_color(
"provided query has a {} success rate...".format(success_rate) "provided query has a {} success rate".format(success_rate)
)) ))
else: else:
logger.fatal(set_color( logger.warning(set_color(
"did not find any URLs with given query '{}' writing query to blacklist...".format(query), level=50 "did not find any URLs with given query '{}' writing query to blacklist".format(query), level=50
)) ))
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME, blacklist=True) write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME, blacklist=True)
shutdown()
logger.info(set_color( logger.info(set_color(
"found a total of {} URLs with given query '{}'...".format(len(true_retval), query) "found a total of {} URLs with given query '{}'".format(len(true_retval), query)
)) ))
return list(true_retval) if len(true_retval) != 0 else None
def search_multiple_pages(query, link_amount, verbose=False, **kwargs): def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
@ -431,7 +435,7 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
search_engine = AUTHORIZED_SEARCH_ENGINES["search-results"] search_engine = AUTHORIZED_SEARCH_ENGINES["search-results"]
logger.warning(set_color( logger.warning(set_color(
"searching multiple pages will not be done on Google...".format(search_engine), level=30 "searching multiple pages will not be done on Google".format(search_engine), level=30
)) ))
if not parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch): if not parse_blacklist(query, BLACKLIST_FILE_PATH, batch=batch):
@ -455,11 +459,11 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
while len(retval) <= link_amount: while len(retval) <= link_amount:
if verbose: if verbose:
logger.debug(set_color( logger.debug(set_color(
"searching page number {}...".format(page_number), level=10 "searching page number {}".format(page_number), level=10
)) ))
if page_number % 10 == 0: if page_number % 10 == 0:
logger.info(set_color( logger.info(set_color(
"currently on page {} of search results...".format( "currently on page {} of search results".format(
page_number page_number
) )
)) ))
@ -481,44 +485,44 @@ def search_multiple_pages(query, link_amount, verbose=False, **kwargs):
page_number += 1 page_number += 1
else: else:
logger.warning(set_color( logger.warning(set_color(
"hit max page number {}...".format(MAX_PAGE_NUMBER), level=30 "hit max page number {}".format(MAX_PAGE_NUMBER), level=30
)) ))
break break
else: else:
logger.warning(set_color( logger.warning(set_color(
"no more results found for given query '{}'...".format(query), level=30 "no more results found for given query '{}'".format(query), level=30
)) ))
break break
except KeyboardInterrupt: except KeyboardInterrupt:
logger.error(set_color( logger.error(set_color(
"user aborted, dumping already found URL(s)...", level=40 "user aborted, dumping already found URL(s)", level=40
)) ))
write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME) write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
logger.info(set_color( logger.info(set_color(
"found a total of {} URL(s)...".format(len(retval)), level=25 "found a total of {} URL(s)".format(len(retval)), level=25
)) ))
shutdown() shutdown()
except Exception as e: except Exception as e:
logger.exception(set_color( logger.exception(set_color(
"Zeus ran into an unexpected error '{}'...".format(e), level=50 "Zeus ran into an unexpected error '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
shutdown() shutdown()
if len(retval) > 0: if len(retval) > 0:
logger.info(set_color( logger.info(set_color(
"a total of {} URL(s) found out of the requested {}...".format(len(retval), link_amount), level=25 "a total of {} URL(s) found out of the requested {}".format(len(retval), link_amount), level=25
)) ))
file_path = write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME) file_path = write_to_log_file(retval, URL_LOG_PATH, URL_FILENAME)
if show_success: if show_success:
amount_of_urls = len(open(file_path).readlines()) amount_of_urls = len(open(file_path).readlines())
success_rate = calculate_success(amount_of_urls) success_rate = calculate_success(amount_of_urls)
logger.info(set_color( logger.info(set_color(
"provided query has a {} success rate...".format(success_rate) "provided query has a {} success rate".format(success_rate)
)) ))
return list(retval) return list(retval)
else: else:
logger.warning(set_color( logger.warning(set_color(
"did not find any links with given query '{}' writing to blacklist...".format(query), level=30 "did not find any links with given query '{}' writing to blacklist".format(query), level=30
)) ))
write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME) write_to_log_file(query, BLACKLIST_FILE_PATH, BLACKLIST_FILENAME)

142
zeus.py
View file

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import io import io
import sys
import time import time
import shlex import shlex
import warnings import warnings
@ -14,7 +15,8 @@ from lib.header_check import main_header_check
from lib.core.parse import ZeusParser from lib.core.parse import ZeusParser
from lib.core.errors import ( from lib.core.errors import (
InvalidInputProvided, InvalidInputProvided,
InvalidProxyType InvalidProxyType,
ZeusArgumentException
) )
from lib.core.common import ( from lib.core.common import (
start_up, start_up,
@ -43,10 +45,19 @@ warnings.simplefilter("ignore")
if __name__ == "__main__": if __name__ == "__main__":
# this will take care of most of the Unicode errors.
reload(sys)
sys.setdefaultencoding("utf-8")
sys.setrecursionlimit(1500)
opt = ZeusParser.cmd_parser() opt = ZeusParser.cmd_parser()
ZeusParser().single_show_args(opt) ZeusParser().single_show_args(opt)
# verify all the arguments passed before we continue
# with the process
ZeusParser().verify_args()
# run the setup on the program # run the setup on the program
setup(verbose=opt.runInVerbose) setup(verbose=opt.runInVerbose)
@ -58,11 +69,11 @@ if __name__ == "__main__":
if opt.runInVerbose: if opt.runInVerbose:
being_run = find_running_opts(opt) being_run = find_running_opts(opt)
logger.debug(set_color( logger.debug(set_color(
"running with options '{}'...".format(being_run), level=10 "running with options '{}'".format(being_run), level=10
)) ))
logger.info(set_color( logger.info(set_color(
"log file being saved to '{}'...".format(get_latest_log_file(CURRENT_LOG_FILE_PATH)) "log file being saved to '{}'".format(get_latest_log_file(CURRENT_LOG_FILE_PATH))
)) ))
@ -83,14 +94,14 @@ if __name__ == "__main__":
if urls_to_use is None: if urls_to_use is None:
logger.error(set_color( logger.error(set_color(
"unable to run attacks appears that no file was created for the retrieved data...", level=40 "unable to run attacks appears that no file was created for the retrieved data", level=40
)) ))
shutdown() shutdown()
options = [ options = [
opt.runSqliScan, opt.runPortScan, opt.runSqliScan, opt.runPortScan,
opt.adminPanelFinder, opt.runXssScan, opt.adminPanelFinder, opt.runXssScan,
opt.performWhoisLookup, opt.performClickjackingScan, opt.performWhoisLookup, opt.performClickjackingScan,
opt.searchGithub, opt.pgpLookup opt.pgpLookup
] ]
if any(options): if any(options):
with open(urls_to_use) as urls: with open(urls_to_use) as urls:
@ -98,38 +109,47 @@ if __name__ == "__main__":
current = i current = i
if "webcache" in url: if "webcache" in url:
logger.warning(set_color( logger.warning(set_color(
"ran into unexpected webcache URL skipping...", level=30 "ran into unexpected webcache URL skipping", level=30
)) ))
current -= 1 current -= 1
else: else:
logger.info(set_color( if not url.strip() == "http://" or url == "https://":
"currently running on '{}' (target #{})...".format( logger.info(set_color(
url.strip(), current "currently running on '{}' (target #{})".format(
), level=25 url.strip(), current
)) ), level=25
logger.info(set_color( ))
"fetching target meta-data..." logger.info(set_color(
)) "fetching target meta-data"
main_header_check( ))
url, verbose=opt.runInVerbose, agent=agent_to_use, identified = main_header_check(
proxy=proxy_to_use, xforward=opt.forwardedForRandomIP, url, verbose=opt.runInVerbose, agent=agent_to_use,
identify_plugins=opt.identifyPlugin, identify_waf=opt.identifyProtection, proxy=proxy_to_use, xforward=opt.forwardedForRandomIP,
show_description=opt.showPluginDescription identify_plugins=opt.identifyPlugin, identify_waf=opt.identifyProtection,
) show_description=opt.showPluginDescription
run_attacks( )
url.strip(), if not identified:
sqlmap=opt.runSqliScan, nmap=opt.runPortScan, pgp=opt.pgpLookup, logger.error(set_color(
xss=opt.runXssScan, whois=opt.performWhoisLookup, admin=opt.adminPanelFinder, "target is refusing to allow meta-data dumping, skipping", level=40
clickjacking=opt.performClickjackingScan, github=opt.searchGithub, ))
verbose=opt.runInVerbose, batch=opt.runInBatch, run_attacks(
auto_start=opt.autoStartSqlmap, xforward=opt.forwardedForRandomIP, url.strip(),
sqlmap_args=opt.sqlmapArguments, nmap_args=opt.nmapArguments, sqlmap=opt.runSqliScan, nmap=opt.runPortScan, pgp=opt.pgpLookup,
show_all=opt.showAllConnections, do_threading=opt.threadPanels, xss=opt.runXssScan, whois=opt.performWhoisLookup, admin=opt.adminPanelFinder,
tamper_script=opt.tamperXssPayloads, timeout=opt.controlTimeout, clickjacking=opt.performClickjackingScan, github=opt.searchGithub,
proxy=proxy_to_use, agent=agent_to_use, conf_file=opt.sqlmapConfigFile, verbose=opt.runInVerbose, batch=opt.runInBatch,
threads=opt.amountOfThreads auto_start=opt.autoStartSqlmap, xforward=opt.forwardedForRandomIP,
) sqlmap_args=opt.sqlmapArguments, nmap_args=opt.nmapArguments,
print("\n") show_all=opt.showAllConnections, do_threading=opt.threadPanels,
tamper_script=opt.tamperXssPayloads, timeout=opt.controlTimeout,
proxy=proxy_to_use, agent=agent_to_use, conf_file=opt.sqlmapConfigFile,
threads=opt.amountOfThreads, force_ssl=opt.forceSSL
)
print("\n")
else:
logger.warning(set_color(
"malformed URL discovered, skipping", level=30
))
proxy_to_use, agent_to_use = config_headers( proxy_to_use, agent_to_use = config_headers(
@ -146,7 +166,7 @@ if __name__ == "__main__":
# use a personal dork as the query # use a personal dork as the query
if opt.dorkToUse is not None and not opt.searchMultiplePages: if opt.dorkToUse is not None and not opt.searchMultiplePages:
logger.info(set_color( logger.info(set_color(
"starting dork scan with query '{}'...".format(opt.dorkToUse) "starting dork scan with query '{}'".format(opt.dorkToUse)
)) ))
try: try:
selenium_search.parse_search_results( selenium_search.parse_search_results(
@ -159,19 +179,19 @@ if __name__ == "__main__":
supported_proxy_types = ("socks5", "socks4", "https", "http") supported_proxy_types = ("socks5", "socks4", "https", "http")
logger.fatal(set_color( logger.fatal(set_color(
"the provided proxy is not valid, specify the protocol and try again, supported " "the provided proxy is not valid, specify the protocol and try again, supported "
"proxy protocols are {} (IE socks5://127.0.0.1:9050)...".format( "proxy protocols are {} (IE socks5://127.0.0.1:9050)".format(
", ".join(list(supported_proxy_types))), level=50 ", ".join(list(supported_proxy_types))), level=50
)) ))
except Exception as e: except Exception as e:
if "Permission denied:" in str(e): if "Permission denied:" in str(e):
logger.fatal(set_color( logger.fatal(set_color(
"your permissions are not allowing Zeus to run, " "your permissions are not allowing Zeus to run, "
"try running Zeus with sudo...", level=50 "try running Zeus with sudo", level=50
)) ))
shutdown() shutdown()
else: else:
logger.exception(set_color( logger.exception(set_color(
"ran into exception '{}'...".format(e), level=50 "ran into exception '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
pass pass
@ -189,7 +209,7 @@ if __name__ == "__main__":
if dork_to_use is None: if dork_to_use is None:
logger.warning(set_color( logger.warning(set_color(
"there has been no dork to specified to do the searching, defaulting to random dork...", level=30 "there has been no dork to specified to do the searching, defaulting to random dork", level=30
)) ))
dork_to_use = get_random_dork() dork_to_use = get_random_dork()
@ -197,14 +217,14 @@ if __name__ == "__main__":
if opt.amountToSearch is None: if opt.amountToSearch is None:
logger.warning(set_color( logger.warning(set_color(
"did not specify amount of links to find defaulting to 75...", level=30 "did not specify amount of links to find defaulting to 75", level=30
)) ))
link_amount_to_search = 75 link_amount_to_search = 75
else: else:
link_amount_to_search = opt.amountToSearch link_amount_to_search = opt.amountToSearch
logger.info(set_color( logger.info(set_color(
"searching Google using dork '{}' for a total of {} links...".format( "searching Google using dork '{}' for a total of {} links".format(
dork_to_use, link_amount_to_search dork_to_use, link_amount_to_search
) )
)) ))
@ -218,11 +238,11 @@ if __name__ == "__main__":
except Exception as e: except Exception as e:
if "Error 400" in str(e): if "Error 400" in str(e):
logger.fatal(set_color( logger.fatal(set_color(
"failed to connect to search engine...".format(e), level=50 "failed to connect to search engine".format(e), level=50
)) ))
else: else:
logger.exception(set_color( logger.exception(set_color(
"failed with unexpected error '{}'...".format(e), level=50 "failed with unexpected error '{}'".format(e), level=50
)) ))
shutdown() shutdown()
@ -234,7 +254,7 @@ if __name__ == "__main__":
for dork in dorks.readlines(): for dork in dorks.readlines():
dork = dork.strip() dork = dork.strip()
logger.info(set_color( logger.info(set_color(
"starting dork scan with query '{}'...".format(dork) "starting dork scan with query '{}'".format(dork)
)) ))
try: try:
selenium_search.parse_search_results( selenium_search.parse_search_results(
@ -244,7 +264,7 @@ if __name__ == "__main__":
) )
except Exception as e: except Exception as e:
logger.exception(set_color( logger.exception(set_color(
"ran into exception '{}'...".format(e), level=50 "ran into exception '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
pass pass
@ -256,10 +276,10 @@ if __name__ == "__main__":
random_dork = get_random_dork().strip() random_dork = get_random_dork().strip()
if opt.runInVerbose: if opt.runInVerbose:
logger.debug(set_color( logger.debug(set_color(
"choosing random dork from etc/dorks.txt...", level=10 "choosing random dork from etc/dorks.txt", level=10
)) ))
logger.info(set_color( logger.info(set_color(
"using random dork '{}' as the search query...".format(random_dork) "using random dork '{}' as the search query".format(random_dork)
)) ))
try: try:
selenium_search.parse_search_results( selenium_search.parse_search_results(
@ -271,7 +291,7 @@ if __name__ == "__main__":
except Exception as e: except Exception as e:
logger.exception(set_color( logger.exception(set_color(
"ran into exception '{}' and cannot continue, saved to current log file...".format(e), "ran into exception '{}' and cannot continue, saved to current log file".format(e),
level=50 level=50
)) ))
request_issue_creation() request_issue_creation()
@ -281,7 +301,7 @@ if __name__ == "__main__":
elif opt.spiderWebSite: elif opt.spiderWebSite:
problem_identifiers = ["http://", "https://"] problem_identifiers = ["http://", "https://"]
if not URL_REGEX.match(opt.spiderWebSite): if not URL_REGEX.match(opt.spiderWebSite):
err_msg = "URL did not match a true URL{}..." err_msg = "URL did not match a true URL{}"
if not any(m in opt.spiderWebSite for m in problem_identifiers): if not any(m in opt.spiderWebSite for m in problem_identifiers):
err_msg = err_msg.format(" issue seems to be that http:// " err_msg = err_msg.format(" issue seems to be that http:// "
"or https:// is not present in the URL") "or https:// is not present in the URL")
@ -317,7 +337,7 @@ if __name__ == "__main__":
# enumerate a file and run attacks on the URL's provided # enumerate a file and run attacks on the URL's provided
elif opt.fileToEnumerate is not None: elif opt.fileToEnumerate is not None:
logger.info(set_color( logger.info(set_color(
"found a total of {} URL's to enumerate in given file...".format( "found a total of {} URL's to enumerate in given file".format(
len(open(opt.fileToEnumerate).readlines()) len(open(opt.fileToEnumerate).readlines())
) )
)) ))
@ -325,7 +345,7 @@ if __name__ == "__main__":
else: else:
logger.critical(set_color( logger.critical(set_color(
"failed to provide a mandatory argument, you will be redirected to the help menu...", level=50 "failed to provide a mandatory argument, you will be redirected to the help menu", level=50
)) ))
time.sleep(2) time.sleep(2)
zeus_help_menu_command = shlex.split("python zeus.py --help") zeus_help_menu_command = shlex.split("python zeus.py --help")
@ -333,7 +353,7 @@ if __name__ == "__main__":
except IOError as e: except IOError as e:
if "Invalid URL" in str(e): if "Invalid URL" in str(e):
logger.exception(set_color( logger.exception(set_color(
"URL provided is not valid, schema appears to be missing...", level=50 "URL provided is not valid, schema appears to be missing", level=50
)) ))
request_issue_creation() request_issue_creation()
shutdown() shutdown()
@ -344,38 +364,40 @@ if __name__ == "__main__":
)) ))
shutdown() shutdown()
elif "No such file or directory" in str(e): elif "No such file or directory" in str(e):
logger.exception(e)
logger.fatal(set_color( logger.fatal(set_color(
"provided file does not exist, make sure you have the full path...", level=50 "provided file does not exist, make sure you have the full path", level=50
)) ))
shutdown()
else: else:
logger.exception(set_color( logger.exception(set_color(
"Zeus has hit an unexpected error and cannot continue, error code '{}'...".format(e), level=50 "Zeus has hit an unexpected error and cannot continue, error code '{}'".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()
except KeyboardInterrupt: except KeyboardInterrupt:
logger.fatal(set_color( logger.fatal(set_color(
"user aborted process...", level=50 "user aborted process", level=50
)) ))
shutdown() shutdown()
except UnboundLocalError: except UnboundLocalError:
logger.warning(set_color( logger.warning(set_color(
"do not interrupt the browser when selenium is running, " "do not interrupt the browser when selenium is running, "
"it will cause Zeus to crash...", level=30 "it will cause Zeus to crash", level=30
)) ))
except ZeusArgumentException:
shutdown()
except Exception as e: except Exception as e:
if "url did not match a true url" in str(e).lower(): if "url did not match a true url" in str(e).lower():
logger.error(set_color( logger.error(set_color(
"you did not provide a URL that is capable of being processed, " "you did not provide a URL that is capable of being processed, "
"the URL provided to the spider needs to contain protocol as well " "the URL provided to the spider needs to contain protocol as well "
"ie. 'http://google.com' (it is advised not to add the GET parameter), " "ie. 'http://google.com' (it is advised not to add the GET parameter), "
"fix the URL you want to scan and try again...", level=40 "fix the URL you want to scan and try again", level=40
)) ))
shutdown() shutdown()
elif "Service geckodriver unexpectedly exited" in str(e): elif "Service geckodriver unexpectedly exited" in str(e):
logger.fatal(set_color( logger.fatal(set_color(
"it seems your firefox version is not compatible with the geckodriver version, " "it seems your firefox version is not compatible with the geckodriver version, "
"please re-install Zeus and try again...", level=50 "please re-install Zeus and try again", level=50
)) ))
shutdown() shutdown()
elif "Max retries exceeded with url" in str(e): elif "Max retries exceeded with url" in str(e):
@ -387,7 +409,7 @@ if __name__ == "__main__":
shutdown() shutdown()
else: else:
logger.exception(set_color( logger.exception(set_color(
"ran into exception '{}' exception has been saved to log file...".format(e), level=50 "ran into exception '{}' exception has been saved to log file".format(e), level=50
)) ))
request_issue_creation() request_issue_creation()