네트워크 통신을 조작하여 통신 내용을 도청하거나 조작하는 공격 기법
(출처 : https://textbook.cs161.org/crypto/key-exchange.html)
즉, 중간자는 Alice와 Bob이 교환하던 키를 탈취해 변조하여 세션키 K1, K2를 얻어낸다.
from Crypto.Util.number import getPrime
from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
import hashlib
import random
class Person(object):
def __init__(self, p):
self.p = p
self.g = 2
self.x = random.randint(2, self.p - 1)
def calc_key(self):
self.k = pow(self.g, self.x, self.p)
return self.k
def set_shared_key(self, k):
self.sk = pow(k, self.x, self.p)
aes_key = hashlib.md5(str(self.sk).encode()).digest()
self.cipher = AES.new(aes_key, AES.MODE_ECB)
def encrypt(self, pt):
return self.cipher.encrypt(pad(pt, 16)).hex()
def decrypt(self, ct):
return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)
flag = open("flag", "r").read().encode()
prime = getPrime(1024)
print(f"Prime: {hex(prime)}")
alice = Person(prime)
bob = Person(prime)
alice_k = alice.calc_key()
print(f"Alice sends her key to Bob. Key: {hex(alice_k)}")
print("Let's inturrupt !")
alice_k = int(input(">> "))
if alice_k == alice.g:
exit("Malicious key !!")
bob.set_shared_key(alice_k)
bob_k = bob.calc_key()
print(f"Bob sends his key to Alice. Key: {hex(bob_k)}")
print("Let's inturrupt !")
bob_k = int(input(">> "))
if bob_k == bob.g:
exit("Malicious key !!")
alice.set_shared_key(bob_k)
print("They are sharing the part of flag")
print(f"Alice: {alice.encrypt(flag[:len(flag) // 2])}")
print(f"Bob: {bob.encrypt(flag[len(flag) // 2:])}")
해당 코드는 두 송수신자가 키를 교환하여 세션키를 얻어내는 과정으로, g는 2임을 알았기 때문에 중간자는 이를 이용하여 둘 사이의 세션키를 탈취할 수 있다.
해당 프로세스를 기반으로 solution.py 코드를 만들어내 플래그를 탈취한다.
#!/usr/bin/python3
from pwn import *
from Cryptodome.Util.number import getPrime
from Cryptodome.Util.Padding import pad, unpad
from Cryptodome.Cipher import AES
import hashlib
import random
class Person(object):
def __init__(self, p):
self.p = p
self.g = 2
self.x = random.randint(2, self.p - 1)
def calc_key(self):
self.k = pow(self.g, self.x, self.p)
return self.k
def set_shared_key(self, k):
self.sk = pow(k, self.x, self.p)
aes_key = hashlib.md5(str(self.sk).encode()).digest()
self.cipher = AES.new(aes_key, AES.MODE_ECB)
def encrypt(self, pt):
return self.cipher.encrypt(pad(pt, 16)).hex()
def decrypt(self, ct):
return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)
p = remote("host3.dreamhack.games",20278)
# p 받아옴
p.recvuntil(b"Prime: ")
prime = int(p.recvline()[:-1],16)
# 클래스 생성
attacker_a = Person(prime)
attacker_b= Person(prime)
# Alice의 공개키 탈취
p.recvuntil(b"Alice sends her key to Bob. Key: ")
alice_k = int(p.recvline()[:-1],16)
attacker_a.set_shared_key(alice_k)
p.sendafter(b">> ",b'32\n')
# Bob의 공개키 탈취
p.recvuntil(b"Bob sends his key to Alice. Key: ")
bob_k = int(p.recvline()[:-1],16)
attacker_b.set_shared_key(bob_k)
p.sendafter(b">> ",b'32\n')
# flag 복호화
p.recvuntil(b"Alice: ")
alice_encrypt_message = p.recvline()[:-1].decode()
p.recvuntil(b"Bob: ")
bob_encrypt_message = p.recvline()[:-1].decode()
flag = ''
flag = attacker_a.decrypt(alice_encrypt_message)
flag += attacker_b.decrypt(bob_encrypt_message)
print("FLAG : {}".format(flag))