2015-09-25 86 views
0

我有以下代碼:SqlDataAdapter - 防止表名上的SQL注入?

SqlDataAdapter adapter = new SqlDataAdapter("SELECT TOP 0 * FROM [tableName]", conn); 
DataTable dt = new DataTable(); 
adapter.FillSchema(dt, SchemaType.Mapped); 

我使用它來構建表架構的DataTable

通常情況下,當人們詢問SQL注入,他們都在談論查詢參數:),我的問題是關於表名:

SELECT TOP 0 * 
FROM [tableName] 

[tableName]實際上將是動態的/在運行時確定(這是一個框架btw)...

tableName傳入該方法是不可信的,所以我想確保沒有任何有趣的業務正在進行?

我是否必須手動擦洗表名(並且我確信我會錯過什麼)?還是有一個內置的方法呢?或者以某種方式防止表名上的SQL注入?

+4

獲取有效表名稱的列表,並根據可信列表檢查您的輸入 – Steve

+0

我對設計用於從任何表中返回數據的框架非常謹慎。這是一個非常好的指示,你正在計劃使用select *來使所有東西都變得通用。雖然這看起來很酷,但它是有代價的。這個成本就是性能。你不能像這樣調整查詢。 –

+0

如果你決定使用這樣的動態sql路由,你應該在QuoteName中包裝tableName。 –

回答

1

您可以使用下面的查詢來獲取數據庫中的所有表的列表,並使用它作爲一個白名單:

SELECT TABLE_NAME FROM <DATABASE_NAME>.INFORMATION_SCHEMA.Tables 
WHERE TABLE_TYPE='BASE TABLE' 

更換

<DATABASE_NAME> 

與你的數據庫名稱。

如果有人試圖輸入不在該列表中的表名,則不要執行該查詢。

更新

至於「多個連接字符串」的情況下,你也可以使用一個簡單的查詢來檢查當前數據庫名:

SELECT db_name() 

所以,你應該能夠很容易地工藝一個只需從當前數據庫獲取有效表名稱列表的方法,無論connection-string/db-name是否爲動態。而在事物的宏偉計劃中,我懷疑這兩個查詢是否會影響應用程序的性能,就像您所說的那樣,如果需要,您可以輕鬆地緩存表列表。

+1

嗯......不知道我想走那條路......連接字符串和表名是通過模板動態生成的,所以它可能有多個連接字符串,表名等等。另外,這將會是高流量的方法,所以我不想做任何超級昂貴的東西。我可以緩存表列表,但正如我所說,可以有多個數據庫,表,連接字符串等。如果表名無效,我可以拋出異常,只是不想讓某人潛行在那裏注射。 – SledgeHammer

+0

對於INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @PARAMETER,您是否有任何衡量FillSchema比搜索更便宜的方法? – Steve

+0

@SledgeHammer - 有效的點,只是更新了我的答案一點點:-) – HaukurHaf

-1

你可以保持的SqlDataAdapter並使用

Adapter.selectcommand.parameters.add(@ 「無所謂」,值)

編輯:對不起!我錯過了與表名相關的部分,這段代碼不起作用。 :( 我道歉。

+0

你確定你可以使用表名作爲參數嗎? – Paparazzi

+0

我很確定你不能..... – HaukurHaf

1

表名傳遞到方法我不信任,所以我想讓 確定沒有任何有趣的事情發生?

一種方法是首先執行參數化的查詢,傳遞表名稱作爲參數(nvarchar的最大長度爲128)到QUOTENAME功能:

SELECT QUOTENAME(@TableName) AS ScrubbedTableName; 

返回的值然後可以在被使用的TableAdapter查詢沒有SQL注入的風險。但是,如果指定了預期以外的表格,這不會阻止元數據的公開。