压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

如何防御Node.js中不安全的重定向

概念

對于Web開發人員來說,不安全或未經驗證的重定向是一個必須要注意的地方。Express框架能夠為重定向提供本地支持,使其易于實現和使用。但是,Express卻將對輸入進行驗證的這項工作留給了開發者。

根據OWASP.org對“未經驗證的重定向和轉發”的定義,其概念如下:

未經驗證的重定向和轉發是指,Web應用程序接受不受信任的輸入,而該輸入可能導致Web應用程序將請求重定向到用戶輸入中包含的不受信任的URL。

通常,會在登錄和身份驗證的過程用到重定向,從而讓用戶在登陸之后重新回到登錄前的頁面。此外,還有其他方案能夠實現這一點,具體根據業務需求或應用程序的類型而有所不同。

安全問題

如果不驗證用戶輸入的重定向,那么攻擊者就能夠進行網絡釣魚詐騙,竊取用戶憑據或執行其他惡意操作。

需要注意的是,當在Node.js或Express中實現重定向時,在服務器端進行輸入驗證非常重要。

如果攻擊者發現某個站點沒有驗證外部用戶提交的輸入,那么攻擊者可能會生成一個特制的鏈接,并在論壇、社交媒體或其他公共平臺發布,以便誘導用戶單擊該鏈接。

從表面上看,這些URL的域名確實屬于用戶將要(或正在)訪問的合法站點。例如:https://example.com/login?url=http://examp1e.com/bad/things ,確實是屬于example.com 域名。

然而,如果服務器端的重定向邏輯沒有對URL參數中的數據進行驗證,那么用戶最終訪問到的網站可能是偽造的釣魚站點(例如 examp1e.com )。

這只是攻擊者如何利用不安全的重定向邏輯的一個簡單示例。

不安全重定向的示例

在下面的代碼中,我們看到/login接收來自URL參數的未經驗證的數據,并且直接就將其傳遞給Express的res.redirect()方法。因此,只要用戶通過身份驗證,Express就會將用戶重定向到輸入或提供的任何URL。

var express = require('express');
var port = process.env.PORT || 3000;
var app = express();

app.get('/login', function (req, res, next) {

    if(req.session.isAuthenticated()) {

        res.redirect(req.query.url);
    }
}); 

app.get('/account', function (req, res, next) {
    res.send('Account page');
});

app.get('/profile', function (req, res, next) {
    res.send('Profile page');
});

app.listen(port, function() {
    console.log('Server listening on port ' + port);
});

防范方案1:輸入驗證

通常情況下,應該盡可能避免在代碼中用到重定向和轉發。

如果必須要在代碼中使用重定向,那么首選的方案是使用事先定義的映射到特定目標的鍵。這種方案被稱為白名單方法。具體實現方式如下:

1、baseHostname確保任何重定向都將不會離開我們的域名。

2、redirectMapping是一個對象,它將事先定義的鍵(例如傳遞給URL參數的內容)映射到服務器上的指定路徑。

3、validateRedirect()方法判斷事先定義的鍵是否存在。如果存在,就會返回重定向到相應路徑。

4、修改/login邏輯,將baseHostname和redirectPath變量連接在一起,避免使用戶提供的輸入內容直接進入到Express的res.redirect()方法。

5、最后,使用encodeURI()方法作為額外的保證,確保串聯字符串的URI部分被正確編碼,只允許合法的重定向。

參考代碼如下:

//Configure your whitelist
var baseHostname = "https://example.com";
var redirectMapping = {
    'account': '/account',
    'profile': '/profile'
}

//Create a function to validate whitelist
function validateRedirect(key) {
    if(key in redirectMapping) {

        return redirectMapping[key];
    }else{

        return false;
    }
}

app.get('/login', function (req, res, next) {
    if(req.session.isAuthenticated()) {
        redirectPath = validateRedirect(req.query.url);

        if(redirectPath) {
            res.redirect(encodeURI(baseHostname + redirectPath));
        }else{
            res.send('Not a valid redirect!');
        }
    }
});

防范方案2

在某些情況下,將每種合法的重定向列成白名單是不切實際的,但開發者仍然需要進行重定向,并且希望將重定向限制在域的范圍內。這時,如果外部提供的值能夠遵循特定模式(例如:都是16個字符的字符串,由字母和數字組成),可以采用這種方案。僅包含字母和數字的字符串是最為理想的,因為它們不包含任何可能有助于目錄遍歷、路徑遍歷等攻擊的特殊字符(例如省略號、斜杠等)。

舉例來說,開發人員可能希望用戶在登陸后,能重定向回到電子商務網站上的特定項目。由于電子商務網站針對每種產品都有一個唯一的值,由字母和數字組成,因此開發者可以根據RegEx白名單驗證外部輸入,從而實現安全的重定向。在這種情況下,使用的是productId變量,如下面代碼所示:

//配置白名單

var baseHostname = "https://example.com";

app.get('/login', function (req, res, next) {
    productId = (req.query.productId || '');
    whitelistRegEx = /^[a-zA-Z0-9]{16}$/;

    if(productId) {

        //Validate the productId is alphanumeric and exactly 16 characters
        if(whitelistRegEx.test(productId)) {

            res.redirect(encodeURI(baseHostname + '/item/' + productId));
        }else{

            //The productId did not meet the RegEx whitelist, so return an error
            res.send('Invalid product ID');
        }
    }else{

        //No productId was provided, so redirect to home page
        res.redirect('/');
    }
});

最后,警告用戶他們正在被自動重定向是非常重要的。如果實際上需要將用戶重定向到域名之外,那么可能需要在流程中創建一個中間頁面,如下圖所示,該頁面能夠提醒用戶,并明確告知將要重定向到的URL。

上一篇:GandCrab勒索病毒分析報告

下一篇:第十二期“安全+”端點安全沙龍成功舉辦