Files
recon-pipeline/recon/__init__.py
epi052 7a24d85db4 Add scan tests (#12) - tests of current codebase complete
* recon.targets tests added

* restructured tests logically

* fixed yaml error

* fixed job names

* recon.__init__ tests added

* recon.config tests added

* recon.amass.ParseAmassScan tests added

* fixed test destined to fail on CI pipeline

* testing amass partially complete

* Changed the dir layout (#6) and fixed paths (#8)

this commit closes #6 and #8
updated existing tests to utilize new paths

* tests of current codebase complete

* added is_kali check to searchsploit test

* added test_web action to pipeline
2020-02-04 06:33:00 -06:00

187 lines
7.7 KiB
Python

# flake8: noqa E231
import sys
import socket
import inspect
import pkgutil
import importlib
from pathlib import Path
from collections import defaultdict
import cmd2
import recon
from recon.config import tool_paths
# tool definitions for recon-pipeline's auto-installer
tools = {
"luigi-service": {
"installed": False,
"dependencies": ["luigi"],
"commands": [
f"sudo cp {str(Path(__file__).parent.parent / 'luigid.service')} /lib/systemd/system/luigid.service",
f"sudo cp $(which luigid) /usr/local/bin",
"sudo systemctl daemon-reload",
"sudo systemctl start luigid.service",
"sudo systemctl enable luigid.service",
],
"shell": True,
},
"luigi": {"installed": False, "dependencies": ["pipenv"], "commands": ["pipenv install luigi"],},
"pipenv": {"installed": False, "dependencies": None, "commands": ["sudo apt-get install -y -q pipenv"],},
"masscan": {
"installed": False,
"dependencies": None,
"commands": [
"git clone https://github.com/robertdavidgraham/masscan /tmp/masscan",
"make -s -j -C /tmp/masscan",
f"sudo mv /tmp/masscan/bin/masscan {tool_paths.get('masscan')}",
"rm -rf /tmp/masscan",
],
},
"amass": {"installed": False, "dependencies": None, "commands": ["sudo apt-get install -y -q amass"],},
"aquatone": {
"installed": False,
"dependencies": None,
"shell": True,
"commands": [
"mkdir /tmp/aquatone",
"wget -q https://github.com/michenriksen/aquatone/releases/download/v1.7.0/aquatone_linux_amd64_1.7.0.zip -O /tmp/aquatone/aquatone.zip",
"unzip /tmp/aquatone/aquatone.zip -d /tmp/aquatone",
f"sudo mv /tmp/aquatone/aquatone {tool_paths.get('aquatone')}",
"rm -rf /tmp/aquatone",
],
},
"corscanner": {
"installed": False,
"dependencies": None,
"shell": True,
"commands": [
f"sudo bash -c 'if [[ -d {Path(tool_paths.get('CORScanner')).parent} ]] ; then cd {Path(tool_paths.get('CORScanner')).parent} && git pull; else git clone https://github.com/chenjj/CORScanner.git {Path(tool_paths.get('CORScanner')).parent}; fi'",
f"pip install -q -r {Path(tool_paths.get('CORScanner')).parent / 'requirements.txt'}",
"pip install -q future",
],
},
"gobuster": {
"installed": False,
"dependencies": ["go"],
"commands": [
"go get github.com/OJ/gobuster",
"(cd ~/go/src/github.com/OJ/gobuster && go build && go install)",
],
"shell": True,
},
"tko-subs": {
"installed": False,
"dependencies": ["go"],
"commands": [
"go get github.com/anshumanbh/tko-subs",
"(cd ~/go/src/github.com/anshumanbh/tko-subs && go build && go install)",
],
"shell": True,
},
"subjack": {
"installed": False,
"dependencies": ["go"],
"commands": ["go get github.com/haccer/subjack", "(cd ~/go/src/github.com/haccer/subjack && go install)",],
"shell": True,
},
"webanalyze": {
"installed": False,
"dependencies": ["go"],
"commands": [
"go get github.com/rverton/webanalyze/...",
"(cd ~/go/src/github.com/rverton/webanalyze && go build && go install)",
],
"shell": True,
},
"recursive-gobuster": {
"installed": False,
"dependencies": None,
"shell": True,
"commands": [
f"sudo bash -c 'if [[ -d {Path(tool_paths.get('recursive-gobuster')).parent} ]] ; then cd {Path(tool_paths.get('recursive-gobuster')).parent} && git pull; else git clone https://github.com/epi052/recursive-gobuster.git {Path(tool_paths.get('recursive-gobuster')).parent}; fi'",
],
},
"go": {"installed": False, "dependencies": None, "commands": ["sudo apt-get install -y -q golang"],},
}
def get_scans():
""" Iterates over the recon package and its modules to find all of the \*Scan classes.
**A contract exists here that says any scans need to end with the word scan in order to be found by this function.**
Example:
``defaultdict(<class 'list'>, {'AmassScan': ['recon.amass'], 'MasscanScan': ['recon.masscan'], ... })``
Returns:
dict containing mapping of ``classname -> [modulename, ...]`` for all potential recon-pipeline commands
"""
scans = defaultdict(list)
# recursively walk packages; import each module in each package
# walk_packages yields ModuleInfo objects for all modules recursively on path
# prefix is a string to output on the front of every module name on output.
for loader, module_name, is_pkg in pkgutil.walk_packages(path=recon.__path__, prefix="recon."):
importlib.import_module(module_name)
# walk all modules, grabbing classes that we've written and add them to the classlist defaultdict
# getmembers returns all members of an object in a list of tuples (name, value)
for name, obj in inspect.getmembers(sys.modules[__name__]):
if inspect.ismodule(obj) and not name.startswith("_"):
# we're only interested in modules that don't begin with _ i.e. magic methods __len__ etc...
for subname, subobj in inspect.getmembers(obj):
if inspect.isclass(subobj) and subname.lower().endswith("scan"):
# now we only care about classes that end in [Ss]can
scans[subname].append(f"recon.{name}")
return scans
# options for ReconShell's 'install' command
install_parser = cmd2.Cmd2ArgumentParser()
install_parser.add_argument("tool", help="which tool to install", choices=list(tools.keys()) + ["all"])
# options for ReconShell's 'scan' command
scan_parser = cmd2.Cmd2ArgumentParser()
scan_parser.add_argument("scantype", choices_function=get_scans)
scan_parser.add_argument(
"--target-file",
completer_method=cmd2.Cmd.path_complete,
help="file created by the user that defines the target's scope; list of ips/domains",
)
scan_parser.add_argument(
"--exempt-list", completer_method=cmd2.Cmd.path_complete, help="list of blacklisted ips/domains",
)
scan_parser.add_argument(
"--results-dir", completer_method=cmd2.Cmd.path_complete, help="directory in which to save scan results",
)
scan_parser.add_argument(
"--wordlist", completer_method=cmd2.Cmd.path_complete, help="path to wordlist used by gobuster",
)
scan_parser.add_argument(
"--interface",
choices_function=lambda: [x[1] for x in socket.if_nameindex()],
help="which interface masscan should use",
)
scan_parser.add_argument("--recursive", action="store_true", help="whether or not to recursively gobust")
scan_parser.add_argument("--rate", help="rate at which masscan should scan")
scan_parser.add_argument(
"--top-ports", help="ports to scan as specified by nmap's list of top-ports (only meaningful to around 5000)",
)
scan_parser.add_argument(
"--ports", help="port specification for masscan (all ports example: 1-65535,U:1-65535)",
)
scan_parser.add_argument("--threads", help="number of threads for all of the threaded applications to use")
scan_parser.add_argument("--scan-timeout", help="scan timeout for aquatone")
scan_parser.add_argument("--proxy", help="proxy for gobuster if desired (ex. 127.0.0.1:8080)")
scan_parser.add_argument("--extensions", help="list of extensions for gobuster (ex. asp,html,aspx)")
scan_parser.add_argument(
"--local-scheduler", action="store_true", help="use the local scheduler instead of the central scheduler (luigid)",
)
scan_parser.add_argument(
"--verbose", action="store_true", help="shows debug messages from luigi, useful for troubleshooting",
)