[ASP.NET]Data Filter Injection attack

最近公司的程式有被掃到「Data Filter Injection attack」的問題,
是什麼造成「Data Filter Injection attack」的問題呢?
又該如何解決呢?

最近公司的程式有被掃到「Data Filter Injection attack」的問題,程式大約如下,

1.Get時先將資料從DB中取出來,然後放在ViewState之中


protected void Page_Load(object sender, EventArgs e)
{
	if(!Page.IsPostBack ){
		DataTable dt = new DataTable("myDT");
		dt.Columns.Add("c1", typeof(string));
		for(int i=0;i<5;i++){
			dt.Rows.Add(i.ToString());
		}
		ViewState["myDT"] = dt;
	}
}

 

2.在需要的時候,再依QueryString中的值來Filter!


DataTable dt = ViewState["myDT"] as DataTable;
if (dt != null)
{
	string filter = string.Format("c1 = '{0}'"
		, Server.HtmlEncode(Request.QueryString["id"]));
	var drs = dt.Select(filter);
	foreach(DataRow dr in drs){
		Response.Write(dr["c1"]);
	}
}

 

以上的程式有幾個問題

1.將DataTable放在ViewState之中,每次Postback都會在Client及Server傳遞,造成效能的影響。

2.ViewState有可能會被Client竄改。

3.DataTable的Select Filter沒有經過處理,會有Injection的問題。

image

而第2、3點就是會有「Data Filter Injection attack」的問題。

 

針對以上的問題,可以用以下的方式來解決。

1.使用ASP.NET WebForms 常常被人說ViewState過大,所以可以在BasePage中將原本存在Hidden欄位(HiddenFieldPageStatePersister),改放到Session(SessionPageStatePersister)之中。


public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter {
	public override PageStatePersister GetStatePersister() {
		return new SessionPageStatePersister(Page);
	}
}

 

2.資料可以在使用到時,再到DB中取得,並透過參數方式查詢。或是將它存到Cache或Session之中。


protected void Page_Load(object sender, EventArgs e)
{
	if(!Page.IsPostBack ){
		DataTable dt = new DataTable("myDT");
		dt.Columns.Add("c1", typeof(string));
		for(int i=0;i<5;i++){
			dt.Rows.Add(i.ToString());
		}
		Cache[string.Format("{0}-myDT", Session.SessionID)] = dt;
	}
}

 

3.1.DataTable的Select Filter要處理(請針對資料型態來處理或判斷資料型別),以避免Injection的問題。


DataTable dt2 = Cache[string.Format("{0}-myDT", Session.SessionID)] as DataTable;
if (dt2 != null)
{
	string filterValue = Server.HtmlEncode(Request.QueryString["id"]);
	if(!string.IsNullOrEmpty(filterValue)){
		string filter = string.Format("c1 = '{0}'", filterValue.Replace("'", "''"));
		var drs = dt2.Select(filter);
		foreach (DataRow dr in drs)
		{
			Response.Write(dr["c1"]);
		}
	}
}

 

3.2.或是改用Linq方式來查詢(要加入System.Data.DataSetExtensions參考),如下,


DataTable dt2 = Cache[string.Format("{0}-myDT", Session.SessionID)] as DataTable;
if (dt2 != null)
{
	string filterValue = Server.HtmlEncode(Request.QueryString["id"]);
	if(!string.IsNullOrEmpty(filterValue)){
		var drs2 = dt2.AsEnumerable()
			.Where(r => r.Field<string>("c1")
				.Equals(filterValue, StringComparison.InvariantCultureIgnoreCase)).Select(r=>r);
		foreach (DataRow dr in drs2)
		{
			Response.Write(dr["c1"]);
		}
	}
}

 

參考資料

HiddenFieldPageStatePersister

SessionPageStatePersister

DataTableExtensions.AsEnumerable

 

如果大家有其他的方式,請分享給大家知道,謝謝大家!

Hi, 

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

請大家繼續支持 ^_^