您好,登錄后才能下訂單哦!
原文鏈接: https://paper.seebug.org/1006/
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:
詳見: https://wiki.archlinux.org/index.php/Desktop_entries_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
KDE的桌面配置解析參考了XDG的方式,但是包含了KDE自己實現的功能;并且其實現與XDG官方定義的功能也有出入,正是此出入導致了漏洞。
在KDE文檔中有如下的話( https://userbase.kde.org/KDE_System_Administration/Configuration_Files#Shell_Expansion ):
Shell ExpansionSo 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 EntriesThe 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}
為了提供更加靈活的設置解析,KDE實現并支持了動態配置,而此處的${USER}尤其令人注意,該項取自環境變量,可以推測,此處與命令執行肯定有聯系。
每當KDE桌面系統要讀取圖標等桌面配置時,就會調用一次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}這樣的系統變量直接調用系統命令,這個做法是不太妥當的。
Summary:It is very unclear at this point what a valid use case for this featurewould possibly be. The old documentation only mentions $(hostname) asan example, which can be done with $HOSTNAME instead.
漏洞發現者在沒有通知官方的情況下直接公布了漏洞細節,這個做法比較有爭議。在發現漏洞時,首先將0day交給誰也是個問題,個人認為可以將漏洞提交給廠商,待其修復后再商議是否要公布。可能國際上的hacker思維與國內有著比較大的差異,在Dominik Penner的Twitter下竟然有不少的人支持他提前公布0day,他自己也解釋是想要在defcon開始之前提交自己的0day,這個做法以及眾人的反應值得去品味。
[1] 漏洞細節:
https://gist.github.com/zeropwn/630832df151029cb8f22d5b6b9efaefb
[2] 發現者推特:
https://twitter.com/zer0pwn/status/1158167374799020039
[3] 演示視頻:
https://www.youtube.com/watch?v=l4z7EOQQs84
[4] 官方修復細節:
https://mail.kde.org/pipermail/kde-announce/2019-August/000047.html
[5] 修復補丁:
https://cgit.kde.org/kconfig.git/commit/?id=5d3e71b1d2ecd2cb2f910036e614ffdfc895aa22
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。