简介

尽管进程都设置了环境变量,它们往往被用户,开发者甚至是系统本身所忽略。对于一个像样的系统来说,环境变量就是其最根本,这里的系统包括但不仅限于Unix (Linux, BSD), Windows以及OS X。在微软操作系统的世界中,环境变量在其第一个版本DOS时期就已经出现,且一直沿用至今。环境变量得到重视还得从2014年9月份爆发的ShellShock漏洞说起。

关于ShellShock可参考

ShellShock(破壳)漏洞余威不减:新ShellShock蠕虫扫描大量脆弱主机展开攻击

SEED实验系列:ShellShock攻击实验

破壳(ShellShock)漏洞样本分析报告

该漏洞在Unxi系统中通过环境变量注入,进而执行命令。

进程的环境

简言之,环境就是一个可用于进程或者用户读取写入的变量的集合。变量可由用户,程序或者是系统进行设置,用于提升运行进程时的灵活性。比如文件系统中的路径,用户名和控制执行流程的标志。

Windows下的环境

Windows下的环境变量可以使用DOS命令设置进行读取和写入:读取:

set <variable> 

写入:

set <variable>=<value> 

在命令行单独键入“set”会显示所有当前可用的变量。注意本文中说描述的“当前可用”意思是非常相似的进程可用 —— 用户运行命令解析器这里也可以用编程的方式调用API函数代替set命令:

Kernel32!SetEnvironmentVariable 

产生的结果都是一样的。只有在当前进程及其子进程中改变这些值才会产生效果。只要条件允许,系统将替换所有%VARIABLE%的值。这个替换过程被称作“扩展”(expansion)。例如我们在命令行下键入:

echo %username% 

输出的结果应该为扩展之后变量的值,与键入用户名的结果是一样的。

环境波动

正如前面所说的,环境变量已经通过一个进程设置。Windows称这种类型的环境为“不稳定的环境”。当进程正在运行时它保持该变量,当结束进程不会留下任何痕迹。在Windows中还有另外一种类型的环境变量集合,其覆盖整个系统范围,在启动过程依然持续。管理员用户可以在系统属性页面下进行设置,通过使用setx命令影响所有用户,或者直接通过设置注册表值:

HKEY_CURRENT_USER\Environment 

注册表值中的扩展

Windows注册表支持REG_EXPAND_SZ类型的值,一个字符串类型的注册表值,其命令读取进程以扩展其内的所有变量,扩展进程在程序使用该值之前执行。这个过程保证了需要依赖注册表中值的程序能正常运行,开发者不必再跟踪环境变量值。

Windows程序下的扩展

通过注册表进行搜索,很显然其中使用了一个扩展过的路径引用了许多程序,函数库,对象。即反过来依赖于环境。最常见的变量为“SystemRoot”,在正常情况下,其指向Windows安装路径,一般为“C:\Windows”。

简单总结

我们拥有可用于Windows进程的环境变量,且能自动扩展以及可以由用户设置。通过这些路径可以引用部分Windows函数库。以下为基于环境变量扩展的攻击场景

场景1:”DLL注入”

假设:

如果通过一个扩展了的环境字符串加载DLL文件,攻击者通过改变环境变量可获得一个进程来加载该文件,但需在创建之前提供给这个进程。

换句话说,任何一个在攻击者控制下的进程,攻击者都可以对它进行环境设置。

可能性:

加载的DLL文件,不管是被复制,修改,完全替换,对于加载它的进程来说权限都是一样的。“注射”一个DLL到不同的进程中而不使用任何注射技术。

应用:

最简单粗暴的方法便是使用命令行。大概流程如下:

  • 在C:\Wherever中创建C:\Windows副本
  • 设置环境变量set SystemRoot=C:\Wherever
  • 结束并重启explorer.exe进程taskkill /F /IM explorer.exe   C:\Windows\explorer.exe
  • 资源管理器将会启动并从攻击者目录加载相当多的DLL。攻击者可以替换它们并改变执行流程。

场景2:远程加载DLL

除了需要添加到等式这个因素以外,基本与上一个场景一样。在Windows,API在请求一个文件或是目录路径时通常会接收一个指向远程机器的UNC路径。这个过程将会使用SMB协议尝试访问指定的路径。

假设:

如果攻击者将%SystemRoot%扩充到一个UNC网络路径,Windows将使用SMB协议尝试从远程路径加载该图片

可能性:

从一个被攻击者控制的服务器上远程加载DLL,同时也泄漏了受害者机器的IP地址。

