2016-05-30 38 views
4

我有一個登錄頁面https://example.com/login#destination其中destination是用戶試圖瀏覽時,他們需要登錄到目標網址導航之前相對。
(即https://example.com/destination確保URL是通過JavaScript的location.replace()

中的JavaScript我想使用是

function onSuccessfulLogin() { 
    location.replace(location.hash.substring(1) || 'default') 
} 
  • 這將導致XSS漏洞,攻擊者提供的鏈接
    https://example.com/login#javascript:..

  • 此外,我需要防止導航到一個相似的網站後登錄。
    https://example.com/login#https://looks-like-example.com
    https://example.com/login#//looks-like-example.com

如何調整onSuccessfulLogin以確保哈希#部分提供的URL是相對URL,而不是與javascript:https://或其他任何絕對的導航方案開始?

一個想法是評估該網址,並在導航前查看location.origin是否保持不變。您可以建議 如何做到這一點,或更好的方法?

+0

首先想到發生在我身上的是一個ajax HEAD請求...然後成功重定向 – charlietfl

+0

沒有足夠的數據來制定一個完整的解決方案,但是爲了使事情變得簡單一些,並且對代碼更加友好,我可以借給你我的JavaScript位置構造函數,可以按照以下方式使用它。 'var loc = new Loc(sURL); loc = loc.hash.split(「#」)[1]; if(/javascript|http/i.test(loc.protocol)){loc.hash = default;位置= loc.href};'但我仍然需要更好地澄清情況。 –

+0

@GeorgeBailey,當然不是 - 但是如果你還沒有很好地閱讀:我的原始答覆是我說「我可以借給你」,以防你喜歡我的主張。 –

回答

1

從OWASP建議上Preventing Unvalidated Redirects and Forwards

建議任何這樣的目的地輸入被映射到一個值,而不是實際的URL或URL的一部分,並且該服務器端代碼轉換此值添加到目標網址。

因此,一個安全的方法將被映射某些鍵真實URL:

// https://example.com/login#destination 

var keyToUrl = { 
    destination: 'https://example.com/destination', 
    defaults: 'https://example.com/default' 
}; 

function onSuccessfulLogin() { 
    var hash = location.hash.substring(1); 
    var url = keyToUrl[hash] || keyToUrl.defaults; 

    location.replace(url); 
} 

你也可以考慮提供URL的唯一路徑一部分,並與代碼中的主機名追加它:

// https://example.com/login#destination 

function onSuccessfulLogin() { 
    var path = location.hash.substring(1); 
    var url = 'https://example.com/' + path; 

    location.replace(url); 
} 

雖然我會堅持映射。

+0

啊,是的,正在等待'location.origin +'/''('https:// example.com')看起來是一個很好的解決方案。對不起,但在這個特定的項目中,我們不會使用映射,儘管它們會提供額外的價值。 –

0

這是一個關於XSS漏洞的好處。

我相信所有協議只使用英文字母字符,所以像/^[a-z]+:/i這樣的正則表達式會檢查這些字符。或者,如果我們感覺更具包容性,/^[^:\/?]+:/只允許/?後跟:。然後,我們可以結合起來,與/^\/\/測試一個自由協議的URL,這給了我們:

// Either 
var rexIsProtocol = /(?:^[a-z]+:)|(?:^\/\/)/i; 
// Or 
var rexIsProtocol = /(?:^[^:\/?]+:)|(?:^\/\/)/i; 

然後將試驗是這樣的:

var url = location.hash.substring(1).trim(); // trim to deal with whitespace 
if (rexIsProtocol.test(url)) { 
    // It starts with a protocol 
} else { 
    // It doesn't 
} 

這就是說,只有一個我想你需要特別爲javascript:僞protcol困擾,所以你可能只是測試。