CVE-2020-27304 - RCE通过目录遍历在CivetWeb HTTP服务器

CivetWeb -安全漏洞863x300

背景

JFrog最近披露了一个目录遍历问题CivetWeb这是一个非常流行的嵌入式web服务器/库,既可以作为一个独立的web服务器使用,也可以作为一个库添加到现有的应用程序的web服务器功能。这个问题已分配给cve - 2020 - 27304

这个目录遍历问题很容易被利用,并且可以导致远程代码执行,特别是当web服务器以root身份运行时——由于攻击者有能力添加或覆盖随后执行的文件。

谁会受到影响?

这个问题影响了CivetWeb版本1.8到1.14(包括),最近修复了1.15版本

此问题只影响使用内置文件上传表单处理程序的基于web的civetweb应用程序。
用技术术语来说,基于web的civetweb应用程序在以下情况下是脆弱的:

  1. 该应用程序通过调用CivetWeb的来处理HTTP表单数据handle_form_request并提供(必选的)用户定义的field_found回调函数
  2. field_found回调函数返回MG_FORM_FIELD_STORAGE_STORE表示文件上传操作
  3. field_found回调函数提供(强制的)路径输出参数,其中路径依赖于文件名输入参数(该参数直接来自HTTP表单数据)

请注意,此场景是使用CivetWeb的文件上传功能的标准方式,并作为完整的工作示例在“embedded_c的例子。

CivetWeb内置的文件上传功能

允许HTTP客户端向服务器上传文件的Web服务器,通常选择使用基于表单的文件上传(RFC 1867),通常在客户端(web浏览器)端看起来是这样的:

CivetWeb内置的文件上传功能

CivetWeb服务器包含对这种文件上传的内置支持mg_handle_form_requestAPI。

希望在其web服务中支持文件上传的开发人员可以简单地使用回调函数调用此APIMG_FORM_FIELD_STORAGE_STORE不变:

Struct mg_form_data_handler FDH = {field_found_callback, field_get_callback, field_stored_callback, 0};...mg_handle_form_request(康涅狄格州,外籍家庭);

回调函数片段示例:

Int field_found_callback (const char *key, const char *filename, char *path, size_t pathlen, void *user_data){…Snprintf (path, pathlen, "/tmp/%s", filename);返回MG_FORM_FIELD_STORAGE_STORE;...}

路径遍历问题

路径遍历问题的根本原因实际上是缺少对基于linux的CivetWeb构建的验证。

CivetWeb的相关源代码mg_handle_form_request处理HTTP请求的方法如下:

Int mg_handle_form_request(struct mg_connection *conn, struct mg_form_data_handler *fdh){…if (field_storage == MG_FORM_FIELD_STORAGE_STORE) {if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) {fstore.access.fp = NULL;} file_size = 0;如果(fstore.access。fp != NULL) {size_t n = (size_t)fwrite(val, 1, (size_t)vallen, fstore.access.fp);...}

mg_fopen函数,该函数负责创建上传的文件,它通过调用mg_path_suspicious函数,但该函数只检查Windows版本的路径分隔符:

/*拒绝含有特殊字符的文件*/ static int mg_path_suspicious(const struct mg_connection *conn, const char *path) {const uint8_t *c = (const uint8_t *)path;...而(* c) {((* c  == '>') || (* c  == '<') || (* c  == '|')) { /* stdin和stdout重定向字符* /返回0;} #if defined(_WIN32) if (*c == '\\') {/* Windows反斜杠*/返回0;} #else if (*c == '/') {/* Linux & */返回0;}……

因此,当为Linux或OSX编译CivetWeb时,上载的文件名根本没有路径遍历消毒。

看到“embedded_c“源存储库中提供的web服务示例容易受到此问题的影响,该漏洞很可能在支持文件上传的CivetWeb实例中被利用。

解决问题

CivetWeb的维护者通过两种不同的方式解决了这个问题

  1. 一些表单处理代码将对文件名进行规范化处理(在它被赋给field_found中定义的点段RFC 3986
  2. embedded_c示例已更新,以显示如何过滤路径分隔符字符(/或\取决于平台),如定义RFC 7578

我们赞赏CivetWeb的维护者以最专业的方式解决了这个问题——密切遵循HTTP表单和uri的rfc。这通常是最佳实践,从这里可以看出,它使实现更能抵抗路径遍历攻击。我们建议其他OSS实现者坚持任何现有的相关rfc,或者使用符合这些rfc的外部库。

自动检测受影响的工件

自动漏洞扫描可用于识别包含易受攻击的CivetWeb版本的工件。进一步的上下文分析可以确定CVE在每个扫描工件中的适用性——也就是说,如果CVE-2020-27304实际上是可开发的。

在高级术语中,上下文分析器需要执行以下步骤来确定对CVE-2020-27304的敏感性:

  1. 检测对导出API的所有调用mg_handle_form_request
  2. 分析指定为的第二个参数的所有回调函数mg_handle_form_request(field_found回调函数)
  3. 检查是否有任何回调函数将数据写入路径输出参数,其中数据被文件名输入参数污染(w.r.t数据流分析)
  4. 验证用户没有实现自己的路径遍历过滤机制文件名输入参数

结论与致谢

总之,我们强烈建议任何正在使用web库或设计自己的web库的人考虑到路径遍历攻击,并清除来自潜在用户输入的任何文件名(或者更好的是——根据相关rfc实现)。

我们要感谢CivetWeb的维护者,他们在很短的时间内以非常彻底的方式验证并解决了这个问题。

除了暴露新安全漏洞和威胁,JFrog为开发人员和安全团队提供了方便的访问他们的软件的最新相关信息的自动安全扫描JFrog x光.请继续关注我们的产品更新,包括关键漏洞暴露(CVE)的自动上下文适用性分析,允许开发人员只修复具有现实安全影响的问题,从而节省时间和精力。