初学万能密码代码审计
字数 1178 2025-08-09 22:00:37

万能密码漏洞代码审计与分析

漏洞概述

本教学文档分析一个典型的SQL注入漏洞案例,通过"万能密码"绕过登录验证。该漏洞存在于一个PHP网站的登录验证逻辑中,攻击者可以通过构造特殊的SQL语句绕过密码验证直接登录系统。

环境搭建

  1. 使用工具:phpstudy
  2. 靶场部署:
    • 下载靶场代码
    • 放置在phpstudy的域名站点管理目录
    • 设置非80端口(示例中使用3456端口)
    • 访问地址:www.a.com:3456

漏洞复现步骤

  1. 访问后台登录页面
  2. 使用Firefox插件"live HTTP headers"抓包
  3. 捕获的登录请求参数:user_name=11111&user_pass=1111
  4. 真正的请求地址:www.a.com:3456/checkUser.php
  5. 使用万能密码' or 1#作为用户名
  6. 成功绕过登录验证

代码审计分析

关键文件:checkUser.php

if(isset($_POST["user_name"]) && isset($_POST["user_pass"])) {
    // 检测用户名和密码参数是否设置
    $username = $_POST["user_name"];
    $password = md5($_POST["user_pass"]);
    
    // 构造SQL查询语句
    $sql = "select * from users where user_name='$username' and user_pass='$password'";
    
    // 执行查询
    $mysql = new mysql();
    $row = $mysql->getOne($sql);
    
    if($row) {
        // 登录成功逻辑
    } else {
        // 登录失败逻辑
    }
}

漏洞成因

  1. 未过滤的用户输入:直接将用户输入的user_nameuser_pass拼接到SQL语句中
  2. 密码MD5加密$password = md5($password);导致在密码字段使用万能密码不可行
  3. SQL语句构造:拼接后的SQL语句可以被注入

万能密码原理

当使用' or 1#作为用户名时,构造的SQL语句变为:

select * from users where user_name='' or 1#' and user_pass='6512bd43d9caa6e02c990b0a82652dca'

解释:

  • #在MySQL中表示注释,会注释掉后面的所有内容
  • 实际执行的SQL:select * from users where user_name='' or 1
  • or 1条件永远为真,因此会返回users表中的数据

数据库查询分析

mysql.class.php中:

public function getOne($sql) {
    $res = $this->link->query($sql);
    $row = $res->fetch_assoc();
    return $row;
}
  • fetch_assoc()只获取查询结果的第一行
  • 使用万能密码登录时,会返回数据库中的第一条用户记录

漏洞验证

  1. 成功登录时的SQL语句:

    select * from users where user_name='xxxx' or 1#' and user_pass='6512bd43d9caa6e02c990b0a82652dca'
    
  2. 失败登录时的SQL语句(万能密码放在密码字段):

    select * from users where user_name='xxxx' and user_pass='' or 1#'
    

    由于密码经过MD5加密,这种构造方式无法成功

防御措施

  1. 使用预处理语句(PDO/prepared statements)

    $stmt = $pdo->prepare("SELECT * FROM users WHERE user_name = ? AND user_pass = ?");
    $stmt->execute([$username, $password]);
    
  2. 输入验证与过滤

    • 对用户输入进行严格验证
    • 使用mysqli_real_escape_string()等函数转义特殊字符
  3. 最小权限原则

    • 数据库用户只赋予必要的最小权限
  4. 错误处理

    • 不要将数据库错误信息直接显示给用户
  5. 密码处理

    • 继续使用加盐哈希处理密码(示例中已使用MD5,但建议使用更安全的如bcrypt)

总结

该漏洞是典型的SQL注入漏洞,由于直接将用户输入拼接到SQL语句中且未做任何过滤导致。通过代码审计可以发现:

  1. 登录验证逻辑存在SQL注入点
  2. 密码字段由于MD5加密,注入难度较大
  3. 用户名字段可直接注入,使用' or 1#可绕过验证
  4. 系统会返回数据库中的第一条用户记录

修复此类漏洞的关键在于使用参数化查询和严格的输入验证。

万能密码漏洞代码审计与分析 漏洞概述 本教学文档分析一个典型的SQL注入漏洞案例,通过"万能密码"绕过登录验证。该漏洞存在于一个PHP网站的登录验证逻辑中,攻击者可以通过构造特殊的SQL语句绕过密码验证直接登录系统。 环境搭建 使用工具:phpstudy 靶场部署: 下载靶场代码 放置在phpstudy的域名站点管理目录 设置非80端口(示例中使用3456端口) 访问地址: www.a.com:3456 漏洞复现步骤 访问后台登录页面 使用Firefox插件"live HTTP headers"抓包 捕获的登录请求参数: user_name=11111&user_pass=1111 真正的请求地址: www.a.com:3456/checkUser.php 使用万能密码 ' or 1# 作为用户名 成功绕过登录验证 代码审计分析 关键文件:checkUser.php 漏洞成因 未过滤的用户输入 :直接将用户输入的 user_name 和 user_pass 拼接到SQL语句中 密码MD5加密 : $password = md5($password); 导致在密码字段使用万能密码不可行 SQL语句构造 :拼接后的SQL语句可以被注入 万能密码原理 当使用 ' or 1# 作为用户名时,构造的SQL语句变为: 解释: # 在MySQL中表示注释,会注释掉后面的所有内容 实际执行的SQL: select * from users where user_name='' or 1 or 1 条件永远为真,因此会返回users表中的数据 数据库查询分析 在 mysql.class.php 中: fetch_assoc() 只获取查询结果的第一行 使用万能密码登录时,会返回数据库中的第一条用户记录 漏洞验证 成功登录时的SQL语句: 失败登录时的SQL语句(万能密码放在密码字段): 由于密码经过MD5加密,这种构造方式无法成功 防御措施 使用预处理语句(PDO/prepared statements) 输入验证与过滤 对用户输入进行严格验证 使用 mysqli_real_escape_string() 等函数转义特殊字符 最小权限原则 数据库用户只赋予必要的最小权限 错误处理 不要将数据库错误信息直接显示给用户 密码处理 继续使用加盐哈希处理密码(示例中已使用MD5,但建议使用更安全的如bcrypt) 总结 该漏洞是典型的SQL注入漏洞,由于直接将用户输入拼接到SQL语句中且未做任何过滤导致。通过代码审计可以发现: 登录验证逻辑存在SQL注入点 密码字段由于MD5加密,注入难度较大 用户名字段可直接注入,使用 ' or 1# 可绕过验证 系统会返回数据库中的第一条用户记录 修复此类漏洞的关键在于使用参数化查询和严格的输入验证。