NoSQL 注入以及如何避免它們
NoSQL注入漏洞是使用NoSQL數據庫的Web應用程序中的錯誤。此Web應用程序安全問題使惡意方可以繞過身份驗證,提取數據,修改數據,甚至獲得對應用程序的完全控制。NoSQL注入攻擊是缺乏數據清理的結果。
與傳統的SQL注入類似,NoSQL注入只是眾多注入攻擊中的一種。它們被設計為利用不使用SQL的現代數據庫。NoSQL(不僅是SQL)一詞用于描述使用不太嚴格的結構的數據庫,并且可以指許多不同類型的數據庫,包括那些使用諸如鍵值,鍵文檔,列族或圖形之類的模型數據庫。
盡管NoSQL數據庫引擎具有不同的結構,并且不支持SQL語句和SQL查詢,但它們仍允許用戶執行查詢。它們不支持一種標準化語言,因此查詢語言取決于實現方式:數據庫(例如MongoDB,Redis,Google Cloud Datastore等),語言(例如Python,PHP等)和框架(例如Node)。 js,Angular)。但是,NoSQL查詢通常基于JSON,并且可以包含用戶輸入。如果未對此輸入進行消毒,則它們很容易受到注入。
PHP應用程序中的MongoDB注入示例
為了了解如何構造NoSQL查詢以及它如何容易受到注入攻擊,我們將重點介紹最流行的NoSQL數據庫:MongoDB,并將使用PHP訪問它。這是訪問MongoDB進行身份驗證的代碼段的簡單示例。
$username = $_POST['username'];
$password = $_POST['password'];
$connection = new MongoDB\Client('mongodb://localhost:27017');
if($connection) {
$db = $connection->test;
$users = $db->users;
$query = array(
"user" => $username,
"password" => $password
);
$req = $users->findOne($query);
}
如您所見,在此示例中,用于身份驗證的用戶名和密碼來自POST請求,然后直接在查詢中使用。與其他類型的注入類似,惡意用戶可能會提供欺騙數據庫的NoSQL注入有效負載。
要成功執行MongoDB注入,只要攻擊者提供以下惡意輸入數據作為POST請求就足夠了:
username[$eq]=admin&password[$ne]=foo
查詢操作符[$ne]表示不相等。因此,結果查詢將找到用戶名為admin且密碼不是foo的第一條記錄。如果將此代碼用于身份驗證,則攻擊者將以admin用戶身份登錄。
可以以類似的方式使用更多的操作符,例如[$lt]和[$gt]以及[$regex]。通過按順序嘗試組合并評估結果,正則表達式甚至可以使攻擊者枚舉上述情況下的所有用戶。
高級攻擊和JavaScript注入
MongoDB查詢支持常用的運算符$where,它引入了嚴重的NoSQL攻擊(包括JavaScript對象)的可能性。
例如,開發人員可能希望以$where以下方式使用運算符來訪問特定用戶的記錄:
$query = array('$where' => 'this.name === \''.$name.'\'');
在這種情況下,攻擊者可能會提供以下空字符串比較技巧$name:
'; return '' == '
結果,查詢將變為:
"$where": "this.name === ''; return '' == ''"
攻擊者將收到整個用戶列表。
由于$where操作符實際上是JavaScript代碼,因此攻擊者還可以傳遞包含任意JavaScript的惡意字符串,例如:
'; while(true){}'
本示例創建一個永無止境的循環,并導致拒絕服務攻擊。
如何避免NoSQL注入
為了避免NoSQL注入,您必須始終將用戶輸入視為不受信任。您可以執行以下操作來驗證用戶輸入:
- 使用 sanitization library 。例如,mongo-sanitize或mongoose。
- 如果找不到適合您環境的庫,請將用戶輸入轉換為所需的類型。例如,將用戶名和密碼轉換為字符串。
- 在MongoDB的情況下,切勿在用戶輸入中使用
where,mapReduce或group運算符,因為這些運算符使攻擊者能夠注入JavaScript,因此比其他運算符更加危險。為了加強安全性,在mongod.conf如果可能的話,設置javascriptEnabled為false。 - 此外,請始終使用最小特權模型:以盡可能低的特權運行您的應用程序,以便即使被利用,攻擊者也無法訪問其他資源。