当前位置: 首页 > news >正文

【网络安全】四、中级篇:SQL注入详解

SQL 注入(SQL Injection)是 Web 安全领域最常见且危害极大的攻击方式之一。它通过将恶意 SQL 代码插入到用户输入中,欺骗数据库执行非预期操作,可能导致数据泄露、权限提升甚至服务器被控。

一、SQL 注入的攻击手段

1. 万能密码注入

1.1 原理

利用 SQL 逻辑漏洞,通过构造恒真条件绕过登录验证。当后台将用户输入直接拼接到 SQL 查询时,攻击者可注入' OR '1'='1' -- 等语句使查询条件永远为真。

1.2 示例场景

假设有登录验证代码:

// 漏洞代码
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";

攻击方式:在用户名输入框填入 ' OR '1'='1' -- ,密码任意输入。拼接后的 SQL 变为:

SELECT * FROM users WHERE username='' OR '1'='1' -- ' AND password='任意值'

-- 注释掉后续语句,'1'='1使条件恒真,直接绕过登录。

2. 联合查询注入(UNION Injection)

2.1 原理

利用UNION操作符拼接额外查询,在页面返回结果中获取数据库信息。要求前后查询的列数一致,常用于获取数据库版本、表名、字段名等敏感信息。

2.2 示例场景

假设有商品查询代码:

// 漏洞代码
\$id = $\_GET\['id'];
\$sql = "SELECT name, price FROM products WHERE id=\$id";
\$result = mysqli\_query(\$conn, \$sql);

攻击步骤:

  1. 测试列数:?id=1 UNION SELECT 1,2--+(若页面显示 2,则说明存在 2 列)
  2. 获取数据库版本:?id=1 UNION SELECT 1,version()--+
  3. 获取表名:?id=1 UNION SELECT 1,table_name FROM information_schema.tables--+
  4. 获取字段名:?id=1 UNION SELECT 1,column_name FROM information_schema.columns WHERE table_name='users'--+

3. 布尔盲注(Boolean-based Blind Injection)

3.1 原理

当注入不返回明确结果时,通过构造条件判断语句(如AND 1=1/AND 1=2),根据页面返回的真假状态(如 “存在” 或 “不存在”)逐步猜解数据。

3.2 示例场景

查询用户是否存在的代码:

// 漏洞代码
\$id = $\_GET\['id'];
\$sql = "SELECT \* FROM users WHERE id=\$id";
\$result = mysqli\_query(\$conn, \$sql);
if(mysqli\_num\_rows(\$result) > 0) {
    echo "用户存在";
} else {
    echo "用户不存在";
}

攻击步骤:

  1. 判断数据库长度:?id=1 AND length(database())>5--+(根据返回判断长度)
  2. 猜解数据库名:?id=1 AND substr(database(),1,1)='t'--+(逐个字符验证)

4. 时间盲注(Time-based Blind Injection)

4.1 原理

当页面无任何状态差异时,利用sleep()等函数通过延迟响应判断条件是否成立。若条件为真则延迟,为假则正常响应。

4.2 示例场景

无返回信息的查询接口:

// 漏洞代码
\$id = $\_GET\['id'];
\$sql = "SELECT \* FROM logs WHERE id=\$id";
mysqli\_query(\$conn, \$sql); // 无结果输出

攻击步骤:

  1. 判断数据库首字母:?id=1 AND IF(substr(database(),1,1)='t',sleep(5),1)--+
  2. 若请求延迟 5 秒,则首字母为 ‘t’,以此类推猜解完整信息。

二、SQL 注入的防御方法

1. 输入验证与过滤

