|
from base64 import b64decode, b64encode |
|
from Crypto.Cipher import AES |
|
import hmac |
|
import hashlib |
|
import json |
|
|
|
# --- Configuration --- |
|
# The Laravel application key, base64 decoded. Must be the same key used for encryption. |
|
APP_KEY_STR = 'base64{{m4g}}/PPRFq4e6T1dwOFEEEckhU+ZedBGZtiM/BRSJE7g='.replace("base64", "").replace("}", "").replace("{", "").replace("}", "") |
|
print(f"Using APP_KEY: {APP_KEY_STR}") |
|
APP_KEY = b64decode(APP_KEY_STR) |
|
|
|
# The full encoded cookie from Laravel's XSRF-TOKEN. |
|
# Replace this with the cookie you want to decrypt. |
|
encoded_cookie = 'eyJpdiI6InVXejczdzhRV1Q0WFBKckExR2lrQWc9PSIsInZhbHVlIjoiU0M2ME85NzJUTmdSNkEzaGEzV0VpQTZKTUFZbEJyd1ptdmNSdWdNc0UrS2NRQUlUNUlYa1hycFhJNmxkZWZhK0duOHk2ZzA5amNsUnFMN08ybkZiaTFlNkJvbmNLbnJVSDlkcnArSEZDZXhla2pCcC9xai9VY1JrUG1nYkhYUUciLCJtYWMiOiI3YjA0MTY4ZWQwZjVmNjI5ODJjYWQ3NDNkNjlmY2E2OGVmMmQ0YzA1ZWQ4ZTcwZDY1MGExN2YxNTlkNWUyNDUxIiwidGFnIjoiIn0=' |
|
# --- End Configuration --- |
|
|
|
def unpad(s): |
|
"""Removes PKCS7 padding.""" |
|
padding_len = s[-1] |
|
if padding_len > 16 or padding_len == 0: |
|
# Invalid padding |
|
return s |
|
return s[:-padding_len] |
|
|
|
def decrypt_laravel_cookie(encoded_cookie, app_key): |
|
""" |
|
Reverses the Laravel encryption process to decrypt a cookie. |
|
""" |
|
try: |
|
# 1. Base64 Decode the cookie |
|
decoded_json = b64decode(encoded_cookie) |
|
|
|
# 2. JSON Decode to get the payload parts |
|
payload = json.loads(decoded_json) |
|
|
|
iv_b64 = payload['iv'] |
|
value_b64 = payload['value'] |
|
mac_from_cookie = payload['mac'] |
|
print(f"[+] Value from cookie: IV={iv_b64}, Value={value_b64}, MAC={mac_from_cookie}") |
|
# 3. Verify the MAC |
|
# The MAC is a SHA256 HMAC of the base64-encoded IV and value concatenated. |
|
mac_data = (iv_b64 + value_b64).encode() |
|
expected_mac = hmac.new(app_key, mac_data, hashlib.sha256).hexdigest() |
|
|
|
if not hmac.compare_digest(expected_mac, mac_from_cookie): |
|
print("[-] MAC verification failed! The cookie may have been tampered with.") |
|
return None |
|
|
|
print("[+] MAC verification successful.") |
|
|
|
# 4. Base64 Decode IV and Ciphertext |
|
iv = b64decode(iv_b64) |
|
ciphertext = b64decode(value_b64) |
|
|
|
# 5. Decrypt using AES-256-CBC |
|
cipher = AES.new(app_key, AES.MODE_CBC, iv) |
|
decrypted_padded = cipher.decrypt(ciphertext) |
|
|
|
# 6. Remove PKCS7 Padding |
|
plaintext = unpad(decrypted_padded) |
|
|
|
return plaintext |
|
|
|
except (json.JSONDecodeError, KeyError, ValueError) as e: |
|
print(f"[-] An error occurred during decoding/decryption: {e}") |
|
return None |
|
|
|
if __name__ == "__main__": |
|
if encoded_cookie == '<your_cookie_here>': |
|
print("[!] Please edit the script and replace '<your_cookie_here>' with the actual cookie value.") |
|
else: |
|
print(f"[+] Attempting to decrypt cookie: {encoded_cookie[:30]}...") |
|
|
|
decrypted_payload = decrypt_laravel_cookie(encoded_cookie, APP_KEY) |
|
|
|
if decrypted_payload: |
|
print("\n[+] Decryption successful! Original plaintext:") |
|
try: |
|
# Try to print as a string, fallback to bytes |
|
print(decrypted_payload.decode()) |
|
except UnicodeDecodeError: |
|
print(decrypted_payload) |
|
|
|
# Optionally, save to a file |
|
with open("decrypted_payload.txt", "wb") as f: |
|
f.write(decrypted_payload) |
|
print("\n[+] Decrypted payload saved to 'decrypted_payload.txt'") |
Also see: https://medium.com/studocu-techblog/sharing-encrypted-laravel-cookies-with-next-js-8d270c19df6a