作者:Ethan@知道創宇404實驗室
時間:2019年8月21日
英文版本: http://www.bjnorthway.com/1020/

漏洞概述

Webmin是一個基于Web的界面,用于Unix的系統管理。使用任何支持表和表單的瀏覽器,可以設置用戶帳戶,Apache,DNS,文件共享等。

2019年8月10日,在pentest上發布了Webmin CVE-2019-15107遠程代碼執行漏洞。

該漏洞由于password_change.cgi文件在重置密碼功能中存在一個代碼執行漏洞,該漏洞允許惡意第三方在缺少輸入驗證的情況下而執行惡意代碼,后經知道創宇404實驗室發現,該漏洞的存在實則是sourceforge上某些版本的安裝包和源碼被植入了后門導致的。

漏洞復現

官方給的漏洞影響版本為Webmin<=1.920,于是當晚我使用了Webmin 1.920的版本進行的測試。

在1.920版本中漏洞的觸發需要開啟密碼重置功能,“Webmin-> Webmin Configuration-> Authentication”下把允許用戶使用舊密碼設置新密碼的選項給選上,并保存!

Webmin重啟后,查看webmin的配置文件,可以發現passwd_mode的值已經從0變為了2

然后在密碼修改處執行抓包,然后在old參數上加上|ifconfig

發現成功執行了命令!

想著換個用戶試試吧,23333,結果出現下面的情況!

為什么換個root用戶就不行了,這里的root用戶是Linux系統的root用戶,我登陸使用的就是這個用戶。。

我再隨便使用個用戶試試?

經測試用戶為空也可以,用戶為webmin用戶也可以,其創建方式如下:

其中root是Linux系統賬戶,認證方式為Unix authenticaton,ethan賬戶是自己創建的webmin 賬戶,認證方式無。

這樣問題就來了,為什么會有這樣的區別?這就不得不開啟一個perl菜鳥審計perl代碼的道路,感謝@Longofo的幫助!

漏洞點分析

首先在password_change.cgi的第12行,我們可以得知想觸發漏洞必須passwd_mode=2,也就必須開啟密碼重置功能。否則就會顯示Password changing is not enabled!

$miniserv{'passwd_mode'} == 2 || die "Password changing is not enabled!";

接著分析password_change.cgi的12行到31行,如下:

# Is this a Webmin user?
if (&foreign_check("acl")) {
    &foreign_require("acl", "acl-lib.pl");
    ($wuser) = grep { $_->{'name'} eq $in{'user'} } &acl::list_users();
    if ($wuser->{'pass'} eq 'x') {
        # A Webmin user, but using Unix authentication
        $wuser = undef;
        }
    elsif ($wuser->{'pass'} eq '*LK*' ||
           $wuser->{'pass'} =~ /^\!/) {
        &pass_error("Webmin users with locked accounts cannot change ".
                    "their passwords!");
        }
    }

從注釋看,這段代碼主要判斷是不是webmin user。并且請求了一個acl-lib.pl,看名字就知道是功能性文件,功能應該就是訪問控制之類的。在第21~22行的作用是獲取請求中的user,并且判斷是否屬于Webmin user!但是這個x讓我不知所然,為什么把$wuserx這個值比較呢?。于是我把acl::list_users()的值嘗試著打印出來!

返回如下數據:

通過返回的數據,我們可以知道root用戶并且使用Unix authenticaton設置(默認)的pass的值為x,而我自己創建沒有選擇認證方式的用戶,pass的值為一串加密的字符串。也就是說如果我們傳進的user是系統用戶登陸且認證方式為Unix authenticaton的賬戶時,$wuser 的值會被賦值為undef

在if條件語句外,我們把$wuser的值給打印下

if條件語句里面把$wuser 的值打印出來印證一下

而在perl語言中undef是變量未初始化時的默認值,一般情況下,將其當作空或0就好了,在需要作為數值的時候,undef代表的就是0,需要字符串的時候,undef就是空字符串。這里應該是對系統用戶密碼的修改和其它用戶進行了區分。

