Featured image of post CouchDB远程代码执行漏洞深度解析

CouchDB远程代码执行漏洞深度解析

本文详细分析了CouchDB因原生JSON解析器与JavaScript解析器处理重复键差异导致的安全漏洞(CVE-2017-12635),攻击者可利用此漏洞创建管理员账户并实现远程代码执行,同时探讨了对npm注册表的潜在影响。

CouchDB远程代码执行漏洞

Max Justicz
2017年11月14日

摘要

背景

作者此前曾报道过rubygems.org的反序列化漏洞导致代码执行的问题。向上游项目依赖注入恶意软件是一种危险的攻击向量,多数组织尚未做好充分防护。

基于此,作者开始研究registry.npmjs.org(npm包分发服务器)的漏洞。据其首页显示,npm注册表每周处理超过30亿次包下载。

CouchDB技术细节

npm注册表使用CouchDB,这是一种支持数据复制的"NoSQL"数据库。其核心是存储JSON文档的键值库,具备数据验证、查询和用户认证功能,使用Erlang编写但允许用户通过JavaScript编写文档验证脚本。

CouchDB通过_users系统数据库管理用户账户。创建或修改用户时(通常通过PUT请求/_users/org.couchdb.user:用户名),服务器会调用JavaScript的validate_doc_update函数验证修改合法性。

漏洞原理

漏洞源于JavaScript JSON解析器与CouchDB内部jiffy解析器(Erlang实现)处理重复键的差异:

  • Erlang解析器:jiffy:decode("{\"foo\":\"bar\", \"foo\":\"baz\"}") 返回两个键值对
  • JavaScript解析器:JSON.parse() 仅保留最后一个键值

CouchDB内部数据获取函数couch_util:get_value仅返回第一个匹配值,导致可构造特殊payload绕过验证:

1
2
3
4
5
6
7
8
curl -X PUT 'http://localhost:5984/_users/org.couchdb.user:oops' \
--data-binary '{
  "type": "user",
  "name": "oops",
  "roles": ["_admin"],
  "roles": [],
  "password": "password"
}'

Erlang端会识别roles["_admin"],而JavaScript端仅看到空数组,从而成功创建管理员账户。

权限提升与RCE

获取管理员权限后,可通过CouchDB的查询服务器语言配置功能(本质为execv包装器)实现远程代码执行。值得注意的是,通过Web界面查看用户时因JavaScript解析会显示空角色字段,增加了隐蔽性。

对npm的影响分析

经考证,registry.npmjs.org虽采用类似CouchDB的用户创建流程,但自2015年起已使用自定义认证系统,因此不受此漏洞影响(作者初始判断有误)。但npm的"skim数据库"确实存在RCE风险,不过该组件在当前架构中的具体作用尚不明确。

结论与建议

使用多个解析器处理相同数据时,必须确保各解析器行为一致性。JSON标准未规定重复键处理方式更凸显了该问题的重要性。

致谢

感谢CouchDB团队通过security@邮箱快速响应并修复漏洞。


comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计