สวัสดีค้าบวันนี้จะมาเขียน Writeups ของข้อ sshv3 ในการแข่งขัน Fincybersec2020 นะค้าบ
เป็นโจทย์ข้อยากที่สุด(แต่มี writeup คล้ายกันตามเน็ต)ในหมวด cryptography
โจทย์เป็นอย่างไร
มีเว็บมาให้พร้อม source code เป็นเว็บฝากข้อความ และให้รหัสเรามาทำการเรียกข้อความได้อีกครั้ง
แต่พอลองดู source code แล้ว flag จริงๆ ไม่ได้เกี่ยวกับส่วนฝากข้อความ แต่แลดูไม่ปลอดภัยเนื่องจากมีการใช้ key และ nonce ในการเข้ารหัส ciphertext และ tag ที่ซ้ำกัน โดยเข้ารหัสแบบ AES-GCM และใช้ ข้อความ "username:" ตามด้วย username ของ user ในการทำ ciphertext
def __init__(self, key, nonce):
self.encryptor = Encryptor(key, nonce)
self.nonce = nonce
self.users = [
{
"username": "admin",
"password": os.urandom(30).hex()
},
{
"username": "dummy",
"password": "dummy"
},
{
"username": "test1",
"password": "test1"
},
{
"username": "test2",
"password": "test2"
}
]
class Encryptor(object):
def __init__(self, key, nonce):
self.nonce = nonce
self.key = key
def encrypt(self, plaintext):
key = AES.new(self.key, AES.MODE_GCM, nonce=self.nonce)
ciphertext, tag = key.encrypt_and_digest(plaintext.encode())
return ciphertext.hex() + ":" + tag.hex()
def decrypt(self, ciphertext):
words = [bytes.fromhex(c) for c in ciphertext.split(":")]
ciphertext = words[0]
tag = words[1]
key = AES.new(self.key, AES.MODE_GCM, nonce=self.nonce)
return key.decrypt_and_verify(ciphertext, tag)
def login(self, username, password):
for user in self.users:
if user["username"] == username and user["password"] == password:
token = self.encryptor.encrypt("username:%s" % username)
return token
return None
ลองทำการหา write up ที่มีในเน็ตแล้วทำความเข้าใจ
พอทำการลองหา write up ctf ของ การเข้ารหัส AES-GCM พบของ meowmeowxw พบว่าต้องมี ciphertext กับ tag ของ admin จึงจะทำ token ได้โดย token จะมี format เป็น ciphertext:tag
แก้ได้จำเป็นต้องมีอะไรบ้าง
ลองแก้ให้ได้ admin cypher text
เนื่องจากทราบทั้ง plaintext และ cyphertext และมี plaintext ที่ เราต้องการ cipher ตาม algorithm ที่ทำ cipher ของ GCM แล้ว ใช้ GCTR function ซึ่งคือ นำ plaintext ไป xor กับ key นี้เอง หากเรา นำ plaintext มา xor กับ ciphertext ก็จะได้กลับมาเป็น key ไว้ใช้ cipher plaintext
เพิ่มเติม GCTR
ลองแก้ให้ได้ token
นำเอาโค๊ด exploit ของ meowmeowxw มาแก้ ตัวแปรต่างๆอิงตามการอธิบายของ meowmeowxw โลด
เพราะเนื่องจากขนาด block เล็กกว่าจึงต้องทำการคำนวณสมการ polynomial ใหม่ ได้เป็น
$G(X) = C{\scriptstyle 1,1}X^2+LH+EJ$ (1)
$G(X) = C{\scriptstyle 2,1}X^2+LH+EJ$ (2)
$G(X) = C{\scriptstyle 3,1}X^2+LH+EJ$ (3)
เมื่อเราแก้สมการ polynomial มาแล้วจาก (1) + (2) ก็จะได้ค่า H ที่ทำการคิดค่า Tag นำ H ไปแทนในสมการ (1) หรือ (2) เพื่อให้ได้ EJ และนำไปใช้ในสมการ (3) ให้ได้ Tag มานั้นเอง
พอรันแล้วก็นำ token ไปใช้และเข้า path /admin
ตอนแรกไม่คาดว่าจะเขียนเป็น writeup แต่เนื่องจากมีคนขอมาแต่ทิ้งช่วงมานานหน่อยเนื่องจากติดสอบ คาดว่าเนื้อหาที่ได้เขียนมาไม่ได้ให้ความเข้าใจในการแก้โจทย์ทั้งหมด แต่หวังว่าจะเป็นแนวทางสำหรับผู้ที่พบเจอโจทย์แนวเข้ารหัสว่าแม้ข้อยากก็มักง่ายเมื่อโชคดีเจอ write up ใน google เช่นเดียวกับการป้องกันระบบที่จำเป็นต้องมีการ update อันตรายใหม่ๆเสมอ เพื่อไม่ให้โดน exploit ที่เจอในอากู๋เล่นงาน