NodeJS路徑遍歷:示例及預防

  讓我們來看看什麼是路徑遍歷攻擊,以及在Node.js中可以採用哪些方法來阻止這種攻擊。

  構建一個安全而健壯的應用程序需要考慮的因素很多,並非一件容易的事情。要確保覆蓋所有潛在的漏洞是一項十分艱鉅的任務,這需要大量的經驗和指導。在這些漏洞中,有一個和系統目錄訪問安全相關的漏洞,它通常會在程序進行路徑遍歷時受到攻擊。

  理解這一點有助於你找到解決問題的辦法。網絡上有大量相關的資源可以幫助你解決該問題,本文只是諸多資源中的一個。

  本文旨在介紹路徑遍歷攻擊的原理,以及使用Node.js可以採取哪些方法來阻止這類攻擊。首先,我們將簡要介紹什麼是路徑遍歷攻擊,然後將探討一些常見的示例,最後介紹如何修復這些漏洞。通過本文的介紹,你應該對路徑訪問遍歷有一個基本的瞭解,並能夠在你的程序中阻止相關的漏洞。

  請注意,本文是專門針對Node.js開發人員的。因此,我們希望你對Node.js開發棧有一個基本的瞭解。如果你還沒有嘗試過,請查看Node.js指南以獲得更多的信息。

路徑遍歷介紹

  什麼是路徑遍歷攻擊?它是一種利用服務器端糟糕的訪問控制漏洞而實現的攻擊,特別是對文件的訪問。在這類攻擊中,攻擊者試圖通過嚮應用程序中注入無效或惡意的內容來訪問服務器上受限制的文件。可以把它看作是SQL注入,但針對的是系統目錄而不是數據庫。

  很明顯,能夠訪問服務器上未經授權的文件,其後果可想而知。攻擊者一旦獲取了這種權限,他就可以在我們的系統中造成非常嚴重的破壞,從而危及用戶信息。

  下面讓我們更加深入地研究導致此漏洞的原因,以及你的服務器運行什麼樣的系統是何等重要。現在,讓我們先看看幾個路徑遍歷攻擊的示例。

路徑遍歷攻擊示例

  你可能會問,一個典型的路徑遍歷攻擊是什麼樣的?

  其實很簡單:

../../etc/passwd

  出乎你的預料,對嗎?

  路徑遍歷攻擊的核心思想就是找到一種方法,訪問開發人員和應用程序不希望你訪問的文件夾。因此,如果你對如何訪問路徑和Linux命令行有所瞭解的話,你就可以在不受保護的應用程序中進行相應的操作,從而實現路徑遍歷攻擊。

  下面是一些具體的例子。

相對路徑攻擊

  相對路徑攻擊本質上就和我們上面所描述的一樣。如果應用程序缺少有效的用戶輸入驗證,攻擊者可以利用該漏洞試圖訪問服務器中受限制的文件。這樣情況下,passwd文件中包含我們在服務器上的密鑰就有可能被泄露。

  當然,你可以增強用戶輸入驗證,以減輕這種漏洞所帶來的風險。一種簡單的方法是使用path.normalize()並對用戶輸入進行特殊字符過濾——順便說一下,你應該始終對用戶輸入的內容進行過濾和驗證——這可以避免許多問題。

有毒的Null字節攻擊

  在HTTP請求中,通過在字符串的末尾添加NULL字節和\0,攻擊者可以繞開用戶輸入驗證和過濾,從而訪問未經授權的文件和目錄。

  那會是怎樣的呢?就像這樣:

/../../../../../../../../../../../../../../../../etc/passwd%00

  請注意末尾的%00。我們的驗證程序最終可能會將其翻譯爲\0.txt\0,從而允許訪問passwd文件。

  爲了阻止此類攻擊,你只需要添加下面的代碼對用戶輸入的內容進行驗證:

if (user_input.indexOf('\0') !== -1) {
return respond('Access denied');
}

  還算簡單,對吧?

  路徑遍歷攻擊其實並不複雜。正如我們前面所提到的,它依賴於糟糕的訪問控制邏輯的實現或者一些邊界值判斷。不過這些漏洞可能非常危險,我們應該儘可能地阻止或減少這些漏洞的發生,好消息是要做到這一點並不難。

其它阻止Node.js中路徑遍歷攻擊的方法

  當然,還有許多方法可以用來增強我們應用程序的安全性。JavaScript已經足夠成熟,它提供了大量的文檔用以指導我們採用不同的方法來減少攻擊,這裏我將列出其中一部分。

路徑前綴驗證

  在應用程序中只允許某種級別的遍歷會怎麼樣?在某些情況下,你可能希望應用程序允許用戶在不同的文件夾中查找文件——例如,個人資料圖片和文章都存放在不同的文件夾中。你可以在代碼中進行硬編碼來驗證路徑字符串,就像請求特定資源時使用的變量一樣,但是這樣做可能導致前綴路徑遍歷攻擊。

  如果用戶被允許在應用程序中輸入點和斜線等字符,那麼攻擊者就可以自由地遍歷目錄。爲了阻止這種情況的發生,我們需要驗證用戶的輸入並過濾掉這些字符,或者直接顯示錯誤信息。

白名單

  白名單是一種直接有效的方法,它可以減少漏洞被利用的可能性。當然,你不能指望白名單一定能派上用場,但在需要的時候總是能起到一定的作用。

  一個簡單的例子是驗證用戶輸入的內容是否符合某個預定義的標準。例如,如果你規定應用程序只允許創建和處理路徑中包含小寫字母和數字字符的文件,那麼你就可以驗證用戶輸入的內容中只包含這類字符。

if (!/^[a-z0-9]+$/.test(user_input)) {
return respond('Access denied');
}

  通過添加以上驗證方法,你可以針對惡意攻擊添加一層額外的防護。

路徑連接

  最後,我們將實現一個通用的驗證方案,爲我們可能面臨的所有這些漏洞提供一個較爲健壯的方法,最終生成一個安全的路徑字符串。

  這個解決方案的代碼看起來是這樣的:

var root = '/var/www/';
exports.validatePath = (user_input) => {
if (user_input.indexOf('\0') !== -1) {
return 'Access denied';
}
if (!/^[a-z0-9]+$/.test(user_input)) {
return 'Access denied';
}
var path = require('path');
var safe_input = path.normalize(user_input).replace(/^(\.\.(\/|\\|$))+/, '');
var path_string = path.join(root, safe_input);
if (path_string.indexOf(root) !== 0) {
return 'Access denied';
}
return path_string;
}

  正如你所看到的,我們將前面討論過的所有檢查和驗證方法合併到一起,包括可能對系統造成的任何風險。

寫在最後

  JavaScript是一種成熟而健壯的語言,因此有無數種方法可以解決這個問題。然而這些方法都不是最完美的,只有滿足你的需求並進行了充分測試的方法纔是最好的。

  雖然解決方法看起來很簡單,但要確保執行良好的路徑遍歷安全策略十分重要。我們需要儘可能地覆蓋應用程序中的潛在缺口。當然,技術在不斷更新,將來會出現更強大、更全面的解決方案來防止此類問題的發生。只要我們的方法有效且具備創造性,我們總會堵住系統中存在的漏洞。

原文地址:Node.js Path Traversal Guide: Examples and Prevention

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章