1.1.本地復現
當時發現url中有一個引數file=/home/task.php,靈機一動,把/home/task.php替換成了../../../../../../etc/passwd
接著傳送帶有php程式碼的請求,先phpinfo試一試。
接著就是包含日誌了,感覺馬上就要起飛了,結果很突然,no such file了,又換了幾個路徑,還是這樣。
沒辦法只是試試包含一下配置檔案,結果….一樣。
這可咋辦,眼瞅著就要getshell了,沒路徑啊,突然想到還有一個ssh log可以嘗試包含一下,立刻來了精神頭,噼裡啪啦一頓敲,食指放在Enter鍵上,猶豫不決,豁出去了!只見我眼睛一閉,重重按下回車,當我慢慢睜開眼時,欣喜若狂,終於沒有no such file 了
接下來就很簡單了直接ssh連線:
ssh '<?=eval($_REQUEST[1])?>'@remotehost
2.檔案包含小知識
2.1.包含函式
1、PHP共有4個與檔案包含相關的函式:
include
require
include_once
require_once
2、Include與include_once的區別:
(1)Include:會將指定的檔案載入並執行裡面的程式;重複引用的情況下載入多次。
例如:
這裡include兩次1.php檔案,所以就會包含1.php兩次。
(2)Include_once:會將指定的檔案載入並執行裡面的程式;此行為和include語句類似,唯一區別是如果該檔案中已經被包含過,則不會再次包含。
例如:
這裡include_once了兩次1.php檔案,但只會包含1.php一次。
(3)require和requireonce的用途與上面兩個一樣,但區別就是require和requireonce會載入頁面最開始執行。Include和include_once會按程式碼順序執行。
2.2.支援的協議和封裝協議
File:// ——訪問本地檔案系統
http(s):// ——訪問HTTP(s)網址
ftp:// ——訪問FTP(s) URLs
php:// ——訪問各個輸入/輸出流(I/O streams)
zlib:// ——壓縮流
data:// ——資料(RFC 2397)
glob:// ——查詢匹配的檔案路徑模式
phar:// ——PHP歸檔
ssh2:// ——Secure Shell 2
rar:// ——RAR
ogg:// ——音訊流
expect:// ——處理互動式的流
2.3.常用偽協議講解:
1. file://
(1)這個協議可以展現本地檔案系統,預設目錄是當前的工作目錄。
(2)例如:file:///etc/passwd、file://key.txt
2. php://
(1) php://input是個可以訪問請求的原始資料的只讀流,可以訪問請求的原始資料的只讀流,將post請求中的資料作為php程式碼執行。
(2) php://filter是一種元封裝器,設計用於資料流開啟時的篩選過濾應用。
3、phar://
(1)phar://資料流包裝器自PHP5.3.0起開始有效
(2)例如:phar://E:/phpstudy/www/1.zip/phpinfo.txt
phar://1.zip/phpinfo.txt
2.4.偽協議利用方式小總結:
3.1.Getshell之session
條件:session檔案路徑已知,且session檔案中內容部分可控。
獲取session檔案路徑:
1、session檔案的儲存路徑可以在phpinfo的session.save_path看到。
2、預設路徑:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session的檔名格式為sess_[phpsessid]。而phpsessid在傳送的請求的cookie欄位中可以看到。
利用:
1.要包含並利用的話,需要能控制部分sesssion檔案的內容。可以先包含進session檔案,觀察裡面的內容,然後根據裡面的欄位來發現可控的變數,從而利用變數來寫入payload,並之後再次包含從而執行php程式碼。
2.例如現在有一個session.php可控使用者會話資訊值:
3.可以看到這個session.php檔案中的使用者會話資訊username的值是使用者可控制的,那我們就可以傳入惡意程式碼進行攻擊利用。
4.將惡意程式碼傳入以後,接下來就要利用檔案包含漏洞去包含這個惡意程式碼。
5.從返回結果來看,我們的payload和惡意程式碼已經正常解析和執行。
3.2.Getshell之日誌
3.2.1.訪問日誌
條件:需要知道伺服器日誌的儲存路徑,且日誌檔案可讀。
日誌儲存預設路徑:
1.apache+Linux日誌預設路徑:/etc/httpd/logs/accesslog或/var/log/httpd/accesslog
2.apache+win2003日誌預設路徑:D:\xampp\apache\logs\access.log、D:\xampp\apache\logs\error.log
3.IIS6.0+win2003預設日誌檔案:C:\WINDOWS\system32\Logfiles
4.IIS7.0+win2003 預設日誌檔案:%SystemDrive%\inetpub\logs\LogFiles
5.nginx 日誌檔案:日誌檔案在使用者安裝目錄logs目錄下,假設安裝路徑為/usr/local/nginx,那日誌目錄就是在/usr/local/nginx/logs下面
利用:
1.多數情況,web伺服器會將請求寫入到日誌檔案中,比如說apache。在使用者發起請求時,會將請求寫入access.log,當發生錯誤時將錯誤寫入error.log。預設情況下,日誌儲存路徑在/etc/httpd/logs/下。
2.但如果是直接發起請求,會導致一些符號被編碼使得包含無法正確解析。可以使用burp截包後修改。
3.正常的php程式碼已經寫入了 /etc/httpd/logs/access.log。然後包含即可執行程式碼。
4.但有的時候,log的存放地址會被更改。這個時候可以通過讀取相應的配置檔案後,再進行包含。
中介軟體預設配置檔案存放路徑:
1.apache+linux 預設配置檔案
/etc/httpd/conf/httpd.conf或/etc/init.d/httpd
2. IIS6.0+win2003 配置檔案
C:/Windows/system32/inetsrv/metabase.xml
3. IIS7.0+WIN 配置檔案
C:\Windows\System32\inetsrv\config\applicationHost.config
3.2.2.SSH log
條件:需要知道ssh-log的位置,且可讀。
ssh日誌預設路徑:
1./var/log/auth.log
2./var/log/secure
利用:
1.用ssh連線:
ssh '<?php phpinfo(); ?>'@remotehost
之後會提示輸入密碼,隨便輸入就可以。
2.然後利用檔案包含,包含日誌檔案:
3.3.Getshell之environ
條件:
php以cgi方式執行,這樣environ才會保持UA頭。
environ檔案儲存位置已知,且有許可權訪問environ檔案。
environ檔案預設位置:
proc/self/environ
利用:
1.proc/self/environ中會儲存user-agent頭。如果在user-agent中插入php程式碼,則php程式碼會被寫入到environ中。之後再包含它,即可。
2.例如我們現在訪問一個網站,使用burpsuite抓包,將惡意程式碼插入到user-agent中。
3.利用檔案包含漏洞去包含proc/self/environ,成功執行php程式碼。
3.4.Getshell之利用phpinfo
條件:存在phpinfo頁面並且存在檔案包含漏洞
原理:
當我們給PHP傳送POST資料包時,如果資料包裡包含檔案區塊,PHP就會將檔案儲存成一個臨時檔案,路徑通常為:/tmp/php[6個隨機字元],這個臨時檔案,在請求結束後就會被刪除。
因為phpinfo頁面會將請求上下文中的所有變數打出來,所以我們如果向phpinfo頁面傳送包含檔案區塊的資料包,就可以在返回包裡找到臨時檔名,也就是$_FILES變數中的內容。
利用:
首先我們使用vulhub的指令碼(https://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py),他可以實現包含臨時檔案,而這個臨時檔案的內容是:\<?php fileputcontents('/tmp/p','\<?=eval(\$_REQUEST[1])?>‘)?>。成功包含這個檔案後就會生成新的檔案/tmp/p,這個檔案就會永久的留在目標機器上。
寫入成功以後,我們利用檔案包含來執行任意命令。
原理:
那麼為啥vulhub的指令碼是如何做到在臨時指令碼檔案刪除前去包含的呢,其實就是用到了條件競爭,具體流程大致如下:
首先傳送包含webshell的資料包給phpinfo頁面,並用大量的垃圾資料將header和get等位置填滿。
因phpinfo頁面會將所有資料列印出來,第一個步驟中的垃圾資料就會將phpinfo頁面撐的非常大。而php預設輸出緩衝區大小為4096,也可以理解為php每次返回4096個位元組給socket連線。
所以,這裡直接操作原生socket,每次讀取4096個位元組。只要我們讀取到位元組裡包含臨時檔名,就立刻傳送檔案包含漏洞利用的資料包。因為第一個資料包的socket連線沒有結束,所以臨時檔案還沒有刪除,我們就可以檔案包含成功。
3.5.Getshell之上傳檔案
條件:有上傳點,知道上傳上去的檔名和存放目錄。
利用:
- 這裡用一個靶場簡單演示一下,找個檔案上傳點,上傳一個帶有php惡意程式碼的圖片。
- 我們現在已知檔名稱和路徑,可以利用檔案包含漏洞去包含這個圖片,就可以成功執行php程式碼了。
1、在很多場景中都需要去包含web目錄之外的檔案,如果php配置了open_basedir,則會包含失敗。
2、對可以包含的檔案進行限制,可以採用白名單的方式,或設定可以包含的目錄。
3、對危險字元進行過濾。
4、儘量不使用動態包含等等
本作品採用《CC 協議》,轉載必須註明作者和本文連結