之后将尝试使用已登录用户的凭证对远程服务器进行身份验证,为攻击者提供更多的参考信息。

应用:

与场景1类似,但是需要使用远程路径。例如我们可以使用本地机器上共享的C盘:

set SystemRoot=\\127.0.0.1\c$\Windows 

场景3:启动时加载DLL

就目前而言,此攻击还算不上持久性攻击。这也意味着重启系统,或者是重启进程,我们之前的努力都白费了。

假设:

攻击者可以设置永久性(non-volatile)环境变量,将影响到系统控制流程而不论是否进行重启。

可能性:

在操作系统启动期间或在满足特定条件时远程加载DLL

应用:

与场景1类似,但是攻击者可以使用setx命令来代替set命令:

setx SystemRoot C:\ Wherever 

重启系统,开始从攻击者的目录下将DLL加载到各种进程中。

场景4:提升权限 #1

到目前为止,我们讨论了攻击者控制下可能对其他进程有影响的环境变量。 这些其他进程都属于首先执行命令的用户,并且以中等完整性级别运行。

如果用户被允许以较高权限执行进程,由微软的用户帐户控制机制所定义。该进程将作为svchost.exe的子进程在用户控制以外的预设环境下被创建。

问题来了,创建的子进程将得到当前用户环境的一个副本。

绕过Windows UAC机制到底能不能算是特权提升,这就看读者的理解了。虽然微软不认为这是一个漏洞,但通常又会采取行动来解决这些问题。

基于道德要求,我们已经向微软报告了此问题,并且在发文前收到“非漏洞”的响应。

假设:

基于默认配置,在用户不知情的情况下,有特定的进程被授予高完整性(或特权提升)。一般来说,有一个由微软选定的允许静默运行的可执行文件集合。

这份清单是应该是在系统安全性和用户友好体验之间提出的一个合理折中方案。 攻击者可以利用这种妥协,使操作系统在加载不受信任的DLL时运行这些特殊的可执行文件,从而绕过安全机制运行具有提升特权的DLL。

可能性:

在没有用户同意或对用户通知的情况下提升权限,这在默认配置下是可能发生的。管理员可以选择通过重写默认UAC设置来提高安全性,从而使Windows显示请求此权限的所有进程的提示。

然而,攻击者仍然可以放置恶意的DLL文件,之后在用户的同意下进行加载。这种套路可以使用许多合法进程来设置,Windows任务管理器(taskmgr.exe)就是一个例子。

应用:

  • 按照场景3中所述设置环境。
  • 以管理员身份运行自动提权进程。在本例中,我们使用lpksetup.exe:

    ShellExecute(0,”runas”,”C:\\Windows\\System32\\lpksetup.exe”,NULL,NULL,0); 

情景5:提升权限#2

在前面的例子中,我们已经演示了使用ShellExecute来运行提权程序, Windows还提供COM对象供用户加载。

COM组件的概念及其内部工作原理不在本文探讨范围之内,对于我们而言,其与使用不同机制加载的常规进程,可执行文件或函数库没有太大的不同。

假设:

如果有一个COM对象允许在用户不知情的情况下以更高权限加载 – 攻击者可以使用该机制,来替代执行命令以及创建自己的进程。

可能性:

不产生新进程的前提下,进行特权提升。

应用:

本例中,选择的对象是由Windows提供的允许更改防火墙设置的COM接口。

该对象的CLSID为{752438CB-E941-433F-BCB4-8B7D2329F0C8}

1.与场景4/1相同

2.

CoInitialize();

CoCreateInstance() with the given CLSID, returning a pointer to an IFwlCpl interface.

IFwlCpl->LaunchAdvancedUI() 

这会加载mmc.exe,在Windows的管理控制台中的svchost.exe子进程得到特权提升,与此同时从攻击者的C:\Wherever加载一个DLL

结论

Windows中的环境变量扩展允许攻击者在攻击之前收集系统的相关信息,并最终通过运行单个用户级命令或者更改一个注册表键值来对系统进行完全和持久的控制。

该向量还允许攻击者以DLL形式的代码加载到其他合法软件的进程或操作系统本身,并将其行为伪装为目标进程的操作,而不必使用代码注入技术或使用内存处理。以管理员身份运行的第三方服务也可能受到此攻击,允许普通用户提升其在系统内的权限。

概念验证可以看看BreakingMalware提供的Python脚本

传送门

*参考来源:breakingmalware,FB小编鸢尾编译