首页
社区
课程
招聘
[原创]EFS Web Server 7.2 GET请求缓冲区溢出漏洞分析与利用
发表于: 2017-3-28 21:13 5387

[原创]EFS Web Server 7.2 GET请求缓冲区溢出漏洞分析与利用

2017-3-28 21:13
5387

分析来源:https://www.exploit-db.com/exploits/39008/

为什么去分析它呢,来源于k0shl在i春秋的课程


目录


在csdn用markdown写,也直接上传md文件吧

http://blog.csdn.net/u012763794/article/details/66970749

EFS Web Server是一个可以通过web端管理服务器文件的软件,发送GET请求长度过长会触发缓冲区溢出漏洞 
分析来源:https://www.exploit-db.com/exploits/39008/

WinXP sp3 中文版 
EFS Web Server7.2 
immunity debugger 
windbg 
IDA 
mona

由于作者使用的覆盖SEH程序的地址在ImageLoad.dll中,没ASLR,所以利用比较稳定,打开就弹出计算器

我们将payload该成全是A吧,buff = "A"*4500 
windbg附加后运行,发送我们的4500个A


我们看到发生了一个应用异常,可以看到eax的值为0x41414141,那么eax的值我们是可以控制的咯,那具体是不知可以覆盖SEH,跟着这里引发异常,导致可以执行我们的shellcode呢

那我们看看eax的值来源于哪里呢,ida打开sqlite3.dll,定位到如下函数

看到这里只知道eax来源于上层函数 
我们看看堆栈调用

根据第一个返回地址61c6286c我们定位到_sqlite3LockAndPrepare函数 
这里还是没看到eax的来源

那我们还是看fsws.exe的004968f4 吧

我们在sub_4968D0函数开头下断 
第三次断下来就看到ecx指向我们的41414141

那这个0x41414141是什么时候复制到栈上的呢 
我们对02057058下一个写入断点吧 
在这里暂停了下来


我们用ida看看这个地址,分析多了,看到这个write_char,就会联想上层调用了sprintf


那我们看看堆栈信息

确实004f9698在sprintf函数内

那我们继续看下一个返回地址

我们看看最后拼接的语句:bp 00497745 
第一次断下来,我们执行到sprintf函数,看看栈上的参数

这么长的畸形字符串复制到栈上,使用sprintf格式化前有进行加成,这就造成栈溢出了 
看看确实拼接成sql语句了

最后拿去给给sqlite3.dll处理的时候造成异常 
具体路径如下,sprintf执行完下一条语句是调用sub_4968D0函数 
sub_4968D0->sqlite3_prepare_v2->sqlite3LockAndPrepare->sqlite3SafetyCheckOk(在这函数里面异常)

那么0154249c上的畸形字符串哪里来,来源于sub_52DF03函数的memcpy函数的复制

作者使用的是覆盖SEH的方法,那是不是只能覆盖SEH呢?(是不是没执行到ret指令程序就崩溃掉了呢) 
我们看看返回地址有多远 
char v15; // [sp+20h] [bp-100Ch]@3 
我们要溢出的buf距离ebp都㓟0x100c,即4108个字节

当然函数这里没有生成栈帧 
那我们看看触发异常获取栈上02057058的值

那是可以覆盖返回地址的,我们尝试用4150个A 
!mona pattern_create 4150

计算一下 
!mona pattern_offset 0x38664637 
地址是4073(为什么比v15距离ebp的4180字节要小呢,因为前面还有sql语句的长度啊,O(∩_∩)O哈哈~) 
但是下面的payload没起作用,服务器也没崩,调试也正常返回了 
buff = "A" * 4073 + jmp_esp + "\x90" * 20 + shellcode 
那为什么之前eip会是0x38664637呢 
跟踪一下看看,确实会retn到0x38664637 
是不是我们的payload有什么问题呢 
通过调试进一步排查,是触发了异常,也是一开始我们所看到的异常, 
我们向前回溯看看这个eax的值来源于02057058,值是391c5a09

我们再看看我们的shellcode,从倒数第二个字节起向前数4个字节,刚好是0x391c5a09,那说明是我们的shellcode过长,覆盖到了上一函数栈帧的数据,导致异常的发生

那怎么解决?

对于第二点我发现过短了 
buff = "A" * 4073 + jmp_esp + "\x90" * 12 + shellcode 
调试发现没有复制0154249c的0x41414141 
而且也不是where name,应该后面的数据影响了

在后面加3个\x90就会异常

最后排查测试,这样是可以执行jmp esp的 
buff = "A" * 4073 + jmp_esp 
那我们在后面搞个先前跳转不就行了?

最终exp:

当然你也可以将shellcode改为弹窗的(注可能有些shellcode不能执行,有些位置的某些字符可能影响程序的执行流程或者sql查询的结果) 
下面看看我们弹窗效果

这里写图片描述

那使用覆盖SEH是不是没遇到这么多麻烦呢?

首先定位SEH

可以看到位置为4061,跟作者的exp写的是一样的,但这里是NEXT SEH的位置而已哦

我们先看看作者的思路

我们看到暂停下来后,确实到了我们伪造的SEH程序处理的位置 
其实windbg比较难看 
我们用od吧^_^ 
下面是在系统异常处理的时候获取我们伪造的SEH程序的位置

我们看看执行到10019798时,栈的情况,发现esp+8的位置就是我们之前NEXT SEH的位置

这里写图片描述

不信看图

最后在Next SEH的指令跳过了垃圾代码,从而执行shellcode

就是下面这一串,作者为什么加

如果不加,程序的执行流程有点变化有点问题,从而触发不了异常

那么是不是一定要加到4500那么长呢,肯定不是啊

我在最后加50个A也行啊,10个A也行,甚至4个A也行

3个就不行了(但是3个的时候又不是那个问题,调试了一下发现程序的执行的流程,拼接的sql语句没问题,问题是最后拼接3个A的话,竟然没导致异常,从而不能触发SEH,而是执行到了函数最后的ret指令,返回到了0x90909090处了,导致最后不能正确执行shellcode) 
那怎么让后面接3个A也行呢,就是将payload中shellcode的前9-12个0x90替换为jmp esp的地址即可,不信看看下面是不是这样

但是为什么这样?,这是一个需要进一步探索的问题 
下面这个是最后加50个A的payload,buf的值

使用安全的snprintf,或者对字符串长度进行限制

由于使用sprintf格式化sql语句查询的时候对长度没有严格限制,导致缓冲区溢出,漏洞利用无论是覆盖返回地址还是覆盖SEH都有一些坑



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
强悍,学习了
2017-3-29 17:56
0
雪    币: 413
活跃值: (274)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
Dongoing 强悍,学习了
谢谢
2017-3-30 09:39
0
游客
登录 | 注册 方可回帖
返回
//