匯總下php中md5()的安全問題
安全問題1:
1.x=任意字符串 md5('x')=0e***
2.y=任意字符串 md5('y')=0e***
如果x==y,php會返回true,在有些時候可以繞過邏輯判斷
x==0 /y==0都為true,有些時候可以用來繞過邏輯判斷
原理:php使用==會把兩邊的數值進行類型轉換,0e***都轉換成了0
例子var_dump(md5('240610708') == md5('QNKCDZO')); 返回true
修復方案,進行類型匹配使用強等於(===)進行判斷
安全問題2:
md5 ( string $str
[, bool $raw_output
= FALSE
] ) : string
如果設置第二個參數為true,那么 MD5 報文摘要將以16字節長度的原始二進制格式返回。
就是說返回16個字節
漏洞測試demo:
md5_login.html
<html> <head>用戶登錄</head> <form name="LoginForm" method="post" action="md5_loop.php" onSubmit="return InputCheck(this)"> <p> <label for="username" class="label">用戶名:</label> <input id="username" name="username" type="text" class="input" /> <p/> <p> <label for="password" class="label">密 碼:</label> <input id="password" name="password" type="password" class="input" /> <p/> <p> <input type="submit" name="submit" value=" 確 定 " class="left" /> </p> </form> </html>
md5_loop.php
<?php $username=$_POST['username']; $password=$_POST['password']; error_reporting(0); $link = mysql_connect('localhost', 'root', 'root'); if (!$link) { die('Could not connect to MySQL: ' . mysql_error()); } // 選擇數據庫 $db = mysql_select_db("test", $link); if(!$db) { echo 'select db error'; exit(); } // 執行sql //$password = "admin"; $sql = "SELECT * FROM login WHERE username='$username' and password = '".md5($password,true)."'"; var_dump($sql); $check_query=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' ); if($result = mysql_fetch_array($check_query)){ echo "login true"; } else { exit('登錄失敗!點擊此處 <a href="javascript:history.back(-1);">返回</a> 重試'); } //$row1 = mysql_fetch_row($result); //var_dump($row1); mysql_close($link); ?>
當用戶輸入任意賬號和密碼ffifdyop
就可以登錄系統:
任意登錄原理講解:
首先是sql語句:
SELECT * FROM login WHERE username='hello' and password=''
如果password萬能密碼是SELECT * FROM login WHERE username='hello' and password='' or '1'--+
他會提示登錄成功,如果是' or '1aaa會進行類型轉換,轉換成int類型的1,or '1aaa相當於1,那么' or 'a1就相當於0
0相當於false
因為設置md5設置第二個參數是true,那么會自動截取前16個字節的數據
就是:md5('ffifdyop')= 276f722736c95d99e921722cf9ed621c
獲取十六個字節=276f722736c95d99
十六個字節轉換成字符串就是%27%6f%72%27%36%c9%5d%99
解碼
再次帶入數據庫查詢就是:
SELECT * FROM login WHERE username='hello' and password = ''or'6蒥欓!r,b'
mysql中,只要不是0和空等,那就為true。
修復方案:md5+鹽(salt)+別設置true
黑盒測試的時候可以嘗試:任意賬號+密碼ffifdyop