本文将以作者在K7 Security防病毒软件中发现的漏洞为例,简要讨论对这些安全产品进行漏洞研究的方法。
目标选择
俗话说,越危险的地方往往越安全,让网络攻击者们绞尽脑汁的安全产品在部分人眼里也能成为拿来利用的工具,因为这些安全产品无论是在内核(作为驱动程序)中还是在用户环境(作为特权服务)中都是受信任且有权限的,这也意味着如果攻击者以此为突破口侵入用户电脑,就能执行恶意代码或其他恶意操作。
防病毒软件存在于操作系统的低权限空间中,用户通过UI组件执行一些高权限操作,例如启用禁用、添加目录或文件排除项、扫描文件查找恶意软件等,防病毒软件必须访问操作系统对象,并对其操作(例如读取文件、注册表项、内存等)后才能进行恶意软件检测,此外无论在何种情况下,防病毒软件都要能够执行权限操作,以将系统保持在受保护状态。
攻击面
如前所述,防病毒产品位于高低权限边界的两侧,如下图所示:
让我们看看如何理解这个图。用户通过用户界面执行权限操作,命令是以某种形式的进程间通信(IPC)传递给服务进程的,在安全检查通过的情况下,由服务进程代为执行。通过服务进程,用户能够从低权限空间间接地修改高权限对象。例如杀毒软件将其配置存储在HKEY_LOCAL_MACHINE hive注册表中,该hive位于高权限空间中,需要由高权限进程进行修改。
再举一个例子,用户可以通过用户界面扫描恶意软件(如果不允许防病毒软件也就失去了意义),这么一个简单的操作,可能会出什么问题呢?由于执行恶意软件扫描是服务进程的职责,所以界面要将信息传达给服务进程才能指定要扫描的文件。它必须与文件交互才能执行扫描,即它必须在磁盘上找到文件并读取其内容。如果在读取文件数据并对其进行了扫描的过程中发现了恶意软件,并且防病毒软件没有将文件锁定在磁盘上,则可能会将恶意软件替换为指向高特权目录中的文件的符号链接。
我们以notepad.exe为例具体说明,当K7杀毒软件扫描完成并且确定恶意软件后,服务进程可以删除恶意文件,但恶意软件被我们替换为了指向notepad.exe的链接,如果杀毒软件检测不到并拒绝符号链接,将毫无疑问地删除notepad.exe。这是“检查到使用时间”(Time of Check to Time of Use,TOCTOU)竞态条件错误的示例。同样,由于服务过程充当代理,来自低权限的用户能够间接修改高权限对象。
漏洞利用
此漏洞允许低权限用户通过防病毒软件设置修改(几乎)任意注册表数据,但权限较低的用户(非管理员)不能对防病毒软件设置做更改。
绕过管理检查
为了缩小这种管理检查的执行方式,可以在再次访问设置页面时使用procmon来标识操作系统活动。当当前用户与正在记录的操作系统进行交互时,这将触发防病毒软件重新检查当前用户的管理状态。当然,由于我们的权限较低,而procmon要求的权限较高,因此在实际环境中不可行。但是由于我们控制了测试环境,因此可以在有权访问管理员帐户的情况下允许procmon运行,将promon设置为由进程K7TSMain捕获用户界面进程执行的活动。
当procmon开始记录时,尝试访问设置页面将触发procmon立即显示结果:
可以看出,防病毒软件将管理检查存储在AdminNonAdminIsValid中的注册表中,即“Event Properties ”,该值将显示0表示禁止非管理员用户。
既然已经知道在哪里执行检查,下一步就是绕过它。procmon显示用户指示的进程在低权限空间中运行,而“integrity”为“medium”表示我们拥有该进程。如果它不受保护,我们只需钩住RegQueryValue函数并修改返回值即可。
使用x32dbg连接到K7TSMain.exe进程的尝试是可行的,当我们再次访问设置页面时,RegQueryValueExA上的断点已被设置。
单击设置页面时,x32dbg捕获断点。要查询的值名称为ProductType,但我们需要AdminNonAdminIsValid,继续操作将触发下一个断点:
现在我们可以看到AdminNonAdminIsValid。修改返回值能让函数一直运行直到返回,但调用函数看起来像RegQueryValueExA的封装器:
因此再次继续直到返回显示执行检查的函数:
这里有一个对值1的检查,但是注册表数据当前返回的值是0。这决定了这个函数的返回值,所以我们可以改变[esp+4]或改变返回值来绕过检查:
拦截进程间通信
在Windows中有多种进程间通信方法可用,如邮件槽、文件映射、COM和命名管道。我们必须弄清楚在产品中实现了什么才能分析协议。一种简单的方法是使用API Monitor来记录进程发出的选择函数调用,我们可以看到K7 杀毒软件对命名管道函数的引用:
注意,调用模块是K7AVOptn.dll,而不是k7tsm .exe。如果我们看一下通过TransactNamedPipe传输的数据,可以看到一些有趣的信息:
首先,它看起来像是扩展名列表(.ocx,.exe,.com),用|分隔,其中有些具有通配符匹配。这可能是扫描恶意软件的扩展列表。如果我们查看防病毒软件存储配置的注册表,则可以在RTFileScanner项的ScanExtensions值下看到类似的内容:
继续往下看,其中一个包含一些非常有趣的数据:
看起来杀毒软件似乎是通过指定(特权)注册表项和它们的值的完整键路径来应用值。下一步显然是查看更改其中一个键及其值是否可以使用。这可以通过在x32dbg中的TransactNamedPipe函数上进行断点来完成:
在这里,找到第二个参数中的输入缓冲区,并修改数据以在HKEY_LOCAL_MACHINE hive中添加或更改键,如下所示:
如果可以更改此注册表项的值,则将强制高特权进程加载AppInit_DLL中列出的DLL,即我们控制的DLL。要启用此功能,还必须将LoadAppInit_DLLs值设置为1(默认情况下为0)。结果:
触发有效载荷
你可能已经注意到,注册表项在Wow6432Node内,它是注册表的32位副本(这款产品是32位的),因此Windows将自动重定向注册表更改。在64位Windows中,进程通常是64位的,因此通过appinit_dll加载有效负载DLL的可能性不大。一种可靠的方法是利用杀毒软件的特权组件。最简单的方法就是重新启动计算机,重新加载所有防病毒进程,这种方法并是很实用。在UI上单击,会显示更新函数在NT AUTHORITY\SYSTEM用户下运行K7TSHlpr.exe:
由于它是32位应用程序,因此Windows会将AppInit_DLLs DLL加载到进程空间中。
使用system(“cmd”)作为有效载荷,将通过UI0Detect服务在NT AUTHORITY\ system帐户上下文中提示用户一个交互式会话:
选择查看消息将显示以下内容:
接下来我们就获得了root权限。自动利用过程请详见GitHub。
本文翻译自:https://0x00sec.org/t/anti-virus-exploitation-local-privilege-escalation-in-k7-security-cve-2019-16897/17655/1如若转载,请注明原文地址: https://www.4hou.com/vulnerable/21833.html