OpenEMR SQL注入漏洞分析

0x01 漏洞预警

OpenEMR是OpenEMR社区的一套开源的医疗管理系统。该系统可用于医疗实践管理、电子医疗记录、处方书写和医疗帐单申请。 OpenEMR 5.0.2之前版本中的interface/forms/eye_mag/save.php文件存在SQL注入漏洞。该漏洞源于基于数据库的应用缺少对外部输入SQL语句的验证。攻击者可利用该漏洞执行非法SQL命令。

0x02 漏洞分析

查看版本diff:OpenEMR <5.0.2

存在两处sql注入漏洞

sql1
sql2

发现是由于sql语句直接拼接造成得sql注入

1
2
3
4
$sql = "DELETE from categories_to_documents where document_id IN (SELECT id from documents where documents.url like '%" . $filename . "')";
sqlQuery($sql);
$sql = "DELETE from documents where documents.url like '%" . $filename . "'";
sqlQuery($sql);

这里直接将$filename传入sql语句,没有进行任何过滤。

下载cms 5.0.17进行查看

1
2
$filename = $pid."_".$encounter.".pdf";
$encounter = $_REQUEST['encounter'];

可以看到我们可以控制encounter参数从而造成sql注入漏洞
sqlmap

本文主要回顾一下防御方法

1
2
3
4
$sql = "DELETE from categories_to_documents where document_id IN (SELECT id from documents where documents.url like ?)";
sqlQuery($sql, ['%'.$filename]);
$sql = "DELETE from documents where documents.url like ?";
sqlQuery($sql, ['%'.$filename]);

在这里使用了参数化查询方法防止sql注入sqlQuery($sql, ['%'.$filename]);
跟入sqlQuery函数

发现使用了mysqli_fetch_array() 函数

语法
mysqli_fetch_array(result,resulttype);

参数 描述
result 必需。规定由 mysqli_query()、mysqli_store_result() 或 mysqli_use_result() 返回的结果集标识符。
resulttype 可选。规定应该产生哪种类型的数组。可以是以下值中的一个:
MYSQLI_ASSOC 数字数组
MYSQLI_NUM 关联数组
MYSQLI_BOTH

这里的$link是查询数据库的sql语句 $statement是传入的filename参数,规定查询字符串。

在执行参数化查询的时候,服务器把sql语句发送到数据库,数据库编译sql语句放入缓存池中,等服务器执行execute时,传入数据库的sql注入语句不进行编译,而是找到之前在缓存池的sql模板,传参,执行,所以sql注入语句只会被当作参数处理。

参考:

https://github.com/Wezery/CVE-2019-14529

预编译

参数化查询

Java MySQL Prepared Statement

-------------本文结束感谢您的阅读-------------