2013-03-14 63 views
4

我目前有一個網站,具有正常的註冊和登錄,用ASP.net編碼。 我正在使用Access數據庫,而我的朋友使用C#類來處理大部分數據庫操作(executeQuery,executeRead,isExits ...)。使用ASP.net和Access數據庫從SQL注入安全的網站

現在我幾乎完成了構建我的網站,我想開始添加安全性 - 主要是對我的數據庫。我已經搜索了一段時間的關於這個主題的教程,但是我找不到任何好的exept舊的microsoft msdn文章,我不能真正地讓它的代碼工作。 我現在擁有的最遠的地方就是不允許在用戶名和密碼中使用任何危險字符(例如', - ,;),但它有種感覺,好像它是我可以使用的更糟糕的解決方案(爲什麼我的用戶不應該使用這些字符?)。

我認爲我找到的最好的解決方案是在聲明後將變量插入到查詢字符串中(與「WHERE username = @ user」或類似的東西有關),但我無法獲得它與Access和我的oleDBManager一起使用。

這是我目前的註冊碼。 handle()從字符串中刪除所有',並且Validate()檢查字符串中的危險部分。

 string username = user.Text; 
     string password = pass.Text; 
     bool isThingy = false; 
     if (handle(ref password)) isThingy = true; 
     if (handle(ref username)) isThingy = true; 

     if (username != "" && username != null) 
     { 
      if (password != "" && password != null) 
      { 
       if (Validate(username, password)) 
       { 
        if ((db.IsExist("SELECT * FROM Table1 WHERE username='" + username + "'") == false)) 
        { 
         int a = db.ExecuteQuery("INSERT INTO `Table1`(`username`, `password`, `logins`, `email`, `fname`, `lname`, `country`, `city`, `birthday`, `userid`) VALUES ('" + username + "', '" + password + "', '0', '', '', '', '', '', '', '" + Convert.ToString(Convert.ToInt32(db.ExecuteCellRead("SELECT MAX(userid) FROM Table1")) + 1) + "');"); 

         if (!isThingy) errorLabel.Text = "Your user has been successfully registered"; 
         else errorLabel.Text = "The ' token is invalid. your user was registered absence the '."; 
        } 
        else 
         errorLabel.Text = "This username is already taken"; 
       } 
       else errorLabel.Text = "Invalid name format"; 

      } 
      else errorLabel.Text = "Please enter a password"; 
     } 
     else errorLabel.Text = "Please enter a user name"; 

作爲oleDBManager(在我的代碼命名爲DB):

private OleDbConnection link; // The link instance 
    private OleDbCommand command; // The command object 
    private OleDbDataReader dataReader; // The data reader object 
    private OleDbDataAdapter dataAdapter; // the data adapter object 
    private DataTable dataTable; // the data table object 
    private string dbName; // the Database filename 
    private int version; // the usersTableG office version 
    private string connectionString; // the connection string for the database connection 
    private string provider; // the matching driver string for the connection string 
    private string path; // the path to the database file 


... 


    public int ExecuteQuery(string query) 
    { 
     this.link.Open(); 
     int rowsAffected; 
     // --- 
     this.command = new OleDbCommand(query, this.link); 
     try 
     { 
      rowsAffected = this.command.ExecuteNonQuery(); 
     } 
     catch (InvalidOperationException e) 
     { 
      if (e.Data == null) 
       throw; 
      else 
       rowsAffected = -1; 
     } 
     finally 
     { 
      this.command.Dispose(); 
      this.link.Close(); 
     } 
     // --- 
     return rowsAffected; 
    } 

    public bool IsExist(string query) 
    { 
     this.link.Open(); 
     // --- 
     this.command = new OleDbCommand(query, this.link); 
     this.dataReader = this.command.ExecuteReader(); 
     bool a = this.dataReader.Read(); 
     // --- 
     this.command.Dispose(); 
     this.link.Close(); 
     // --- 
     return a; 
    } 

    public string ExecuteCellRead(string query) 
    { 
     string output = ""; 
     this.dataTable = this.ExcecuteRead(query); 

     foreach (DataRow row in this.dataTable.Rows) 
     { 
      foreach (object obj in row.ItemArray) 
      { 
       output += obj.ToString(); 
      } 
     } 

     return output; 
    } 

所以,你可能會看到,主要的問題是,用戶現在不能使用字符」。 它假設最好的解決方案是在SQL查詢中使用@變量,但我不知道如何。

[感謝您的幫助] PS。我已經改變了我的表格的名稱;)

編輯:你們大多數人告訴我要使用這些參數化查詢,但如果你能給我一個如何使用它們的例子,做到這一點



所以,感謝@Remou,我FINAL代碼:

db.DoWeirdStackOverFlowStuff(
    "INSERT INTO `Table1`(`username`, `password`, `logins`) VALUES (@username, @password, '0');" 
    , new string[] { "@username", "@password" } 
    , new string[] { username, password }); 

