mirror of
https://github.com/aljazceru/recon-pipeline.git
synced 2025-12-18 23:04:21 +01:00
* 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
187 lines
7.7 KiB
Python
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",
|
|
)
|