浅谈在CTF题中三种MD5比较

admin 2023年3月12日20:24:59浅谈在CTF题中三种MD5比较已关闭评论320 views字数 3054阅读10分10秒阅读模式

MD5是什么?

MD5是一种应用广泛的密码散列函数,MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年面世,用于取代MD4,MD5也是由MD2\MD3\MD4迭代而来的,由于其算法的复杂度高和不可逆性,截至目前,依然是应用最广泛的算法之一,虽然复杂程度很高,但是很快有专家在1996年提出MD5这种算法是存在弱点,容易被破解,再到后来2004年,被证实无法防止碰撞,目前MD5也很常见与验证文件的完整性,数据库密码,数字签名等领域;

MD5特征

MD5由于0-9,a-f组成的最低16位,最高32位的哈希字符串

md5本质也是哈希函数,是一种单向密码体制,在上面提到的MD5不可逆性,主要是体现在任意值可以转换成MD5,但是MD5却不能直接逆转成一个准确的字符串,就算是100位字符串转成md5,也是会得到一串32位的哈希字符串,在某乎看了一些大佬的解释,普通字符串在加密的md5过程中,只会挑取一些有用的信息进行计算,过程中丢弃了大部分的信息,这也是不可逆的原因,就好比一盆泼出去的水,怎么可能完整收的回来。一个字符串可能就只是对应一个md5值,但是算出来的md5值可能会对应多个值,虽然这看起来不可逆,但是通过MD5碰撞还是有可能逆向出来的。

现在最大的md5查询网站还是md5在线解密破解,md5解密加密 (cmd5.com),可以解出来比较多常见的md5编码。

浅谈在CTF题中三种MD5比较

大致了解了MD5算法,接下来开始进入正题!!!

"=="和"==="的区别

== 是等于运算符,而===是全等运算符,两者之间最大的区别在于如何处理等号两边的字符串。首先==是一种常见于弱类型题目中,之所以常用于弱类型,是因为在进行比较时,不同类型的,会被转换成数字,如下所示:

var_dump('1' == 1); //true
var_dump('1a' == 1); //true
var_dump('1a1' == 1); //true
var_dump('a123' == 0); //true
var_dump('1aa' == 0); //false

同时还要特别提到一点,就是0exxxxxxxxxxxxxxxxxxxxxxxxxxxx,php在处理0e开头的字符串时,会当成科学计数法进行处理,0e123222222等于0,0e66666666666666666666等于0,0e后面跟任何数字都等于0,php手册的解释如下

浅谈在CTF题中三种MD5比较

翻译:这种比较是正确的,因为两个md5()散列都以“0e”开头,所以PHP类型杂耍将这些字符串理解为科学符号。根据定义,任何幂的零都是零。

弱类型

show_source(__FILE__);
include('flag.php');
\$username = \$_GET['username'];
\$password = \$_GET['password'];
if(\$username != \$password){
if(md5(\$username) == md5(\$password)){
echo 'GET_FLAG:'.\$flag;
}else{
echo 'md5校验出错...';
}
}else{
echo '用户名密码不能相等!';
}

上面的例题中,要求两个字符串不能相等,但是又要求他们的MD5相等,看着无理取闹,实际上一切皆有可能。

上面我们补充了一个点,就是0e后面无论跟多大的数字都等于0,而且代码中的第四行md5($key_1) == md5($key_2)用的是==,也就是说,这里存在弱类型比较,由于md5几乎很难找得到相等的,除非被加密的两个值相等,还真的想不出不同值如何相等,但是如果让两个0e开头的字符串进行比较呢?这里任意挑了四个经过md5加密后是0e开头的字符串来进行对比,结果都等于true。

浅谈在CTF题中三种MD5比较

说明两个0e开头的值进行比较,会被当成科学计数法,0e永远等于零,所以就比较成功了。所以这一题的题解意见很明显了,就是找两个值加密后0e开头,且0e后面是纯数字的字符串即可,这里列出来一些常见的:

| 字符串 | 所对应的MD5值 |
| ------------- | ---------------------------------- |
| QNKCDZO | 0e830400451993494058024219903391 |
| s878926199a | 0e545993274517709034328855841020 |

| s155964671a | 0e342768416822451524974117254469 |
| -------------- | ---------------------------------- |
| s1502113478a | 0e861580163291561247404381396064 |

| s1885207154a | 0e509367213418206700842008763514 |
| -------------- | ---------------------------------- |
| s214587387a | 0e848240448830537924465865611904 |

