2012-02-09 172 views
4

我通常會創建參數化查詢以避免SQL注入攻擊。不過,我有這個特殊的情況下,我還沒有完全能夠做到這一點:此查詢是否存在SQL注入風險?如果是這樣,我該如何避免它?

public DataSet getLiveAccountingDSByParameterAndValue(string parameter, string value) 
{ 
    string sql = "select table_ref as Source, method as Method, sip_code as Code, " + 
     " from view_accountandmissed " + 
     " where " + parameter + " like @value " + 
     " order by time DESC "; 
    MySqlCommand cmd = commonDA.createCommand(sql); 
    cmd.Parameters.Add("@value", MySqlDbType.String); 
    cmd.Parameters["@value"].Value = "%" + value + "%"; 

    MySqlDataAdapter objDA = commonDA.createDataAdapter(cmd); 
    DataSet objDS = new DataSet(); 
    objDA.Fill(objDS); 
    return objDS; 
} 

正如你所看到的,我創建@value作爲參數,但如果我試圖做同樣的參數查詢將失敗。

那麼,這個查詢是否存在SQL注入的風險?另外,考慮到參數設置DropDownList的SelectedValue(不是TextBox,所以輸入是有限的)。如果是這樣,我該如何改進這個查詢?

+2

有一定的風險。設想一些惡意用戶通過瀏覽器開發工具修改你的輸入表單,並輸入類似'1 = 1; DROP TABLE important_table; ...'作爲參數值... – 2012-02-09 10:01:20

+2

隨着網站(因爲它的標籤爲asp.net)不信任任何客戶端,因爲它可以用JS(包括下拉列表)修改。 – 2012-02-09 10:01:56

+0

+1用於檢查。這肯定有一個SQL注入風險。 – Curt 2012-02-09 10:02:45

回答

4

是的,有:

" where " + parameter + " like @value " + 

參數的值是你的風險。在回發中,您應該檢查所選值是否在下拉列表的一組起始值中。

使該參數成爲枚舉並將枚舉傳遞給函數。這將消除風險(喜歡的東西:未測試):

public DataSet getLiveAccountingDSByParameterAndValue(ParameterEnum parameter, string value) 
..... 
    " where " + parameter.ToString() + " like @value " + 

的ParameterEnum包含在下拉列表中的所有可能值的列表。在您的代碼後面,將選定的值解析爲枚舉。

+1

由於ASP.NET 2.0會檢查當'EnableEventValidation'設置爲'true'時,項目已經改變。你會得到一個異常:「回發或回調參數無效」。 http://odetocode.com/blogs/scott/archive/2006/03/20/asp-net-event-validation-and-invalid-callback-or-postback-argument.aspx – 2012-02-09 10:06:53

+0

默認情況下,您是正確的。但如果你是其他人確實改變了默認值,你就會有風險。 – Peter 2012-02-09 10:09:55

+0

是的,但我認爲值得注意。大多數時候人們會抱怨這個功能,並問如何擺脫它,但這是一個很好的例子,當它有用。 – 2012-02-09 10:11:45

2

So, is there a risk of SQL Injection with this query?

我想是的,它很容易被SQL注入。例如,參數 = 「1 = 1 OR值」

Also, take into account that parameter is set by a DropDownList's SelectedValue (not a TextBox, so the input is limited)

其實並不重要。惡意用戶可以在可執行文件本身或網絡數據包上注入任何值(並因此發送DropDown上不存在的值)。

If so, how can I improve this query?

您應該檢查參數參數,並與下拉值進行比較。對於更通用的數據,我認爲應該有庫來檢查這些事情(但我沒有C#的想法......)。

1
var columns = new [] {"column1", column2", ....}; 
if (!columns.Contains(parameter)) 
    return or do something else 

編輯
唯一的SQL注入風險是在傳遞列名稱,其中使用字符串連接子句。沒有其他辦法。真正的盾牌是檢查列名是否有效,它存在於表中。
即使ASP .Net有事件驗證(檢查發佈的值是其中一個下拉列表),您無法基於此,因爲可以禁用此保護。
與like一起使用的參數不是SQL注入對象

+0

這是如何回答這個問題的? – m0skit0 2012-02-09 10:03:30

+0

列名是衆所周知的,因此請檢查參數是否爲有效列名 – 2012-02-09 10:04:59

+0

仍然不好,因爲您可能不希望所有列都被訪問。而且你還使用* Contains *,它允許像「column1; DROP TABLE ...」這樣的東西。「 – m0skit0 2012-02-09 10:08:55

1

由於ASP.NET自動驗證回發和回調參數以查看它們是否有所不同。所以這是一個很好的例子,它對EnableEventValidation有用。

http://odetocode.com/blogs/scott/archive/2006/03/20/asp-net-event-validation-and-invalid-callback-or-postback-argument.aspx

你會得到那麼以下情況除外:

"Invalid postback or callback argument"

你可以確保它的設置爲 true在頁面的 Init事件明確地將其設置在代碼隱藏,例如:

protected void Page_Init(object sender, EventArgs e) 
{ 
    // don't remove this 
    Page.EnableEventValidation = True; 
} 

編輯:哎呀,其實這個設置不能從代碼隱藏的改變,但編譯,但會引發以下運行時錯誤:

The 'EnableEventValidation' property can only be set in the page directive or in the configuration section.

+0

+1使我們意識到這一點。諷刺的是,我也曾經抱怨過這個屬性。儘管如此,我還是給了@peer正確的答案,因爲我可能在某些特定情況下禁用了頁面事件驗證 – aleafonso 2012-02-09 10:30:24

+0

@aleafonso:是的,因此我已經展示瞭如何確保它在此頁面設置爲true,並且不會(即使有人在頁面指令或web.config中設置了「EnableEventValidation = false」)。 – 2012-02-09 10:35:45

+0

我希望我能標記兩個答案是正確的,因爲他們都是正確的。非常感謝 – aleafonso 2012-02-09 10:45:11

相關問題