[Security - SQL Injection 類別] 較安全的程式碼撰寫方法 - 前篇

  • 5972
  • 0
  • 2015-11-27

[Security - SQL Injection 類別] 較安全的程式碼撰寫方法

前言:

造成資安問題的原因繁多,本篇以紀錄AP端 - SQL Injection 類別為主,請參考OWASPOWASP Top 10

OWASP Top 10 For 2010:(Injection 問題)

之前看到祭司大的這噗 ~ 反思~大家都說SqlParameter就能全擋掉SQL Injection....

正好公司起了專案,所以自己整理一些資料放上來紀錄,亦不定時更新,以下的示範、寫法、觀念上不足之處,請大家不吝給予指正。

前置介紹與準備:

資料庫:AdventureWorks

檢視表:HumanResources.vEmployee,資料總筆數:290 筆

輸出欄位:City, FirstName, Phone, EmailAddress, AddressLine1

命令:SELECT City, FirstName, Phone, EmailAddress, AddressLine1 FROM HumanResources.vEmployee WHERE City='Seattle' (查出筆數為 44 筆)

以下操作方式;並以 SQL Server Profiler 追縱事件命令 (如何操作 SQL Server Profiler,可參考使用 SQL Server Profiler 追蹤事件)

1. 觸發不安全寫法,傳入City 條件參數:

    a. 正常值:Seattle

    b. 不正常值:'or'1'='1

2. 觸發較安全寫法,傳入City 條件參數:

    a. 正常值:Seattle

    b. 不正常值:'or'1'='1

SQL Server Profiler 畫面:

畫面:

ASP.NET前置介紹與準備:

一、.CS 未使用SqlParameter方式進行查詢動作

///<summary>
///未使用SqlParameter方式進行查詢動作 
///</summary>
protected void btnUnSecurity_Click(object sender, EventArgs e) 
{ 
    DataTable dt = new DataTable(); 
    string sqlStatement = string.Empty; 
    using (ConnectionString) 
    { 
        try 
        { 
            ConnectionString.Open(); 
            SqlCommand sqlCommand; 
            sqlStatement = @"SELECT City,FirstName,Phone,EmailAddress,AddressLine1 FROM HumanResources.vEmployee WHERE City='" + this.txtCity1.Text.Trim() + "'"; 
            sqlCommand = new SqlCommand(sqlStatement, ConnectionString); 
            SqlDataAdapter adapter = new SqlDataAdapter(sqlCommand); 
            adapter.Fill(dt); 
        } 
        catch 
        { 
            this.lblMsg.Text = "無符合的資料!"; 
            this.lblMsg.ForeColor = Color.Red; 
        } 
    } 
	
    if (dt.Rows.Count > 0) 
    { 
        this.lblTotal.Text = dt.Rows.Count.ToString(); 
        this.gvEmployee.DataSource = dt; 
        this.gvEmployee.DataBind(); 
    } 
    else 
    { 
        this.lblMsg.Text = "無符合的資料!"; 
        this.lblMsg.ForeColor = Color.Red; 
        this.lblTotal.Text = "0"; 
        this.gvEmployee.DataSource = null; 
        this.gvEmployee.DataBind(); 
    } 
}

畫面結果圖:

a. Web 畫面 - 輸入 參數:Seattle

SQL Server Profiler 畫面:

追蹤紀錄:

實際執行命令:

b. Web 畫面 - 輸入 參數:'or'1'='1

SQL Server Profiler 畫面:

追蹤紀錄:

實際執行命令:

說明:

未使用 SqlParameter 方式,傳入值是 「'or'1'='1」時,條件 or 1=1,恆成立,會導致甚麼資料都可以查詢出,

甚至如果 輸入值為「'or'1'='1; drop table [Table_Name]」,可想而知其嚴重性,故較為不安全。

二、.CS 使用SqlParameter方式進行查詢動作

///<summary>
///使用SqlParameter方式進行查詢動作 
///</summary>
protected void btnSecurity_Click(object sender, EventArgs e) 
{ 
    DataTable dt = new DataTable(); 
    string sqlStatement = string.Empty; 
    using (ConnectionString) 
    { 
        try 
        { 
            ConnectionString.Open(); 
            SqlCommand sqlCommand; 
            sqlStatement = @"SELECT City,FirstName,Phone,EmailAddress,AddressLine1 FROM HumanResources.vEmployee WHERE City=@City"; 
            sqlCommand = new SqlCommand(sqlStatement, ConnectionString); 
            sqlCommand.Parameters.AddWithValue("@City",this.txtCity1.Text.Trim()); 
            SqlDataAdapter adapter = new SqlDataAdapter(sqlCommand); adapter.Fill(dt); 
        } 
        catch 
        { 
            this.lblMsg.Text = "無符合的資料!"; 
            this.lblMsg.ForeColor = Color.Red; 
        } 
    } 
	
    if (dt.Rows.Count > 0) 
    { 
        this.lblTotal.Text = dt.Rows.Count.ToString(); 
        this.gvEmployee.DataSource = dt; 
        this.gvEmployee.DataBind(); 
    } 
    else 
    { 
        this.lblMsg.Text = "無符合的資料!"; 
        this.lblMsg.ForeColor = Color.Red; 
        this.lblTotal.Text = "0"; 
        this.gvEmployee.DataSource = null; 
        this.gvEmployee.DataBind(); 
    } 
}

畫面結果圖:

a. Web 畫面 - 輸入 參數:Seattle

SQL Server Profiler 畫面:

追蹤紀錄:

實際執行命令:

說明:

使用 SqlParameter 方式,命令轉換為 Store Procedure 執行處理,傳入值則會以 「字串」 參數給 Where 條件使用。

其中的 nvarchar(7) ,是以輸入的 字串長度  而定。

b. Web 畫面 - 輸入 參數:'or'1'='1

SQL Server Profiler 畫面:

追蹤紀錄:

實際執行命令:

說明:

使用 SqlParameter 方式,命令轉換為 Store Procedure 執行處理,傳入值則會以 「字串」 參數給 Where 條件使用,其中的 nvarchar(9) ,是以輸入的 字串長度  而定。

所以即使傳入值是 「'or'1'='1」,也將其視為 ''or'1'='1' 的字串,故較為安全。

結語說明:

後續亦會逐步更新相關寫法。

以上為的示範,寫法、觀念上不足之處,請大家見諒,也麻煩大家不吝給予指教。

參考資料:

1. 黑暗大的一系列 資安文章 (一定要拜讀的)

2. Will 保哥 的系列 資安文章 (一定要拜讀的)