Tamu CTF 2023 - MD5 (crypto, md5 collision)

MD5 jail?!?!?!?!
Author: anomie

  • [114 solves / 373 points]

Analysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import hashlib
import subprocess
from pwn import *

def md5sum(b: bytes):
return hashlib.md5(b).digest()[:3]


whitelisted_cmd = b'echo lmao'
whitelisted_hash = md5sum(whitelisted_cmd)

print(repr(whitelisted_hash))
print(repr(hex(u32(whitelisted_hash.ljust(4, b'\x00')))))

def main():
while True:
cmd = input('> ').encode()
if cmd == b'exit':
print('Goodbye')
exit()

if md5sum(cmd) != whitelisted_hash:
print(f'Invalid command, try "{whitelisted_cmd.decode()}"')
continue

try:
out = subprocess.check_output(['/bin/bash', '-c', cmd])
print(out.decode())
except subprocess.CalledProcessError as e:
print(f'Command returned non-zero exit status {e.returncode}')

if __name__ == "__main__":
main()

문제 스크립트에서 md5sum 함수를 살펴보면 3바이트만 리턴한다.

문제 풀이에 앞서 md5 collision에 대해 간단히 살펴봤다. md5는 같은 입력값이면 항상 같은 출력값이 나온다. 서로 다른 값을 입력할 경우 같은 출력값이 나올 확률은 굉장히 낮지만 같은 값이 나올 가능성이 존재한다. 예를 들면 AAAABBBBmd5를 적용했을 때 출력값이 같을 수도 있다는 의미이다. 이런 상황을 md5 collision이라고 한다.

문제 스크립트는 ‘echo lmao’를 md5sum 함수를 거친 후의 값과 같으면 입력값을 bash로 실행할 수 있다. 막막해보이지만 사실 md5sum 함수에서의 전체 해시값의 3바이트만 똑같은 입력값을 찾으면 된다.

Solve

나는 쉘을 획득하기 위해 bash #을 고정으로 두고 # 주석 뒤에 숫자를 적어줘서 브루트포싱으로 md5 해시가 3바이트만 똑같은 경우를 찾으려고 했고, 성공했다!

Solve Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# from pwn import *

# p = remote("tamuctf.com", 443, ssl=True, sni="md5")
# p.sendlineafter('>','bash # 2695494')
# p.interactive()

import hashlib

def md5sum(b: bytes):
return hashlib.md5(b).digest()[:3]

whitelisted_cmd = b'echo lmao'
whitelisted_hash = md5sum(whitelisted_cmd)

for i in range(0x1000000000):
input_cmd = b'bash # ' + str(i).encode()
input_hash = md5sum(input_cmd)
# print(repr(hex(u32(input_hash.ljust(4, b'\x00')))))

if input_hash != whitelisted_hash:
continue
else:
print("###############################################")
print(input_cmd)
break

# $ cat flag.txt >&2

Flag

1
gigem{3_bYt3_MD5_1s_Ju5t_pr00f_0f_W0rK}