PHP程式碼審計——Day3-Snow Flake

smile_2233發表於2024-04-04

漏洞解析

// 實現了一個基本的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文字
參考這位師傅的:

相關文章