函數:
md5($string,bool): 得到一個字符串散列值。
其中第二個參數默認爲false,表示該函數返回值是32個字符的十六進制數。
若指定爲true,則表示函數返回的是16字節的二進制格式(這樣通過瀏覽器解析會出現亂碼)。
md5($password,true)的SQL注入問題
這裏需要注意一下MYSQL中的一些數值比較的特徵。
1.當數字和字符串比較時,若字符串的數字部分(需要從頭開始)和數字是相同的,那麼則返回的是true。
select if(1="1a","相等","不相等") as test
if(exp1,stat1,stat2):類似於高級語言中三元運算符。當exp1爲true的是否返回stat1,爲false返回stat2
2.以數字開頭的字符串,若開頭的字符不是0,那麼在做邏輯運算的時候返回的是1,也就是true。
比如以下語句就是一個萬能密碼的例子:
select * from user where password =''or'1234a';
解釋一下:'1234a’會被當做true對待。而任何數和true做邏輯或運算返回的值都是true.
看這個md5($password,true)的漏洞
select * from usera where username = 'admin' and password = md5($pass,true)
若我們可找到字符串,在對該字符串進行md5後能夠得到 'or’加上一個非0的字符就可以繞過。這裏我們可以用到的字符串爲:ffifdyop。它的md5結果是:276f722736c95d99e921722cf9ed621c 。通過這個結果我們可以發現得到16字節的二進制被解析爲字符的結果是:'or’6後面接亂碼 (27是單引號的16進制編碼,67是字母o的16進制…)這樣後構造的sql語句就位
select * from user where password=' 'or'6xxx'
和上面分析的萬能密碼是一致的。
兩變量值不相等,md5計算散列值後相等的繞過
- ==的繞過
PHP中==是判斷值是否相等,若兩個變量的類型不相等,則會轉化爲相同類型後再進行比較。PHP在處理哈希字符串的時候,它把每一個以0e開頭的哈希值都解析爲0。常見的如下:
在md5加密後以0E開頭
- QNKCDZO
- 240610708
- s878926199a
- s155964671a
一下值在sha1加密後以0E開頭
- aaroZmOk
- aaK1STfY
payload: /?a=QNKCDZO&b=240610708
<?php
if($_GET['a'] !== $_GET['b']){
if(md5($_GET['a']) == md5($_GET['b'])){
echo "flag";
}
}
?>
- ===的繞過
===會比較類型,這個時候可以用到PHP中md5()函數無法處理數組(會返回NULL)來實現繞過。
payload: /?a[]=1&b[]=2 (上面==的例子也可以用數組繞過)
<?php
if($_GET['a'] !== $_GET['b']){
if(md5($_GET['a']) === md5($_GET['b'])){
echo "flag";
}
}
?>
MD5碰撞
可以谷歌查找一下MD5值相同的不同字符串。