2019年7月,FortiGuard Labs在九个不同WordPress插件中发现并报告了九个SQL注入漏洞,这些流行插件使用广泛,包括了广告,捐赠,图库,表格,新闻和视频播放。 成千上万的WordPress网站正在使用这些插件,其中有些站点非常有名。
所有被发现的漏洞都分配了CVE,同时也具有FortiGuard Labs编号,它们分别是:FG-VD-19-092, FG-VD-19-094, FG-VD-19-095, FG-VD-19-096, FG-VD-19-097, FG-VD-19-098, FG-VD-19-099, FG-VD-19-101和 FG-VD-19-102。
有趣的是,9个漏洞中有8个都使用相同的代码模式,因此容易受到SQL注入攻击。 尽管非常可能被利用,但开发人员大多没有仔细过滤用户输入。 在这种情况下,虽然WordPress Core提供了各种内置方法,以确保用户的输入都经过清理,但也无济于事。
在这篇文章我们将介绍一组WordPress安全机制,分析一部分漏洞,并演示攻击者利用的方式,并且以开发者角度介绍如何防范。
撰写本文时,所述漏洞都由已供应商修复。
当用户输入会被用于构造SQL语句,且没有被正确清理,则会发生SQL注入。 例如下面这段代码:
粗略一看,上述代码容易遭到SQL注入影响,因为程序将从$_GET
中接受$id
,然后直接传入到SQL查询语句中,其间没有任何清理。但情况不是这样,在最新版本的WordPress中,$_POST/$_GET/$_REQUEST/$_COOKIE中的值会经过magic quotes(魔术引号) 处理[1]。这一点可以帮助WordPress保持一致并且提供良好的安全性能。因此,上述代码不会受到SQL注入影响。
WordPress除了强制向输入内容添加斜杠外,它还提供了几个内置的过滤函数,用于清理用户输入和保护内容输出[2]。例如, 开发者可以使用sanitize_email()
来清理电子邮件的地址,使用sanitize_text_field()
来清理文本,使用sanitize_sql_orderby()
来验证SQL的ORDER BY
语句等。 WordPress中的sanitize_*()
类辅助函数已经覆盖了大多数用户输入类型。
尽管WordPress Core正在尽最大努力帮助开发者防止常见攻击,这些攻击通常因用户的恶意输入导致,但不够精湛的编程能力和滥用转义功能仍会导致一些简单但又关键的漏洞。
这是一个经典的SQL注入漏洞,位于v5.2版本的AdRotate插件中,免费版和收费版都受影响。 漏洞位于dashboard/publisher/adverts-edit.php,第52行:
$ad_edit_id用于构造SQL查询语句。该变量来自adrotate_manage函数的$_GET
:
由于esc_attr
方法只会转义HTML属性,而且在SQL查询中$ad_edit_id
并未使用双引号转义,因此我们可以向$ad_edit_id
中注入有效负载,从而执行任意SQL语句。
虽然需要登入后台管理界面,但由于此处缺少CSRF令牌,攻击者可以通过SQL注入窃取会话令牌(需要少量交互),并且导致XSS:
在后续补丁中,开发者只是用单引号包裹了$ad_edit_id
变量。
时间线:
从2007年以来,NextGEN Gallery一直都业界标准的WordPress图库插件,每年新增超过150万次的下载量。 通过该插件可以非常容易地处理图片,并且也能够满足专业人士的使用。 在撰写本文时,NextGEN Gallery的安装量已超900000次,是图库类型中最受欢迎的插件[3]。
漏洞存在于AJAX API,用户可以在撰文时添加图库的图片。
modules/attach_to_post/package.module.attach_to_post.php中的get_displayed_gallery_entities_action
函数负责展示所选图库的图片。在119行,程序通过POST方法创建一个图库对象,然后遍历数组参数displayed_gallery
。对象的属性由helper函数esc_sql
转义。 在130行将会调用get_entities
方法,该方法定义于modules/nextgen_gallery_display/package.module.nextgen_gallery_display.php:
传入的$request
为both,因此调用第832行中的_get_image_entities
。
该函数的作用是执行一个查询,然后返回要展示的图库中的所有图片。 在1041行可以看出,程序应用了基于$sort_by
和$sirt_direction
的order排序值,参数都是从创建的图库对象检索的。只要是可以使用NextGEN Gallery的用户,都可以更改参数来创建某个图库对象。 尽管对象的所有属性都会经由esc_sql
方法清理,但实际上,攻击者不用转义引号即可在ORDER BY中注入SQL语句。因此 esc_sql
无法保护NextGEN Gallery免受SQL注入攻击。
Imagely团队正确地修复了该漏洞。仅允许ORDER BY子句中的固定值,用户无法控制输入,所以该查询是安全的。
时间线:
通过类似的方式,我发现另外七个插件也同样受SQL注入的影响。 其中一个尝试为排序值使用白名单策略,但由于编码错误而未能实现。
Give是WordPress上评分最高,下载量最多并且功能最好的捐赠插件[4]。
漏洞位于includes/donors/class-give-donors-query.php的get_order_query
函数:
注释表明get_order_query
方法用于删除ORDER BY子句中不存在的列,并通过helper函数esc_sql
过滤排序值。 但删除工作不会按预设的那样,因为在第467行中unset
不存在的列后,在第470行中继续插入排序值并且进行转义。我们都已经知道esc_sql
对于防止ORDER BY子句中的SQL注入没有用。 因此攻击者仍然可以构造恶意查询语句。 同样,我们可以使用SQL盲注技术来利用此漏洞。
Impress团队的补丁中只更改了1行代码就可以使得程序功能恢复,此时查询完全安全。
时间线:
其他漏洞也具有相同代码模式,并且补丁非常相似。
在本文,我们提出了一些开发WordPress插件时需要注意的地方,插件应该尽量防止SQL注入攻击。 WordPress社区有一份完整的插件开发手册[5]。 作为开发者,应始终参考WordPress编码标准并遵循最佳实践原则。 此外,下面这几条建议有助于避免SQL注入,并且还可以防止用户输入恶意字符导致的其他漏洞:
sanitize_sql_orderby()
可以修复本文的所有漏洞。esc_sql
函数。esc_sql
函数,但请将转义后的值用引号包裹。WordPress是最著名的一款CMS,占互联网上CMS的61.0%,并且占所有网站的34.3%[6]。 根据Wordfence的报告,WordPress中52%的漏洞都是由于WordPress插件[7]。 通过这点,可以推测WordPress插件是网络犯罪份子的重要攻击点。 SQL注入不是一种新兴技术,但它总可以对Web应用程序和服务器构成严重威胁。 为避免这种情况,开发人员应始终参考编码标准并遵循最佳实践原则。
参考来源:fortinet.com