Skip to content

Commit

Permalink
list module functionality and helpful menu banners on first time
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephTLucas committed Jan 21, 2024
1 parent 6af0536 commit b4e82d4
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <joe@joetl.com>"]
license = "GPL-3.0-only"
Expand Down
12 changes: 12 additions & 0 deletions vger/exploit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
)
63 changes: 62 additions & 1 deletion vger/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
"""
. ,;
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
],
)
Expand All @@ -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()
Expand All @@ -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",
Expand Down

0 comments on commit b4e82d4

Please sign in to comment.