MD5绕过
Posted H3rmesk1t
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MD5绕过相关的知识,希望对你有一定的参考价值。
MD5绕过
MD5弱类型比较
<?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";
}
}
?>
<?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'])) and (md5(md5($_GET['val2'])) == md5(md5($_GET['val1']))))
echo $flag;
else
echo "you can't get flag";
}
}
?>
方法一:数组绕过
由于md5不能加密数组,在加密数组的时候会返回NULL,所以我们可以传入两个数组
数组绕过适用于源码中没有判断变量类型或内容,如果加上了过滤函数就不能使用了
常见过滤函数如下:
ctype_alnum ( string $text ) : bool
// 如果text中所有的字符全部是字母和(或者)数字,返回 TRUE 否则返回FALSE
is_numeric ( mixed $var ) : bool
// 如果 var 是数字和数字字符串则返回 TRUE,否则返回 FALSE
方法二:科学计数法绕过
可以传入两个md5加密后是0e开头的字符串,需要注意的地方是,这个以0e开头的字符串只能是纯数字,这样php在进行科学计算法的时候才会将它转化为0;可以查找以0e开头md5加密相等的字符串,也可以自己编写代码,提供以下脚本
<?php
for($a=1;$a<=1000000000;$a++){
$md5 = md5($a);
if(preg_match('/^0e\\d+$/',$md5)){
echo $a;
echo "\\n";
echo $md5;
echo "\\n";
}
}
常见的字符串
byGcY
0e591948146966052067035298880982
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
240610708
0e462097431906509019562988736854
314282422
0e990995504821699494520356953734
571579406
0e972379832854295224118025748221
903251147
0e174510503823932942361353209384
双MD5判断
对于有些题目,可能会经过两次MD5值的判断
MD5和双MD5以后的值都是0e开头的
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
脚本
# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def cmp_md5(substr, stop_event, str_len,. start=0, size=20):
global CHARS
while not stop_event.is_set():
rnds = ''.join(random.choice(CHARS) for _ in range(size))
md5 = hashlib.md5(rnds)
value = md5.hexdigest()
if value[start: start+str_len] == substr:
print rnds
stop_event.set()
'''
#碰撞双md5
md5 = hashlib.md5(value)
if md5.hexdigest()[start: start+str_len] == substr:
print rnds+ "=>" + value+"=>"+ md5.hexdigest() + "\\n"
stop_event.set()
'''
if __name__ == '__main__':
substr = sys.argv[1].strip()
start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0
str_len = len(substr)
cpus = multiprocessing.cpu_count()
stop_event = multiprocessing.Event()
processes = [multiprocessing.Process(target=cmp_md5, args=(substr,
stop_event, str_len, start_pos))
for i in range(cpus)]
for p in processes:
p.start()
for p in processes:
p.join()
扩展构造
若有要求 md5 值的明文长度很小,其中只能出现一种字母,那么可以写脚本获取明文
$a = $_POST['a'];
$b = $_POST['b'];
$m = $_GET['m'];
$n = $_GET['n'];
if (!(ctype_alnum($a)) || (strlen($a) > 5) || !(ctype_alnum($b)) || (strlen($b) > 6))
{
echo "a OR b fail!";
die();
}
if ((strlen($m) > 1) || (strlen($n) > 1))
{
echo "m OR n fail";
die();
}
$val8 = md5($a);
$val9 = strtr(md5($b), $m, $n);
echo PHP_EOL;
echo "<p>val8 : $val8</p>";
echo PHP_EOL;
echo "<p>val9 : $val9</p>";
echo PHP_EOL;
if (($val8 == $val9) && !($a === $b) && (strlen($b) === 5))
{
echo "nice,good job,give you flag:";
echo file_get_contents('/var/www/html/flag.php');
}
代码的意思就是需要一个长度小于等于 5 的字符串的 md5 值是科学计数法样式
还需要一个长度等于 5 的字符串的 md5 值在替换一个字符后能变成科学计数法样式的 md5,这也是我们要求的
import hashlib
import string
str_list = list(string.letters + string.digits)
for i in range(0, len(str_list)):
for j in range(0, len(str_list)):
for k in range(0, len(str_list)):
for l in range(0, len(str_list)):
for m in range(0, len(str_list)):
tmp = str_list[i] + str_list[j] + str_list[k] + str_list[l] + str_list[m]
str_hash = hashlib.md5(tmp).hexdigest()
check = str_hash[0:2]
str_hash = str_hash[2:32]
a = str_hash.replace('a', '1')
b = str_hash.replace('b', '1')
c = str_hash.replace('c', '1')
d = str_hash.replace('d', '1')
e = str_hash.replace('e', '1')
f = str_hash.replace('f', '1')
g = str_hash.replace('g', '1')
h = str_hash.replace('h', '1')
i1 = str_hash.replace('i', '1')
j1 = str_hash.replace('j', '1')
k1 = str_hash.replace('k', '1')
l1 = str_hash.replace('l', '1')
m1 = str_hash.replace('m', '1')
n = str_hash.replace('n', '1')
o = str_hash.replace('o', '1')
p = str_hash.replace('p', '1')
q = str_hash.replace('q', '1')
r = str_hash.replace('r', '1')
s = str_hash.replace('s', '1')
t = str_hash.replace('t', '1')
u = str_hash.replace('u', '1')
v = str_hash.replace('v', '1')
w = str_hash.replace('w', '1')
x = str_hash.replace('x', '1')
y = str_hash.replace('y', '1')
z = str_hash.replace('z', '1')
if check == '0e' and (
a.isdigit() or b.isdigit() or c.isdigit() or d.isdigit() or e.isdigit() or f.isdigit() or g.isdigit() or h.isdigit() or i1.isdigit() or j1.isdigit() or k1.isdigit() or l1.isdigit() or m1.isdigit() or n.isdigit() or o.isdigit() or p.isdigit() or q.isdigit() or r.isdigit() or s.isdigit() or t.isdigit() or u.isdigit() or v.isdigit() or w.isdigit() or x.isdigit() or y.isdigit() or z.isdigit()):
print tmp
print str_hash
MD5强类型比较
<?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";
}
}
?>
方法一:数组绕过
因为是强类型比较,用0e开头的字符串是没办法绕过的了,但是PHP自身的特性使得可以提交一个数组
而md5函数传入数组的返回值都是NULL,这样就可以绕过强类型比较了
方法二:使用md5加密后两个完全相等的两个字符串绕过
利用fastcoll_v1.0.0.5.exe来生成符合条件的字符串
构造:
(1)创建一个文本文件,写入任意的文件内容,命名为ywj.txt (源文件)
(2)运行fastcoll输出以下参数:-p 是源文件,-o是输出文件
执行命令:fastcoll_v1.0.0.5.exe -p ywj.txt -o 1.txt 2.txt
对产生的1.txt和2.txt文件进行测试
<?php
function readmyfile($path){
$fh = fopen($path, "rb");
$data = fread($fh, filesize($path));
fclose($fh);
return $data;
}
echo '二进制md5加密 '. md5( (readmyfile("D:\\\\ctf工具\\\\fastcoll_v1.0.0.5.exe\\\\1.txt")))."\\n";
echo 'url编码 '. urlencode(readmyfile("D:\\\\ctf工具\\\\fastcoll_v1.0.0.5.exe\\\\1.txt"))."\\n";
echo '二进制md5加密 '.md5( (readmyfile("D:\\\\ctf工具\\\\fastcoll_v1.0.0.5.exe\\\\2.txt")))."\\n";
echo 'url编码 '. urlencode(readmyfile("D:\\\\ctf工具\\\\fastcoll_v1.0.0.5.exe\\\\2.txt"))."\\n";
二进制md5加密 ecd33e3e09ff2a58e1d9ed7189dc186b
url编码 abc%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D6%16y%AC%CE%C5%A1LrY5fn%94%10%D9%01%C3%AC%F8%AAN%21%D0%27%BE%3Ej%A7%以上是关于MD5绕过的主要内容,如果未能解决你的问题,请参考以下文章