1. 程式人生 > >hash碰撞POC

hash碰撞POC

limit set 是否 put self. have data 思想 try

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

hash碰撞POC