SQL注入漏洞 詳解

來源:互聯網
上載者:User

標籤:應用程式   serve   一個   cat   產生   檔案中   arch   詳細   資料庫預存程序   

漏洞影響

 

攻擊者利用該漏洞可能導致

1.網頁被篡改

2.資料被篡改

3. 核心資料被竊取

4. 資料庫所在伺服器被攻擊變成傀儡主機

 

解決方案:

1.      過濾使用者輸入的內容,檢查使用者輸入的內容中是否有非法內容。如,|(豎線符號)、 & (& 符號)、;(分號)、$(貨幣符號)、%(百分比符號)、@(at 符號)、\‘(單引號)、"(引號)、\\\‘(反斜線轉義單引號)、\\"(反斜線轉義引號)、<>(角括弧)、()(括弧)、+(加號)、 CR(斷行符號符,ASCII 0x0d)、 LF(換行,ASCII 0x0a)、,(逗號)、\\(反斜線)、)(結束括弧)等符號。

2.      過濾危險的SQL語句關鍵字,如select,from,update,insert,delete等。

3.      利用預存程序,將資料訪問抽象化,讓使用者不直接存取表或視圖。當使用預存程序時,請利用 ADO 命令對象來實施它們,以強化變數類型。

4.      使用防注入系統。

5.      修複樣本

Asp.Net

以下是保護 Web 應用程式免遭 SQL 插入式攻擊的兩種可行方法:

5.1  使用預存程序,不用動態構建的 SQL 查詢字串。將參數傳遞給 SQL Server 預存程序的方式,可防止使用單引號和連字號。

以下是如何在ASP.NET 中使用預存程序的簡單樣本:

  \‘ Visual Basic example

  Dim DS As DataSet

  Dim MyConnection AsSqlConnection

  Dim MyCommand AsSqlDataAdapter

 

  Dim SelectCommand As String= "select * from users where username = @username"

  ...

  MyCommand.SelectCommand.Parameters.Add(NewSqlParameter("@username", SqlDbType.NVarChar, 20))

 MyCommand.SelectCommand.Parameters("@username").Value =UserNameField.Value

 

 

  // C# example

  String selectCmd ="select * from Authors where state = @username";

  SqlConnection myConnection =new SqlConnection("server=...");

  SqlDataAdapter myCommand =new SqlDataAdapter(selectCmd, myConnection);

 

 myCommand.SelectCommand.Parameters.Add(newSqlParameter("@username", SqlDbType.NVarChar, 20));

  myCommand.SelectCommand.Parameters["@username"].Value= UserNameField.Value;

5.2  您可以使用驗證控制項,將輸入驗證添加到“Web 表單”頁面。驗證控制項提供適用於所有常見類型的標準驗證的易用機制,例如,測實驗證日期是否有效,或驗證值是否在範圍內,以及進行自訂編寫驗證的方法。此外,驗證控制項還可以使您能夠完整定義向使用者顯示錯誤資訊的方式。驗證控制項可搭配“Web 表單”頁面的類檔案中處理的任何控制項使用,其中包括 HTML 和 Web 伺服器控制項。為了確保使用者輸入僅包含有效值,您可以使用以下其中一種驗證控制項:

5.2.1 “RangeValidator”:檢查使用者條目(值)是否在指定的上下界限之間。 您可以檢查配對數字、字母字元和日期內的範圍。

5.2.2 “RegularExpressionValidator”:檢查條目是否與Regex定義的模式相匹配。 此類型的驗證使您能夠檢查可預見的字元序列,如電子郵件地址、電話號碼、郵遞區號等中的字元序列。最後:驗證控制項不會阻止使用者輸入或更改頁面處理流程;它們只會設定錯誤狀態,併產生錯誤訊息。程式員的職責是,在執行進一步的應用程式特定操作前,測試代碼中控制項的狀態。有兩種方法可檢查使用者輸入的有效性: 1. 測試常規錯誤狀態:在您的代碼中,測試頁面的 IsValid 屬性。該屬性會將頁面上所有驗證控制項的 IsValid 屬性值匯總(使用邏輯 AND)。如果將其中一個驗證控制項設定為無效,那麼頁面屬性將會返回 false。 2. 測試個別控制項的錯誤狀態:在頁面的“驗證器”集合中迴圈,該集合包含對所有驗證控制項的引用。然後,您就可以檢查每個驗證控制項的 IsValid 屬性。

 

PHP

5.3過濾使用者輸入

將任何資料傳給 SQL 查詢之前,應始終先使用篩選技術來適當過濾。 這無論如何強調都不為過。 過濾使用者輸入可讓許多注入缺陷在到達資料庫之前便得到更正。

5.4將使用者輸入加引號

不論任何資料類型,只要資料庫允許,便用單引號括住所有使用者資料。

5.5 轉義資料值

如果使用 MySQL4.3.0 或更新的版本,您應該用 mysql_real_escape_string() 來轉義所有字串。 如果使用舊版的 MySQL,便應該使用mysql_escape_string() 函數。如果未使用 MySQL,您可以選擇使用特定資料庫的特定換碼功能。如果不知道換碼功能,您可以選擇使用較一般的換碼功能,例如,addslashes()。

如果使用 PEAR DB 資料庫抽象層,您可以使用DB::quote() 方法或使用 ? 之類的查詢預留位置,它會自動轉義替換預留位置的值。參考資料http://ca3.php.net/mysql_real_escape_string

http://ca.php.net/mysql_escape_string

http://ca.php.net/addslasheshttp://pear.php.net/package-info.php?package=DB

 

5.6輸入資料驗證:雖然為方便使用者而在用戶端層上提供資料驗證,但仍必須始終在伺服器層上執行資料驗證。用戶端驗證本身就不安全,因為這些驗證可輕易繞過,例如,通過禁用 Javascript。一個好的設計通常需要 Web 應用程式架構,以提供伺服器端公用程式常式,從而驗證以下內容:必需欄位,欄位資料類型(預設情況下,所有 HTTP 要求參數都是“字串”),欄位長度,欄位範圍,欄位選項,欄位模式, cookie 值,HTTP 響應等,以下部分描述一些檢查的樣本。

  // PHP example to validaterequired fields

  functionvalidateRequired($input) {

      ...

      $pass = false;

      if(strlen(trim($input))>0){

          $pass = true;

      }

      return $pass;

      ...

  }

  ...

  if(validateRequired($fieldName)) {

      // fieldName is valid,continue processing request

      ...

  }

J2EE

** 先行編譯語句:

以下是保護應用程式免遭 SQL 注入(即惡意篡改 SQL 參數)的三種可行方法。使用以下方法,而非動態構建 SQL 陳述式:

5.7 PreparedStatement,通過先行編譯並且儲存在PreparedStatement 對象池中。 PreparedStatement 定義 setter 方法,以註冊與受支援的 JDBC SQL 資料類型相容的輸入參數。例如,setString 應該用於 VARCHAR 或 LONGVARCHAR 類型的輸入參數(請參閱 Java API,以擷取進一步的詳細資料)。通過這種方法來設定輸入參數,可防止攻擊者通過注入錯誤字元(如單引號)來操縱 SQL 陳述式。

如何在 J2EE 中使用 PreparedStatement 的樣本:

 

  //J2EE PreparedStatemenet Example

  //Get a connection to the database

 Connection myConnection;

  if(isDataSourceEnabled()) {

     // using the DataSource to get a managed connection

     Context ctx = new InitialContext();

     myConnection =((DataSource)ctx.lookup(datasourceName)).getConnection(dbUserName, dbPassword);

  }else {

     try {

         // using the DriverManager to get a JDBC connection

         Class.forName(jdbcDriverClassPath);

         myConnection = DriverManager.getConnection(jdbcURL, dbUserName,dbPassword);

     } catch (ClassNotFoundException e) {

         ...

     }

  }

  ...

  try{

     PreparedStatement myStatement =myConnection.prepareStatement("select * from users where username =?");

      myStatement.setString(1, userNameField);

     ResultSet rs = myStatement.executeQuery();

     ...

     rs.close();

  }catch (SQLException sqlException) {

     ...

  }finally {

     myStatement.close();

     myConnection.close();

  }

 

 

5.8 CallableStatement,擴充PreparedStatement 以執行資料庫 SQL 預存程序。該類繼承 PreparedStatement 的輸入 setter 方法(請參閱上面的 [1])。

以下樣本假定已建立該資料庫預存程序:

CREATE PROCEDURE select_user (@usernamevarchar(20)) AS SELECT * FROM USERS WHERE USERNAME = @username;

如何在 J2EE 中使用 CallableStatement 以執行以上預存程序的樣本:

 

  //J2EE PreparedStatemenet Example

  //Get a connection to the database

 Connection myConnection;

  if(isDataSourceEnabled()) {

     // using the DataSource to get a managed connection

     Context ctx = new InitialContext();

     myConnection =((DataSource)ctx.lookup(datasourceName)).getConnection(dbUserName, dbPassword);

  }else {

     try {

         // using the DriverManager to get a JDBC connection

         Class.forName(jdbcDriverClassPath);

         myConnection = DriverManager.getConnection(jdbcURL, dbUserName,dbPassword);

     } catch (ClassNotFoundException e) {

         ...

     }

  }

  ...

  try{

     PreparedStatement myStatement = myConnection.prepareCall("{?= callselect_user ?,?}");

     myStatement.setString(1, userNameField);

     myStatement.registerOutParameter(1, Types.VARCHAR);

     ResultSet rs = myStatement.executeQuery();

     ...

     rs.close();

  }catch (SQLException sqlException) {

     ...

  }finally {

     myStatement.close();

     myConnection.close();

  }

 

 

5.9實體 Bean,代表持久儲存機制中的EJB 業務對象。實體 Bean 有兩種類型:bean 管理和容器管理。當使用 bean 管理的持久性時,開發人員負責撰寫訪問資料庫的 SQL 代碼。當使用容器管理的持久性時,EJB 容器會自動產生 SQL 代碼。因此,容器要負責防止惡意嘗試篡改產生的 SQL 代碼。

如何在 J2EE 中使用實體 Bean 的樣本:

  //J2EE EJB Example

  try{

      // lookup the User home interface

     UserHome userHome = (UserHome)context.lookup(User.class);   

     // find the User remote interface

     User = userHome.findByPrimaryKey(new UserKey(userNameField));   

     ...   

  }catch (Exception e) {

      ...

  }

 

 

推薦使用的 JAVA 工具不適用

參考資料http://java.sun.com/j2se/1.4.1/docs/api/java/sql/PreparedStatement.htmlhttp://java.sun.com/j2se/1.4.1/docs/api/java/sql/CallableStatement.html

SQL注入漏洞 詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.