作者: HACHp1@知道创宇404实验室 日期: 2019/08/08
KDE Frameworks是一套由KDE社群所编写的库及软件框架,是KDE Plasma 5及KDE Applications 5的基础,并使用GNU通用公共许可证进行发布。其中所包含的多个独立框架提供了各种常用的功能,包括了硬件集成、文件格式支持、控件、绘图功能、拼写检查等。KDE框架目前被几个Linux发行版所采用,包括了Kubuntu、OpenMandriva、openSUSE和OpenMandriva。
2019年7月28日Dominik Penner(@zer0pwn)发现了KDE framework版本<=5.60.0时存在命令执行漏洞。
2019年8月5日Dominik Penner在Twitter上披露了该漏洞,而此时该漏洞还是0day漏洞。此漏洞由KDesktopFile类处理.desktop或.directory文件的方式引起。如果受害者下载了恶意构造的.desktop或.directory文件,恶意文件中注入的bash代码就会被执行。
2019年8月8日,KDE社区终于在发布的更新中修复了该漏洞;在此之前的三天内,此漏洞是没有官方补丁的。

PoC有多种形式,此处使用三种方式进行复现,第1、2种为验证性复现,第3种为接近真实情况下攻击者可能使用的攻击方式。
1.PoC1: 创建一个文件名为”payload.desktop”的文件:

在文件中写入payload:

保存后打开文件管理器,写入的payload被执行:

文件内容如下:

2.PoC2:
创建一个文件名为” .directory”的文件:

使用vi写入内容(此处有坑,KDE的vi输入backspace键会出现奇怪的反应,很不好用):

写入payload:

保存后打开文件管理器,payload被成功执行:

3.PoC3: 攻击者在本机启动NC监听:

攻击者将payload文件打包挂载至Web服务器中,诱导受害者下载:

受害者解压文件:

解压后,payload会被执行,攻击者接收到反连的Shell:

.directory或.desktop文件记录该目录下的解析配置。KDE的桌面配置解析参考了XDG的方式,但是包含了KDE自己实现的功能;并且其实现与XDG官方定义的功能也有出入,正是此出入导致了漏洞。
在KDE文档中有如下的话(https://userbase.kde.org/KDE_System_Administration/Configuration_Files#Shell_Expansion):
Shell Expansion
So called Shell Expansion can be used to provide more dynamic default values. With shell expansion the value of a configuration key can be constructed from the value of an environment variable.
To enable shell expansion for a configuration entry, the key must be followed by [$e]. Normally the expanded form is written into the users configuration file after first use. To prevent that, it is recommend to lock the configuration entry down by using [$ie].
Example: Dynamic Entries
The value for the "Email" entry is determined by filling in the values of the $USER and $HOST environment variables. When joe is logged in on joes_host this will result in a value equal to "joe@joes_host". The setting is not locked down.
[Mail Settings]
Email[$e]=${USER}@${HOST}${USER}尤其令人注意,该项取自环境变量,可以推测,此处与命令执行肯定有联系。readEntry函数;从Dominik Penner给出的漏洞细节中,可以看到追踪代码的过程。整个漏洞的执行过程如下:
首先,创建恶意文件:payload.desktop
[Desktop Entry]
Icon[$e]=$(echo hello>~/POC.txt)进入文件管理器,此时系统会对.desktop文件进行解析;进入解析Icon的流程,根据文档中的说明,参数中带有[$e]时会调用shell动态解析命令:
kdesktopfile.cpp:
QString KDesktopFile::readIcon() const
{
Q_D(const KDesktopFile);
return d->desktopGroup.readEntry("Icon", QString());
}跟进,发现调用了KConfigPrivate::expandString(aValue):
kconfiggroup.cpp:
QString KConfigGroup::readEntry(const char *key, const QString &aDefault) const
{
Q_ASSERT_X(isValid(), "KConfigGroup::readEntry", "accessing an invalid group");
bool expand = false;
// read value from the entry map
QString aValue = config()->d_func()->lookupData(d->fullName(), key, KEntryMap::SearchLocalized,
&expand);
if (aValue.isNull()) {
aValue = aDefault;
}
if (expand) {
return KConfigPrivate::expandString(aValue);
}
return aValue;
}再跟进,结合之前对KDE官方文档的解读,此处是对动态命令的解析过程,程序会把字符串中第一个出现的$(与第一个出现的)之间的部分截取出来,作为命令,然后调用popen执行:
kconfig.cpp
QString KConfigPrivate::expandString(const QString &value)
{
QString aValue = value;
// check for environment variables and make necessary translations
int nDollarPos = aValue.indexOf(QLatin1Char('$'));
while (nDollarPos != -1 && nDollarPos + 1 < aValue.length()) {
// there is at least one $
if (aValue[nDollarPos + 1] == QLatin1Char('(')) {
int nEndPos = nDollarPos + 1;
// the next character is not $
while ((nEndPos <= aValue.length()) && (aValue[nEndPos] != QLatin1Char(')'))) {
nEndPos++;
}
nEndPos++;
QString cmd = aValue.mid(nDollarPos + 2, nEndPos - nDollarPos - 3);
QString result;
// FIXME: wince does not have pipes
#ifndef _WIN32_WCE
FILE *fs = popen(QFile::encodeName(cmd).data(), "r");
if (fs) {
QTextStream ts(fs, QIODevice::ReadOnly);
result = ts.readAll().trimmed();
pclose(fs);
}
#endif自此,漏洞利用过程中的代码执行流程分析完毕;可以看到KDE在解析桌面设置时,以直接使用执行系统命令获取返回值的方式动态获得操作系统的一些参数值;为了获得诸如${USER}这样的系统变量直接调用系统命令,这个做法是不太妥当的。
[e]属性的功能:
Summary:
It is very unclear at this point what a valid use case for this feature
would possibly be. The old documentation only mentions $(hostname) as
an example, which can be done with $HOSTNAME instead.${USER}变量的值而已。在命令执行上有些许杀鸡用牛刀的感觉。本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1006/
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。