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

PHP + MongoDB 注入漏洞原理與防範

     編輯:PHP 相關知識

漏洞成因:PHP 陣列參數特性

PHP 允許通過 URL 參數直接提交陣列,例如:

login.php?username=admin&passwd[$ne]=1

後端 $_GET['passwd'] 將得到:

array(1) { ["$ne"]=> string(1) "1" }

MongoDB 查詢操作符注入

若後端直接將用戶輸入拼入 MongoDB 查詢:

$collection->find([
    'username' => 'admin',
    'passwd'   => $_GET['passwd']  // 未過濾,直接傳入
]);

攻擊者提交 passwd[$ne]=1,實際執行的查詢變為:

db.collection.find({
    username: 'admin',
    passwd: { $ne: 1 }   // 「不等於 1」恆為真,繞過密碼驗證
})

若同時注入 username[$ne]=1&passwd[$ne]=1,可遍歷所有用戶記錄。

實測演示

<?php
// 測試參數接收
$passwd = $_GET['passwd'];
var_dump($passwd);
// 訪問 ?passwd[$ne]=1 輸出:
// array(1) { ["$ne"]=> string(1) "1" }

修復方案:強制類型轉換

在構建查詢前,將所有用戶輸入強制轉為預期的標量類型:

$collection->find([
    'username' => (string)$_GET['username'],
    'passwd'   => (string)$_GET['passwd']
]);

轉為字串後,$ne 等操作符失去作用,查詢退化為精確匹配。

更完善的防禦策略

  1. 白名單驗證:僅允許預期的鍵名與值格式,拒絕含有 $ 開頭鍵的陣列。
  2. 使用查詢建構器/ODM:如 MongoDB PHP Library 的 MongoDB\Driver\Query、MongoDB\Model\BSONDocument 或 Laravel MongoDB ODM,避免手動拼裝陣列。
  3. 輸入過濾中間件:在框架入口統一遞歸清理 $_GET、$_POST、$_REQUEST 中的陣列鍵名,移除或轉義 $ 開頭鍵。
  4. 最小權限資料庫用戶:應用使用僅擁有必要集合讀寫權限的資料庫帳號,避免使用 admin 或 root。
  5. 啟用 MongoDB 認證與 TLS:防止未授權存取與中間人竄改。

類比:SQL 注入的 NoSQL 版本

原理與經典 SQL 注入相似:

-- SQL 注入
SELECT * FROM users WHERE username='admin' AND passwd!='1';

-- MongoDB 注入
db.users.find({ username: 'admin', passwd: { $ne: 1 } })

核心都是**未經驗證的用戶輸入直接進入查詢語句構建**,導致邏輯被竄改。

總結

  • PHP 的陣列參數特性 + MongoDB 查詢操作符 = 注入風險。
  • **永遠不要信任外部輸入**,查詢前務必做類型強制轉換或白名單驗證。
  • 優先使用成熟的 ODM/查詢建構器,減少手寫查詢陣列。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved