1. 程式人生 > >sql注入攻擊初探與例項分析

sql注入攻擊初探與例項分析

      來看看錶的結構:

mysql> show create table zzz;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                            |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| zzz   | CREATE TABLE `zzz` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `password` varchar(64) NOT NULL,
  `score` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> 

      表內容:

mysql> select * from zzz;
+----+-------+----------+-------+
| id | name  | password | score |
+----+-------+----------+-------+
|  1 | taoge | 123      |   100 |
+----+-------+----------+-------+
1 row in set (0.00 sec)

mysql> 

      要說明的是, 把密碼明文儲存起來, 本身就是不安全的。 即使用密文儲存, 也不安全, 應該考慮用加鹽雜湊。 但本文為了簡便起見, 先不討論這個問題。

      現在假設有一個頁面, 需要使用者輸入name和password,  然後查詢score的值, 頁面請求傳送到後臺, 後臺查詢虛擬碼為:

string strName = ... ;
string strPassword = ... ;

select * from zzz where name=strName and password=strPassword  ...

      此時,如果taoge自己查詢, 那麼輸入name(taoge)和password(123)後, 執行的查詢操作是:

mysql> select * from zzz where name='taoge' and password='123';
+----+-------+----------+-------+
| id | name  | password | score |
+----+-------+----------+-------+
|  1 | taoge | 123      |   100 |
+----+-------+----------+-------+
1 row in set (0.00 sec)

mysql> 

       可以正確查到自己的分數, 合情合理。

      但是, 上面的程式碼有sql注入風險, 假設Jack想查詢taoge的分數, 但又不知道taoge的密碼, 怎麼辦呢? 還是可以查詢到的: Jack在頁面分別輸入

       使用者名稱: taoge' or 1 = 1 ; #     

         密碼:hehe

        那麼, 經頁面傳到後臺後, 後臺執行的操作是:

mysql> select * from zzz where name='taoge' or 1 = 1 ; #' and password='hehe';
+----+-------+----------+-------+
| id | name  | password | score |
+----+-------+----------+-------+
|  1 | taoge | 123      |   100 |
+----+-------+----------+-------+
1 row in set (0.00 sec)

      可見, 即使Jack不知道taoge的密碼123, 也是可以通過sql注入的方式得逞的。 在上面語句中, #充當了註釋符號的作用, 而1=1永遠為真, 所以,這相當於繞過了後臺的密碼校驗邏輯。

      後臺系統該怎麼對抗這種sql注入攻擊呢?

      1.  對每個引數進行嚴格校驗

      2. mysql_real_escape_string搞起

      3. 防緩衝區溢位

      ......

      有關sql的注入攻擊, 後面也會繼續介紹。