天天看點

MySQL隐式轉化整理存在的安全問題總結

今天還是和往常一樣看着微信推的訂閱号文章

有一篇 select * from user where uersname=0引起了我的思考

其實這個問題是MySQL隐式轉化整理存在的安全問題

網上一搜比較多,我這裡就參考師傅們寫的文章進行總結和學校

官方給的解釋:

MySQL 的隐式類型轉換原則:

– 兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 做比較時會傳回 1,這兩種情況都不需要做類型轉換

– 兩個參數都是字元串,會按照字元串來比較,不做類型轉換

– 兩個參數都是整數,按照整數來比較,不做類型轉換

– 十六進制的值和非數字做比較時,會被當做二進制串,和數字做比較時會按下面的規則處理

– 有一個參數是 TIMESTAMP 或 DATETIME,并且另外一個參數是常量,常量會被轉換為 timestamp

– 有一個參數是 decimal 類型,如果另外一個參數是 decimal 或者整數,會将整數轉換為 decimal 後進行比較,如果另外一個參數是浮點數,則會把 decimal 轉換為浮點數進行比較

– 所有其他情況下,兩個參數都會被轉換為浮點數再進行比較

注意一個安全問題:假如 password 類型為字元串,查詢條件為 int 0 則會比對上。

在這裡我就隻是總結用法,詳細的原理下面會給出師傅們連結。防止重複造輪子

在一般的網站登入的使用者名和密碼都是varchar類型

這樣就可能存在安全問題(下面讨論就是比較經典,師傅們可以自由發揮好)

select * from user where uersname=$_POST['username']
user表有
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin1   |    12345 |
|  2 | admin2   |      123 |
|  3 | admin3   |      321 |
+----+----------+----------+
           

我們就可以直接利用payload:

select * from user where uersname=0

進行查詢

MariaDB [test]> select * from user where username=0;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin1   |    12345 |
|  2 | admin2   |      123 |
|  3 | admin3   |      321 |
+----+----------+----------+
           

原因就是上面說的進行了隐式轉化 username是varchar類型,但是查詢的時候使用了0(int)類型

這樣username的值就進行了隐式轉化成0,剛剛好0=0,就查詢出來了全部

MariaDB [test]> select "admin"=0;
+-----------+
| "admin"=0 |
+-----------+
|         1 |
+-----------+
#這樣我們就可以嘗試新方法的萬能密碼
           

但是如果username字段裡面的值不能字母開頭的是數字開頭的那就不能進行萬能密碼

MariaDB [test]> select "1213admin"=0;
+---------------+
| "1213admin"=0 |
+---------------+
|             0 |
+---------------+
           

總結:

0. 從上面的例子可以看出,當把字元串轉為數字的時候,其實是從左邊開始處理的。

  1. 如果字元串的第一個字元就是非數字的字元,那麼轉換為數字就是0
  2. 如果字元串以數字開頭

    2.1 如果字元串中都是數字,那麼轉換為數字就是整個字元串對應的數字

    2.2 如果字元串中存在非數字,那麼轉換為的數字就是開頭的那些數字對應的值

參考

https://www.cnblogs.com/rollenholt/p/5442825.html