首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 安全:直接用 $ 取值而非 $_GET 的字元逸出風險與對策

     編輯:PHP 綜合知識

危險程式碼分析

<?php
function myAddslashes($string, $force = 0) {
    !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
    if (!MAGIC_QUOTES_GPC || $force) {
        if (is_array($string)) {
            foreach ($string as $key => $val) {
                $string[$key] = myAddslashes($val, $force);
            }
        } else {
            $string = addslashes($string);
        }
    }
    return $string;
}

// 將 $_GET/$_POST/$_COOKIE 直接註冊為全域變數 $var
foreach (['_COOKIE', '_POST', '_GET'] as $_request) {
    foreach ($$_request as $_key => $_value) {
        if ($_key{0} !== '_') { // 略過 _ 開頭
            $$_key = myAddslashes($_value);
        }
    }
}

echo $urls; // 直接使用 $urls 變數
?>

三大風險

  1. 變數覆蓋攻擊:攻擊者傳送 `?GLOBALS[foo]=bar` 或 `?_SESSION[admin]=1` 覆蓋超全域陣列 (PHP 5.4+ `register_globals` 已移除,但此碼手動模擬同樣效果)
  2. 注入繞過:`addslashes()` **非**資料庫防注入方案,多位元組編碼 (GBK/Big5) 可繞過,唯有**預處理語句**有效
  3. XSS 洞:`addslashes` 不處理 HTML 實體 (`<` `>` `&`),輸出到 HTML 仍會觸發腳本

現代正確做法

<?php
// 1. 顯式從超全域陣列取值
$name = $_GET['name'] ?? '';
$ids = $_POST['ids'] ?? [];

// 2. 資料庫:預處理語句 (PDO)
$stmt = $pdo->prepare('SELECT * FROM users WHERE name = ?');
$stmt->execute([$name]);

// 3. HTML 輸出:htmlspecialchars
echo '<div>' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</div>';

// 4. JS 輸出:json_encode
echo '<script> const name = ' . json_encode($name, JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP) . '; </script>';

// 5. Shell 指令:escapeshellarg / escapeshellcmd
$cmd = 'convert ' . escapeshellarg($input) . ' output.png';

歷史背景補充

  • `register_globals` (PHP 4.2 預設 Off, 5.4 移除) 將 EGPCS 直接註冊為全域變數,極度危險
  • `magic_quotes_gpc` (5.4 移除) 自動 `addslashes` 給 GPC,造成重複逸出、編碼問題、誤導安全感
  • 現代框架 (Laravel, Symfony) **完全不依賴** 這兩項,請確認 `php.ini` 已關閉
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved