Langflow CORS链式漏洞 | CVE-2025-34291 复现&研究

0x0 背景介绍

Langflow是一个用于构建AI应用的低代码可视化IDE。它就像是LangChain的"乐高版",通过拖拽组件、连接线条,你就能快速搭建起复杂的LLM(大语言模型)工作流。Langflow 1.6.9及之前版本存在一个链式漏洞,可导致账户接管和远程代码执行。过度宽松的CORS配置(allow_origins='*' 且 allow_credentials=True)与配置为SameSite=None的刷新令牌Cookie相结合,使得恶意网页能发起包含凭据的跨域请求并成功调用刷新接口。攻击者控制的源站因此可获取受害者会话的新access_token/refresh_token组合。获取的令牌允许访问需认证的端点(包括内置的代码执行功能),使攻击者能执行任意代码并实现完全系统入侵。

0x1 环境搭建

1、Ubuntu24+Docker搭建配置

  • 嗯!不要嫌弃
bash 复制代码
#0、项目目录
langflow-cve-poc/
├── .env
├── docker-compose.yml
├── nginx.conf
├── ssl/
│   ├── self.crt
│   └── self.key
└── poc.html

#1、创建项目文件夹
mkdir langflow-cve-poc && cd langflow-cve-poc

#2、.env(身份认证配置-模拟被读取)
LANGFLOW_AUTO_LOGIN=False
LANGFLOW_SUPERUSER=admin
LANGFLOW_SUPERUSER_PASSWORD=admin
LANGFLOW_SECRET_KEY=dBuuuB_FHLvU8T9eUNlxQF9ppqRxwWpXXQ42kM2_fb
LANGFLOW_NEW_USER_IS_ACTIVE=False
LANGFLOW_DATABASE_URL=sqlite:////app/data/langflow.db
LANGFLOW_SKIP_STARTER_PROJECTS=true

#3、docker-compose.yml
services:
  langflow:
    image: langflowai/langflow:1.6.9
    expose:
      - "7860"
    env_file:
      - .env
    volumes:
      - ./data:/app/data
    restart: unless-stopped

  nginx:
    image: nginx:latest
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - langflow
    restart: unless-stopped
	
	
#4、nginx.conf(反向代理 + HTTPS)
events {}

http {
  server {
    listen 443 ssl;
    server_name localhost;

    ssl_certificate /etc/nginx/ssl/self.crt;
    ssl_certificate_key /etc/nginx/ssl/self.key;

    location / {
      proxy_pass http://langflow:7860;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto https;
    }
  }
}
#5、ssl证书
mkdir ssl
cd ~/langflow-cve-poc/ssl

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout self.key -out self.crt \
  -subj "/C=US/ST=State/L=City/O=LangflowPOC/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
  
#6、创建本地 data 目录并赋权

mkdir -p ~/langflow-cve-poc/data
chmod 777 ~/langflow-cve-poc/data 
  
#7、启动环境
docker compose up -d

2、 环境访问:

PS:镜像大小是10G,请自行考虑下,

  • 打印启动日志,大约2分钟就可以访问
bash 复制代码
docker logs -f langflow-cve-poc-langflow-1

0x2 漏洞复现

1、本地检测

bash 复制代码
https://github.com/Kai-One001/cve-/blob/main/Langflow_CORS_CVE_2025_34291_POC.html

2、复现截图

  • 未登录状态利用失败
  • 登录状态利用成功

3、手动复现步骤

  • burp验证可跨域

4、复现流量特征 (PCAP)

  • 后续的代码执行其实是CVE-2025-3248的方式,因为3248修复是对接口进行认证处理

0x3 漏洞原理分析

OS:看见大项目的代码,头就大,万幸的是我们现在站在巨人的肩膀,去仰望太阳会容易些

小结 :本次漏洞核心其实是cors跨域分享导致复用CVE-2025-32483248漏洞修复其实是对接口进行认证处理,本次漏洞是发现认证后的token可以共享出来,导致3248相当于未修复
CORS(跨域资源共享)Cross-Origin Resource Sharing是一种基于HTTP头的安全机制,它允许一个网页从不同域名(不同源)的服务器请求资源,从而克服了浏览器的同源策略限制。

1、漏洞定位

  • 通过IntelliJ IDEA 定位查询CORSMiddleware(技巧:具体类/函数名)锁定文件main.py-create_app函数中
python 复制代码
def create_app():
    """Create the FastAPI app and include the router."""
    from langflow.utils.version import get_version_info

    __version__ = get_version_info()["version"]
    configure()
    lifespan = get_lifespan(version=__version__)
    app = FastAPI(
        title="Langflow",
        version=__version__,
        lifespan=lifespan,
    )
    app.add_middleware(
        ContentSizeLimitMiddleware,
    )

    setup_sentry(app)

    settings = get_settings_service().settings

    # Warn about future CORS changes
    warn_about_future_cors_changes(settings)

    # Configure CORS using settings (with backward compatible defaults)
    origins = settings.cors_origins
    if isinstance(origins, str) and origins != "*":
        origins = [origins]

    # Apply current CORS configuration (maintains backward compatibility)
    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=settings.cors_allow_credentials,
        allow_methods=settings.cors_allow_methods,
        allow_headers=settings.cors_allow_headers,
    )
    app.add_middleware(JavaScriptMIMETypeMiddleware)