由我們上面的分析可知,在用戶為root的情況下$wuser的值為undef

if ($wuser) {
    # Update Webmin user's password
    $enc = &acl::encrypt_password($in{'old'}, $wuser->{'pass'});
    $enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'},qx/$in{'old'}/);
    $perr = &acl::check_password_restrictions($in{'user'}, $in{'new1'});
    $perr && &pass_error(&text('password_enewpass', $perr));
    $wuser->{'pass'} = &acl::encrypt_password($in{'new1'});
    $wuser->{'temppass'} = 0;
    &acl::modify_user($wuser->{'name'}, $wuser);
    &reload_miniserv();
    }

也就是說如果傳入的user為系統用戶無法進入第37行的if條件語句,從而無法執行第40行qx/...../的命令執行代碼。當我們傳入的用戶為空或者不存在時,$wuser的值為{},但是會進入if條件語句

關于命令執行是否需要|,我們通過分析第207行到217行的pass_error可知,不需要|,亦可進行命令執行回顯。

sub pass_error
{
&header(undef, undef, undef, undef, 1, 1);
print &ui_hr();

print "<center><h3>",$text{'password_err'}," : ",@_,"</h3></center>\n";

print &ui_hr();
&footer();
exit;
}

另有蹊蹺

繼續探究的原因是覺得qx/..../的蹊蹺,因為官方給的修補是直接刪除了qx/..../如圖:

是不是越看越感覺這個漏洞是被"加上去的",在Github上下載的1.920版本并無qx/..../,啊咧咧,一頭霧水啊。。。通過git log -p命令并未發現與qx/..../相關的記錄。而在sourceforge上下載的源碼和安裝包卻有漏洞代碼。后門?

2012年在網站SourceForge韓國CDN節點疑似被入侵,熱門下載資源phpMyadmin被植入后門。在Seebug上有收錄:https://www.seebug.org/vuldb/ssvid-60402

在Github上找到另外一些訊息,https://github.com/webmin/webmin/issues/947

在1.890版本中,同樣存在漏洞代碼,這一次簡直是赤裸裸的后門。。。

我從sourceforge下載1.890版本,進行了探究。漏洞點如下:

通過分析我們可以得知,這個漏洞點的觸發只需要傳一個expired參數執行命令即可。不需要之前的passwd_mode=2的必要條件。

也就是說,在1.890版本中漏洞的觸發不需要任何依賴。是代碼疏漏還是惡意后門?

驗證想法

這里我們通過更直觀的方式來驗證,通過把Github和sourceforge的源碼下載下來,然后進行diff

Webmin 1.920版本的password_change.cgi文件

Webmin 1.890版本的password_change.cgi文件

通過Github和sourceforge的文件對比,我們可以發現,sourceforge的代碼明顯存在問題,極有可能是被植入了后門。

后經驗證確認,只有sourceforge的代碼和安裝包存在后門漏洞。各版本的情況如下:

其中以1.890版本的后門漏洞觸發依賴最小,危害最大!猜測這應該是最初始的后門,后來植入后門的時候沒有考慮到代碼邏輯的問題,導致漏洞觸發受到了限制!

漏洞修補

  • 直接升級到1.930版本

  • 臨時修補方案,可以定位漏洞代碼所在的行,然后剔除,下圖為1.920版本:

下圖為1.890版本:

將所示標注替換為$miniserv{'passwd_mode'} == 2 || die "Password changing is not enabled!";即可,替換的代碼為Github無后門代碼。

事后感想

本來正常的一次應急沒想到,發展成了對后門文件的探究。果然是生活不息,搞事不止啊!感謝@Longofo,幫忙測試大量文件和代碼。黑哥也在medium上發表了The stories behind Webmin CVE-2019–15107這篇文章來描述后門發現的過程:https://medium.com/@80vul/the-stories-behind-cve-2012-5159-198eaad2449d


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1019/