漏洞解析
// 實現了一個基本的MVC(Model-View-Controller)結構,透過動態載入控制器類和資料,並呼叫控制器的方法來實現基本的頁面渲染。
// 自動載入函式,用於動態載入類檔案。當使用尚未定義的類時,PHP會自動呼叫該函式來載入類檔案。此處,__autoload 函式會嘗試載入與類名 $className 對應的檔案。
function __autoload($className) {
include $className;
}
$controllerName = $_GET['c'];
$data = $_GET['d'];
// 檢查指定的類是否已經定義。如果控制器類已經定義,則表示該類存在,可以例項化
if (class_exists($controllerName)) {
$controller = new $controllerName($data['t'], $data['v']);
$controller->render();
} else {
echo 'There is no page with this name';
}
// 控制器類負責處理業務邏輯和渲染檢視。在建構函式中,它接收模板名稱和變數陣列作為引數,並將它們儲存在私有屬性中。render() 方法根據變數陣列中的內容來渲染檢視。
class HomeController {
private $template;
private $variables;
public function __construct($template, $variables) {
$this->template = $template;
$this->variables = $variables;
}
public function render() {
if ($this->variables['new']) {
echo 'controller rendering new response';
} else {
echo 'controller rendering old response';
}
}
}
考察點:檔案包含漏洞;例項化任意物件漏洞
1、檔案包含漏洞
class_exists
:(PHP 4, PHP 5, PHP 7)
- 功能 :檢查類是否已定義
- 定義 : bool class_exists ( string $class_name[, bool $autoload = true ] )
$class_name 為類的名字,在匹配的時候不區分大小寫。預設情況下 $autoload 為 true ,當 $autoload 為 true 時,會自動載入本程式中的 __autoload 函式;當 $autoload 為 false 時,則不呼叫 __autoload 函式。
使用class_exists()
函式來判斷使用者傳過來的控制器是否存在,預設情況下,如果程式存在 __autoload
函式,那麼在使用 class_exists()
函式就會自動呼叫本程式中的 __autoload
函式,檔案包含漏洞就出現在這個地方。攻擊者可以使用路徑穿越來包含任意檔案,當然使用路徑穿越符號的前提是 PHP5~5.3(包含5.3版本)版本 之間才可以。例如類名為: ../../../../etc/passwd
的查詢,將檢視passwd檔案內容
2、例項化任意物件漏洞
例項化類的類名$controllerName
和 傳入類的引數$data
都是使用者輸入可控,於是可以透過這個漏洞,呼叫php程式碼庫的任意建構函式。即使程式碼本身不包含易受攻擊的建構函式,我們也可以使用PHP的內建類 SimpleXMLElement
來進行 XXE 攻擊,進而讀取目標檔案的內容,甚至命令執行(前提是安裝了PHP擴充外掛expect)。
SimpleXMLElement
:(PHP 5, PHP 7)
- 功能 :用來表示XML文件中的元素,為PHP的內建類。
demo演示
<?php
$xml = <<< EOF
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///C:/PHP/flag.txt">
]>
<x> &xxe;</x>
EOF;
$xml_class = new SimpleXMLElement($xml, LIBXML_NOENT);
var_dump($xml_class);
?>
構造payload:?c=SimpleXMLElement&d=xml文字
參考這位師傅的: