从零开始代码审计HMS v1.0 SQL注入漏洞深度剖析医疗管理系统作为医院核心业务支撑平台其安全性直接关系到患者隐私和医疗数据完整性。2022年曝光的HMS v1.0 SQL注入漏洞CVE-2022-23366为我们提供了一个绝佳的学习案例本文将带您从开发者视角逐步拆解这个典型的安全漏洞。1. 漏洞背景与环境搭建HMSHospital Management System是一款面向中小型医疗机构的开源管理系统采用PHPMySQL架构开发。其1.0版本的doctorlogin.php文件存在字符型SQL注入漏洞攻击者无需任何认证即可通过构造特殊输入执行任意SQL命令。搭建测试环境# 使用Docker快速搭建测试环境 docker run -d -p 8080:80 --name hms-vuln \ -e MYSQL_ROOT_PASSWORDroot \ -v ./hms:/var/www/html \ php:7.4-apache环境配置完成后我们需要重点关注以下文件结构/hms ├── includes │ ├── db_connect.php │ └── functions.php ├── doctorlogin.php └── index.php提示实际审计时建议使用虚拟机隔离环境避免影响生产系统2. 漏洞定位与初步分析通过黑盒测试发现当在医生登录页面提交特殊字符时系统返回异常数据库错误信息。这提示我们可能存在SQL注入点。典型测试用例正常输入loginiddoctor1password123456测试输入loginiddoctor1password123456对比两种输入的响应差异后者返回了MySQL语法错误这证实了我们的猜想。关键代码段分析// doctorlogin.php 关键片段 $loginid $_POST[loginid]; $password $_POST[password]; $sql SELECT * FROM doctors WHERE loginid$loginid AND password$password; $result mysqli_query($conn, $sql);这段代码直接将用户输入拼接到SQL语句中没有任何过滤或参数化处理是典型的一阶SQL注入漏洞。3. 深入代码审计技术细节3.1 漏洞形成机制该漏洞属于字符型注入攻击者可以通过单引号闭合原始查询然后插入恶意SQL代码。漏洞形成的根本原因包括未经验证的用户输入直接使用$_POST变量而未做任何过滤字符串拼接方式构造SQL使用变量插值而非参数化查询错误信息泄露默认配置下显示详细数据库错误漏洞利用链分析用户输入 → 直接拼接SQL → 数据库执行 → 结果返回 ↑ 无任何过滤或参数化处理3.2 安全编码对比下表对比了危险写法与安全写法的关键区别危险写法安全写法防护原理$sql SELECT * FROM users WHERE id$id$stmt $conn-prepare(SELECT * FROM users WHERE id?)参数化查询直接使用$_GET/$_POST使用filter_input()过滤输入验证显示详细错误信息自定义错误页面信息控制4. 漏洞修复与防御方案4.1 即时修复方案对于已部署的系统可采取以下临时措施// 临时修复方案 - 输入过滤 $loginid mysqli_real_escape_string($conn, $_POST[loginid]); $password mysqli_real_escape_string($conn, $_POST[password]);注意这仅是临时方案转义函数不能完全防止SQL注入4.2 长期解决方案推荐使用PDO预处理语句// 使用PDO的完整安全方案 $stmt $pdo-prepare(SELECT * FROM doctors WHERE loginid :loginid AND password :password); $stmt-execute([ :loginid $_POST[loginid], :password $_POST[password] ]);防御措施优先级使用参数化查询PDO/mysqli预处理实施最小权限原则数据库账户权限限制部署WAFWeb应用防火墙定期安全审计与渗透测试5. 代码审计实战技巧在实际审计过程中我通常会采用以下方法定位SQL注入漏洞入口点追踪查找所有接收用户输入的PHP文件$_GET/$_POST/$_REQUEST跟踪输入变量在代码中的传递路径危险函数识别# 使用grep查找潜在危险代码 grep -rn mysqli_query ./ grep -rn SELECT.*FROM.*WHERE.*\ ./动态调试技巧在数据库层记录实际执行的SQL语句使用Xdebug进行步进调试典型漏洞模式识别表模式特征风险等级示例直接拼接用户输入高危SELECT * FROM users WHERE id$id使用mysql_系列函数中高危mysql_query(SELECT...)未过滤的ORDER BY子句中危$order $_GET[order]; ... ORDER BY $order6. 安全开发最佳实践基于多年审计经验我总结出以下安全编码规范输入验证原则白名单优于黑名单尽早验证严格验证类型、长度、格式多重检查数据库操作规范// 安全示例PDO预处理异常处理 try { $pdo new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES false ]); $stmt $pdo-prepare(INSERT INTO logs (message) VALUES (?)); $stmt-execute([$userInput]); } catch (PDOException $e) { error_log(Database error: . $e-getMessage()); showGenericError(); }安全工具链集成静态分析工具PHPStan、Psalm动态扫描工具OWASP ZAPGit Hooks预检查在最近一次医疗系统审计中我们发现即使使用了预处理语句如果配置不当如PDO::ATTR_EMULATE_PREPAREStrue仍可能导致注入风险。这提醒我们安全措施需要全面考虑各种边界情况。
从一次简单的登录绕过看起:HMS v1.0 SQL注入漏洞(CVE-2022-23366)的代码审计入门
发布时间:2026/5/19 10:06:15
从零开始代码审计HMS v1.0 SQL注入漏洞深度剖析医疗管理系统作为医院核心业务支撑平台其安全性直接关系到患者隐私和医疗数据完整性。2022年曝光的HMS v1.0 SQL注入漏洞CVE-2022-23366为我们提供了一个绝佳的学习案例本文将带您从开发者视角逐步拆解这个典型的安全漏洞。1. 漏洞背景与环境搭建HMSHospital Management System是一款面向中小型医疗机构的开源管理系统采用PHPMySQL架构开发。其1.0版本的doctorlogin.php文件存在字符型SQL注入漏洞攻击者无需任何认证即可通过构造特殊输入执行任意SQL命令。搭建测试环境# 使用Docker快速搭建测试环境 docker run -d -p 8080:80 --name hms-vuln \ -e MYSQL_ROOT_PASSWORDroot \ -v ./hms:/var/www/html \ php:7.4-apache环境配置完成后我们需要重点关注以下文件结构/hms ├── includes │ ├── db_connect.php │ └── functions.php ├── doctorlogin.php └── index.php提示实际审计时建议使用虚拟机隔离环境避免影响生产系统2. 漏洞定位与初步分析通过黑盒测试发现当在医生登录页面提交特殊字符时系统返回异常数据库错误信息。这提示我们可能存在SQL注入点。典型测试用例正常输入loginiddoctor1password123456测试输入loginiddoctor1password123456对比两种输入的响应差异后者返回了MySQL语法错误这证实了我们的猜想。关键代码段分析// doctorlogin.php 关键片段 $loginid $_POST[loginid]; $password $_POST[password]; $sql SELECT * FROM doctors WHERE loginid$loginid AND password$password; $result mysqli_query($conn, $sql);这段代码直接将用户输入拼接到SQL语句中没有任何过滤或参数化处理是典型的一阶SQL注入漏洞。3. 深入代码审计技术细节3.1 漏洞形成机制该漏洞属于字符型注入攻击者可以通过单引号闭合原始查询然后插入恶意SQL代码。漏洞形成的根本原因包括未经验证的用户输入直接使用$_POST变量而未做任何过滤字符串拼接方式构造SQL使用变量插值而非参数化查询错误信息泄露默认配置下显示详细数据库错误漏洞利用链分析用户输入 → 直接拼接SQL → 数据库执行 → 结果返回 ↑ 无任何过滤或参数化处理3.2 安全编码对比下表对比了危险写法与安全写法的关键区别危险写法安全写法防护原理$sql SELECT * FROM users WHERE id$id$stmt $conn-prepare(SELECT * FROM users WHERE id?)参数化查询直接使用$_GET/$_POST使用filter_input()过滤输入验证显示详细错误信息自定义错误页面信息控制4. 漏洞修复与防御方案4.1 即时修复方案对于已部署的系统可采取以下临时措施// 临时修复方案 - 输入过滤 $loginid mysqli_real_escape_string($conn, $_POST[loginid]); $password mysqli_real_escape_string($conn, $_POST[password]);注意这仅是临时方案转义函数不能完全防止SQL注入4.2 长期解决方案推荐使用PDO预处理语句// 使用PDO的完整安全方案 $stmt $pdo-prepare(SELECT * FROM doctors WHERE loginid :loginid AND password :password); $stmt-execute([ :loginid $_POST[loginid], :password $_POST[password] ]);防御措施优先级使用参数化查询PDO/mysqli预处理实施最小权限原则数据库账户权限限制部署WAFWeb应用防火墙定期安全审计与渗透测试5. 代码审计实战技巧在实际审计过程中我通常会采用以下方法定位SQL注入漏洞入口点追踪查找所有接收用户输入的PHP文件$_GET/$_POST/$_REQUEST跟踪输入变量在代码中的传递路径危险函数识别# 使用grep查找潜在危险代码 grep -rn mysqli_query ./ grep -rn SELECT.*FROM.*WHERE.*\ ./动态调试技巧在数据库层记录实际执行的SQL语句使用Xdebug进行步进调试典型漏洞模式识别表模式特征风险等级示例直接拼接用户输入高危SELECT * FROM users WHERE id$id使用mysql_系列函数中高危mysql_query(SELECT...)未过滤的ORDER BY子句中危$order $_GET[order]; ... ORDER BY $order6. 安全开发最佳实践基于多年审计经验我总结出以下安全编码规范输入验证原则白名单优于黑名单尽早验证严格验证类型、长度、格式多重检查数据库操作规范// 安全示例PDO预处理异常处理 try { $pdo new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES false ]); $stmt $pdo-prepare(INSERT INTO logs (message) VALUES (?)); $stmt-execute([$userInput]); } catch (PDOException $e) { error_log(Database error: . $e-getMessage()); showGenericError(); }安全工具链集成静态分析工具PHPStan、Psalm动态扫描工具OWASP ZAPGit Hooks预检查在最近一次医疗系统审计中我们发现即使使用了预处理语句如果配置不当如PDO::ATTR_EMULATE_PREPAREStrue仍可能导致注入风险。这提醒我们安全措施需要全面考虑各种边界情况。