统信安全应急响应中心第一时间发布了漏洞修复方案
polkit
里的pkexec
程序,而polkit
是桌面环境里广泛使用的DBus
进程间通讯机制所依赖的安全模块之一,因此这个漏洞的波及面确实还是挺大的。不过在桌面团队修洞的过程中,我们发现在缺省(未开启开发者模式)情况下,统信UOS是不受主流攻击方式所影响的。pkexec
为suid
程序
当argc
(命令行参数个数变量)为0时,pkexec
会读取argv[1]
变量,而由于Linux进程的内存布局中环境变量是紧接着命令行参数的,因此实际上会读取到第一个环境变量。
读取到argv[1]
之后,若其不是以/
开头的(即不是绝对路径),则pkexec
会将其理解为相对路径,继而会在环境变量中查找PATH
变量,将其转换为实际路径。
若PATH
环境变量包含一个攻击者可控的路径,则pkexec
转换后的实际路径将会是这个攻击者可控的路径下的一个子目录,则显然此实际路径也是攻击者可控的。
pkexec
会对argv[1]
赋值,将其修改为上述得到的实际路径,但是我们知道argv[1]
此时实际上指向的是pkexec
的第一个环境变量,也就是说,pkexec
将自己的第一个环境变量修改为这个实际路径了。
pkexec
会在程序运行过程中调用g_printerr
函数,这个函数会在运行的时候按需载入GCONV_PATH
环境变量指向的路径下的gconv-modules
文件中写明的外部动态链接库(so),并运行其中的初始化函数gconv_init
。
这样,攻击者只需要:
gconv-modules
文件,并将文件内容设置为指向某个so
文件。so
文件中实现gconv_init
函数,此函数主要就是生成一个root shell(由于pkexec默认开启SUID),而在so库的此函数中,设置当前进程用户的uid为0,即可提权到root用户。pkexec
,而且在调用的时候通过命令行参数设置使得pkexec
得到的argc
为0,将环境变量中的第一个设置为非/
开头的一个相对路径,将环境变量中的PATH
变量的值设置为GCONV_PATH=
开头的字符串,使得对应的路径指向上述存储gconv-modules
文件的路径。就可以最终获得一个root shell了。
其中第一步与第三步可以有多种方法实现,虽然常见的PoC给出的是可执行程序,但是也可以通过脚本施行攻击,但是第二步需要生成一个so文件,就是在这里,新生成的so文件因为没有有效证书签名,因此在缺省的统信UOS上无法被载入执行。
当然,除了使用gconv
的外挂插件之外,从理论上来说,也可以思考如何利用环境变量从pkexec
的外部载入程序,但是这个实施难度显然就更高了。