Skip to content

Commit

Permalink
Uninstall command (#66)
Browse files Browse the repository at this point in the history
* Add do_uninstall function

* uninstall f/ amass/aqua/go

* uninstall functional on all tools

* Add in missed fixes from rebase

* solve permission issue

* Removes un-needed vars from yaml

* Resolves go test issues

* adds framework for uninstall tests

* Fixes uninstall tests for Go tools

* Adds uninstall testing for luigi and improves uninstall

* Adds uninstall testing for searchsploit

* Update installation documentation
  • Loading branch information
GreaterGoodest authored Jun 27, 2020
1 parent 9e863a2 commit 1ad3adc
Show file tree
Hide file tree
Showing 19 changed files with 272 additions and 93 deletions.
2 changes: 2 additions & 0 deletions docs/overview/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ up the pipeline.
The installer maintains a (naive) list of installed tools at ``~/.local/recon-pipeline/tools/.tool-dict.pkl``. The installer in no way attempts to be a package manager. It knows how to execute the steps necessary to install its tools. Beyond that, it's
like Jon Snow, **it knows nothing**.

Tools can also be uninstalled using the ``uninstall all`` command. It is also possible to individually uninstall them in the same manner as shown above.

.. raw:: html

<script id="asciicast-294414" src="https://asciinema.org/a/294414.js" async></script>
Expand Down
83 changes: 77 additions & 6 deletions pipeline/recon-pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def cluge_package_imports(name, package):
get_scans,
scan_parser,
install_parser,
uninstall_parser,
status_parser,
database_parser,
db_detach_parser,
Expand Down Expand Up @@ -322,15 +323,24 @@ def do_scan(self, args):

self.add_dynamic_parser_arguments()

@cmd2.with_argparser(install_parser)
def do_install(self, args):
""" Install any/all of the libraries/tools necessary to make the recon-pipeline function. """
def _get_dict(self):
"""Retrieves tool dict if available"""

# imported tools variable is in global scope, and we reassign over it later
global tools

persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"

if persistent_tool_dict.exists():
tools = pickle.loads(persistent_tool_dict.read_bytes())

return tools

@cmd2.with_argparser(install_parser)
def do_install(self, args):
""" Install any/all of the libraries/tools necessary to make the recon-pipeline function. """

tools = self._get_dict()
if args.tool == "all":
# show all tools have been queued for installation
[
Expand All @@ -343,8 +353,6 @@ def do_install(self, args):
self.do_install(tool)

return
if persistent_tool_dict.exists():
tools = pickle.loads(persistent_tool_dict.read_bytes())

if tools.get(args.tool).get("dependencies"):
# get all of the requested tools dependencies
Expand Down Expand Up @@ -374,7 +382,7 @@ def do_install(self, args):
if addl_env_vars is not None:
addl_env_vars.update(dict(os.environ))

for command in tools.get(args.tool).get("commands"):
for command in tools.get(args.tool).get("install_commands"):
# run all commands required to install the tool

# print each command being run
Expand Down Expand Up @@ -420,6 +428,69 @@ def do_install(self, args):
)

# store any tool installs/failures (back) to disk
persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"
pickle.dump(tools, persistent_tool_dict.open("wb"))

@cmd2.with_argparser(uninstall_parser)
def do_uninstall(self, args):
""" Uninstall any/all of the libraries/tools used by recon-pipeline"""
tools = self._get_dict()
if args.tool == "all":
# show all tools have been queued for installation
[
self.poutput(style(f"[-] {x} queued", fg="bright_white"))
for x in tools.keys()
if tools.get(x).get("installed")
]

for tool in tools.keys():
self.do_uninstall(tool)

return

if not tools.get(args.tool).get("installed"):
return self.poutput(style(f"[!] {args.tool} is not installed.", fg="yellow"))
else:
retvals = list()

self.poutput(style(f"[*] Removing {args.tool}...", fg="bright_yellow"))
if not tools.get(args.tool).get("uninstall_commands"):
self.poutput(style(f"[*] {args.tool} removal not needed", fg="bright_yellow"))
return

for command in tools.get(args.tool).get("uninstall_commands"):
self.poutput(style(f"[=] {command}", fg="cyan"))

proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

out, err = proc.communicate()

if err:
self.poutput(style(f"[!] {err.decode().strip()}", fg="bright_red"))

retvals.append(proc.returncode)

if all(x == 0 for x in retvals):
# all return values in retvals are 0, i.e. all exec'd successfully; tool has been uninstalled

self.poutput(style(f"[+] {args.tool} removed!", fg="bright_green"))

tools[args.tool]["installed"] = False
else:
# unsuccessful tool removal

tools[args.tool]["installed"] = True

self.poutput(
style(
f"[!!] one (or more) of {args.tool}'s commands failed and may have not been removed properly; check output from the offending command above...",
fg="bright_red",
bold=True,
)
)

# store any tool installs/failures (back) to disk
persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"
pickle.dump(tools, persistent_tool_dict.open("wb"))

@cmd2.with_argparser(status_parser)
Expand Down
1 change: 1 addition & 0 deletions pipeline/recon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .config import top_udp_ports, top_tcp_ports, defaults, web_ports
from .parsers import (
install_parser,
uninstall_parser,
scan_parser,
status_parser,
database_parser,
Expand Down
3 changes: 3 additions & 0 deletions pipeline/recon/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
install_parser = cmd2.Cmd2ArgumentParser()
install_parser.add_argument("tool", help="which tool to install", choices=list(tools.keys()) + ["all"])

# options for ReconShell's 'uninstall' command
uninstall_parser = cmd2.Cmd2ArgumentParser()
uninstall_parser.add_argument("tool", help="which tool to uninstall", choices=list(tools.keys()) + ["all"])

# options for ReconShell's 'status' command
status_parser = cmd2.Cmd2ArgumentParser()
Expand Down
7 changes: 5 additions & 2 deletions pipeline/tools/amass.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
installed: false
dependencies: [go]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/amass]
path: &path !join_path [!get_default "{gopath}", "bin/amass"]
environ: {"GO111MODULE": "on", "GOPATH": !get_default "{gopath}"}

commands:
install_commands:
- !join [*gotool, get github.com/OWASP/Amass/v3/...]

uninstall_commands:
- !join [rm, *path]


9 changes: 6 additions & 3 deletions pipeline/tools/aquatone.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
installed: false
tools: &tools !get_default "{tools-dir}"
path: &aqua !join_path [*tools, aquatone]
path: &path !join_path [*tools, aquatone]

commands:
install_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
- bash -c 'if [[ ! $(which unzip) ]]; then sudo apt install -y zip; fi'
- unzip /tmp/aquatone/aquatone.zip -d /tmp/aquatone
- !join [mv /tmp/aquatone/aquatone, *aqua]
- !join [mv /tmp/aquatone/aquatone, *path]
- rm -rf /tmp/aquatone
- bash -c 'found=false; for loc in {/usr/bin/google-chrome,/usr/bin/google-chrome-beta,/usr/bin/google-chrome-unstable,/usr/bin/chromium-browser,/usr/bin/chromium}; do if [[ $(which $loc) ]]; then found=true; break; fi ; done; if [[ $found = false ]]; then sudo apt install -y chromium-browser ; fi'

uninstall_commands:
- !join [rm, *path]
5 changes: 4 additions & 1 deletion pipeline/tools/go.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ installed: false
bashrc: &bashrc !join_path [!get_default "{home}", .bashrc]
path: &gotool !join_path [!get_default "{goroot}", go/bin/go]

commands:
install_commands:
- wget -q https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz -O /tmp/go.tar.gz
- !join [tar -C, !get_default "{goroot}", -xvf /tmp/go.tar.gz]
- !join ["bash -c 'if [ ! $(grep $(dirname", *gotool, ")", *bashrc, ") ]; then echo PATH=${PATH}:$(dirname", *gotool, ") >>", *bashrc, "; fi'"]

uninstall_commands:
- !join [sudo, rm, -r, !get_default "{goroot}"]
8 changes: 6 additions & 2 deletions pipeline/tools/gobuster.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
installed: false
dependencies: [go, seclists]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/gobuster]
path: &path !join_path [!get_default "{gopath}", bin/gobuster]
environ: {"GOPATH": !get_default "{gopath}"}
home: &home !get_default "{home}"

