一、首先是MD5()函數的作用?
MD5()函數的作用是計算字元串的MD5散列。
傳回值:如果成功則傳回已計算的 MD5 散列,如果失敗則傳回 FALSE。
二、PHP == 弱類型比較繞過?
代碼:
<?php
highlight_file(__FILE__);
error_reporting(0);
$flag = "flag{H3rmesk1t_is_a_loser}";
$val1 = $_GET['val1'];
$val2 = $_GET['val2'];
if (isset($_GET['val1']) and isset($_GET['val2']))
{
if ($_GET['val1'] != $_GET['val2'])
{
if ((md5($_GET['val1']) == md5($_GET['val2'])))
echo $flag;
else
echo "you can't get flag";
}
}
?>//此時如果輸入 ver1[]=1&ver2[]=2,傳回flag
這裡比較的是PHP弱類型,需要繞過MD5()。
方法一:數組繞過
由于MD5不能加密數組,在加密數組的時候會傳回NULL,是以我們可以傳入兩個數組繞過。适用于源碼中沒有判斷變量類型或内容,如果加上了過濾函數就不能使用了。
常見的過濾函數:
ctype_alnum(string $text):bool類型
//如果text中所有的字元都是字母或者數字,則傳回true,否則false
is_numeric(mixed $ver):bool類型
//如果ver是數字或者數字字元串,則傳回true,否則傳回false
例如:
<?php
highlight_file(_FILE_);
error_reporting(0);
$flag="flag{123456789}";
$ver1=$_GET['ver1'];
$ver2=$_GET['ver2'];
if(isset($_GET['ver1'])and isset($_GET['ver2']))
{
if($GET['ver1']!=$_GET['ver2'])
{
if((md5($_GET['ver1'])==md5($_GET['ver2'])) and is_numeric($_GET['ver1']) and is_numeric($_GET['ver2']))
echo $flag;//如果加密和ver1和ver2相等且ver1和ver2都是數字或者數字字元串,則..
else
echo "you can't get flag";
}
}
?>//此時如果輸入 ver1[]=1&ver2[]=2,傳回you can't get flag
方法二:科學計數法繞過
原理:可以傳入兩個md5加密後是0e開頭的字元串,但這個以0e開頭的字元串隻能是純數字,這樣php在進行科學計算法的時候會将它轉化為0。
<?php
for($a=1;$a<=1000000000;$a++){
$md5 = md5($a);
if(preg_match('/^0e\d+$/',$md5)){//preg_match函數是進行正規表達式的比對,成功傳回1,否則傳回0,前面的參數是要搜尋的模式、字元串形式,後面的參數指輸入的字元串。
echo $a;
echo "\n";
echo $md5;
echo "\n";
}
}
?>//加密後是0e開頭的數字字元串:
QNKCDZO
240610708
314282422
s878926199a
s155964671a
s214587387a
s214587387a
例如:
<?php
highlight_file(_FILE_);
error_reporting(0);
$flag="flag{123456789}";
$ver1=$_GET['ver1'];
$ver2=$_GET['ver2'];
if(isset($_GET['ver1'])and isset($_GET['ver2']))
{
if($GET['ver1']!=$_GET['ver2'])
{
if((md5($_GET['ver1'])==md5($_GET['ver2'])) and ctype_alnum($_GET['ver1']) and ctype_alnum($_GET['ver2']))
echo $flag;//如果加密和ver1和ver2相等且ver1和ver2都是數字或者數字字元串,則..
else
echo "you can't get flag";
}
}
?>//此時如果輸入 ver1=240610708&ver2=314282422,傳回$flag,此時ver1和ver2加密後都是0e開頭
雙MD碰撞繞過
md和md5後都是以0e開頭的字元串:
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
三、PHP===強類型比較繞過?
代碼:
<?php
highlight_file(_FILE_);
error_reporting(0);
$flag = "flag{122365944454}";
$ver1=$_GET['ver1'];
$ver2=$_GET['ver2'];
if (isset($_GET['ver1']) and isset($_GET['ver2']))
{
if ($_GET['ver1'] != $_GET['ver2']){
if(md5($_GET['ver1'])===md5($_GET['ver2']))
echo $flag;
else
echo "you can't get flag";
}
}
?>
方法:數組繞過
原理同上、過程同上,可使用。
注:使用md5加密後完全相等的兩個字元串繞過,不能用。
這是剛剛同上第二種方法,加密後’oe’開頭的字元串,但因為強比較會比較類型和值,是以不能用這個方法來繞過。
當然可以試試加密後類型和值都完全相等的字元串。有篇部落格說可以利用fastcoll_v1.0.0.5.exe來生成符合條件的字元串,還沒試過,待考察。
連結:https://blog.csdn.net/LYJ20010728/article/details/116779357
四、sql注入類的MD5繞過?
起因:為了資訊的安全,在資料庫裡存放密碼的時候都是進行了加密處理的,大多數查詢語句在沒有進行處理的情況下應該是:
原理:ffifdyop經過MD5加密後變為’or’6xxx阿巴阿巴,
而在mysql中,在用作布爾型判斷時,以數字開頭的字元串會被當成整型,不過由于是字元串,是以後面必須要有單引号括起來的,比如:‘xxx’or’6xxxxxx’,就相當于’xxx’or 6,就相當于 'xxx’or true,是以傳回值是true。
是以查詢時就變成了:
sql代碼:select * from flag where user='amdin' and password=''or'6xxxx',等于 password=''or true == ture
進而實作了繞過。
開始做題:
題目叫easy md5,但是進去看見一個輸入框,直覺跟sql有關,是以往輸入框裡面輸入ffifdyop試試,
果然頁面發生變化:

打開f12看源碼,發現:
這裡直接用科學計數法繞過a和b
這裡我構造了一個payload,
發現一直是404,
發現是自己多打了一個斜杠(部落客糾結了一個小時)
于是修改payload,
得到頁面:
終于看見希望了,flag近在咫尺!
這裡看代碼是php強類型比較,用數組繞過,構造payload如下圖:
得到結果: