0x00 檔案包含
本地包含
本地檔案包含(Local File Include)簡稱 LFI,檔案包含在php中,一般涉及到的危險函數有
include()
、
include_once()
、
require()
、
require_once()
,在包含檔案名中存在可控變量的話就可能存在包含漏洞,由于這幾個函數的特性也可能産生其他漏洞,後面一一講到。
示例:
php
$file = $_GET['name'];
include($file);
?>
payload:
http://127.0.0.1/test.php?name=D:\phpstudy\PHPTutorial\MySQL\my.ini
這是個最簡單的檔案包含,沒有任何過濾。但是一般程式不會這麼寫,他一般會指定字尾,這樣我們就需要截斷來繞過了。
php
$file = $_GET['name'];
include($file . "html");
?>
在PHP5.2.x中我們可以通過使用%00來截斷後面的内容、也可以使用路徑長度截斷不過都在php5.3中被修複了。
payload:
http://127.0.0.1/test.php?name=D:\phpstudy\PHPTutorial\MySQL\my.ini%00
利用字元.或者/.或者./來截斷,系統檔案路徑長度限制:windows 259個byteslinux 4096個bytes。
遠端包含
遠端檔案包含漏洞(Remote File Inclusion)簡稱RFI,他需要我們的php.ini中配置
allow_url_include
、
allow_url_fopen
。
1.包含遠端檔案
需要打開
allow_url_include=On
、
allow_url_fopen=On
他可以利用?号截斷,不受版本限制
payload:
http://127.0.0.1/test.php?name=http://127.0.0.1/1.txt?
2.僞協定
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:// — 處理互動式的流
各種僞協定的使用方法網上很多,大家搜尋一下吧。
實戰審計
直接看首頁index.php
php
//單一入口模式
error_reporting(0); //關閉錯誤顯示
$file=addslashes($_GET['r']); //接收檔案名
$action=$file==''?'index':$file; //判斷為空或者等于index
include('files/'.$action.'.php'); //載入相應檔案
?>
他會包含files目錄下的檔案,因為他沒有過濾../是以可以包含任意目錄下的檔案,由于加了字尾是以漏洞存在于低版本。
0x01 任意檔案删除
任意檔案删除審計一般來說我們都是搜尋函數
unlink
然後回溯去看。
inc\zzz_file.php
首先判斷傳入的參數是否為空,然後拼接路徑,第516行中出現了一個函數
ifstrin
,我們跟進看看
隻是個簡單的判斷沒啥特殊情況,我們再來看看拿來調用了這個檔案。
function file_path( $path ) {
$list=array();
$path= substr( $path, 0, strrpos( $path, '/' ));
$list=splits($path,'/');
return $list;
}
function arr_search($arr1, $arr2 ) {
$result=false;
foreach ( $arr1 as $v ) {
if(in_array( $v,$arr2 )) return true;
}
return $result;
}
擷取參數,然後看看我們傳入的路徑是否存在這個數組裡面的值,也就是基本上是沒有過濾的,因為我們完全可以通過../ 跳回去。
payload:
POST /zzzp6p/admin/save.php?act=delfile
path=/zzzp6p/upload/../install/1install.lock
這裡我們走的下面的分支不能删除
array('php','db','mdb','tpl')
這個數組的檔案。
要删除任意檔案隻需要使用
path=/zzzp6p/runtime/../install/1.db
讓
ifstrin()
為true走上面的分支即可。
一般來說我們任意檔案删除 是配合删除install.lock來達到網站重裝漏洞。
0x02 任意檔案下載下傳
任意檔案下載下傳常見于檔案的顯示和下載下傳的地方,一般關注的檔案是和下載下傳有關的,比如download。當然你還可以搭建源碼,來尋找能夠下載下傳的地方。
常見的下載下傳或讀取函數:
file_get_contents()
、
readfile()
、
fopen()
在網上找到個别人審計的執行個體,結合起來審計一下,用到的源碼是EarMusic20180820_UTF8
搜尋down相關的詞語,找到檔案\template\default\source\down.php
我們看看
$file
參數怎麼來的,先是調用函數
getfield()
,轉到函數去看看
不出意外應該是從資料庫中讀取路徑,再來看看
geturl()
函數
構造下載下傳位址,這些地方沒什麼問題,我們來看看什麼地方對儲存位址的表中插入了資料,搜尋表名
lyric
。
\source\user\music\ajax.php
我們看到
$lyric
經過
checkrename
、
SafeRequest
這兩個函數的清洗,先來轉到函數
SafeRequest
。
我們傳入的mode是get,然後經過
addslashes()
的轉義,下面在替換為空,也就是我們基本上是不能使用
\\
了,我們在看看
checkrename
這裡正則比對了我們的
.\
?iframe=
.php?
這裡完全看不懂他比對字尾為php?這個的意義何在,直接php就繞過了。
是以綜合起來就是不要帶有
\和./
這裡我們隻要傳入絕對路徑就可以了
登陸前台找到上傳歌曲的頁面在歌詞位址中插入payload
payload:
D:/phpstudy/PHPTutorial/WWW/Ear_Music/template/default/source/down.php
0x03 檔案上傳
檔案上傳隻有一個函數
move_uploaded_file()
一般來說,我們就可以搜尋這個函數來回溯,看他的驗證方式,是黑名單還是白名單,是否是前端限制,是否隻是簡單的驗證了檔案頭,是否是能繞過的正則比對,是否渲染了圖檔。
結合zzzphp來審計一下檔案上傳,全局搜尋
move_uploaded_file
\zzzcms\inc\zzz_file.php
回溯看看那裡調用了這個函數
典型的黑名單驗證,可以使用asa繞過,隻需要在背景添加這個擴充名
上傳即可,當然也可以通過上圖中的 switch分支,隻要傳入的 type不是他的類型就可以跳過背景添加這個步驟。
0x04 文末
對檔案的操作還見于寫入其他配置檔案,典型的有thinkphp緩存檔案寫入。
由于幾天沒更新公衆号了,一直在寫關于代碼審計wiki相關的文章,文章基本都是從0開始沒啥門檻。
文章轉載自404師傅的公衆号