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

背景
的目录遍历问题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。
如果开发人员想要在他/她的web服务中支持文件上传,可以简单地用一个回调函数调用这个API,这个回调函数返回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。= NULL) {size_t n = (size_t)fwrite(val, 1, (size_t) value, 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 define (_WIN32) if (*c == '\\') {/* Windows反斜杠*/返回0;} #else if (*c == '/') {/* Linux &号*/返回0;}……
因此,当为Linux或OSX编译CivetWeb时,根本不需要对上传的文件名进行路径遍历处理。
既然“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输出参数,其中数据被filename输入参数污染(w.r.t数据流分析)
- 对象上没有实现自己的路径遍历过滤机制
文件名输入参数
结论和致谢
总之,我们强烈建议任何使用web库或设计自己的web库的人考虑路径遍历攻击,并清除来自潜在用户输入的任何文件名(或者更好-根据相关rfc实现)。
我们要感谢CivetWeb的维护者,他们在很短的时间内以非常彻底的方式验证并修复了这个问题。
除了暴露新安全漏洞通过自动安全扫描,JFrog为开发人员和安全团队提供了轻松访问其软件最新相关信息的方法JFrog x光。继续关注我们的产品更新,包括针对关键漏洞暴露(CVE)的自动上下文适用性分析,允许开发人员通过仅修复具有实际安全影响的问题来节省时间和精力。