[BUUOJ记录] [BJDCTF2020]Easy MD5

各种关于md5的Bypass操作,都是基本操作,考察数组绕过、弱类型比较绕过以及md5($password,true) ByPass

1、利用md5($password,true)实现SQL注入

[BUUOJ记录] [BJDCTF2020]Easy MD5

 

 F12或者Burp抓取响应头可以看到Hint,也就是后端处理的SQL语句:

select * from 'admin' where password=md5($pass,true)

突破点在md5($pass,true)这里,先来看看md5函数的用法:

[BUUOJ记录] [BJDCTF2020]Easy MD5

 

 可以看到这里的raw参数是True,意为返回原始16字符二进制格式。

也就是说如果md5值经过hex转成字符串后为 'or'+balabala这样的字符串,则拼接后构成的SQL语句为:

select * from `admin` where password=''or'balabala'

当'or'后面的值为True时,即可构成万能密码实现SQL注入,这里我们需要知道的是MySQL的一个特性:

在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。 要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。 当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。
当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)  
select * from `admin` where password=''or'1abcdefg'    --->  True
select * from `admin` where password=''or'0abcdefg'    --->  False
select * from `admin` where password=''or'1'           --->  True
select * from `admin` where password=''or'2'           --->  True
select * from `admin` where password=''or'0'           --->  False

只要'or'后面的字符串为一个非零的数字开头都会返回True,这就是我们的突破点。

我们可以通过这个脚本来获得满足我们要求的明文:

<?php 
for ($i = 0;;) { 
 for ($c = 0; $c < 1000000; $c++, $i++)
  if (stripos(md5($i, true), '\'or\'') !== false)
   echo "\nmd5($i) = " . md5($i, true) . "\n";
 echo ".";
}
?>

//引用于 http://mslc.ctf.su/wp/leet-more-2010-oh-those-admins-writeup/

这里提供一个最常用的:ffifdyop,该字符串md5加密后若raw参数为True时会返回 'or'6<trash> (<trash>其实就是一些乱码和不可见字符,这里只要第一位是非零数字即可被判定为True,后面的<trash>会在MySQL将其转换成整型比较时丢掉)

所以如果这里我们输入ffifdyop,后端的SQL语句会变成:

select * from `admin` where password=''or'6<trash>'           --->  True

成功构成SQL注入,我们在本题直接输入ffifdyop即可进入下一关

[BUUOJ记录] [BJDCTF2020]Easy MD5

 

 2、PHP md5弱类型比较

进入第二关后右键查看源代码可以从注释中得到后端PHP的一部分源码:

$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
    // wow, glzjin wants a girl friend.

可以看到,赵师傅又在征婚了  这里要求a和b明文值不同,但md5值相同,注意这里是两个等于号,是弱相等,所以我们可以利用PHP的弱类型比较突破,寻找两个明文不同但md5值为"0exxxxx"的字符串,可以参考我之前的一篇文章:https://www.cnblogs.com/yesec/p/12232075.html

这里直接提供两个QNKCDZO和s214587387a,用GET传值直接过关

3、数组绕过

进入第三关给出了源码:

 <?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} 

可以看到依旧是md5比较,但是不同于第二关,这一关是“===“强相等,很明显2中的方法没办法通过

刚才推荐的那一片文章里文末也提到了这种方法,这里需要知道的是PHP的一些特性:

md5(array()) = null
sha1(array()) = null    
ereg(pattern,array()) = null vs preg_match(pattern,array) = false
strcmp(array(), "abc") = null
strpos(array(),"abc") = null

引用自 https://blog.csdn.net/q1352483315/article/details/89469928

md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。

所以直接POST传入param1[]=1&param2[]=2即可得到Flag:

[BUUOJ记录] [BJDCTF2020]Easy MD5

 

 

 

上一篇:谷歌支付 Android 之父 9000 万美元,为其性丑闻埋单


下一篇:[BJDCTF2020]Cookie is so stable