[ASP.NET]Open Redirect(Input Validation and Representation, Data Flow)

本篇介紹如何解決Open Redirect(Input Validation and Representation, Data Flow)問題

在系統中,可能會有程式會讀取某個QueryString的值,然後 Redirect 過去那支程式。

如果該QueryString的值沒有驗證過,就會有 Open Redirect 的問題哦!

專案如下,

image

Code如下,

Default.aspx


<form id="form1" runat="server">
<div>
	<asp:Button ID="btnA" runat="server" Text="A.aspx" 
		OnClientClick="window.navigate('webForm1.aspx?url=A.aspx&x=c.aspx');return false;" />
	<asp:Button ID="btnB" runat="server" Text="B.aspx" 
		OnClientClick="window.navigate('webForm1.aspx?url=b.aspx');return false;" />
	<asp:Button ID="btnFun001" runat="server" Text="fun001.aspx" 
		OnClientClick="window.navigate('webForm1.aspx?url=fun1%2ffun001.aspx');return false;" />
</div>
</form>

 

Default.aspx.cs


protected void Page_Load(object sender, EventArgs e)
{
	string navigateUrl = Request.QueryString["url"];
	if (Uri.IsWellFormedUriString(navigateUrl, UriKind.RelativeOrAbsolute))
	{
		Response.Redirect(navigateUrl, false);
	}
}

 

因為如果我知道該支程式沒有檢查的話,我可以給別的url參數,然後讓系統導到釣魚網站去!

例如在Browser中輸入 http://localhost:29432/Default.aspx?url=http://www.dotblogs.com.tw/rainmaker/

或是在Fiddler的FiddlerScript中OnBeforeRequest事件中加入無論如何,都導到我的Blog


if (oSession.HostnameIs("localhost:29432")){
	var s_url = (oSession.url).Split("?")[0];
	oSession.url = s_url + "?url=http://www.dotblogs.com.tw/rainmaker/";
}

 

那有什解法呢?

如果以接收url的方式,就是建立一份白名單(允許的url清單),然後檢查 url 是否在那個白名單之中。

所以可以在 Global.asax.cs 的 Application_Start 事件中建立白名單,然後存放到 Application 之中,如下,


protected void Application_Start(object sender, EventArgs e)
{
	//將AP允許的url放進來
	List<string> allowUrls = new List<string>();
	allowUrls.Add("a.aspx");
	allowUrls.Add("b.aspx");
	allowUrls.Add("fun1/fun001.aspx");
	Application["allowUrls"] = allowUrls;
}

 

所以原本的從 QueryString 讀取到的 url ,需要透過 白名單 的檢查,如下,


protected void Page_Load(object sender, EventArgs e)
{
	string navigateUrl = Request.QueryString["url"];
	if (Uri.IsWellFormedUriString(navigateUrl, UriKind.RelativeOrAbsolute))
	{
		string allowUrl = GetAllowUrl(navigateUrl);
		if (!string.IsNullOrWhiteSpace(allowUrl))
		{
			Response.Redirect(allowUrl, false);
		}
	}
}

 

檢查的 GetAllowUrl Function (到白名單之中Search),如下,


public string GetAllowUrl(string url)
{
	string result = string.Empty;
	List<string> allowUrls = Application["allowUrls"] as List<string>;
	if (allowUrls != null)
	{
		result = allowUrls.Where(s => string.Equals(s, url, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
	}
	return result;
}

 

這樣如果在Browser輸入 http://localhost:29432/Default.aspx?url=http://www.dotblogs.com.tw/rainmaker/ 也不會被導過去哦!

另外,一種方式是透過傳遞白名單的Key值,然後再透過這個Key值去白名單中取得允許的url,再導過去,也是可以的哦!

 

像我們的系統架構會由Portal去navigate到各WebAP,而在各WebAP中都有一支共用的程式去驗證後再導到要去的程式。
所以可以寫個HttpModule去建立白名單資料,然後再由那支共用的程式去驗證再導過去。

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^