Security/암호학(Cryptography)

[CryptoHack] Flipping Cookie

그믐​ 2023. 5. 4. 17:07
반응형

 

 

제 웹사이트를 위한 쿠키를 얻을 수 있지만 flag를 읽는 데 도움이 되지 않습니다... 제 생각에는 말이죠.

 

from Crypto.Cipher import AES
import os
from Crypto.Util.Padding import pad, unpad
from datetime import datetime, timedelta


KEY = ?
FLAG = ?


@chal.route('/flipping_cookie/check_admin/<cookie>/<iv>/')
def check_admin(cookie, iv):
    cookie = bytes.fromhex(cookie)
    iv = bytes.fromhex(iv)

    try:
        cipher = AES.new(KEY, AES.MODE_CBC, iv)
        decrypted = cipher.decrypt(cookie)
        unpadded = unpad(decrypted, 16)
    except ValueError as e:
        return {"error": str(e)}

    if b"admin=True" in unpadded.split(b";"):
        return {"flag": FLAG}
    else:
        return {"error": "Only admin can read the flag"}


@chal.route('/flipping_cookie/get_cookie/')
def get_cookie():
    expires_at = (datetime.today() + timedelta(days=1)).strftime("%s")
    cookie = f"admin=False;expiry={expires_at}".encode()

    iv = os.urandom(16)
    padded = pad(cookie, 16)
    cipher = AES.new(KEY, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(padded)
    ciphertext = iv.hex() + encrypted.hex()

    return {"cookie": ciphertext}

 

분석


check_admin함수에서는 cookie와 iv를 입력받는다.

AES_CBC를 가지고 복호화하는 과정을 거치는데, 복호화하고 패딩을 제거한 문자열에서

;로 구분했을 때, admin=True라는 문장이 있으면 flag를 준다.

 

그럼 get_cookie부분은 어떨까. admin=False와 cookie의 만료 시간을 적고 byte로 바꾼다.

바꾼 문자열을 AES_CBC로 암호화하여 돌려준다.

 

admin=False라는 내용은 한 블록 내에 들어간다.

우리가 입력받는건 cookie와 iv인데, cookie암호화 과정이 예측되도록 그대로 준다 쳐도 iv를 잘 바꾸면 복호화 결과를 admin=True가 나오도록 할 수는 없을까

 

풀이


아니 뭐야 iv를 주잖아;; 계속 고민했는데

 

 

iv와 원문을 알고 있으므로 iv를 입력하는 부분에  iv ^ 원문 ^ admin=true 이런 값을 넣으면 된다.

복호화 이후에 iv와 xor을 하게 되는데 위와 같이 입력하면 iv ^ 원문이 xor에 의해 날아가고 admin = true 만 남을 것이기 때문이다.

 

import requests
from pwn import *

url = 'https://aes.cryptohack.org/flipping_cookie/'

def check_admin(cookie, iv):
    furl = url + f'check_admin/{cookie}/{iv}/'
    r = requests.get(furl)
    js = r.json()
    try :
        print(js['flag'])
    except:
        print(js['error'])
    

def get_cookie():
    furl = url + 'get_cookie/'
    r = requests.get(furl)
    js = r.json()
    return bytes.fromhex(js['cookie'])

cookie = get_cookie()
iv = cookie[: 16]
ciphertext = cookie[16 :]
plain16 = b'admin=False;expi'
shot = b'admin=True;;;;;;'

payload = xor(xor(iv, plain16), shot)

check_admin(ciphertext.hex(), payload.hex())

 

이걸 코드로 구현하면 된다.

 

 

반응형