FlagShop
F12查看源码,发现一段js代码
|
|
大概就是GET传参readfile
或writefile
访问/backend.php
路由读写文件,此处存在一个任意文件读取漏洞,通过readfile
可以读取backend.php内容:
|
|
然后利用目录穿越读index.php文件内容:
|
|
审计backend.php代码,fseek函数存在利用点,fseek利用参考procfs_bypass.php脚本,看不懂就西湖论剑 Flagshop 分析复现。
我老菜狗了,直接照着做一遍。。。
先了解一下fseek函数:
fseek() 函数在打开的文件中定位。
该函数把文件指针从当前位置向前或向后移动到新的位置,新位置从文件头开始以字节数度量。
该函数配合fwrite函数能实现在文件中指定位置插入自定义内容的功能。
既然想要修改地址,那就一定要先知道函数的地址,可以通过读取/proc/self/maps
得到当前进程的动态链接库和内存地址。
由于system函数在libc库中,所以直接读取/lib/x86_64-linux-gnu/libc-2.19.so
内容,通过wget
命令下载。
接下来寻找函数地址:
|
|
得到函数偏移地址:
1337: 0000000000046590 45 FUNC WEAK DEFAULT 12 system@@GLIBC_2.2.5
1681: 00000000000ef160 90 FUNC WEAK DEFAULT 12 open@@GLIBC_2.2.5
对于为什么0x7ffff5f40000
是system函数的起始地址?我的理解是:这个内存拥有可执行权限r-xp
,而其他三个并没有,因此这个内存地址是system函数的起始地址。
计算system函数地址:
|
|
知道system函数的地址之后就可以将open函数的地址替换为system函数的地址,这样在执行file_get_contents函数时命令实际执行的却是system函数,可以将readflag的结果输出到文件,或者反弹shell。
接下来就是计算open函数的地址,这里需要用到/proc/self/exe
。
在Linux2.2的内核及其之后,/proc/pid/exe是直接执行的二进制文件的符号链接.这个符号链接能够被取消.尝试打开这个文件就相当与打开了二进制文件,甚至可以通过重新输入/proc/pid/exe重新运行一个对应于pid的二进制文件.在一个多线程的程序中,如果主线程已经退出了,就无法访问这个符号链接.
在Linux2.0及其之前,/proc/pid/exe是指向当前进程执行的二进制文件.
将文件下载下来,使用下面的脚本计算open函数的偏移。
|
|
函数地址都已经得到了,接下来就是修改open函数地址,变成system函数地址,这需要文件/proc/self/mem
。
/proc/self/mem是进程的内存内容,通过修改该文件相当于直接修改当前进程的内存。该文件不能直接读取,需要结合maps的映射信息来确定读的偏移值。即无法读取未被映射的区域,只有读取的偏移值是被映射的区域才能正确读取内存内容。
也就是说,我们需要修改/proc/self/mem
使open函数的地址变成system的地址。
payload:
|
|
然后读取/tmp/i_o_u_hlq
文件获得flag。
吐槽一下,不会pwn的weber不是好ctfer。。。