md5哈希长度扩展攻击

MD5的已经被证实十分不可靠,对于MD5最著名的攻击当属这个长度扩展攻击了,这个攻击方式主要从其算法的原理入手。
具体可见 这里不再照抄
https://www.cnblogs.com/p00mj/p/6288337.html
题目的大意是这样的:服务器端有一个长度在8-32之间的随机盐值,你发送一个用户名过去,他会将盐值+用户名拼接起来得到md5(盐值+用户名) 返回给你
获得flag的方法为用户名中包含指定字符串,如果事先发送一个包含指定字符串的用户名且密码为空的话,服务器会识别到然后结束对话
可以简单理解为我们需要一个这样的key
md5(盐值+用户名+指定字符串) 来获得flag
听起来不可能事实现,但是当我们深入到MD5算法中去,就会发现长度扩展攻击的可怕之处。
我们将字符串按照原理补齐,每一块64个字节,不足则填\x80+一堆\x00+字节长度*8(即位长度,按照小端存储方式)
举个例子 如果有57个字节 则将其变成总共128个字节
57 + \x80 + \x00 * (128-57-1-8) + little_endian(bit_len = len*8)
对每一块分成16组做运算 初始向量为A,B,C,D 固定的 第一块做这样一次运算后变成A’ B’ C’ D’ (如果只有一块时 将A’B’C’D’拼接为MD5)
第二块用前一块的A’B’C’D’ 继续运算…
直到最后一块 AnBnCnDn 其结果就是答案(我们要求的MD5) 可以看下面代码中的get_init_vec函数 表示了md5和4个向量的关系
解题思路:用于salt没有很大,最长也就32个字节,所以我们先发一个短的用户名给服务器 服务器会帮我们算出第一块的md5并返回给我们,于是我们得到了第二块的初向量(第一块的结果) 于是乎我们即可利用他,将制定字符串放进用户名,手动构造得到第二块,对其再跑一次MD5算法得到最后我们想要的结果 把构造好的用户名和MD5发给服务器即可收到我们的flag

#coding=utf-8
import urllib
import os,math,re,sys
from pwn import *
import base64
import urllib
import binascii
file_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]

def get_init_vec(data):
	print "0x"+data[0:8].decode('hex')[::-1].encode('hex')
	print "0x"+data[8:16].decode('hex')[::-1].encode('hex')
	print "0x"+data[16:24].decode('hex')[::-1].encode('hex')
	print "0x"+data[24:32].decode('hex')[::-1].encode('hex')

def get_my_mdX(data):
	import execjs
	my_mdx = open(os.path.join(file_dir, 'mdx.js')).read()
	js = execjs.compile(my_mdx)
	return js.call('mdX',data)
def cal(x):
	x*=8
	s = str("%016x"%(x)).decode('hex')[::-1]
	return s
# leak_exp = {"username": "QUFBRFdH", "passcode": ""}
	# 得到第一块加密的结果向量 作为第二块的初向量
get_init_vec("619f93f7629561eb4b349ec7b76b4b29")
"""
0xf7939f61
0xeb619562
0xc79e344b
0x294b6bb7
"""
part = 'xxxxxx'+'\x80'+'\x00'*(64-6-8-1)+cal(70)
part_hex = part.encode('hex')
print part_hex
print get_my_mdX("61616164776780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003002000000000000")
for salt_length in range(8,33):
	username = 'AAADWG' +'\x80'+'\x00'*(64-salt_length-1-8-6)+cal(salt_length+6)+'aaadwg'
	passcode = "2d67ce095b15e192c613e40ea69876ea"
	username = base64.b64encode(username)
	passcode = base64.b64encode(passcode)
	exp = '{ "username":"'+username+'","passcode":"'+passcode+'"}'
	print exp
	r = remote("10.214.10.13",11013)
	context.log_level = 'debug'
	r.recvuntil("tication:")
	r.sendline(exp)
	print r.recvall()
	r.close()

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值