commands:
install_commands:
- !join [*gotool, get github.com/OJ/gobuster]

uninstall_commands:
- !join [rm, *path]
10 changes: 8 additions & 2 deletions pipeline/tools/luigi-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ installed: false
project-dir: &proj !get_default "{project-dir}"
service-file: &svcfile !join_path [*proj, luigid.service]

commands:
install_commands:
- !join [sudo cp, *svcfile, /lib/systemd/system/luigid.service]
- !join [sudo cp, *svcfile, $(which luigid), /usr/local/bin]
- !join [sudo cp, $(which luigid), /usr/local/bin]
- sudo systemctl daemon-reload
- sudo systemctl start luigid.service
- sudo systemctl enable luigid.service

uninstall_commands:
- sudo systemctl disable luigid.service
- sudo systemctl stop luigid.service
- sudo rm /lib/systemd/system/luigid.service
- sudo rm /usr/local/bin/luigid /usr/local/bin/luigid.service

shell: true
11 changes: 7 additions & 4 deletions pipeline/tools/masscan.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
installed: false
tools: &tools !get_default "{tools-dir}"
path: &masscan !join_path [*tools, masscan]
path: &path !join_path [*tools, masscan]

commands:
install_commands:
- git clone https://github.com/robertdavidgraham/masscan /tmp/masscan
- make -s -j -C /tmp/masscan
- !join [mv /tmp/masscan/bin/masscan, *masscan]
- !join [mv /tmp/masscan/bin/masscan, *path]
- rm -rf /tmp/masscan
- !join [sudo setcap CAP_NET_RAW+ep, *masscan]
- !join [sudo setcap CAP_NET_RAW+ep, *path]

uninstall_commands:
- !join [rm, *path]
9 changes: 6 additions & 3 deletions pipeline/tools/recursive-gobuster.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
installed: false
dependencies: [gobuster]
tools: &tools !get_default "{tools-dir}"
path: !join_path [*tools, recursive-gobuster/recursive-gobuster.pyz]
path: &path !join_path [*tools, recursive-gobuster/recursive-gobuster.pyz]
recursive-parent: &parent !join_path [*tools, recursive-gobuster]

commands:
install_commands:
- !join ["bash -c 'if [ -d", *parent, "]; then cd", *parent,
"&& git fetch --all && git pull; else git clone https://github.com/epi052/recursive-gobuster.git",
*parent, " ; fi'"]
*parent, "; fi'"]

uninstall_commands:
- !join [sudo, rm, -r, *parent]
13 changes: 8 additions & 5 deletions pipeline/tools/searchsploit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ dependencies: [exploitdb]
home: &home !get_default "{home}"
tools: &tools !get_default "{tools-dir}"
exploitdb-file: &exploitdb !get_tool_path "{exploitdb[path]}"
path: &searchsploit !join_path [*tools, exploitdb/searchsploit]
path: &path !join_path [*tools, exploitdb/searchsploit]
searchsploit-rc: &ss_rc !join_path [*exploitdb, ".searchsploit_rc"]
homesploit: &homesploit !join_path [*home, ".searchsploit_rc"]
sed-command: &sedcom !join_empty ["'s#/opt#", *tools, "#g'"]

