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 的异常调用

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

相关推荐
梁萌2 小时前
idea使用AI插件(CodeGeeX)
java·ide·ai·intellij-idea·插件·codegeex
weixin_537217063 小时前
亲子教育资源合集
经验分享
吴爃4 小时前
N8N调用系统接口进行AI分析
运维·人工智能·ai
TeleostNaCl4 小时前
OpenWrt | 使用 nftables 规则禁用小明投影仪内置 DoT 服务的流量
经验分享·智能路由器·电视盒子·智能电视·tv·智能tv
tokepson4 小时前
反向传播
深度学习·算法·ai·反向传播
roamingcode4 小时前
2025年技术变革浪潮:从 AI Agent 标准化到人类认知重构
人工智能·ai·重构·agent·skill·mcp
我命由我123454 小时前
开发中的英语积累 P21:Parentable、Guideline、Manifest、Expire、Condition、Optimize
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
小北方城市网4 小时前
第 5 课:Vue 3 HTTP 请求与 UI 库实战 —— 从本地数据到前后端交互应用
大数据·前端·人工智能·ai·自然语言处理
wayuncn4 小时前
AI领域核心概念解析:模型、模型参数、模型大小、计算精度
人工智能·ai·ai智能体·ai定制开发