前言
前天参加web安全测试大赛决赛,遇到了一个题目,在网上找到了类似的题目,但是当时看了下看不懂,拿着payload无法利用,因此这几天一直在复现比赛的题目,顺便记录一下什么是hash长度拓展攻击
0x01 什么是hash长度拓展攻击
hash长度拓展攻击,概括一下就是由于hash的生成机制使得我们可以人为的在原先的明文基础上添加新的拓展字符,从而使得原本的加密链变长,进一步控制加密链的最后一节,使得我们得以控制最终的结果。
这里简单介绍一下hash算法。
hash算法
hash算法又叫做散列算法。是一种把任意长度的字符串加密为固定长度的字符串的加密算法,该算法生成的密文就是散列值。简单说hash算法就是一种通过单向函数加密明文生成信息摘要的算法。
现在常用的has算法有MD5和SHA-1。这里就以MD5算法为例,解释一下hash长度扩展攻击。
要去利用MD5算法解释该攻击方式,那就要先去了解一下MD5的加密过程
0x02 MD5加密
MD5
MD5算法是典型的一种信息摘要算法,它是由md2、md3和md4演变而来的。无所是哪一种的MD算法都是将一个任意长度的字符串加密为一串固定长度的密文。在这整个加密过程中,会将明文字符串转换为一个128位的消息摘要,接着把消息摘要转换为一个十六进制的字符串就会得到32位的字符串,也就是我们平时见到的MD5密文
因为MD5加密过程经过了压缩,加密和hash算法,所以MD5加密的内容是不可逆的
MD5算法过程
要了解算法的原理过程,肯定要有一个算法的流程图,这样看起来就会很明白了
按照这个图片,我们可以把流程分为下面几个步骤:
- 把消息分为n个分组
- 对最后一个消息分组进行填充
- 和输入量进行运算,运算结果位下一个分组的输入量
- 输出最终结果
MD5算法实现
因为单纯讲过程过于枯燥而且不易明白,所以这里采用举例子方式进行解释
加密举例
比如现在我们要对明文0123456789abcdef进行加密,首先第一步,将明文字符串转换为二进制字符串,这里贴出转换脚本
def text_to_binary(text_str):
binary_str = ' '.join(format(ord(x), 'b') for x in text_str)
return binary_str
text_input = '0123456789abcdef'
binary_output = text_to_binary(text_input)
print('binary result is:{0}'.format(binary_output))
#转换结果 00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000 00111001 01100001 01100010 01100011 01100100 01100101 01100110
由于一个ASCII码字符对应8位二进制字符,那么我们现在就得到了128位二进制字符,为了方便观看,我们在010(winhex)里面写入这些内容,因为010(winhex)是16进制,所以还要去转换为16进制字符。
def binary_to_hex(binary_str):
decimal_number = int(binary_str, 2)
hex_number = hex(decimal_number)
return hex_number
binary_input = '110000110001110010110011110100110101110110110111111000111001110000111000101100011110010011001011100110'
hex_output = binary_to_hex(binary_input)
print('hex result is:{0}'.format(hex_output))
#转换结果:0x80
在010(winhex)写入内容
这样子看起来就舒服多了,下面要对明文进行填充,使得明文位长度mod 512=448(bit)。进行填充的方式前面说了,就是在二进制下第一个补1,后面的依次补0 。但是在这里咱们是以十六进制形式在010里演示的,而对于十六进制来说,一个十六进制字符对应4个二进制字符,所以对于010里面数据来说,10000000(2)==80(16),补充上去就是
然后后面依次补0,直至满足上面式子为止。得到最终补位结果
然后进行补位。
现在经过填充明文有448it,也就是56byte,还需要补位8byte。原始明文为0123456789abcdef
共16byte,有16 * 8=128bit,转换为十六进制为80,写入倒数第八个byte位,之后补7byte的0x00 。
接下来就用这64byte的数据进行计算,与初始向量进行运算
计算信息的摘要需要用补位结果的数据进行运算,也就是补位后的512bit的消息,在计算时候有一个初始的向量,这里初始的向量是一个固定的值
A 01 23 45 67 0x67452301
B 89 AB CD EF 0xEFCDAB89
C FE DC BA 98 0x98BADCFE
D 76 54 32 10 0x10325476
由于在计算机存储中采用的是小端存储方式,所以上面的初始化向量在程序中的初始化代码为后面的0x部分。
然后将刚才的512bit消息和初始化向量进行第一轮的运算,之后初始化向量会被新的值覆盖,最后一轮的向量经过高低位互换后就是计算出的MD5值。
高低位互换:
abcdef->fedcba
这个高低位互换的过程如下:
假如最后一轮的运算后的向量值为:
A=0xabcdef12
B=0xabcdef12
C=0xabcdef12
D=0xabcdef12
那么进行高低位互换之后得到的数值为:
12 ef cd ab
12 ef cd ab
12 ef cd ab
12 ef cd ab
进行拼接得到最后加密结果
12efcdab12efcdab12efcdab12efcdab
hash长度扩展攻击
hash长度的拓展攻击的实现就是基于上面的最后一轮的值进行的,下面结合一下这次做题遇到的一个题目进行解释
<?php
error_reporting(0);
$flag=getenv("DASFLAG");
if(isset($_GET["md5"]) && isset($_GET["i"]) && isset($_GET["s"])){
$fl4g = substr_replace($flag, $_GET["s"], $_GET["i"], 1);
if($_GET["md5"] === md5($fl4g)){
echo $flag;
}else{
die("please try again");
}
}else{
highlight_file(__FILE__);
echo md5($flag."yusa");
} 1c3de59d2f68788cc792e0eb7d604710
这个题目核心的地方在if($_GET["md5"] === md5($fl4g)
我们get的变量md5值需要和题目环境变量DASFLAG的值经过字符替换之后的MD5值相同,会给flag。也就是说要去构造MD5的参数值。
这里已知了flag也就是secret值为38位,data值为yusa。
这里给一个例子进行解释
已知secret为‘secret’(攻击者未知)
数据data为‘data’(攻击者已知)
加密方式为MD5(secret+data),也就是俗称的加盐
追加字符为yyds
正常加密:6ee582a1669ce442f3719c47430dadee
将secret和data数据写出来
按照填充规则进行填充
补位
现在如果攻击者进行追加内容的话,填充如下
现在再去计算它的MD5值,就有两种办法了
- 直接使用MD5算法计算(该方法是服务端采用的)
- 通过第一个块结束开始,使用我们已经从签hash中获得的状态并从该状态开始对追加内容进行hash(该方法为攻击者的攻击程序所采用的)
说下服务端:
在发送数据到服务端时候,因为是加盐,而这个盐肯定不是我们自己加的,是由服务器自己按照一定的规则加的盐,也就是secret。
所以我们在发送数据时数据应该是下面的样子
而在攻击者扩展数据情况下发送的数据应该是
而服务端处理的数据因该是
并且会进行hash运算得到密文:6ee582a1669ce442f3719c47430dadee
回到题目
这里就是去按照上面的思路构造MD5参数的值。
首先就是知道了secret长度为42
最后去掉前面的secret,得到
yusa\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00a
进行urlencode编码之后
yusa%5Cx80%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx17%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00%5Cx00a
现在在不知道secret值的情况下,已经得知了flag+yusa的值为1c3de59d2f68788cc792e0eb7d604710
,以及secret位数。而我们现在得到的hash值刚好是下一轮数据经过高低位互换的向量。
也就是说互换之后:
9d e5 3d 1c
8c 78 68 2f
eb e0 92 c7
10 47 60 7d
在网上找了一个python的扩展攻击脚本
# -*- coding: utf-8 -*-
# @Author: King kaki
# @Date: 2018-08-04 12:40:11
# @Last Modified by: kingkk
# @Last Modified time: 2018-08-12 15:08:28
import math
F = lambda x, y, z: ((x & y) | ((~x) & z))
G = lambda x, y, z: ((x & z) | (y & (~z)))
H = lambda x, y, z: (x ^ y ^ z)
I = lambda x, y, z: (y ^ (x | (~z)))
L = lambda x, n: (((x << n) | (x >> (32 - n))) & (0xffffffff))
shi_1 = (7, 12, 17, 22) * 4
shi_2 = (5, 9, 14, 20) * 4
shi_3 = (4, 11, 16, 23) * 4
shi_4 = (6, 10, 15, 21) * 4
m_1 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
m_2 = (1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12)
m_3 = (5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2)
m_4 = (0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9)
def T(i):
return (int(4294967296 * abs(math.sin(i)))) & 0xffffffff
def shift(shift_list):
shift_list = [shift_list[3], shift_list[0], shift_list[1], shift_list[2]]
return shift_list
def fun(fun_list, f, m, shi):
count = 0
global Ti_count
while count < 16:
xx = int(fun_list[0], 16) + f(int(fun_list[1], 16), int(fun_list[2], 16), int(fun_list[3], 16)) + int(m[count], 16) + T(Ti_count)
xx &= 0xffffffff
ll = L(xx, shi[count])
fun_list[0] = hex((int(fun_list[1], 16) + ll) & 0xffffffff)
fun_list = shift(fun_list)
count += 1
Ti_count += 1
return fun_list
def gen_m16(order, ascii_list, f_offset):
ii = 0
m16 = [0] * 16
f_offset *= 64
for i in order:
i *= 4
m16[ii] = '0x' + ''.join((ascii_list[i + f_offset] + ascii_list[i + 1 + f_offset] + ascii_list[i + 2 + f_offset] + ascii_list[i + 3 + f_offset]).split('0x'))
ii += 1
for ind in range(len(m16)):
m16[ind] = reverse_hex(m16[ind])
return m16
def reverse_hex(hex_str):
hex_str = hex_str[2:]
if len(hex_str) < 8:
hex_str = '0' * (8 - len(hex_str)) + hex_str
hex_str_list = []
for i in range(0, len(hex_str), 2):
hex_str_list.append(hex_str[i:i + 2])
hex_str_list.reverse()
hex_str_result = '0x' + ''.join(hex_str_list)
return hex_str_result
def show_result(f_list):
result = ''
f_list1 = [0] * 4
for i in f_list:
f_list1[f_list.index(i)] = reverse_hex(i)[2:]
result += f_list1[f_list.index(i)]
return result
def padding(input_m, msg_lenth=0):
ascii_list = list(map(hex, map(ord, input_m)))
msg_lenth += len(ascii_list) * 8
ascii_list.append('0x80')
for i in range(len(ascii_list)):
if len(ascii_list[i]) < 4:
ascii_list[i] = '0x' + '0' + ascii_list[i][2:]
while (len(ascii_list) * 8 + 64) % 512 != 0:
ascii_list.append('0x00')
msg_lenth_0x = hex(msg_lenth)[2:]
msg_lenth_0x = '0x' + msg_lenth_0x.rjust(16, '0')
msg_lenth_0x_big_order = reverse_hex(msg_lenth_0x)[2:]
msg_lenth_0x_list = []
for i in range(0, len(msg_lenth_0x_big_order), 2):
msg_lenth_0x_list.append('0x' + msg_lenth_0x_big_order[i: i + 2])
ascii_list.extend(msg_lenth_0x_list)
return ascii_list
def md5(input_m):
global Ti_count
Ti_count = 1
abcd_list = ['0x67452301', '0xefcdab89', '0x98badcfe', '0x10325476']
ascii_list = padding(input_m)
for i in range(0, len(ascii_list) // 64):
aa, bb, cc, dd = abcd_list
order_1 = gen_m16(m_1, ascii_list, i)
order_2 = gen_m16(m_2, ascii_list, i)
order_3 = gen_m16(m_3, ascii_list, i)
order_4 = gen_m16(m_4, ascii_list, i)
abcd_list = fun(abcd_list, F, order_1, shi_1)
abcd_list = fun(abcd_list, G, order_2, shi_2)
abcd_list = fun(abcd_list, H, order_3, shi_3)
abcd_list = fun(abcd_list, I, order_4, shi_4)
output_a = hex((int(abcd_list[0], 16) + int(aa, 16)) & 0xffffffff)
output_b = hex((int(abcd_list[1], 16) + int(bb, 16)) & 0xffffffff)
output_c = hex((int(abcd_list[2], 16) + int(cc, 16)) & 0xffffffff)
output_d = hex((int(abcd_list[3], 16) + int(dd, 16)) & 0xffffffff)
abcd_list = [output_a, output_b, output_c, output_d]
Ti_count = 1
print(ascii_list)
return show_result(abcd_list)
# md5-Length Extension Attack: 计算 md5(message + padding + suffix), res = md5(message), len_m = len(message)
def md5_lea(suffix, res, len_m):
global Ti_count
Ti_count = 1
abcd_list = []
for i in range(0, 32, 8):
abcd_list.append(reverse_hex('0x' + res[i: i + 8]))
# print(abcd_list)
ascii_list = padding(suffix, (len_m + 72) // 64 * 64 * 8) # len(message + padding) * 8
# print(ascii_list)
for i in range(0, len(ascii_list) // 64):
aa, bb, cc, dd = abcd_list
order_1 = gen_m16(m_1, ascii_list, i)
order_2 = gen_m16(m_2, ascii_list, i)
order_3 = gen_m16(m_3, ascii_list, i)
order_4 = gen_m16(m_4, ascii_list, i)
abcd_list = fun(abcd_list, F, order_1, shi_1)
abcd_list = fun(abcd_list, G, order_2, shi_2)
abcd_list = fun(abcd_list, H, order_3, shi_3)
abcd_list = fun(abcd_list, I, order_4, shi_4)
output_a = hex((int(abcd_list[0], 16) + int(aa, 16)) & 0xffffffff)
output_b = hex((int(abcd_list[1], 16) + int(bb, 16)) & 0xffffffff)
output_c = hex((int(abcd_list[2], 16) + int(cc, 16)) & 0xffffffff)
output_d = hex((int(abcd_list[3], 16) + int(dd, 16)) & 0xffffffff)
abcd_list = [output_a, output_b, output_c, output_d]
Ti_count = 1
# print(ascii_list)
return show_result(abcd_list)
def url_append(hex_bit):
len_append = '0x{}{}'.format( (18-len(hex_bit))*'0', hex_bit[2:])
len_append = reverse_hex(len_append)[2:]
# print(len_append)
t = ''
for i in range(len(len_append)):
if i % 2 ==0 :
t += '%'+len_append[i:i+2]
else:
pass
return t
if __name__ == '__main__':
'''
修改res为已知哈希值
extend 为拓展值
自动遍历出1-30长度的payload url编码表达式
'''
res = '1c3de59d2f68788cc792e0eb7d604710'
extend = '}'
# print(reverse_hex('0x' + res))
for i in range(45):
hex_bit = hex(i*8)
t = url_append(hex_bit)
print('[%d]' % i,md5_lea(extend,res,i))
# print('{}%80{}{}{}'.format('X'*i, (55-i)*'%00',t, extend) )
print('%80{}{}{}'.format((55-i)*'%00',t, extend) )
# print('{}{}'.format( hex(i), (18-len(hex(i)))*'0') )
# from urllib.parse import unquote
# print(md5_lea('kingkk','571580b26c65f306376d4f64e53cb5c7',10))
最终输出为
[0] 86f46813eda13928aaa468725598c464
%80%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%00%00}
[1] 86f46813eda13928aaa468725598c464
%80%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%08%00%00%00%00%00%00%00}
[2] 86f46813eda13928aaa468725598c464
%80%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%10%00%00%00%00%00%00%00}
[3] 86f46813eda13928aaa468725598c464
%80%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%18%00%00%00%00%00%00%00}
[4] 86f46813eda13928aaa468725598c464
%80%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%20%00%00%00%00%00%00%00}
[5] 86f46813eda13928aaa468725598c464
%80%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%28%00%00%00%00%00%00%00}
[6] 86f46813eda13928aaa468725598c464
%80%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%30%00%00%00%00%00%00%00}
[7] 86f46813eda13928aaa468725598c464
%80%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%38%00%00%00%00%00%00%00}
[8] 86f46813eda13928aaa468725598c464
%80%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%40%00%00%00%00%00%00%00}
[9] 86f46813eda13928aaa468725598c464
%80%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%48%00%00%00%00%00%00%00}
[10] 86f46813eda13928aaa468725598c464
%80%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%50%00%00%00%00%00%00%00}
[11] 86f46813eda13928aaa468725598c464
%80%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%58%00%00%00%00%00%00%00}
[12] 86f46813eda13928aaa468725598c464
%80%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%60%00%00%00%00%00%00%00}
[13] 86f46813eda13928aaa468725598c464
%80%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%68%00%00%00%00%00%00%00}
[14] 86f46813eda13928aaa468725598c464
%80%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%70%00%00%00%00%00%00%00}
[15] 86f46813eda13928aaa468725598c464
%80%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%78%00%00%00%00%00%00%00}
[16] 86f46813eda13928aaa468725598c464
%80%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%80%00%00%00%00%00%00%00}
[17] 86f46813eda13928aaa468725598c464
%80%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%88%00%00%00%00%00%00%00}
[18] 86f46813eda13928aaa468725598c464
%80%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%90%00%00%00%00%00%00%00}
[19] 86f46813eda13928aaa468725598c464
%80%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%98%00%00%00%00%00%00%00}
[20] 86f46813eda13928aaa468725598c464
%80%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%a0%00%00%00%00%00%00%00}
[21] 86f46813eda13928aaa468725598c464
%80%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%a8%00%00%00%00%00%00%00}
[22] 86f46813eda13928aaa468725598c464
%80%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%b0%00%00%00%00%00%00%00}
[23] 86f46813eda13928aaa468725598c464
%80%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%b8%00%00%00%00%00%00%00}
[24] 86f46813eda13928aaa468725598c464
%80%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%c0%00%00%00%00%00%00%00}
[25] 86f46813eda13928aaa468725598c464
%80%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%c8%00%00%00%00%00%00%00}
[26] 86f46813eda13928aaa468725598c464
%80%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%d0%00%00%00%00%00%00%00}
[27] 86f46813eda13928aaa468725598c464
%80%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%d8%00%00%00%00%00%00%00}
[28] 86f46813eda13928aaa468725598c464
%80%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%e0%00%00%00%00%00%00%00}
[29] 86f46813eda13928aaa468725598c464
%80%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%e8%00%00%00%00%00%00%00}
[30] 86f46813eda13928aaa468725598c464
%80%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%f0%00%00%00%00%00%00%00}
[31] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%f8%00%00%00%00%00%00%00}
[32] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%01%00%00%00%00%00%00}
[33] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%08%01%00%00%00%00%00%00}
[34] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%10%01%00%00%00%00%00%00}
[35] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%18%01%00%00%00%00%00%00}
[36] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%20%01%00%00%00%00%00%00}
[37] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%28%01%00%00%00%00%00%00}
[38] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%30%01%00%00%00%00%00%00}
[39] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%38%01%00%00%00%00%00%00}
[40] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%40%01%00%00%00%00%00%00}
[41] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%48%01%00%00%00%00%00%00}
[42] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%50%01%00%00%00%00%00%00}
[43] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%00%58%01%00%00%00%00%00%00}
[44] 86f46813eda13928aaa468725598c464
%80%00%00%00%00%00%00%00%00%00%00%00%60%01%00%00%00%00%00%00}
因为是secret+data为42位,所以最终payload为:
?md5=d9671633e3723203bc2a1479c8412307&i=-1&s=}yusa%80%00%00%00%00%00%00%00%00%00%00%00%00%00%50%01%00%00%00%00%00%00a
得到flag
题外话
这个题目经过了修改之后直接输出了flag,原题不是这样的
贴出来原题代码
<?php
error_reporting(0);
$flag=getenv("DASFLAG");
if(isset($_GET["md5"]) && isset($_GET["i"]) && isset($_GET["s"])){
$fl4g = substr_replace($flag, $_GET["s"], $_GET["i"], 1);
echo $_GET["md5"] === md5($fl4g);
}else{
highlight_file(__FILE__);
echo md5($flag."yusa");
}
这里只会提示正确还是错误,也就是需要去进行盲注出来,原题secret+data为44位,也就是说需要去爆44位的数据,手工工作量很大。本人脚本能力有限,这里暂不给出脚本了,之后写出来了再补。
使用工具进行攻击
这里推荐一款工具-hashpump
速度很快,生成payload
危害性
说了半天,具体有什么危害呢?
比如说现在有一个登录的界面,进行的判断是加密后的密码和MD5(passwd+data)进行比较,很明显是在校验中加盐了,如果我们要绕过的话,就可以利用此攻击方式。
但是在实际中,因为我们不知道secret长度,所以需要对其进行猜测,也就是说,对于长度不正确以及登录失败的信息是不一样的,那么就可以进行判断,利用脚本跑出来他的secret的长度,从而进一步去绕过这个检测机制,成功登录系统。所以说,该问题还是很严重的。
实际上对以下算法都能实现hash长度扩展攻击,包括md4,md5,ripemd-160,sha-0,sha-1,sha-256,sha-512等
如何进行防御
既然这个问题危害很大,那么怎么进行防御呢?
- 增加hash算法的负责度,也就是说在MD5加密之后接着进行一次MD5加密
- 和上类似,加密方式采用HMAC方式,即hash(secret+hash(secret+data)),该方法最早在1996年发表,之后几乎被加到几乎每一种编程语言的标准函数库中
尾言
本次解释中,搜索了一些网上资料以及一些师傅的博客文章汇总了自己的理解才算是写了一篇水平不怎么样的文章,但总的来说还算满意,唯一不足的本人脚本能力实在有限,涉及的脚本暂时没法给出,只能日后补回来了。