commands:
- !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then ln -fs /usr/share/exploitdb",
*exploitdb, "&& ln -fs $(which searchsploit)", *searchsploit,
install_commands:
- !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then sudo ln -fs /usr/share/exploitdb",
*exploitdb, "&& sudo ln -fs $(which searchsploit)", *path,
"; elif [ -d", *exploitdb, "]; then cd", *exploitdb,
"&& git fetch --all && git pull; else git clone https://github.com/offensive-security/exploitdb.git", *exploitdb, "; fi'"]
"&& git fetch --all && git pull; else git clone https://github.com/offensive-security/exploitdb.git", *exploitdb, ; fi']
- !join ["bash -c 'if [ -f", *ss_rc, "]; then cp -n", *ss_rc, *home, "; fi'"]
- !join ["bash -c 'if [ -f", *homesploit, "]; then sed -i", *sedcom, *homesploit, "; fi'"]

uninstall_commands:
- !join [sudo, rm, -r, *exploitdb]
13 changes: 8 additions & 5 deletions pipeline/tools/seclists.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
installed: false
tools: &tools !get_default "{tools-dir}"
path: &secfile !join_path [*tools, seclists]
path: &path !join_path [*tools, seclists]

commands:
- !join ["bash -c 'if [[ -d /usr/share/seclists ]]; then ln -s /usr/share/seclists",
*secfile, "; elif [[ -d", *secfile, "]] ; then cd", *secfile, "&& git fetch --all && git pull;",
"else git clone https://github.com/danielmiessler/SecLists.git", *secfile, "; fi'"]
install_commands:
- !join ["bash -c 'if [[ -d /usr/share/seclists ]]; then ln -s /usr/share/seclists",
*path, "; elif [[ -d", *path, "]] ; then cd", *path, "&& git fetch --all && git pull;",
"else git clone https://github.com/danielmiessler/SecLists.git", *path, "; fi'"]

uninstall_commands:
- !join [sudo, rm, -r, *path]
7 changes: 5 additions & 2 deletions pipeline/tools/subjack.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
installed: false
dependencies: [go]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/subjack]
path: &path !join_path [!get_default "{gopath}", bin/subjack]
environ: {"GOPATH": !get_default "{gopath}"}

fingerprints: !join_path [!get_default "{gopath}", src/github.com/haccer/subjack/fingerprints.json]

commands:
install_commands:
- !join [*gotool, get github.com/haccer/subjack]

uninstall_commands:
- !join [rm, *path]
7 changes: 5 additions & 2 deletions pipeline/tools/tko-subs.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
installed: false
dependencies: [go]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/tko-subs]
path: &path !join_path [!get_default "{gopath}", bin/tko-subs]
environ: {"GOPATH": !get_default "{gopath}"}
providers: !join_path [!get_default "{gopath}", src/github.com/anshumanbh/tko-subs/providers-data.csv]

commands:
install_commands:
- !join [*gotool, get, github.com/anshumanbh/tko-subs]

uninstall_commands:
- !join [rm, *path]
9 changes: 6 additions & 3 deletions pipeline/tools/waybackurls.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
installed: false
dependencies: [go]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/waybackurls]
path: &path !join_path [!get_default "{gopath}", bin/waybackurls]
environ: {"GOPATH": !get_default "{gopath}"}

commands:
- !join [*gotool, get, github.com/tomnomnom/waybackurls]
install_commands:
- !join [*gotool, get, github.com/tomnomnom/waybackurls]

uninstall_commands:
- !join [rm, *path]
7 changes: 5 additions & 2 deletions pipeline/tools/webanalyze.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
installed: false
dependencies: [go]
go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/webanalyze]
path: &path !join_path [!get_default "{gopath}", bin/webanalyze]
environ: {"GOPATH": !get_default "{gopath}"}

commands:
install_commands:
- !join [*gotool, get github.com/rverton/webanalyze/...]

uninstall_commands:
- !join [rm, *path]
Loading

0 comments on commit 1ad3adc

Please sign in to comment.