4

【Web 笔记】Md5 绕过总结

 2 years ago
source link: https://binlep.github.io/2020/02/28/%E3%80%90Web%20%E7%AC%94%E8%AE%B0%E3%80%91md5%20%E7%BB%95%E8%BF%87%E6%80%BB%E7%BB%93/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

md5 太难咯

md5 弱类型比较

参考源码:

<?php
highlight_file(__FILE__);
error_reporting(0);
$val1 = @$_GET['val1'];
$val2 = @$_GET['val2'];
if( $val1 == $val2 ){
die('val1 OR val2 no no no');
}
if( md5($val1) != md5($val2) ){
die('step 1 fail');
}
?>

数组绕过适用于源码中没有判断变量类型或内容,如果加上了过滤函数就不能使用了

常见过滤函数如下:

ctype_alnum ( string $text ) : bool
// 如果text中所有的字符全部是字母和(或者)数字,返回 TRUE 否则返回FALSE

is_numeric ( mixed $var ) : bool
// 如果 var 是数字和数字字符串则返回 TRUE,否则返回 FALSE。

科学计数法绕过

参考源码:

<?php
highlight_file(__FILE__);
error_reporting(0);
$val1 = @$_GET['val1'];
$val2 = @$_GET['val2'];
if( $val1 == $val2 ){
die('val1 OR val2 no no no');
}
if( md5($val1) != md5($val2) ){
die('step 1 fail');
}
?>

它的原理在于:为 0e 开头,后面都是数字的字符串会被识别为科学记数法

常见的明文与密文如下:

byGcY
0e591948146966052067035298880982

QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020

s155964671a
0e342768416822451524974117254469

s214587387a
0e848240448830537924465865611904

s214587387a
0e848240448830537924465865611904

s878926199a
0e545993274517709034328855841020

s1091221200a
0e940624217856561557816327384675

s1885207154a
0e509367213418206700842008763514

若有要求 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,这也是我们要求的

这里采用 FireCC 师傅的脚本:

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 强类型碰撞

两个 md5 碰撞

这里使用 fastcoll 工具来进行哈希碰撞获得两个相同的 md5

工具用法:.\fastcoll.exe init -o file1 file1

用一个源文件 init 制造两个 md5 相同的不同文件,之后将文件内的内容进行 url 编码即可作为变量传递,脚本如下:

import binascii

file1 = open('file1', 'rb').read()
file2 = open('file2', 'rb').read()

def urlencode(bstr):
encoded = ''
for i in bstr:
encoded = encoded + '%' + binascii.b2a_hex(i)
return encoded

print urlencode(file1)
print urlencode(file2)

三个及以上 md5 强碰撞

这个又是一个新知识点了,原理不懂,只会操作,大致原理如下:

MD5(file + col1_a + col2_a) === MD5(file + col1_a + col2_b) === MD5(file + col1_b + col2_a) === MD5(file + col1_b + col2_b)

那么操作流程如下:

.\fastcoll.exe a -o b c
.\fastcoll.exe b -o e f
.\fastcoll.exe e -o g h

这样执行完后会得到 5 个文件,接下来要用脚本来得到 5 个 md5 值相同的文件,脚本如下:

with open('a', 'rb') as a:
base = a.read()

with open('b', 'rb') as b:
file_1 = b.read()
coll_1 = file_1[len(base):]
with open('c', 'rb') as c:
file_2 = c.read()
coll_2 = file_2[len(base):]

with open('e', 'rb') as e:
file_1_1 = e.read()
coll_1_1 = file_1_1[len(file_1):]
with open('f', 'rb') as f:
file_1_2 = f.read()
coll_1_2 = file_1_2[len(file_2):]

with open('g', 'rb') as g:
file_1_1_1 = g.read()
coll_1_1_1 = file_1_1_1[len(file_1_1):]
with open('h', 'rb') as h:
file_1_1_2 = h.read()
coll_1_1_2 = file_1_1_2[len(file_1_2):]


def w(fn, data):
with open("out/" + fn, 'wb') as fp:
fp.write(data)


w("file1", base + coll_1 + coll_1_1 + coll_1_1_1)
w("file2", base + coll_1 + coll_1_1 + coll_1_1_2)
w("file3", base + coll_1 + coll_1_2 + coll_1_1_1)
w("file4", base + coll_1 + coll_1_2 + coll_1_1_2)
w("file5", base + coll_2 + coll_1_1 + coll_1_1_1)

可以在 linux 下用 md5sum 命令来查看文件的 md5 值,之后用脚本将文件内容转化成网页能识别的 url 编码:

import binascii

file1 = open('file1', 'rb').read()
file2 = open('file2', 'rb').read()
file3 = open('file3', 'rb').read()
file3 = open('file4', 'rb').read()
file3 = open('file5', 'rb').read()

def urlencode(bstr):
encoded = ''
for i in bstr:
encoded = encoded + '%' + binascii.b2a_hex(i)
return encoded

print urlencode(file1)
print urlencode(file2)
print urlencode(file3)
print urlencode(file4)
print urlencode(file5)

哈希长度扩展攻击

先留着,懒得写,遇到的时候再整理写上哈哈哈哈


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK