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

背景
JFrog最近披露了一个目录遍历问题CivetWeb,一个非常流行的嵌入式web服务器/库,既可以作为独立的web服务器使用,也可以作为库添加到现有应用程序的web服务器功能。这个问题已经解决了cve - 2020 - 27304.
这种目录遍历问题很容易被利用,并可能导致远程代码执行,特别是当web服务器以根用户身份运行时——由于攻击者能够添加或覆盖随后执行的文件。
谁会真正受到影响?
此问题影响CivetWeb 1.8至1.14版本(含),最近已使用1.15版本.
此问题仅影响使用内置文件上传表单处理程序的civetweb web应用程序。
从技术角度来说,基于civetweb的web应用程序在以下情况下是容易受到攻击的:
- 应用程序通过调用CivetWeb的来处理HTTP表单数据
handle_form_request并提供(强制的)用户定义的field_found回调函数 - 的
field_found回调函数返回MG_FORM_FIELD_STORAGE_STORE表示文件上传操作 - 的
field_found回调函数提供(强制的)路径输出参数,其中路径依赖于文件名输入参数(直接来自HTTP表单数据)。
请注意,此场景是使用CivetWeb文件上传功能的标准方式,并作为完整的工作示例在“embedded_c的例子。
CivetWeb内置的文件上传功能
允许HTTP客户端向服务器上传文件的Web服务器,通常选择使用基于表单的文件上传(RFC 1867),通常在客户端(web浏览器)端看起来是这样的:

CivetWeb服务器包含对这种文件上传的内置支持,通过mg_handle_form_requestAPI。
控件的回调函数可以简单地调用此API,以便在其web服务中支持文件上传MG_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反斜杠*/ return 0;} #else if (*c == '/') {/* Linux & */ return 0;}……
因此,当CivetWeb为Linux或OSX编译时,对于上传的文件名没有路径遍历消毒。
看到“embedded_c”源存储库中提供的web服务示例容易受到此问题的影响,此漏洞很可能在支持文件上传的CivetWeb实例中被利用。
解决问题
CivetWeb维护者用两种不同的方式修复了这个问题
- 的一些表单处理代码现在将规范化文件名(在将其提供给
field_found中定义的点段)RFC 3986 - “embedded_c的例子已经更新,以显示路径分隔符字符(/或\取决于平台)应该如何被过滤掉,定义在RFC 7578
我们赞扬CivetWeb的维护者以最专业的方式解决了这个问题——密切遵循HTTP表单和uri的rfc。这通常是最佳实践,从这里可以看出,它使实现更能抵抗路径遍历攻击。我们建议其他OSS实现者遵循任何现有的相关rfc,或者使用符合这些rfc的外部库。
受影响工件的自动检测
自动漏洞扫描可用于识别包含易受攻击的CivetWeb版本的工件。进一步的上下文分析可以确定CVE在每个扫描工件中的适用性——也就是说,如果CVE-2020-27304实际上是可利用的。
在高级术语中,上下文分析器需要执行以下步骤来确定CVE-2020-27304的易感性:
- 检测对导出API的所有调用
mg_handle_form_request - 分析指定为的第二个参数的所有回调函数
mg_handle_form_request(field_found回调函数) - 检查是否有任何回调函数将数据写入path output参数,其中数据被filename input参数污染(w.r.t数据流分析)
- 上的路径遍历过滤机制,以验证用户是否实现了自己的路径遍历过滤机制
文件名输入参数
结论与鸣谢
总之,我们强烈建议任何正在使用web库或设计自己的web库的人考虑路径遍历攻击,并清除来自潜在用户输入的任何文件名(或者更好的是-根据相关rfc实现)。
我们要感谢CivetWeb的维护者,他们在很短的时间内以非常彻底的方式验证并解决了这个问题。
除了曝光新安全漏洞和威胁,JFrog提供开发人员和安全团队轻松访问最新的相关信息,为他们的软件与自动安全扫描JFrog x光.请继续关注我们的产品更新,包括针对关键漏洞暴露(CVE)的自动上下文适用性分析,允许开发人员通过仅修复具有实际安全影响的问题来节省时间和精力。