对用户输入进行严格校验,限制输入格式(如仅允许数字、字母),过滤或转义特殊字符(如'"=#等)。

// 示例:验证ID必须为数字
\$id = $\_GET\['id'];
if(!is\_numeric(\$id)) {
    die("无效的ID");
}

2. 参数化查询(预编译语句)

核心防御手段:将 SQL 语句与用户输入分离,使用预编译语句传递参数,使数据库无法将参数解析为 SQL 代码。

PHP MySQLi 示例

// 安全代码
\$id = $\_GET\['id'];
\$stmt = \$conn->prepare("SELECT name, price FROM products WHERE id=?");
\$stmt->bind\_param("i", \$id); // "i"表示参数为整数
\$stmt->execute();
\$result = \$stmt->get\_result();

PHP PDO 示例

// 安全代码
\$id = $\_GET\['id'];
\$stmt = \$pdo->prepare("SELECT \* FROM users WHERE username=:username");
\$stmt->execute(\[':username' => \$username]);

3. 使用 ORM 框架

ORM(对象关系映射)框架(如 Laravel 的 Eloquent、ThinkPHP 的模型)内部已实现参数化查询,可避免手动拼接 SQL。

// ThinkPHP ORM示例(安全)
\$user = User::where('username', \$username)->where('password', \$password)->find();

4. 最小权限原则

数据库账号仅分配必要权限(如查询用账号无删除 / 修改权限),即使被注入也能降低危害。

5. 错误信息处理

禁用生产环境的详细错误提示(如不显示mysqli_error()结果),避免泄露数据库结构。

// 生产环境配置
ini\_set('display\_errors', 0);
error\_reporting(0);

6. 定期安全审计

使用工具(如 SQLMap)扫描潜在漏洞,定期更新框架和数据库补丁。

三、PHPStudy 实战案例

1. 环境搭建

1.1 安装 PHPStudy

官网下载并安装,启动 Apache 和 MySQL 服务。

1.2 创建数据库

  • 在PHPStudy上新建testdb数据库
-- 创建用户表
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL,password VARCHAR(50) NOT NULL
);
INSERT INTO users VALUES (1, 'admin', '123456');-- 创建商品表
CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NOT NULL,price DECIMAL(10,2) NOT NULL,category VARCHAR(50) NOT NULL
);-- 插入测试数据
INSERT INTO products VALUES 
(1, '笔记本电脑', 5999.99, '电子产品'),
(2, '机械键盘', 399.99, '电脑配件'),
(3, '无线鼠标', 129.99, '电脑配件');-- 创建日志表
CREATE TABLE logs (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT NOT NULL,action VARCHAR(100) NOT NULL,create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);-- 插入日志数据
INSERT INTO logs VALUES 
(1, 1, '用户登录', '2023-10-01 08:30:00'),
(2, 1, '查看商品', '2023-10-01 09:15:00');

1.3 创建php文件

  • login.php