逻辑:

  • settings.cors_origins = "*" 时,origins 保持为字符串 "*"
  • settings.cors_origins = "https://404abc123.com"时,转换为列表["https://404abc123.com"]
  • 但是:当 settings.cors_origins = ["*"](列表)时,保持不变

2、查看其它配置

  • main.py中可以看到还有其它设置,去查看get_settings_service函数
python 复制代码
settings = get_settings_service().settings
  • IDA没办法跳转到具体声明中( PyCharm / VS Code可以实现),不过在开头有发现,定位到langflow.services.deps文件
python 复制代码
from langflow.services.deps import get_queue_service, get_service, get_settings_service, get_telemetry_service

定位到具体文件

python 复制代码
#src\backend\base\langflow\services\settings\base.py
    # CORS Settings
    cors_origins: list[str] | str = "*" #!!!!
    """Allowed origins for CORS. Can be a list of origins or '*' for all origins.
    Default is '*' for backward compatibility. In production, specify exact origins."""
    cors_allow_credentials: bool = True #!!!!
    """Whether to allow credentials in CORS requests.
    Default is True for backward compatibility. In v1.7, this will be changed to False when using wildcard origins."""
    cors_allow_methods: list[str] | str = "*"
    """Allowed HTTP methods for CORS requests."""
    cors_allow_headers: list[str] | str = "*"
    """Allowed headers for CORS requests."""
  • 俩个危险组合导致允许任意第三方网站发起带 Cookie 的请求,那么如何去获取到这个Cookie呢

根据CORS规范:当allow_origins="*"时,浏览器会拒绝credentials: true的请求。但FastAPIORSMiddleware实现可能允许这种配置,导致安全风险。

3、漏洞升级-刷新令牌接口实现

有一个接口是检验比较单一
位置 : src/backend/base/langflow/api/v1/login.py

python 复制代码
#123:158:src/backend/base/langflow/api/v1/login.py
@router.post("/refresh")
async def refresh_token(
    request: Request,
    response: Response,
    db: DbSession,
):
    auth_settings = get_settings_service().auth_settings

    token = request.cookies.get("refresh_token_lf")

    if token:
        tokens = await create_refresh_token(token, db)
        response.set_cookie(
            "refresh_token_lf",
            tokens["refresh_token"],
            httponly=auth_settings.REFRESH_HTTPONLY,
            samesite=auth_settings.REFRESH_SAME_SITE,
            secure=auth_settings.REFRESH_SECURE,
            expires=auth_settings.REFRESH_TOKEN_EXPIRE_SECONDS,
            domain=auth_settings.COOKIE_DOMAIN,
        )
        response.set_cookie(
            "access_token_lf",
            tokens["access_token"],
            httponly=auth_settings.ACCESS_HTTPONLY,
            samesite=auth_settings.ACCESS_SAME_SITE,
            secure=auth_settings.ACCESS_SECURE,
            expires=auth_settings.ACCESS_TOKEN_EXPIRE_SECONDS,
            domain=auth_settings.COOKIE_DOMAIN,
        )
        return tokens
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Invalid refresh token",
        headers={"WWW-Authenticate": "Bearer"},
    )

问题分析:

  • 接口从Cookie中读取refresh_token_lf,只检查是否有cookie
  • 没有验证请求来源Origin检查
  • 没有CSRF令牌保护
  • 返回新的access_token和refresh_token在响应体中

0x4 修复建议

修复方案

  1. 升级到最新版本:升级到1.6.9以上版本:langflow

  2. 临时防护措施:
    修复CORS配置 :禁止Access-Control-Allow-Origin: * 与 Access-Control-Allow-Credentials: true同时启用
    启用CSRF防护: :在关键接口增加CSRF Token验证机制,防止恶意请求
    关注敏感接口 :监控 /api/v1/refresh/api/v1/validate/code 的异常调用

免责声明:本文仅用于安全研究目的,未经授权不得用于非法渗透测试活动。

相关推荐
哥布林学者1 天前
吴恩达深度学习课程五:自然语言处理 第一周:循环神经网络 (七)双向 RNN 与深层 RNN
深度学习·ai
自己的九又四分之三站台1 天前
HuggingFace
ai
源代码•宸1 天前
Golang语法进阶(协程池、反射)
开发语言·经验分享·后端·算法·golang·反射·协程池
软件小滔1 天前
Mac 上看图?从需求出发的功能匹配
经验分享·macos·mac·应用推荐
qq_318121591 天前
Java大厂面试故事:Spring Boot、微服务与AI场景深度解析
java·spring boot·redis·微服务·ai·kafka·spring security
软件小滔1 天前
MacOS 26.0 网速监控我试了十几款,从系统API到可视化实现
经验分享·macos·mac·应用推荐
Wpa.wk1 天前
性能测试工具 - JMeter工具组件介绍二
运维·经验分享·测试工具·jmeter·自动化·json
GEO科技1 天前
人工智能时代,中华文化如何构建“算法主权”与认知体系?湄洲岛与氧气科技共同探索妈祖文化“非遗+AI”传播新路径
经验分享
LaughingZhu1 天前
Product Hunt 每日热榜 | 2026-01-12
人工智能·经验分享·深度学习·神经网络·产品运营
饭勺oO1 天前
AI 编程配置太头疼?ACP 帮你一键搞定,再也不用反复折腾!
ai·prompt·agent·acp·mcp·skills·agent skill