还有很多......各位师傅可以自己找,但是也没必要,随便挑两个就可以绕过了。

浅谈在CTF题中三种MD5比较

强比较

做了上面的题目之后,大概可以了解到弱类型比较的用法,接下来给大家讲讲===全等于比较,无论是类型还是值,都必须相等,有一样不相等,都会返回false,如果是这样子的话,那么就无法用0e的特性进行比较了,只能找别的方法了,先看代码:

\<?php
header("Content-Type:text/html;charset=utf-8");
show_source(__FILE__);
error_reporting(0);
\$key_1 = \$_GET['key1'];
\$key_2 = \$_GET['key2'];
if(\$key_1 != \$key_2){
if(md5(\$key_1) === md5(\$key_2)){
echo 'flag_ini_there';
}else{
echo 'md5 not ==';
}
}else{
echo '不能相等';
}
?>

主体代码和第一个例子大同小异,主要是==变成了===,这里就不能使用类型不同和0e去解题了,只能另外找别的方法。

md5函数不仅能加密数字,字符串,还能加密数组,虽然加密数组时会报警告warning:Warning: md5() expects parameter 1 to be string, array given in D:\phpstudy_pro\WWW\20221202\index.php on line 2

浅谈在CTF题中三种MD5比较

当传入一个数组给md5时,会发现报了warning,但是在warning下面发现还是执行了var_dump,输出为null,这是我们可以想到,如果两个都是null,那岂不是可以相等了!?话不多说,试试就知道了!

<?php
var_dump(md5(\$_GET['v']) === md5(\$_GET['f']));
?>

传入两个数组,查看布尔值

浅谈在CTF题中三种MD5比较

当两个都为null时,且类型也相同,所以两者比较都为true。这不,题解不就来了,直接传入两个数组,且值不相同即可,传入两个数组已经达到了类型相同的条件,不同的值,虽然没有满足值相等,但是也绕过了\$key_1 != \$key_2,而且这个也不重要,md5加密数组怎样都是等于null的。

传入payload:/?key1[]=1&key2[]=2

浅谈在CTF题中三种MD5比较

kiwiCTF-MD5Games1

```

?>
\

Find a string that has a MD5 digest equal to itself!\

\

\
\
\
\

\Source Code\
```

这道题目和前面俩有点不一样,关键性代码在于$md5==md5($md5),这个代码的意思就是要传入的值等于传入的值md5加密后的值,有点拗口,其实很好理解,就是说比如传入了123,那么如果123=md5(123)就可以继续执行后面的操作了,其实这道题看起来很难,实际上并不会很难,回顾我们刚刚说到的0e,如果两个都是0e开头的值进行比较的话,那么就可以相等。到这里,已经说得很透了,要解除这题,就必须传入一个0exxxxxxxxx(纯数字)等于md5(0exxxxxxxxx),这是就需要要爆破才能找到一个经过md5加密后还是0e开头的值,这里贴上一个临时写的py脚本,跑得有点慢:

import hashlib
for i in range(100000000,99999999999999):
e0 = '0e'+str(i)
md5en = hashlib.md5(e0.encode()).hexdigest()
if md5en[0:2] == '0e' or md5en[3:32].isdigit():
print(e0)

写的脚本可能很慢久才能碰出一个来,所以在网上找了一些现成的可以直接用的:

| \$md5 | md5(\$md5) |
| ------------------- | -------------------------------------- |
| 0e00275209979 | 0e551387587965716321018342879905 |
| 0e00928251504 | 0e148856674729228041723861799600 |
| 0e02739970294 | 0e894318228115677783240047043017 |
| 0e02218562930 | 0e151492820470888772364059321579 |
| 0e01875552079 | 0e780449305367629893512581736357 |
| 0e03393034171 | 0e077847024281996293485700020358 |

随便选一个传入即可得到flag:

浅谈在CTF题中三种MD5比较

这里分享一下我在解题中遇到的疑惑,就是0e后面不要跟有字母,只能是纯数字!!!要不然无法相等,所以使用脚本可能要十分钟到几十分钟才能碰撞出来一个,最好是直接用现成的,毕竟比较快!

题目链接

Catf1agCTF - 综合训练平台

文中三中类型的题目都在平台里面,在WEB区,建议学习完后可以实操一下,以验收是否理解了这个知识点~

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月12日20:24:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅谈在CTF题中三种MD5比较https://cn-sec.com/archives/1599509.html