数字经济共测大赛线下
前言
线下的rw自闭了两天,今天终于有空做一下docker逃逸的题目,也整理一下自己调试的思路,这是一道非常非常非常简单的题目,本来其实也用不到调试的,不过因为自己当局者迷,根本没能静下心好好研究。
程序逻辑
题目给了一个虚拟机,内核版本为4.15.0-54-generic,给了一个有漏洞的内核模块de.ko,漏洞主要存在其中,初始化在bss上的hack上分配了一个堆,并用*(_BYTE *)(hack1 + 8) = 1;
置1,之后给了cred的size大小。
1 | __int64 __fastcall init_module(__int64 a1, __int64 a2) |
read函数将*((_QWORD *)¬e + 1)
的指针的内容拷贝给用户,实际上后面可以看到在这里会分配内存
1 | unsigned __int64 __fastcall de_read(__int64 a1, __int64 user_buf) |
write函数是我们分析的重点,程序根据我们发送的字符串的第一个字节进行switch case,-1则将用户输入拷贝到(¬e+1),-2则将用户输入拷贝到hack(此时可以覆盖hack+8地址处的值),不为-3或者(hack+8)==1会给(¬e+1)处分配一块指定大小的内存,否则(choice==-3且(hack+8)==0)执行后门代码,弹计算器,如果choice==0则释放*(¬e+1),因此最后只要满足后门条件即可
1 | __int64 __fastcall de_write(__int64 a1, char *from) |
漏洞利用
先用一次写清空hack+8的值,之后choice=0xfd调用后门弹计算器
exp.c
1 |
|
调试
进入虚拟机,加载漏洞内核模块,启动docker
1 | sudo insmod /home/b/de.ko |
传输漏洞文件
1 | scp -P23 ./exp* root@localhost |
执行exp,成功
调试docker好像没有直接的方法,我这里是在宿主系统里找到内核文件(/boot/vmlinuz-4.15.0-54-generic),拷贝到我的另一台虚拟机上,使用qemu进行调试。
调试脚本如下:
1 |
|
想要vmlinux的话可以用github的extract脚本提取,这里用不到,启动qemu之后要先查找各种地址
1 | cat /proc/kallsyms | grep de_write |
之后启动gdb,set arch i386:x86-64:intel
设置模拟的架构,target remote localhost:1234
调试内核,add-symbol-file ./de.ko 0xffffffffc03b0000
添加符号表,
刚才我们查找到的hack地址为0xffffffffc03b2500,我们断点下在de_write,continue,在qemu里执行exp,可以看到已经能从gdb断住了,*(hack+8)为1
我们再continue一下,第一次的覆写完成,成功改为0
在0x118处下个断点(commit_creds),成功执行到这里,说明exp执行成功
非预期解
看到知世师傅知世的博客,学到了新的姿势。
docker开启–privileged的情况下其实docker的root跟外部物理机的root权限已经差不多了,我们可以通过mount挂载宿主机的磁盘到内部,进而修改/etc/crontab通过定时任务弹计算器,注意要设置环境变量display=0,注意user要是b(普通用户),display=0的原因可以参见下文display=0,因此只需要在/etc/crontab中加一行1
* * * * * b DISPLAY=:0 /usr/bin/gnome-calculator
即可每分钟弹一次计算器
其他
调试的时候遇到一个问题,%p打印的地址不对,高四字节为0,低四字节不知道是什么,查了之后发现%p输出的是散列值,目地就是不泄漏地址,如果真想输出地址可以用%px,涨知识