<?php
session_start();
// 修改此处的连接端口、用户名、密码、数据库名
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$login_msg = '';// 处理登录请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {// 漏洞代码:直接拼接SQL(无转义、无参数化)$sql = "SELECT username FROM users WHERE username='$username' AND password='$password'";$result = mysqli_query($conn, $sql);if (mysqli_num_rows($result) > 0) {$_SESSION['username'] = $username;header("Location: login_success.php"); // 登录成功页exit;} else {$login_msg = "<span style='color: red;'>用户名或密码错误</span>";}
}mysqli_close($conn);
?><!-- 登录页面HTML -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>用户登录(万能密码漏洞)</title><style>.container { width: 400px; margin: 80px auto; padding: 30px; border: 1px solid #ddd; border-radius: 5px; }.form-group { margin: 15px 0; }label { display: inline-block; width: 80px; font-size: 16px; }input { padding: 8px; width: 250px; border: 1px solid #ddd; border-radius: 3px; }button { width: 100%; padding: 10px; margin-top: 10px; background: #0066cc; color: white; border: none; border-radius: 3px; cursor: pointer; }.msg { margin-top: 15px; text-align: center; }</style>
</head>
<body><div class="container"><h2 style="text-align: center; margin-bottom: 20px;">用户登录(万能密码漏洞)</h2><form method="post"><div class="form-group"><label>用户名:</label><input type="text" name="username" value="<?php echo htmlspecialchars($username); ?>" required></div><div class="form-group"><label>密码:</label><input type="password" name="password" required></div><button type="submit">登录</button><?php if ($login_msg): ?><div class="msg"><?php echo $login_msg; ?></div><?php endif; ?></form></div>
</body>
</html>
  • login_success.php
<!-- 登录成功页(同目录下新建 login_success.php) -->
<?php
// 新建文件:sql-injection-demo/vuln/login_success.php
session_start();
if (!isset($_SESSION['username'])) {header("Location: login.php");exit;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>登录成功</title><style>.container { width: 500px; margin: 50px auto; text-align: center; }.success { font-size: 24px; color: green; margin: 20px 0; }a { color: #0066cc; }</style>
</head>
<body><div class="container"><h2>登录成功!</h2><div class="success">欢迎您,<?php echo htmlspecialchars($_SESSION['username']); ?></div><a href="login.php?logout=1">退出登录</a></div>
</body>
</html>
  • product_query.php
<?php
// 数据库连接(注意:实际开发中不要硬编码密码,此处为测试用)
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
// 连接错误处理
if (!$conn) {die("数据库连接失败:" . mysqli_connect_error());
}// 获取用户输入的商品ID
$product_id = $_GET['product_id'] ?? '';
$product_info = null;
$error_msg = '';if (!empty($product_id)) {// 漏洞代码:直接拼接SQL(无参数化)$sql = "SELECT name, price, category FROM products WHERE id=$product_id";$result = mysqli_query($conn, $sql);if ($result) {$product_info = mysqli_fetch_assoc($result);if (!$product_info) {$error_msg = "未找到ID为 $product_id 的商品";}} else {$error_msg = "查询错误:" . mysqli_error($conn);}
}// 关闭连接
mysqli_close($conn);
?><!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>商品查询(存在注入漏洞)</title><style>.container { width: 600px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; }.form-group { margin: 15px 0; }label { display: inline-block; width: 100px; }input { padding: 5px; width: 300px; }button { padding: 6px 20px; cursor: pointer; }.result { margin-top: 20px; padding: 10px; background: #f5f5f5; }</style>
</head>
<body><div class="container"><h2>商品查询(存在SQL注入漏洞)</h2><!-- 商品查询表单 --><form method="get"><div class="form-group"><label>商品ID</label><input type="text" name="product_id" value="<?php echo htmlspecialchars($product_id); ?>" placeholder="输入商品ID(1-3)"><button type="submit">查询</button></div></form><!-- 显示查询结果 --><?php if ($error_msg): ?><div class="result" style="color: red;"><?php echo $error_msg; ?></div><?php elseif ($product_info): ?><div class="result"><h3>商品信息</h3><p>名称:<?php echo htmlspecialchars($product_info['name']); ?></p><p>价格:<?php echo htmlspecialchars($product_info['price']); ?></p><p>分类:<?php echo htmlspecialchars($product_info['category']); ?></p></div><?php endif; ?></div>
</body>
</html>
  • usser_check.php
<?php
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$user_id = $_GET['user_id'] ?? '';
$check_result = '';if (!empty($user_id)) {// 漏洞代码:直接拼接SQL$sql = "SELECT id FROM users WHERE id=$user_id";$result = mysqli_query($conn, $sql);// 仅返回“存在”或“不存在”,无其他信息(符合布尔盲注场景)if (mysqli_num_rows($result) > 0) {$check_result = "<span style='color: green;'>用户存在</span>";} else {$check_result = "<span style='color: red;'>用户不存在</span>";}
}mysqli_close($conn);
?><!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>用户存在查询(布尔盲注漏洞)</title><style>.container { width: 500px; margin: 50px auto; }.form-group { margin: 20px 0; }input { padding: 5px; width: 200px; }.result { margin-top: 20px; font-size: 18px; }</style>
</head>
<body><div class="container"><h2>用户存在查询(布尔盲注漏洞)</h2><form method="get"><div class="form-group"><label>用户ID</label><input type="text" name="user_id" value="<?php echo htmlspecialchars($user_id); ?>" placeholder="输入用户ID"><button type="submit">查询</button></div></form><?php if ($check_result): ?><div class="result">查询结果:<?php echo $check_result; ?></div><?php endif; ?></div>
</body>
</html>
  • log_record.php
<?php
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$log_id = $_GET['log_id'] ?? '';
$page_msg = "日志操作已执行"; // 固定提示,无结果差异(符合时间盲注场景)if (!empty($log_id)) {// 漏洞代码:直接拼接SQL,无结果输出$sql = "SELECT action FROM logs WHERE id=$log_id";mysqli_query($conn, $sql); // 仅执行查询,不返回任何结果
}mysqli_close($conn);
?><!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>日志记录(时间盲注漏洞)</title><style>.container { width: 500px; margin: 50px auto; }.form-group { margin: 20px 0; }input { padding: 5px; width: 200px; }.msg { margin-top: 20px; font-size: 16px; color: #333; }</style>
</head>
<body><div class="container"><h2>日志记录(时间盲注漏洞)</h2><form method="get"><div class="form-group"><label>日志ID</label><input type="text" name="log_id" value="<?php echo htmlspecialchars($log_id); ?>" placeholder="输入日志ID"><button type="submit">执行日志操作</button></div></form><div class="msg"><?php echo $page_msg; ?></div></div>
</body>
</html>
  • 文件目录结构如下
PHPStudy/WWW/​
└── sql-injection-demo/​├── vuln/                # 漏洞文件目录​│   ├── product_query.php  # 联合查询注入(商品)​│   ├── user_check.php     # 布尔盲注(用户查询)​│   ├── log_record.php     # 时间盲注(日志)​│   ├── login.php          # 万能密码注入(登录)​│   └── login_success.php  # 登录成功页(漏洞版)​└── safe/                # 安全文件目录​├── product_query.php  # 联合查询修复版​├── user_check.php     # 布尔盲注修复版​├── log_record.php     # 时间盲注修复版​├── login.php          # 万能密码修复版​└── login_success.php  # 登录成功页(安全版)

2. 万能密码注入

2.1 攻击演示

  • 访问 http://localhost/vuln/login.php​
  • 输入万能密码:​
    用户名:' OR '1'='1' -- -- 注释掉后续密码判断)​
    密码:任意字符(如123)​
  • 点击登录,直接跳转到login_success.php,绕过验证

2.2 防御

修改login.phplogin_success.phpmysqli_prepare会将不完整的SQL语句先编译,用户输入只能作为参数。

<?php
// safe/login.php
session_start();
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$login_msg = '';// 退出登录逻辑
if (isset($_GET['logout'])) {session_destroy();header("Location: login.php");exit;
}// 处理登录请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {// 安全代码:参数化查询$sql = "SELECT username, password FROM users WHERE username=?";$stmt = mysqli_prepare($conn, $sql);mysqli_stmt_bind_param($stmt, "s", $username); // "s"表示字符串类型mysqli_stmt_execute($stmt);$result = mysqli_stmt_get_result($stmt);$user = mysqli_fetch_assoc($result);// 验证密码(注意:实际开发中密码需加密存储,此处为演示用明文)if ($user && $user['password'] === $password) {$_SESSION['username'] = $user['username'];header("Location: login_success.php");exit;} else {$login_msg = "<span style='color: red;'>用户名或密码错误</span>";}mysqli_stmt_close($stmt);
}mysqli_close($conn);
?><!-- safe/login_success.php -->
<?php
session_start();
if (!isset($_SESSION['username'])) {header("Location: login.php");exit;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>登录成功(安全版)</title><style>.container { width: 500px; margin: 50px auto; text-align: center; }.success { font-size: 24px; color: green; margin: 20px 0; }.tip { color: #666; margin: 10px 0; }a { color: #0066cc; }</style>
</head>
<body><div class="container"><h2>登录成功(安全版)</h2><div class="success">欢迎您,<?php echo htmlspecialchars($_SESSION['username']); ?></div><div class="tip">提示:实际开发中需用md5/sha256等加密存储密码</div><a href="login.php?logout=1">退出登录</a></div>
</body>
</html><!-- 登录页面HTML(safe/login.php 后续代码) -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>用户登录(安全版)</title><style>.container { width: 400px; margin: 80px auto; padding: 30px; border: 1px solid #ddd; border-radius: 5px; }.form-group { margin: 15px 0; }label { display: inline-block; width: 80px; font-size: 16px; }input { padding: 8px; width: 250px; border: 1px solid #ddd; border-radius: 3px; }button { width: 100%; padding: 10px; margin-top: 10px; background: #0066cc; color: white; border: none; border-radius: 3px; cursor: pointer; }.msg { margin-top: 15px; text-align: center; }.safe-tip { font-size: 12px; color: #666; margin-top: 20px; text-align: center; }</style>
</head>
<body><div class="container"><h2 style="text-align: center; margin-bottom: 20px;">用户登录(安全版:参数化查询)</h2><form method="post"><div class="form-group"><label>用户名:</label><input type="text" name="username" value="<?php echo htmlspecialchars($username); ?>" required></div><div class="form-group"><label>密码:</label><input type="password" name="password" required></div><button type="submit">登录</button><?php if ($login_msg): ?><div class="msg"><?php echo $login_msg; ?></div><?php endif; ?></form><div class="safe-tip">万能密码注入已被拦截(参数化查询保护)</div></div>
</body>
</html>

3. 联合查询注入(商品查询)

3.1 攻击演示

  • 访问漏洞页面:http://localhost/vuln/product_query.php
  • 正常查询:输入product_id=1,点击查询,显示笔记本电脑信息​
  • 判断列数:输入'' UNION SELECT 1,2,3--+(返回正常,说明表有 3 列)​,--+的核心作用是注释掉注入点后续的 SQL 代码
  • 获取数据库版本:输入'' UNION SELECT 1,version(),database()--+(显示 MySQL 版本和testdb数据库)​
  • 读取用户表数据:输入'' UNION SELECT username,password,'用户表' FROM users--+(直接获取admin的账号密码)

3.2 防御

修改product_query.php文件

<?php
// 数据库连接
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败:" . mysqli_connect_error());
}$product_id = $_GET['product_id'] ?? '';
$product_info = null;
$error_msg = '';if (!empty($product_id)) {// 安全代码:使用参数化查询(预编译语句)$sql = "SELECT name, price, category FROM products WHERE id=?";// 准备预编译语句$stmt = mysqli_prepare($conn, $sql);// 绑定参数("i"表示参数为整数类型)mysqli_stmt_bind_param($stmt, "i", $product_id);// 执行查询mysqli_stmt_execute($stmt);// 获取结果集$result = mysqli_stmt_get_result($stmt);if ($result) {$product_info = mysqli_fetch_assoc($result);if (!$product_info) {$error_msg = "未找到ID为 $product_id 的商品";}} else {$error_msg = "查询错误:" . mysqli_stmt_error($stmt);}// 关闭预编译语句mysqli_stmt_close($stmt);
}mysqli_close($conn);
?><!-- HTML部分与漏洞文件完全一致,此处省略(直接复制漏洞文件的HTML代码即可) -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>商品查询(安全版)</title><style>.container { width: 600px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; }.form-group { margin: 15px 0; }label { display: inline-block; width: 100px; }input { padding: 5px; width: 300px; }button { padding: 6px 20px; cursor: pointer; }.result { margin-top: 20px; padding: 10px; background: #f5f5f5; }</style>
</head>
<body><div class="container"><h2>商品查询(安全版:参数化查询)</h2><form method="get"><div class="form-group"><label>商品ID</label><input type="text" name="product_id" value="<?php echo htmlspecialchars($product_id); ?>" placeholder="输入商品ID(1-3)"><button type="submit">查询</button></div></form><?php if ($error_msg): ?><div class="result" style="color: red;"><?php echo $error_msg; ?></div><?php elseif ($product_info): ?><div class="result"><h3>商品信息</h3><p>名称:<?php echo htmlspecialchars($product_info['name']); ?></p><p>价格:<?php echo htmlspecialchars($product_info['price']); ?></p><p>分类:<?php echo htmlspecialchars($product_info['category']); ?></p></div><?php endif; ?></div>
</body>
</html>

4. 布尔盲注(用户存在查询)

4.1 攻击演示

  • 访问 http://localhost/vuln/user_check.php
  • 猜解数据库名长度:输入user_id=1 AND length(database())=6--+(返回 “用户存在”,说明数据库名长度为 6,即testdb)​
  • 猜解数据库首字母:输入user_id=1 AND substr(database(),1,1)='t'--+(返回 “存在”,首字母为t)​,substr的第二个参数表示截取的起始位置,第三个参数表示要截取的字符长度
  • 逐步猜解:通过修改substr的第三个参数(1→2→3…),最终得到完整数据库名testdb

4.2 防御

修改user_check.php,同样是通过参数化注入。

<?php
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$user_id = $_GET['user_id'] ?? '';
$check_result = '';if (!empty($user_id)) {// 第一步:输入验证(仅允许数字)if (!is_numeric($user_id)) {$check_result = "<span style='color: orange;'>无效ID:仅允许输入数字</span>";} else {// 第二步:参数化查询$sql = "SELECT id FROM users WHERE id=?";$stmt = mysqli_prepare($conn, $sql);mysqli_stmt_bind_param($stmt, "i", $user_id);mysqli_stmt_execute($stmt);$result = mysqli_stmt_get_result($stmt);if (mysqli_num_rows($result) > 0) {$check_result = "<span style='color: green;'>用户存在</span>";} else {$check_result = "<span style='color: red;'>用户不存在</span>";}mysqli_stmt_close($stmt);}
}mysqli_close($conn);
?><!-- HTML部分与漏洞文件一致,此处省略(复制漏洞文件的HTML代码) -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>用户存在查询(安全版)</title><style>.container { width: 500px; margin: 50px auto; }.form-group { margin: 20px 0; }input { padding: 5px; width: 200px; }.result { margin-top: 20px; font-size: 18px; }</style>
</head>
<body><div class="container"><h2>用户存在查询(安全版:输入验证+参数化)</h2><form method="get"><div class="form-group"><label>用户ID</label><input type="text" name="user_id" value="<?php echo htmlspecialchars($user_id); ?>" placeholder="输入用户ID"><button type="submit">查询</button></div></form><?php if ($check_result): ?><div class="result">查询结果:<?php echo $check_result; ?></div><?php endif; ?></div>
</body>
</html>

5. 时间盲注(日志记录)

5.1 攻击演示

  • 访问 http://localhost/vuln/log_record.php
  • 验证注入点:输入log_id=1 AND sleep(5)--+(页面延迟 5 秒后显示提示,说明存在时间盲注)​
  • 猜解用户表是否存在:输入log_id=1 AND IF(exists(select * from users),sleep(5),1)--+(延迟 5 秒,说明users表存在)

5.2 防御

修改log_record.php文件,核心同样是参数化查询。

<?php
$conn = mysqli_connect('localhost', 'root', 'root', 'testdb');
if (!$conn) {die("数据库连接失败");
}$log_id = $_GET['log_id'] ?? '';
$page_msg = "日志操作已执行";if (!empty($log_id)) {// 安全代码:参数化查询$sql = "SELECT action FROM logs WHERE id=?";$stmt = mysqli_prepare($conn, $sql);mysqli_stmt_bind_param($stmt, "i", $log_id);mysqli_stmt_execute($stmt); // 执行查询,无结果输出mysqli_stmt_close($stmt);
}mysqli_close($conn);
?><!-- HTML部分与漏洞文件一致,此处省略 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>日志记录(安全版)</title><style>.container { width: 500px; margin: 50px auto; }.form-group { margin: 20px 0; }input { padding: 5px; width: 200px; }.msg { margin-top: 20px; font-size: 16px; color: #333; }</style>
</head>
<body><div class="container"><h2>日志记录(安全版:参数化查询)</h2><form method="get"><div class="form-group"><label>日志ID</label><input type="text" name="log_id" value="<?php echo htmlspecialchars($log_id); ?>" placeholder="输入日志ID"><button type="submit">执行日志操作</button></div></form><div class="msg"><?php echo $page_msg; ?></div></div>
</body>
</html>
http://www.dtcms.com/a/423319.html

相关文章:

  • Ceph 分布式存储学习笔记(二):池管理、认证和授权管理与集群配置(下)
  • 网站做百科四川网络推广平台
  • 沈阳做网站的公司jsp做网站de后台管理
  • 驻马店网站开发公司电话管理咨询案例
  • MTK调试-马达
  • 深入探讨Spring Boot项目的构建与部署(指南三)
  • 曲靖网站推广做个什么样的网站
  • Vue3新变化
  • 共识算法的深度探索:从原理到实践的全面指南
  • 微算法科技(NASDAQ: MLGO)研发基于 DPoS 框架的 DL-DPoS(深度链接委托权益证明)机制,增强区块链的共识算法
  • 关于git 或者码云,初始化本地仓库以及把本地仓库与远程仓库关联
  • 私有化部署知识库
  • 济南做外贸网站动漫设计专业是什么
  • 安卓开发---写项目的注意事项
  • 回退到上一个提交的命令
  • 深度学习激活函数:从 Sigmoid 到 GELU 的演变历程
  • JAVA第七学:类和对象
  • 使用过程宏实现自动化新增功能
  • 哈尔滨模板网站建站珠海企业网站制作费用
  • 莱芜网站优化企业内训
  • Linux服务器NAS挂载:Truenas
  • 【图像处理-基础知识】SFIT特征解析
  • 基于杰理AC6321A2做加热产品
  • 最流行的做网站语言合优人才网合川
  • gRPC从0到1系列【8】
  • 阿里-FORGE-生成式推荐SID构建
  • Python脚本(Kafka生产者+消费者)
  • 光伏出海加速!中国企业抢占全球市场
  • 网站排名提升软件网站制作先做数据库还是前台
  • 上海工程咨询行业协会网站优化内链怎么做