Skip to content

SECURITY: Multiple vulnerabilities including code execution via new Function in GeoJSON parsing #21626

@wangshuyan-cheng

Description

@wangshuyan-cheng

Apache ECharts 安全漏洞报告 — 百度BSRC

项目: Apache ECharts (60k⭐)
厂商: 百度 (Baidu)
赏金计划: Baidu SRC (sec.baidu.com, ¥300k max)
完成日期: 2026-05-21


漏洞摘要

# 漏洞类型 严重程度 CVSS
1 new Function代码执行 — GeoJSON解析 HIGH 8.8
2 原型污染 — constructor.prototype HIGH 7.5
3 XSS — tooltip innerHTML MEDIUM 6.1
4 XSS — DataView optionToContent MEDIUM 6.1
5 SVG注入 — 连接图表导出 MEDIUM 5.4
6 XSS — tooltip函数格式化器 LOW 3.5

VULN-1: new Function 代码执行 (HIGH, CVSS 8.8)

文件: src/coord/geo/GeoJSONResource.ts:168

代码:

// GeoJSON解析 fallback
parseInput() {
    try {
        return JSON.parse(source);
    } catch (e) {
        // 在旧浏览器中不安全回退
        return new Function('return (' + source + ');')();
    }
}

JSON.parse失败(如遇到旧浏览器或非严格JSON数据),代码使用new Function()执行用户提供的GeoJSON源。攻击者通过控制地图数据的URL参数,能在legacy浏览器中实现任意JavaScript代码执行。

PoC:

// 如果用户提供了自定义GeoJSON URL
chart.setOption({
    geo: {
        map: 'world',
        // 如果地图加载器使用parseInput()
    }
});
// 当GeoJSON数据为: (function(){/*恶意代码*/})()

影响: 任意代码执行在解析用户提供GeoJSON数据的上下文中。

建议: 移除new Function回退。所有现代浏览器都支持JSON.parse


VULN-2: 原型污染 — constructor.prototype (HIGH, CVSS 7.5)

文件: node_modules/zrender/src/core/util.ts (merge函数)

代码:

function merge(target, source, overwrite) {
    for (var key in source) {
        if (key === '__proto__') continue; // 只拦截__proto__,不拦截constructor
        // ...
        if (typeof sourceVal === 'object') {
            merge(targetVal, sourceVal, overwrite);
        }
    }
}

zrender的merge()函数明确阻止__proto__但没有阻止constructor。精心构造的选项对象如{"constructor": {"prototype": {"polluted": true}}}可以通过递归合并污染Object.prototype。所有选项合并路径受影响:GlobalModel.mergeOptionModel.mergeOptionComponentModel.mergeOption

影响: 影响所有使用ECharts选项合并的应用程序。全局原型污染可能导致后续所有对象的属性访问异常,甚至在某些框架中导致RCE。

建议: 增加constructor键拦截:

if (key === '__proto__' || key === 'constructor') continue;

VULN-3: XSS via tooltip innerHTML (MEDIUM, CVSS 6.1)

文件: src/component/tooltip/TooltipHTMLContent.ts:453

代码:

setContent(content, ...) {
    el.innerHTML = content + arrow;
    // 无HTML净化
}

直接使用innerHTML赋值,在某些渲染路径下不进行HTML编码。虽然默认字符串格式化器已编码,函数格式化器返回任意HTML无净化。

建议: 在非HTML渲染模式加入DOMPurify.sanitize()createHTMLDocument


VULN-4: XSS via DataView optionToContent (MEDIUM, CVSS 6.1)

文件: src/component/toolbox/feature/DataView.ts:358

直接赋值用户提供的optionToContent回调返回的HTML到viewMain.innerHTML


VULN-5: SVG注入 — 连接图表导出 (MEDIUM, CVSS 5.4)

文件: src/core/echarts.ts:1079

从多个连接图表的SVG DOM中拼接原始字符串并赋值为innerHTML。恶意SVG中的<script>标签或事件处理程序会跨图表传播。


VULN-6: XSS via tooltip函数格式化器 (LOW, CVSS 3.5)

文件: src/component/tooltip/TooltipView.ts:858-868

函数格式化器返回值可在非HTML模式下嵌入未编码的用户数据。


报告提交方式

Baidu SRC: sec.baidu.com
邮箱备选: security@baidu.com
说明: 需要中国手机号注册(用户手机15338892617)。
建议通过Baidu SRC平台以中文提交,或在平台无法自动登录时通过邮件发送至security@baidu.com


审计方法

  • 静态代码搜索: grep/rg搜索危险模式(innerHTML, new Function, merge, eval等)
  • 手工追踪代码执行路径
  • 基于ECharts 5.x源码审计

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis issue was not created using the issue template.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions