[CTF]CTF中if (md5(md5($_GET[‘a’])) == md5($_GET[‘b’])) 的繞過


原作者:KTWO
出處:https://www.k2zone.cn/?p=2019

0X00 摘要

CTF中md5判等可使用0e繞過,但是如果是雙md5該如何繞過呢?本文將教你如何繞過md5(md5($_GET[‘a’])) == md5($_GET[b’])。

0X01 引言

在php中,所有變量都是若類型的,在使用if判等的時候要格外小心,使用特殊的參數可能會使本來不相等的if判斷位相等,比如下面的例子。

<?php 

if (isset($_GET['a']) && isset($_GET['b'])) {
	$a = $_GET['a'];
	$b = $_GET['b'];
	if ($a != $b && md5($a) == md5($b)) {
		echo "flag{XXXXX}";
	} else {
		echo "wrong!";
	}

} else {
	echo 'wrong!';
}
?>

上面只要傳入參數a=s1885207154a,b=s1836677006a,即可,為什么呢?看一下這兩個字符串的md5值可以返現分別如下:

MD5值:

md5("s1885207154a") => 0e509367213418206700842008763514

md5("s1836677006a") => 0e481036490867661113260034900752

二者都是0e開頭,在php中0e會被當做科學計數法,就算后面有字母,其結果也是0,所以上面的if判斷結果使true,成功繞過!

0x02 雙MD5碰撞繞過

上面只是小試牛刀,下面看一個升級版:

<?php 

if (isset($_GET['a']) && isset($_GET['b'])) {
	$a = $_GET['a'];
	$b = $_GET['b'];
	if ($a != $b && md5($a) == md5(md5($b)) {
		echo "flag{XXXXX}";
	} else {
		echo "wrong!";
	}

} else {
	echo 'wrong!';
}
?>

雙面的判斷出現了md5(md5($b),有了前面的鋪墊,這里我們第一感覺就是找到一個字符串其MD5值的MD5仍然是0e開頭的那就好了。開始的時候我不敢相信,那幾率得多小啊,但是在昨天做一道md5截斷碰撞的時候我就來了靈感,何不嘗試一下,結果發現原來這種字符串使真的存在,並且碰撞0e開頭的時候不到一秒鍾就能碰撞到。各位觀眾,下面請看:

MD5值:

md5("V5VDSHva7fjyJoJ33IQl") => 0e18bb6e1d5c2e19b63898aeed6b37ea

md5("0e18bb6e1************") => 0e0a710a092113dd5ec9dd47d4d7b86f

原來真的存在0e開頭的MD5值其md5結果也是0e開頭,所以此題答案便出來了。a=s1885207154a,b=V5VDSHva7fjyJoJ33IQl即可繞過if判斷。

其實上面的這種雙md5值0e開頭的字符串有很多,但是網上似乎很見到,幾乎沒有,下面發布一些。

0x03 雙md5結果仍為0e開頭字符串大全

MD5大全:

CbDLytmyGm2xQyaLNhWn

md5(CbDLytmyGm2xQyaLNhWn) => 0ec20b7c66cafbcc7d8e8481f0653d18

md5(md5(CbDLytmyGm2xQyaLNhWn)) => 0e3a5f2a80db371d4610b8f940d296af

770hQgrBOjrcqftrlaZk

md5(770hQgrBOjrcqftrlaZk) => 0e689b4f703bdc753be7e27b45cb3625

md5(md5(770hQgrBOjrcqftrlaZk)) => 0e2756da68ef740fd8f5a5c26cc45064

7r4lGXCH2Ksu2JNT3BYM

md5(7r4lGXCH2Ksu2JNT3BYM) => 0e269ab12da27d79a6626d91f34ae849

md5(md5(7r4lGXCH2Ksu2JNT3BYM)) => 0e48d320b2a97ab295f5c4694759889f

0x04 MD5碰撞腳本
授人以魚不如授人以漁,下面使多線程MD5哈希碰撞腳本,威力巨大。是根據網上代碼改編而成,非原創。

# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def cmp_md5(substr, stop_event, str_len,. start=0, size=20):
    global CHARS
    while not stop_event.is_set():
        rnds = ''.join(random.choice(CHARS) for _ in range(size))
        md5 = hashlib.md5(rnds)
        value = md5.hexdigest()
        if value[start: start+str_len] == substr:
            print rnds
            stop_event.set()
            '''
            #碰撞雙md5
            md5 = hashlib.md5(value)
            if md5.hexdigest()[start: start+str_len] == substr:
            	print rnds+ "=>" + value+"=>"+ md5.hexdigest()  + "\n"
                stop_event.set()
            '''

if __name__ == '__main__':
    substr = sys.argv[1].strip()
    start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0
    str_len = len(substr)
    cpus = multiprocessing.cpu_count()
    stop_event = multiprocessing.Event()
    processes = [multiprocessing.Process(target=cmp_md5, args=(substr,
                                         stop_event, str_len, start_pos))
                 for i in range(cpus)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

上面腳本注釋部分是雙MD5碰撞,取消注釋然后注釋掉16行即可。

使用方法:python md5Crack.py "你要碰撞的字符串" 字符串的起始位置

例如:python md5Crack.py “0e" 0

將產生MD5值為0e開頭的字符串。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM