PASSWORDS AS KEYS

 

문제

대칭 키 알고리즘에서 키는 암호나 다른 예측 가능한 데이터 대신에, 랜덤 바이트여야 합니다. 랜덤 바이트는 암호화 보안 의사 난수 생성기(CSPRNG)를 사용하여 생성되어야 합니다. 키가 어떤 식으로든 예측 가능하면 암호의 보안 수준이 감소하고 암호문에 접근한 공격자가 암호를 해독할 수 있다.

키가 임의의 바이트로 구성된 것처럼 보인다고 해서 키가 반드시 그런 것은 아니다. 이 경우 키는 해싱 기능을 사용하는 간단한 암호에서 파생되어 암호문을 크래킹할 수 있습니다.

이 문제를 해결하기 위해 HTTP 요청을 엔드포인트에 스크립팅하거나, 암호문을 오프라인으로 공격할 수 있습니다.
행운을 빕니다.

https://aes.cryptohack.org/passwords_as_keys/

풀이

더보기
from Crypto.Cipher import AES
import hashlib
import random


# /usr/share/dict/words from
# https://gist.githubusercontent.com/wchargin/8927565/raw/d9783627c731268fb2935a731a618aa8e95cf465/words
with open("/usr/share/dict/words") as f:
    words = [w.strip() for w in f.readlines()]
keyword = random.choice(words)

KEY = hashlib.md5(keyword.encode()).digest()
FLAG = ?


@chal.route('/passwords_as_keys/decrypt/<ciphertext>/<password_hash>/')
def decrypt(ciphertext, password_hash):
    ciphertext = bytes.fromhex(ciphertext)
    key = bytes.fromhex(password_hash)

    cipher = AES.new(key, AES.MODE_ECB)
    try:
        decrypted = cipher.decrypt(ciphertext)
    except ValueError as e:
        return {"error": str(e)}

    return {"plaintext": decrypted.hex()}


@chal.route('/passwords_as_keys/encrypt_flag/')
def encrypt_flag():
    cipher = AES.new(KEY, AES.MODE_ECB)
    encrypted = cipher.encrypt(FLAG.encode())

    return {"ciphertext": encrypted.hex()}

 

 먼저 파일을 열고 word변수에 저장하는데

 

주석에 적혀진 사이트로 가면 단어 사전 파일이 있다.

여기에 있는 단어들을 가져와

임의로 정해 이를 keyword에 저장하고,

이를 또 Key에 md5함수로 해시화한다. 

 

그리고 decrypt함수에선 

ecb모드로 복호화시켜 평문을 16진수로 반환한다.

 

encrypt_flag에선 flag값과 키값을 가져와 암호화 시킨다.

 

 

c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66

일단 사이트에서 encrypt_flag를 실행 했다

이 암호문을  복호화하는 과정에서 이 파일에 있는 단어들로 브루트 포싱을 해보았다.

from Crypto.Cipher import AES
import hashlib

with open('words.txt', 'r') as f:
    words = [w.strip() for w in f.readlines()]

def decrypt(ciphertext, password_hash): # 문제에 가져온 decrypt
    ciphertext = bytes.fromhex(ciphertext)
    key = bytes.fromhex(password_hash)

    cipher = AES.new(key, AES.MODE_ECB)
    try:
        decrypted = cipher.decrypt(ciphertext)
    except ValueError as e:
        return {"error": str(e)}
    return decrypted

ciphertext='c92b7734070205bdf6c0087a751466ec13ae15e6f1bcdd3f3a535ec0f4bbae66'

for dic in words:
    password_hash = hashlib.md5(dic.encode()).hexdigest()
    plaintext = decrypt(ciphertext, password_hash)
    if b'crypto' in plaintext:
        print(plaintext)

플래그값이 나왔다.

플래그값은 crypto{k3y5__r__n07__p455w0rdz?}이다.

 

복사했습니다!