public int DoWeirdStackOverFlowStuff(string query, string[] vars, string[] reps) 
    { 
     this.link.Open(); 
     int rowsAffected; 
     // --- 
     this.command = new OleDbCommand(); 
     this.command.CommandText = query; 
     this.command.CommandType = System.Data.CommandType.Text; 
     this.command.Connection = this.link; 

     //Parameters in the order in which they appear in the query 
     for (int i = 0; i < vars.Length; i++) 
      this.command.Parameters.AddWithValue(vars[i], reps[i]); 

     try 
     { 
      rowsAffected = this.command.ExecuteNonQuery(); 
     } 
     catch (InvalidOperationException e) 
     { 
      if (e.Data == null) 
       throw; 
      else 
       rowsAffected = -1; 
     } 
     finally 
     { 
      this.command.Dispose(); 
      this.link.Close(); 
     } 
     // --- 
     return rowsAffected; 
    } 

用於任何需要這種=]

+1

Visual Studio和在線MSDN都有參數化的sql命令的簡單示例。 – Igor 2013-03-14 16:05:12

+0

這裏是SQL注入預防的介紹https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet(我知道它不是.NET特定的,但校長是相同的) – BLSully 2013-03-14 16:06:07

+2

使用參數化的sql命令。黑名單字符不會阻止你從sql注入。你應該只在你的數據庫中保存密碼哈希值。不是他們自己的密碼。並用鹽來保護它們。 – Peter 2013-03-14 16:09:59

回答

1

的一些注意事項

在MS Access,我已要求UpdateUser兩個保存的查詢,它看起來像這樣:

 UPDATE INTERNETSETTINGS 
     SET url = [@url], 
      databasename = [@databasename], 
      port = [@port], 
      username = [@username], 
      [password] = [@password] 

我可以參照此查詢的名字在我的代碼,使用命令對象:

 OleDbCommand Command = new OleDbCommand(); 

     Command.CommandText = "UpdateUser"; //saved query 
     Command.CommandType = System.Data.CommandType.StoredProcedure; 
     Command.Connection = cn; //a connection to the database 

     //Parameters in the order in which they appear in the query 
     Command.Parameters.AddWithValue("@url", "a"); //a,b,c etc for my test run 
     Command.Parameters.AddWithValue("@databasename", "b"); 
     Command.Parameters.AddWithValue("@port","c"); 
     Command.Parameters.AddWithValue("@username", "d"); 
     Command.Parameters.AddWithValue("@password", "e"); 

     Command.ExecuteNonQuery(); 
+0

我還沒有真正得到進入Web編程的這一部分,因爲我已經有準備的C#類做一切對我來說,我很抱歉,如果我是一個有點慢。查詢在你寫的代碼中出現在哪裏? (請問我用它代替「UpdateUser」嗎?) 感謝 這樣的快速幫助,「a」,「b」,「c」和其他的應該用真實變量代替,right只是檢查) – 2013-03-14 16:53:49

+1

我已經添加了一些額外的筆記。你可以有CommandString的sql字符串或保存的查詢,你需要使用適當的CommandType。保存的查詢是最好的,因爲你可以測試它們,而且它們不會混淆你的代碼。只需使用查詢名稱。至於參數,名稱並不重要,除了作爲提示,但你必須按照正確的順序。正如你所說,a,b,c等用於測試,並且我建議你按照你想要的方式做類似的事情。再次 – Fionnuala 2013-03-14 17:06:04

+0

感謝您的幫助,但是,還有一個問題 - 當我運行它打破的'Command.ExecuteNonQuery()的代碼;'行,並稱「預期的查詢名稱後執行」。我將在一分鐘內添加我當前的代碼。 – 2013-03-14 17:18:26

0

我不記得訪問是否做同樣的事情與SQL Server在這裏,但在SQL Server中,你可以通過它加倍逃避單引號:

username = username.Replace("'", "''"); 

因此,您可以在字符串中包含單引號標記,您可以將它們存儲在數據庫中,並且它們不能用作惡意字符串終結符。

+0

,但然後再次用戶名更改(可以說從「喬的」到「喬的'」,是不是很好 – 2013-03-14 16:17:42

+0

實際上 - 它並沒有什麼被寫入到數據庫中的字段是「喬氏」但你要記住,每次使用SQL這個值的時候做更換儘管如此,參數化查詢是。正確的方法來解決這個問題 – Igor 2013-03-14 16:21:20

+0

這種方法,雖然聊勝於無,仍是不可戰勝的,根據一些 - 檢查出[這個答案和鏈接](http://stackoverflow.com/a/139810/111266)其中某種時髦的Unicode劈勾銷報價 - 翻譯技術。 – 2013-03-14 16:41:27