本篇介紹如何解決Open Redirect(Input Validation and Representation, Data Flow)問題
在系統中,可能會有程式會讀取某個QueryString的值,然後 Redirect 過去那支程式。
如果該QueryString的值沒有驗證過,就會有 Open Redirect 的問題哦!
專案如下,
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,再導過去,也是可以的哦!
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^