emojicrypt
emojicrypt - web
Tên: emojicrypt
Description: Passwords can be more secure. We’re taking the first step.
Có source code
Phân tích
Có 2 chức năng :
- Register: Khi register sẽ không biết password.
- Login: Chỉ cần login được sẽ lấy được flag.
Phân tích source code:
1 | EMOJIS = ['🌀', '🌁', '🌂', '🌐', '🌱', '🍀', '🍁', '🍂', '🍄', '🍅', '🎁', '🎒', '🎓', '🎵', '😀', '😁', '😂', '😕', '😶', '😩', '😗'] |
1 | def generate_salt(): |
EMOJIS có 21 emoji.random.choices(..., k=12) → chọn random 12 emoji.
Rồi ghép lại bằng chuỗi 'aa' (tức emoji1 + 'aa' + emoji2 + 'aa' + …)
Mỗi emoji trong UTF-8 thường có độ dài 4 byte,ghép với chuỗi 'aa' nghĩa là độ dài salt là:4x12 + 2x11 = 70 byte
1 | random_password = ''.join(random.choice(NUMBERS) for _ in range(32)) |
Ghép salt + password → rồi .encode("utf-8") → ra 1 chuỗi byte
Bỏ vào bcrypt.hashpw(...) để hash
📉 Nhưng vấn đề chết người ở đây là: BCRYPT chỉ dùng 72 byte đầu tiên
Phần nào vượt quá 72 byte → bị bỏ luôn
→ Dẫn đến khả năng 2 password khác nhau vẫn hash ra cùng giá trị nếu phần khác nằm sau byte 72
1 | if salt and hash and bcrypt.checkpw((salt + password).encode("utf-8"), hash.encode("utf-8")): |
Do đó thực chất phần password được ghép với satl và hash chỉ có độ dài 2 byte → Có thể brute force được.
Exploit
Sử dụng Intruder của Burpsuite để brute force password chạy từ 00 đến 99:
Lấy flag:
Flag: squ1rrel{turns_out_the_emojis_werent_that_useful_after_all}