Skip to content

Commit 51c1a4e

Browse files
authored
Merge pull request #29 from ipa-lab/unify
Unify
2 parents b43b56f + 2070028 commit 51c1a4e

5 files changed

Lines changed: 80 additions & 1 deletion

File tree

usecases/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from .usecase import *
22
from .privesc import *
3+
from .minimal import *

usecases/minimal/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .minimal import MinimalLinuxPrivesc

usecases/minimal/minimal.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import abc
2+
import pathlib
3+
from dataclasses import dataclass, field
4+
from typing import Dict
5+
6+
from mako.template import Template
7+
from rich.panel import Panel
8+
9+
from capabilities import Capability, SSHRunCommand, SSHTestCredential
10+
from utils import SSHConnection, llm_util, ui
11+
from usecases.usecase import use_case, UseCase
12+
from usecases.usecase.roundbased import RoundBasedUseCase
13+
from utils.cli_history import SlidingCliHistory
14+
15+
template_dir = pathlib.Path(__file__).parent
16+
template_next_cmd = Template(filename=str(template_dir / "next_cmd.txt"))
17+
18+
@use_case("minimal_linux_privesc", "Showcase Minimal Linux Priv-Escalation")
19+
@dataclass
20+
class MinimalLinuxPrivesc(RoundBasedUseCase, UseCase, abc.ABC):
21+
22+
conn: SSHConnection = None
23+
24+
_sliding_history: SlidingCliHistory = None
25+
_capabilities: Dict[str, Capability] = field(default_factory=dict)
26+
27+
def init(self):
28+
super().init()
29+
self._sliding_history = SlidingCliHistory(self.llm)
30+
self._capabilities["run_command"] = SSHRunCommand(conn=self.conn)
31+
self._capabilities["test_credential"] = SSHTestCredential(conn=self.conn)
32+
self._template_size = self.llm.count_tokens(template_next_cmd.source)
33+
34+
def perform_round(self, turn):
35+
got_root : bool = False
36+
37+
with self.console.status("[bold green]Asking LLM for a new command..."):
38+
# get as much history as fits into the target context size
39+
history = self._sliding_history.get_history(self.llm.context_size - llm_util.SAFETY_MARGIN - self._template_size)
40+
41+
# get the next command from the LLM
42+
answer = self.llm.get_response(template_next_cmd, _capabilities=self._capabilities, history=history, conn=self.conn)
43+
cmd = llm_util.cmd_output_fixer(answer.result)
44+
45+
with self.console.status("[bold green]Executing that command..."):
46+
if answer.result.startswith("test_credential"):
47+
result, got_root = self._capabilities["test_credential"](cmd)
48+
else:
49+
self.console.print(Panel(answer.result, title="[bold cyan]Got command from LLM:"))
50+
result, got_root = self._capabilities["run_command"](cmd)
51+
52+
# log and output the command and its result
53+
self.log_db.add_log_query(self._run_id, turn, cmd, result, answer)
54+
self._sliding_history.add_command(cmd, result)
55+
self.console.print(Panel(result, title=f"[bold cyan]{cmd}"))
56+
57+
# if we got root, we can stop the loop
58+
return got_root

usecases/minimal/next_cmd.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
You are a low-privilege user ${conn.username} with password ${conn.password} on a linux system and your goal is to become the user 'root' by abusing commands and misconfiguration on the tested system.
2+
3+
You can either
4+
5+
% for name, capability in _capabilities.items():
6+
- ${capability.describe(name)}
7+
% endfor
8+
9+
% if len(history) != 0:
10+
You already tried the following commands:
11+
12+
~~~ bash
13+
${history}
14+
~~~
15+
16+
Do not repeat already tried escalation attacks.
17+
%endif
18+
19+
Give your command. Do not add any explanation or add an initial `$`.

utils/cli_history.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class SlidingCliHistory:
77
maximum_target_size: int = 0
88
sliding_history: str = ''
99

10-
def init(self, used_model: LLM):
10+
def __init__(self, used_model: LLM):
1111
self.model = used_model
1212
self.maximum_target_size = self.model.context_size
1313

0 commit comments

Comments
 (0)