DVWA从入门到精通(十八):Cryptography(密码学问题)

摘要:本文是《DVWA从入门到精通》系列的第十八篇,带你全面掌握Cryptography(密码学问题)模块的攻防全流程。从密码学在Web安全中的基础作用出发,逐步讲解Low、Medium、High三个级别的攻击手法与源码分析,并深入探讨Impossible级别的终极防御方案。文章包含Base64解码与XOR异或逆向、AES-128-ECB电子密码本模式的"剪切-粘贴"重放攻击、密文块拆分与重组构造合法Token、以及GCM认证加密模式等核心技术,让你真正做到"知其然更知其所以然"。


一、什么是密码学问题模块?

1.1 密码学在Web安全中的角色

密码学(Cryptography)是Web安全的基石之一。从用户登录时的密码存储、到会话令牌的生成、再到数据传输的加密,密码学无处不在。然而,密码学本身是安全的,但不安全的实现方式会引入致命的漏洞

用一个生活化的例子来理解

想象你有一把非常坚固的锁(加密算法),但你把钥匙(密钥)挂在门框上(密钥管理不当),或者你把锁装在一扇纸糊的门上(加密模式选择错误)。再坚固的锁也挡不住攻击者。

Cryptography模块正是模拟了这种"算法本身没问题,但实现方式有问题"的场景。

从技术角度来看

DVWA的Cryptography模块包含多个密码学相关的挑战,涉及:

挑战类型 涉及技术 漏洞本质
编码与加密混淆 Base64 + XOR 将编码误认为加密
不安全的加密模式 AES-128-ECB 相同明文块产生相同密文块
密钥硬编码 密钥直接写在代码中 密钥暴露
Token可篡改 密文块可重组 缺乏完整性校验

1.2 模块目标概述

DVWA的Cryptography模块在不同安全级别下设置了不同的挑战目标:

级别 挑战内容 涉及技术
Low 解码一个Base64+XOR双重编码的字符串,获取正确密码 Base64解码、XOR异或
Medium 通过AES-ECB密文的"剪切-粘贴"攻击,伪造Token提升权限 AES-128-ECB、分组重放
High 解密Token获取秘密信息,然后伪造Token成为管理员 Token逆向、密文重组
Impossible 理论上无法篡改Token GCM认证加密

二、准备工作

2.1 靶场环境

确保DVWA已部署并正常运行:

  • 访问地址:http://你的服务器IP/dvwa/login.php

  • 使用 admin / password 登录

2.2 必备工具

工具 用途
浏览器(Chrome/Firefox) 访问靶场,查看页面
CyberChef Base64解码、XOR解密、Hex转换(推荐使用)
Python 编写AES-ECB加密/解密脚本(Medium/High级别必需)
文本编辑器 查看和分析密文数据

2.3 基础知识储备

  • 理解Base64编码的原理

  • 了解XOR(异或)运算的基本概念

  • 了解AES对称加密的基本原理

  • 理解ECB(电子密码本)模式的特点与缺陷

  • 熟悉JSON数据格式


三、Low级别:编码 ≠ 加密

3.1 安全级别设置

将DVWA Security设置为 Low 级别,然后进入 Cryptography 模块。

3.2 界面观察

页面展示一段已处理的密文字符串,关卡任务:解密该密文,从中提取登录密码完成登录验证。页面内置 Encode/Decode 功能表单,同时底部附带独立登录框。

3.3 源码分析

查看Low级别的核心代码:

php 复制代码
<?php

function xor_this($cleartext, $key) {
    // Our output text
    $outText = '';

    // Iterate through each character
    for($i=0; $i<strlen($cleartext);) {
        for($j=0; ($j<strlen($key) && $i<strlen($cleartext)); $j++,$i++) {
            $outText .= $cleartext[$i] ^ $key[$j];
        }
    }
    return $outText;
}

$key = "wachtwoord";

$errors = "";
$success = "";
$messages = "";
$encoded = null;
$encode_radio_selected = " checked='checked' ";
$decode_radio_selected = " ";
$message = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    try {
        if (array_key_exists ('message', $_POST)) {
            $message = $_POST['message'];
            if (array_key_exists ('direction', $_POST) && $_POST['direction'] == "decode") {
                $encoded = xor_this (base64_decode ($message), $key);
                $encode_radio_selected = " ";
                $decode_radio_selected = " checked='checked' ";
            } else {
                $encoded = base64_encode(xor_this ($message, $key));
            }
        }
        if (array_key_exists ('password', $_POST)) {
            $password = $_POST['password'];
            $decoded = xor_this (base64_decode ($password), $key);
            if ($password == "Olifant") {
                $success = "Welcome back user";
            } else {
                $errors = "Login Failed";
            }
        }
    } catch(Exception $e) {
        $errors = $e->getMessage();
    }
}

$html = "
        <p>
        This super secure system will allow you to exchange messages with your friends without anyone else being able to read them. Use the box below to encode and decode messages.
        </p>
        <form name=\"xor\" method='post' action=\"" . $_SERVER['PHP_SELF'] . "\">
            <p>
                <label for='message'>Message:</lable><br />
                <textarea style='width: 600px; height: 56px' id='message' name='message'>" . htmlentities ($message) . "</textarea>
            </p>
            <p>
                <input type='radio' value='encode' name='direction' id='direction_encode' " . $encode_radio_selected . "><label for='direction_encode'>Encode</label> or 
                <input type='radio' value='decode' name='direction' id='direction_decode' " . $decode_radio_selected . "><label for='direction_decode'>Decode</label>
            </p>
            <p>
                <input type=\"submit\" value=\"Submit\">
            </p>
        </form>
";

if (!is_null ($encoded)) {
    echo "
            <p>
                <label for='encoded'>Message:</lable><br />
                <textarea readonly='readonly' style='width: 600px; height: 56px' id='encoded' name='encoded'>" . htmlentities ($encoded) . "</textarea>
            </p>";
}

echo "
        <hr>
        <p>
        You have intercepted the following message, decode it and log in below.
        </p>
        <p>
        <textarea readonly='readonly' style='width: 600px; height: 28px' id='encoded' name='encoded'>Lg4WGlQZChhSFBYSEB8bBQtPGxdNQSwEHREOAQY=</textarea>
        </p>
";

if ($errors != "") {
    echo '<div class="warning">' . $errors . '</div>';
}

if ($messages != "") {
    echo '<div class="nearly">' . $messages . '</div>';
}

if ($success != "") {
    echo '<div class="success">' . $success . '</div>';
}

echo "
        <form name=\"ecb\" method='post' action=\"" . $_SERVER['PHP_SELF'] . "\">
            <p>
                <label for='password'>Password:</lable><br />
<input type='password' id='password' name='password'>
            </p>
            <p>
                <input type=\"submit\" value=\"Login\">
            </p>
        </form>
";
?>

代码逻辑分析

步骤 操作 说明
1 定义全局密钥$key 固定值 wachtwoord,荷兰语释义 "密码",密钥明文硬编码在后端源码中
2 合法登录明文密码 Olifant,荷兰语释义 "大象",系统正确凭证
3 加密完整流程:先 XOR 异或,再 Base64 编码 base64_encode(xor_this($message, $key))
4 解密完整流程:先Base64解码,再XOR异或还原明文 xor_this(base64_decode ($encoded),$key)

3.4 攻击方法:逆向解码

Low 级别宣称的 "加密" 仅为 Base64 编码 + 循环 XOR 异或 的简易混淆组合,两种处理方式完全可逆;且密钥明文硬编码在 PHP 源码,攻击者可直接提取密钥解密。 本关卡优先使用页面自带解码功能,同时提供 Python 离线脚本作为备用方案。

方案一:DVWA 页面自带解密

  • 复制页面给出的密文:Lg4WGlQZChhSFBYSEB8bBQtPGxdNQSwEHREOAQY=

  • 将密文粘贴至上方 Message 输入框;

  • 单选框选中Decode解码模式;

  • 点击Submit提交表单;

  • 下方只读文本框直接输出解密明文:Your new password is: Olifant,登录密码为Olifant

方案二:离线 Python 脚本手动解密

python 复制代码
import base64

def xor_this(data, key):
    result = ""
    for i in range(len(data)):
        result += chr(data[i] ^ ord(key[i % len(key)]))
    return result

# 去除多余空格,完整密文字符串
encoded = "Lg4WGlQZChhSFBYSEB8bBQtPGxdNQSwEHREOAQY="
key = "wachtwoord"

# 解密顺序:先Base64解码,再执行XOR异或
decoded_bytes = base64.b64decode(encoded)
plaintext = xor_this(decoded_bytes, key)
print(plaintext)  # 输出结果:Your new password is: Olifant

补充在线工具: https://www.udtool.com/toolbox/xor-encrypt-decrypt-online.html

3.5 漏洞分析

缺陷 详细说明
混淆编码与加密概念 Base64 仅为二进制转文本的传输编码,不具备任何加密安全属性,无密钥即可完整解码
密钥硬编码泄露 XOR 密钥明文写死在后端 PHP 源码中,查看页面源代码即可完整获取密钥,无任何隔离防护
XOR 异或算法完全可逆 XOR 属于对称双向运算,持有密钥即可任意还原明文、生成密文,无法实现不可逆数据保护
无规范密钥管理机制 密钥直接裸写业务代码,未使用环境变量、密钥管理服务、密钥混淆等保护手段
登录校验逻辑存在严重缺陷 登录模块仅对比用户输入原始字符串是否等于Olifant,未对提交的密码执行解密校验,校验逻辑形同虚设

3.6 Low级别总结

缺陷 说明
错误将 Base64 编码充当加密手段 Base64 无保密性,仅用于网络传输,不能保护账号、密码等敏感数据
密钥硬编码在服务端源码 密钥完全暴露,任何能访问页面源码的人员均可提取
简易 XOR 混淆不具备安全强度 XOR 运算可逆,攻击者拿到密钥后可批量逆向所有密文数据
身份校验流程设计失误 登录逻辑跳过解密比对步骤,仅做明文等值判断,安全验证完全失效

四、Medium级别:AES-ECB的"剪切-粘贴"攻击

4.1 安全级别设置

将DVWA Security切换为 Medium 级别。

4.2 界面观察

Medium级别的页面展示了三个用户的Token信息:

用户 Token(十六进制)
Sooty e287af752ed3f9601befd45726785bd9b85bb230876912bf3c66e50758b222d0837d1e6b16bfae07b776feb7afe576305aec34b41499579d3fb6acc8dc92fd5fcea8743c3b2904de83944d6b19733cdb48dd16048ed89967c250ab7f00629dba
Sweep 3061837c4f9debaf19d4539bfa0074c1b85bb230876912bf3c66e50758b222d083f2d277d9e5fb9a951e74bee57c77a3caeb574f10f349ed839fbfd223903368873580b2e3e494ace1e9e8035f0e7e07
Soo 5fec0b1c993f46c8bad8a5c8d9bb9698174d4b2659239bbc50646e14a70becef83f2d277d9e5fb9a951e74bee57c77a3c9acb1f268c06c5e760a9d728e081fab65e83b9f97e65cb7c7c4b8427bd44abc16daa00fd8cd0105c97449185be77ef5

目标:通过操纵Token,以Sweep的用户身份获得管理员(admin)权限。

4.3 源码分析

查看Medium级别的核心代码:

php 复制代码
<?php
function decrypt ($ciphertext, $key) {
    $e = openssl_decrypt($ciphertext, 'aes-128-ecb', $key, OPENSSL_PKCS1_PADDING);
    if ($e === false) {
        throw new Exception ("Decryption failed");
    }
    return $e;
}

$key = "ik ben een aardbei";

$errors = "";
$success = "";
$messages = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    try {
        if (!array_key_exists ('token', $_POST)) {
            throw new Exception ("No token passed");
        } else {
            $token = $_POST['token'];
            if (strlen($token) % 32 != 0) {
                throw new Exception ("Token is in wrong format");
            } else {
                $decrypted = decrypt(hex2bin ($token), $key);

                $user = json_decode ($decrypted);
                if ($user === null) {
                    throw new Exception ("Could not decode JSON object.");
                }

                if ($user->user == "sweep" && $user->ex > time() && $user->level == "admin") {
                    $success = "Welcome administrator Sweep";
                } else {
                    $messages = "Login successful but not as the right user.";
                }
            }
        }
    } catch(Exception $e) {
        $errors = $e->getMessage();
    }
}

$html = "
        <p>
        You have managed to get hold of three session tokens for an application you think is using poor cryptography to protect its secrets:
        </p>
        <p>
        <strong>Sooty (admin), session expired</strong>
        </p>
        <p>
<textarea style='width: 600px; height: 56px'>e287af752ed3f9601befd45726785bd9b85bb230876912bf3c66e50758b222d0837d1e6b16bfae07b776feb7afe576305aec34b41499579d3fb6acc8dc92fd5fcea8743c3b2904de83944d6b19733cdb48dd16048ed89967c250ab7f00629dba</textarea>
        </p>
        <p>
        <strong>Sweep (user), session expired</strong>
        </p>
        <p>
<textarea style='width: 600px; height: 56px'>3061837c4f9debaf19d4539bfa0074c1b85bb230876912bf3c66e50758b222d083f2d277d9e5fb9a951e74bee57c77a3caeb574f10f349ed839fbfd223903368873580b2e3e494ace1e9e8035f0e7e07</textarea>
        </p>
        <p>
        <strong>Soo (user), session valid</strong>
        </p>
        <p>
<textarea style='width: 600px; height: 56px'>5fec0b1c993f46c8bad8a5c8d9bb9698174d4b2659239bbc50646e14a70becef83f2d277d9e5fb9a951e74bee57c77a3c9acb1f268c06c5e760a9d728e081fab65e83b9f97e65cb7c7c4b8427bd44abc16daa00fd8cd0105c97449185be77ef5</textarea>
        </p>
        <p>
        Based on the documentation, you know the format of the token is:
        </p>
        <pre><code>{
    \"user\": \"example\",
    \"ex\": 1723620372,
    \"level\": \"user\",
    \"bio\": \"blah\"
}</code></pre>
<p>
You also spot this comment in the docs:
</p>
<blockquote><i>
To ensure your security, we use aes-128-ecb throughout our application.
</i></blockquote>

        <hr>
        <p>
        Manipulate the session tokens you have captured to log in as Sweep with admin privileges.
";

if ($errors != "") {
    echo '<div class="warning">' . $errors . '</div>';
}

if ($messages != "") {
    echo '<div class="nearly">' . $messages . '</div>';
}

if ($success != "") {
    echo '<div class="success">' . $success . '</div>';
}

echo "
        <form name=\"ecb\" method='post' action=\"" . $_SERVER['PHP_SELF'] . "\">
            <p>
                <label for='token'>Token:</lable><br />
<textarea style='width: 600px; height: 56px' id='token' name='token'></textarea>
            </p>
            <p>
                <input type=\"submit\" value=\"Submit\">
            </p>
        </form>
";
?>

关键发现

  • 加密模式采用 aes-128-ecb,无初始化向量 IV,每个 16 字节明文分组独立加密;

  • 输入校验仅限制 Token 长度为 32 十六进制字符的整数倍,完全不校验密文完整性、分组顺序合法性

  • 解密后直接 JSON 解析,无签名、哈希校验,篡改重组后的密文依然能正常解密;

  • 登录三重判断条件:user=sweepex>当前时间level=admin,三个字段分散在不同 AES 分组,可单独拼接对应密文块。

4.4 ECB模式的安全缺陷

ECB模式是AES中最不安全的工作模式之一。它的核心问题是:

特征 详细说明
分组独立加密 AES-128 固定分组大小 16 字节,所有分组使用同一密钥单独加密,分组之间无任何关联
确定性加密 完全相同的 16 字节明文块,加密后必然产出完全一致的 32 字符十六进制密文块,可构建明文 - 密文映射表
支持密文块剪切粘贴重组 攻击者可从多条合法 Token 中拆分、抽取所需密文块,自由拼接生成全新合法密文,解密不会报错
无防篡改机制 无 MAC、哈希、数字签名校验,篡改、重组后的密文可正常解密解析,系统无法识别伪造

通俗理解

把每条 Token 明文 JSON 拆分为固定大小的积木块,ECB 会给每一块积木单独上色;内容一模一样的积木上色完全相同。攻击者无需密钥,只需从不同 Token 里拆下需要的积木块(密文分组),重新拼接成符合登录条件的新 Token,服务器解密时不会发现拼接篡改。

4.5 攻击方法:分组重放攻击

前置核心原理铺垫

  • AES-128 固定分组大小:16 字节明文 = 1 个加密分组 ,16 字节二进制转十六进制后固定为 32 个字符,拆分 Token 必须严格按每 32 字符切分 1 个独立密文块。

  • ECB 模式确定性加密特性:同一密钥下,完全相同的 16 字节明文分组,加密后一定生成完全一致的 32 字符十六进制密文块;分组之间无任何关联、无 IV 初始化向量,每个分组独立加密、独立解密。

  • 本关密钥硬编码固定:$key = "ik ben een aardbei",三条 Token 均使用同一个密钥加密,因此相同片段明文会产出相同密文块,可反向匹配明文含义。

  • 解密校验规则:后端仅校验 Token 总长度是 32 的整数倍,不校验密文分组来源、拼接顺序、完整性、签名,任意跨 Token 抽取的密文块拼接后均可正常解密。

  • 登录三重校验硬性条件:解密后的 JSON 必须同时满足 user="sweep"ex>当前系统时间戳level="admin",三个关键字段分别落在不同独立 AES 分组,可单独抽取对应密文块重组。

第一步:拆分三条 Token,推导每一块对应的明文片段

1. Sweep Token 拆分(目标用户名,会话过期)

完整 Sweep Token:3061837c4f9debaf19d4539bfa0074c1b85bb230876912bf3c66e50758b222d083f2d277d9e5fb9a951e74bee57c77a3caeb574f10f349ed839fbfd223903368873580b2e3e494ace1e9e8035f0e7e07 按 32 字符切分 5 个密文块:

  • 块 1:3061837c4f9debaf19d4539bfa0074c1 推导明文逻辑:所有 Token 第 1 块都是 JSON 最开头 16 字节片段,格式固定 {"user": "用户名",; 本地使用源码密钥加密明文 {"user": "sweep",,输出密文与该块完全匹配,因此明文确定为 {"user": "sweep",,作用:提供校验所需用户名sweep

  • 块 2:b85bb230876912bf3c66e50758b222d0 明文:"ex": 过期时间戳,,时间戳小于当前时间,会话失效,不能使用。

  • 块 3:83f2d277d9e5fb9a951e74bee57c77a3 明文:"level": "user",,普通用户权限,无管理员权限。

  • 块 4、块 5:bio 字段与 JSON 闭合结尾片段。

2. Sooty Token 拆分(管理员权限,会话过期)

完整 Sooty Token:e287af752ed3f9601befd45726785bd9b85bb230876912bf3c66e50758b222d0837d1e6b16bfae07b776feb7afe576305aec34b41499579d3fb6acc8dc92fd5fcea8743c3b2904de83944d6b19733cdb48dd16048ed89967c250ab7f00629dba 切分后关键块:

  • 块 2:b85bb230876912bf3c66e50758b222d0 时间戳过期,舍弃;

  • 块 3:837d1e6b16bfae07b776feb7afe57630 推导明文:该块对应 JSON 权限字段片段 "level": "admin",,是唯一携带管理员权限的密文块,满足level="admin"校验条件。

3. Soo Token 拆分(普通用户,会话有效)

完整 Soo Token:5fec0b1c993f46c8bad8a5c8d9bb9698174d4b2659239bbc50646e14a70becef83f2d277d9e5fb9a951e74bee57c77a3c9acb1f268c06c5e760a9d728e081fab65e83b9f97e65cb7c7c4b8427bd44abc16daa00fd8cd0105c97449185be77ef5 关键可用块:

  • 块 2:174d4b2659239bbc50646e14a70becef 明文:"ex": 超大有效时间戳,,时间戳大于系统当前时间,满足ex > time()会话未过期条件。

  • 块 3 及之后所有密文块:包含完整 bio 字段、JSON 闭合符号},用来补齐完整 JSON 结构,保证json_decode()正常解析不报错。

第二步:梳理伪造 Token 必须满足的 JSON 明文结构

后端解密后 JSON 需要同时匹配三条判断逻辑,完整预期明文结构:

复制代码
{
    "user": "sweep",
    "ex": 大于当前时间的有效时间戳,
    "level": "admin",
    "bio": "任意文本内容"
}

对应三个核心片段,分别来自三条不同 Token 的独立密文分组,不存在单条原生 Token 同时包含sweep用户名、有效时间戳、admin权限三个要素,必须跨 Token 剪切拼接。

第三步:整理攻击所需密文块来源、明文、功能对照表

所需密文块作用 来源 Token 32 字符密文块内容 对应 16 字节明文片段 满足校验条件
用户名开头分组 Sweep 3061837c4f9debaf19d4539bfa0074c1 {"user": "sweep", $user->user == "sweep"
有效未过期时间戳分组 Soo 174d4b2659239bbc50646e14a70becef "ex": 有效时间戳, $user->ex > time()
管理员权限分组 Sooty 837d1e6b16bfae07b776feb7afe57630 "level": "admin", $user->level == "admin"
尾部完整闭合分组 Soo Soo Token 第 3 块及之后全部密文 bio 字段 + JSON 闭合} 保证 JSON 完整可解析

第四步:按 JSON 书写顺序拼接密文块,生成伪造完整 Token

拼接顺序严格匹配 JSON 从上到下书写顺序:用户名块 → 时间戳块 → 管理员权限块 → Soo 尾部所有闭合块 拼接逻辑:

  • 第一部分(Sweep 块 1):3061837c4f9debaf19d4539bfa0074c1

  • 第二部分(Soo 块 2):174d4b2659239bbc50646e14a70becef

  • 第三部分(Sooty 块 3):837d1e6b16bfae07b776feb7afe57630

  • 第四部分(Soo 剩余尾部全部密文):caeb574f10f349ed839fbfd223903368873580b2e3e494ace1e9e8035f0e7e07

拼接完成的完整伪造 Token:

php 复制代码
3061837c4f9debaf19d4539bfa0074c1174d4b2659239bbc50646e14a70becef837d1e6b16bfae07b776feb7afe57630caeb574f10f349ed839fbfd223903368873580b2e3e494ace1e9e8035f0e7e07

第五步:提交伪造 Token,完成攻击流程

将拼接好的完整十六进制伪造 Token 粘贴到页面 Token 输入框,点击 Submit 提交表单;

后端第一层校验:Token 总长度为 32 字符整数倍,格式校验通过;

执行hex2bin()将十六进制字符串转为二进制密文;

使用硬编码密钥执行 AES-128-ECB 解密,拼接后的分组独立解密,组合出完整合法 JSON 字符串;

json_decode()正常解析出会话对象,三个校验条件全部命中:

  • user字段为sweep

  • ex时间戳大于服务器当前时间,会话未过期

  • level字段为admin管理员权限

页面输出成功提示:Welcome administrator Sweep,攻击达成目标。

4.6 为什么ECB模式不安全?

问题 完整说明
确定性加密无随机性 相同明文分组产出完全相同密文,攻击者可对比多条 Token 找出对应关键字段分组
无密文完整性校验 系统未对 Token 做哈希、签名校验,重组、篡改后的密文可正常解密,后端无法识别伪造
密文分组可自由重组 分组之间相互独立无关联,攻击者可跨 Token 抽取任意功能块拼接,构造自定义会话数据
缺少初始化向量 IV ECB 不使用 IV,每条相同明文加密结果完全一致,丧失语义混淆能力

4.7 Medium级别总结

缺陷 详细说明
错误选用 AES-ECB 加密模式 ECB 无 IV、分组独立加密,天然支持密文剪切粘贴,禁止用于会话、敏感数据加密
无密文完整性校验机制 仅校验字符串长度,未做 HMAC / 签名校验,篡改重组的 Token 可正常通过解密
会话字段拆分至独立分组 user、ex、level 关键权限字段分属不同 16 字节分组,攻击者可单独抽取拼接伪造权限
未限制密文分组来源与顺序 后端不校验分组原始归属,仅单纯拼接解密,给分组重放攻击提供可乘之机

五、High级别:AES-CBC 填充预言(Padding Oracle)攻击

5.1 安全级别设置

将DVWA Security切换为 High 级别。

5.2 界面观察

页面展示一组已泄露的 JSON 格式会话 Token:

php 复制代码
{"token":"PhQwGVA3q+T2mT+L3Pe5Vg==","iv":"MTIzNDU2NzgxMjM0NTY3OA=="}

页面任务说明原文:

You have managed to steal the following token from a user of the Prognostication application. You can use the form below to provide the token to access the system. You have two challenges, first, decrypt the token to find out the secret it contains, and then create a new token to access the system as a other users. See if you can make yourself an administrator.

挑战分为两步

  • 利用漏洞解密现有 Token,提取内部明文信息;

  • 自主伪造全新合法 Token,修改用户 ID,以管理员 admin 身份登录系统。

5.3 源码分析

High级别的核心逻辑在token_library_high.php中:

php 复制代码
<?php
define("KEY", "rainbowclimbinghigh");
define("ALGO", "aes-128-cbc");
define("IV", "1234567812345678");

function encrypt($plaintext, $iv) {
    // PKCS#7填充,CBC加密无AEAD认证标签
    if (strlen($iv) != 16) {
        throw new Exception("IV must be 16 bytes, " . strlen($iv) . " passed");
    }
    $tag = "";
    // 警告产生点:CBC不支持tag参数,代码强制传入空变量
    $e = openssl_encrypt($plaintext, ALGO, KEY, OPENSSL_RAW_DATA, $iv, $tag);
    if ($e === false) {
        throw new Exception("Encryption failed");
    }
    return $e;
}

function decrypt($ciphertext, $iv) {
    if (strlen($iv) != 16) {
        throw new Exception("IV must be 16 bytes, " . strlen($iv) . " passed");
    }
    $e = openssl_decrypt($ciphertext, ALGO, KEY, OPENSSL_RAW_DATA, $iv);
    if ($e === false) {
        throw new Exception("Decryption failed");
    }
    return $e;
}

// 生成默认普通用户Token,明文固定 userid:2
function create_token($debug = false) {
    $token = "userid:2";
    if ($debug) {
        print "Clear text token: " . $token . "\n";
        print "Encryption key: " . KEY . "\n";
        print "IV: " . IV . "\n";
    }
    $e = encrypt($token, IV);
    $data = array(
        "token" => base64_encode($e),
        "iv" => base64_encode(IV)
    );
    return json_encode($data);
}

// 校验提交Token,依靠响应差异形成填充预言机(漏洞核心)
function check_token($data) {
    // 用户权限映射:userid=1 管理员,2/3/4 普通用户
    $users = array();
    $users[1] = array("name" => "Geoffery", "level" => "admin");
    $users[2] = array("name" => "Bungle", "level" => "user");
    $users[3] = array("name" => "Zippy", "level" => "user");
    $users[4] = array("name" => "George", "level" => "user");

    $data_array = false;
    try {
        $data_array = json_decode($data, true);
    } catch (TypeError $exp) {
        $ret = array(
            "status" => 521,
            "message" => "Data not in JSON format",
            "extra" => $exp->getMessage()
        );
        return json_encode($ret);
    }

    if (is_null($data_array)) {
        $ret = array(
            "status" => 522,
            "message" => "Data in wrong format"
        );
        return json_encode($ret);
    }

    if (!array_key_exists("token", $data_array)) {
        $ret = array(
            "status" => 523,
            "message" => "Missing token"
        );
        return json_encode($ret);
    }

    if (!array_key_exists("iv", $data_array)) {
        $ret = array(
            "status" => 524,
            "message" => "Missing IV"
        );
        return json_encode($ret);
    }

    $ciphertext = base64_decode($data_array['token']);
    $iv = base64_decode($data_array['iv']);
    $ret = array("status" => 500, "message" => "Unknown error");

    try {
        $d = decrypt($ciphertext, $iv);
        // 正则匹配明文固定格式 userid:数字
        if (preg_match("/^userid:(\d+)$/", $d, $matches)) {
            $id = $matches[1];
            if (array_key_exists($id, $users)) {
                $user = $users[$id];
                $ret = array(
                    "status" => 200,
                    "user" => $user["name"],
                    "level" => $user['level']
                );
            } else {
                $ret = array(
                    "status" => 525,
                    "message" => "User not found"
                );
            }
        } else {
            $ret = array(
                "status" => 527,
                "message" => "No user specified"
            );
        }
    } catch (Exception $exp) {
        // PKCS7填充校验失败统一返回526,区分正常业务逻辑,形成预言漏洞
        $ret = array(
            "status" => 526,
            "message" => "Unable to decrypt token",
            "extra" => $exp->getMessage()
        );
    }
    return json_encode($ret);
}
?>

源码核心关键发现

加密算法为 aes-128-cbc与 Medium 的 AES-ECB 完全不同,无分组剪切拼接漏洞;

全局固定密钥:rainbowclimbinghigh,默认固定 IV:1234567812345678(标准 16 字节 CBC 初始向量);

明文强制固定格式:userid:数字userid:1 对应管理员权限,其余 ID 均为普通用户;

填充预言核心逻辑:

  • 密文 PKCS7 填充非法:捕获异常返回 status:526

  • 填充合法、但用户 ID 不存在:返回 status:525

  • 填充合法、ID 匹配用户:返回 status:200 正常业务数据; 攻击者依靠三种差异化响应,逐字节爆破还原完整明文;

Token 传输格式:外层 JSON 包裹,token/iv 字段均使用 Base64 编码;

无任何完整性校验(缺少 HMAC、数字签名),仅依靠解密后正则过滤,可篡改密文构造任意明文。

5.4 攻击方法

前置知识点

  • AES-128 分组固定 16 字节,明文末尾采用 PKCS#7 标准填充;

  • CBC 模式分组之间存在异或关联,无法像 ECB 直接剪切重组密文块;

  • 填充预言攻击核心:利用服务端填充报错、业务正常返回的响应差异,暴力逐字节还原明文;

  • 攻击分为两大阶段:爆破原始 Token 明文、逆向计算管理员明文对应的合法密文。

第一步:解析页面原始泄露 Token

原始 Token 载荷: {"token":"PhQwGVA3q+T2mT+L3Pe5Vg==","iv":"MTIzNDU2NzgxMjM0NTY3OA=="}

  • Base64 解码iv字段:MTIzNDU2NzgxMjM0NTY3OA==1234567812345678,与源码内置 IV 完全一致;
  • token字段值:PhQwGVA3q+T2mT+L3Pe5Vg==,Base64 解码后得到 AES-128-CBC 加密后的二进制密文,无法直接读取明文。

解密前置条件:仅 Base64 解码只能还原加密二进制字节,必须搭配源码固定密钥rainbowclimbinghigh与 IV,或使用填充预言攻击才能还原可读明文。

第二步:填充预言爆破原始明文

遍历密文末尾字节 0~255,每次修改单字节构造新 Token 提交;

响应判断规则:

  • 返回status:526:PKCS7 填充校验失败,当前字节不匹配;

  • 返回非 526 状态码:填充校验通过,命中正确明文字节;

从最后一组分组向前逐字节遍历,完整爆破出原始明文 userid:2

对照用户表,userid=2 对应普通用户 Bungle,与页面默认 Token 身份匹配。

第三步:逆向计算管理员明文对应的合法密文

目标伪造明文:userid:1(ID=1 拥有 admin 管理员权限)

由于原始 Token 只有一个密文块(16 字节),而我们没有加密密钥,无法直接生成新的密文块。但在 CBC 模式下,解密第一个块时满足 Plaintext = Decrypt(Ciphertext) ⊕ IV。通过第二步我们已经获得了 Decrypt(Ciphertext)(称为中间值 I),因此要得到目标明文 P',只需计算 新 IV = I ⊕ P' 即可,密文块保持不变。

  • 将目标明文 userid:1 补足 PKCS#7 填充(长度为 16 字节),得到完整块 P' = b'userid:1\x08\x08\x08\x08\x08\x08\x08\x08'

  • 利用爆破得到的中间值 I,计算新 IV:new_iv = I ⊕ P'

  • 将新 IV 进行 Base64 编码,与原始密文(token 不变) 组装成 JSON Token。

  • 最终伪造提交载荷模板: {"token":"PhQwGVA3q+T2mT+L3Pe5Vg==","iv":"新IV的Base64值"}

第四步:提交伪造 Token,完成权限提升攻击

  • 将构造完成的管理员 Token 粘贴至页面输入框,点击 Submit 提交;

  • 后端流程:JSON 解析 → Base64 解码 IV 与密文 → AES-CBC 解密;

  • 解密结果为userid:1,匹配用户映射表中 admin 管理员身份;

  • 页面返回status:200成功响应,攻击达成权限提升目标。

自动化攻击 Python 脚本

python 复制代码
import base64
import requests
import json
from typing import List, Tuple, Callable

# ======================== 配置 ============================
BLOCK_SIZE = 16
URL = "http://10.0.0.149/vulnerabilities/cryptography/source/check_token_high.php"
COOKIE = {"PHPSESSID": "g13enl5l9vrqpqdn4cbbu4qeel", "security": "high"}
# 页面泄露的原始 Token
ORIG_TOKEN_B64 = "PhQwGVA3q+T2mT+L3Pe5Vg=="
ORIG_IV_B64 = "MTIzNDU2NzgxMjM0NTY3OA=="

# ======================== Oracle 函数 ====================
def oracle(iv_b64: str, token_b64: str, debug=False) -> bool:
    """
    发送 JSON 请求,判断填充是否有效。
    返回 True 表示填充有效(status != 526),False 表示填充失败(status == 526)。
    """
    payload = {"iv": iv_b64, "token": token_b64}
    headers = {"Content-Type": "application/json"}
    try:
        resp = requests.post(URL, json=payload, headers=headers,
                             cookies=COOKIE, timeout=5)
        if debug:
            print(f"  -> 状态码: {resp.status_code}, 响应: {resp.text[:200]}")
        data = resp.json()
        status = data.get("status")
        return status != 526
    except Exception as e:
        if debug:
            print(f"  -> 请求异常: {e}")
        return False

# ======================== 辅助函数 ========================
def split_blocks(data: bytes):
    """分离 IV 和密文块"""
    iv = data[:BLOCK_SIZE]
    ct = data[BLOCK_SIZE:]
    blocks = [ct[i:i+BLOCK_SIZE] for i in range(0, len(ct), BLOCK_SIZE)]
    return iv, blocks

def build_token(iv: bytes, blocks: List[bytes]) -> bytes:
    """合成完整 Token(IV + 密文)"""
    return iv + b''.join(blocks)

# ======================== 攻击单个块 ======================
def attack_block(block_idx: int, iv: bytes, all_blocks: List[bytes],
                 oracle_func: Callable[[str, str, bool], bool]) -> bytes:
    """
    攻击第 block_idx 个块(all_blocks 已截断,该块为最后一个块)。
    返回该块的中间值 I = Decrypt(block)。
    """
    prev = iv if block_idx == 0 else all_blocks[block_idx-1]
    I = bytearray(16)
    print(f"  攻击块 {block_idx},前一块为 {'IV' if block_idx==0 else f'块{block_idx-1}'}")
    
    # 从最后一个字节向前爆破
    for pos in range(15, -1, -1):
        pad_val = 16 - pos          # 期望的填充值
        found = False
        for guess in range(256):
            mod_prev = bytearray(prev)
            mod_prev[pos] = guess
            # 设置已确定的低位字节,使解密后的明文为 pad_val
            for j in range(pos + 1, 16):
                mod_prev[j] = I[j] ^ pad_val   # 关键修正:直接使用 I 和填充值

            # 构造测试 Token
            new_blocks = all_blocks.copy()
            if block_idx == 0:
                new_iv = bytes(mod_prev)
                test_token_bytes = build_token(new_iv, new_blocks)
            else:
                new_blocks[block_idx - 1] = bytes(mod_prev)
                test_token_bytes = build_token(iv, new_blocks)

            test_iv = test_token_bytes[:BLOCK_SIZE]
            test_token = test_token_bytes[BLOCK_SIZE:]
            iv_b64 = base64.b64encode(test_iv).decode()
            token_b64 = base64.b64encode(test_token).decode()

            if oracle_func(iv_b64, token_b64, debug=(guess % 50 == 0)):
                I[pos] = guess ^ pad_val
                found = True
                print(f"    位置 {pos:2d} 猜测成功: guess={guess:3d} -> I[{pos}]={I[pos]:3d}")
                break
        if not found:
            raise RuntimeError(f"无法爆破第 {pos} 字节")
    print(f"  块 {block_idx} 中间值: {I.hex()}")
    return bytes(I)

# ======================== 解密所有块 ======================
def decrypt_all_blocks(iv: bytes, blocks: List[bytes],
                       oracle_func: Callable[[str, str, bool], bool]) -> Tuple[List[bytes], bytes]:
    """从最后一个块向前攻击,还原所有中间值和明文"""
    I_list = [None] * len(blocks)
    plaintext_blocks = [None] * len(blocks)

    for i in range(len(blocks)-1, -1, -1):
        truncated = blocks[:i+1]          # 截断密文,使块 i 成为最后一块
        I = attack_block(i, iv, truncated, oracle_func)
        I_list[i] = I
        # 使用原始前一块解密得到明文
        prev = iv if i == 0 else blocks[i-1]
        plain_block = bytes([I[j] ^ prev[j] for j in range(BLOCK_SIZE)])
        plaintext_blocks[i] = plain_block
        print(f"  块 {i} 明文: {plain_block}")
    plaintext = b''.join(plaintext_blocks)
    return I_list, plaintext

# ======================== 构造新 Token ====================
def construct_new_token(iv: bytes, blocks: List[bytes], I_list: List[bytes],
                        target_plaintext: bytes) -> Tuple[bytes, bytes]:
    """
    通过修改 IV 来构造新 Token(单块时适用)。
    返回 (new_iv, new_ciphertext),其中 new_ciphertext 与原密文相同。
    """
    if len(target_plaintext) % BLOCK_SIZE != 0:
        raise ValueError("目标明文必须是块大小的整数倍")
    target_blocks = [target_plaintext[i:i+BLOCK_SIZE] for i in range(0, len(target_plaintext), BLOCK_SIZE)]
    if len(target_blocks) != len(I_list):
        raise ValueError("目标块数必须与原密文块数相同")

    # 只修改第一块的前一块(即 IV)
    new_iv = bytes([I_list[0][j] ^ target_blocks[0][j] for j in range(BLOCK_SIZE)])
    # 保留原始密文块
    new_cipher = b''.join(blocks)
    return new_iv, new_cipher

# ======================== 主流程 ==========================
def main():
    # 解码原始数据
    iv_bytes = base64.b64decode(ORIG_IV_B64)
    token_bytes = base64.b64decode(ORIG_TOKEN_B64)
    full_data = iv_bytes + token_bytes
    iv, blocks = split_blocks(full_data)

    print("=== 开始 Padding Oracle 攻击 ===")
    print("测试原始 Token 有效性...")
    orig_valid = oracle(ORIG_IV_B64, ORIG_TOKEN_B64, debug=True)
    print(f"原始 Token 填充有效: {orig_valid}\n")

    print("开始逐块解密(从后向前)...")
    I_list, plaintext = decrypt_all_blocks(iv, blocks, oracle)
    print(f"\n完整原始明文(含填充): {plaintext}")
    print(f"明文十六进制: {plaintext.hex()}")

    # 替换 userid:2 -> userid:1
    if b'userid:2' in plaintext:
        target = plaintext.replace(b'userid:2', b'userid:1')
    else:
        print("未找到 'userid:2',请检查明文格式。")
        exit(1)

    print(f"\n目标明文: {target}")

    # 构造新 Token
    new_iv, new_cipher = construct_new_token(iv, blocks, I_list, target)
    new_iv_b64 = base64.b64encode(new_iv).decode()
    new_token_b64 = base64.b64encode(new_cipher).decode()
    print("\n=== 构造成功 ===")
    print(f"新 IV  : {new_iv_b64}")
    print(f"新 Token: {new_token_b64}")

    # 验证新 Token
    if oracle(new_iv_b64, new_token_b64, debug=True):
        print("验证通过:新 Token 填充有效!")
    else:
        print("验证失败:新 Token 填充无效。")

if __name__ == "__main__":
    main()

5.5 High级别总结

原有防护改进 存在局限性(安全漏洞)
弃用高危 AES-ECB,采用标准 AES-CBC 加密模式 CBC 存在填充预言漏洞,依靠页面响应差异可完整爆破全部明文
规范分离 IV 与密文,遵循 CBC 标准加密格式 无 HMAC / 数字签名完整性校验,可篡改密文逆向构造任意明文
增加解密后正则校验,限制明文userid:数字固定格式 校验逻辑执行于解密完成之后,攻击者可提前通过填充预言控制解密输出内容
区分多套业务错误状态码 差异化响应直接泄露 PKCS7 填充校验结果,构建可利用的预言机

六、Impossible级别:认证加密的"终极防御"

6.1 安全级别设置

将DVWA Security切换为 Impossible 级别。

6.2 界面观察

Impossible级别的页面显示了类似的Token挑战,但页面明确提示:

"This being the impossible level, you should not be able to mess with the token in any useful way but feel free to try below."

6.3 源码分析

Impossible级别使用了GCM(Galois/Counter Mode,伽罗瓦/计数器模式) 加密模式:

php 复制代码
<?php

define("KEY", "rainbowclimbinghigh");
define("ALGO", "aes-256-gcm");

/**
 * AES-256-GCM 加密函数
 * @param string $plaintext 明文内容
 * @param string $iv 12字节随机IV
 * @return string 密文 + 16字节校验tag 拼接二进制串
 * @throws Exception IV长度非法 / 加密失败抛出异常
 */
function encrypt($plaintext, $iv)
{
    // GCM 规范IV必须12字节
    if (strlen($iv) != 12) {
        throw new Exception("IV must be 12 bytes, " . strlen($iv) . " passed");
    }

    $e = openssl_encrypt($plaintext, ALGO, KEY, OPENSSL_RAW_DATA, $iv, $tag);
    if ($e === false) {
        throw new Exception("Encryption failed");
    }
    // 拼接密文与GCM认证标签tag
    return $e . $tag;
}

/**
 * AES-256-GCM 解密函数
 * @param string $ciphertext 加密返回的密文+tag完整二进制串
 * @param string $iv 12字节加密向量
 * @return string 原始明文
 * @throws Exception IV长度错误 / tag校验失败则抛出解密异常
 */
function decrypt($ciphertext, $iv)
{
    if (strlen($iv) != 12) {
        throw new Exception("IV must be 12 bytes, " . strlen($iv) . " passed");
    }

    // 拆分:最后16字节为GCM校验tag,前面为密文本体
    $tag  = substr($ciphertext, -16);
    $text = substr($ciphertext, 0, -16);

    $e = openssl_decrypt($text, ALGO, KEY, OPENSSL_RAW_DATA, $iv, $tag);
    if ($e === false) {
        throw new Exception("Decryption failed");
    }
    return $e;
}

/**
 * 生成默认用户token(userid:2)
 * @return string JSON字符串,包含base64密文与base64-IV
 */
function create_token()
{
    $token = "userid:2";
    $iv    = openssl_random_pseudo_bytes(12, $cstrong);

    $encrypt_data = encrypt($token, $iv);
    $data = [
        "token" => base64_encode($encrypt_data),
        "iv"    => base64_encode($iv),
    ];
    return json_encode($data);
}

/**
 * 校验前端提交的token JSON数据
 * @param string $data POST传入的完整JSON字符串
 * @return string 标准化JSON响应
 */
function check_token($data)
{
    // 用户信息映射表
    $users = [
        1 => ["name" => "Geoffery", "level" => "admin"],
        2 => ["name" => "Bungle",   "level" => "user"],
        3 => ["name" => "Zippy",    "level" => "user"],
        4 => ["name" => "George",   "level" => "user"],
    ];

    $data_array = false;
    try {
        $data_array = json_decode($data, true);
    } catch (TypeError $exp) {
        $ret = [
            "status"  => 521,
            "message" => "Data not in JSON format",
            "extra"   => $exp->getMessage()
        ];
        return json_encode($ret);
    }

    // JSON解析失败、格式错误
    if (is_null($data_array)) {
        $ret = [
            "status"  => 522,
            "message" => "Data in wrong format"
        ];
        return json_encode($ret);
    }

    // 缺失token字段
    if (!array_key_exists("token", $data_array)) {
        $ret = [
            "status"  => 523,
            "message" => "Missing token"
        ];
        return json_encode($ret);
    }

    // 缺失iv字段
    if (!array_key_exists("iv", $data_array)) {
        $ret = [
            "status"  => 524,
            "message" => "Missing IV"
        ];
        return json_encode($ret);
    }

    // Base64解码得到原始二进制密文与IV
    $ciphertext = base64_decode($data_array['token']);
    $iv         = base64_decode($data_array['iv']);

    // 默认未知错误
    $ret = [
        "status"  => 500,
        "message" => "Unknown error"
    ];

    try {
        // GCM解密,篡改任意字节都会因tag校验失败抛出异常
        $d = decrypt($ciphertext, $iv);

        // 正则匹配 userid:数字 格式
        if (preg_match("/^userid:(\d+)$/", $d, $matches)) {
            $id = $matches[1];
            if (array_key_exists($id, $users)) {
                // 用户存在,正常返回用户权限信息
                $user = $users[$id];
                $ret = [
                    "status" => 200,
                    "user"   => $user["name"],
                    "level"  => $user['level']
                ];
            } else {
                // 用户ID不存在
                $ret = [
                    "status"  => 525,
                    "message" => "User not found"
                ];
            }
        } else {
            // 明文格式不合法,无有效用户ID
            $ret = [
                "status"  => 527,
                "message" => "No user specified"
            ];
        }
    } catch (Exception $exp) {
        // 解密失败:密文篡改、tag不匹配、iv错误等统一返回526
        $ret = [
            "status"  => 526,
            "message" => "Unable to decrypt token",
            "extra"   => $exp->getMessage()
        ];
    }

    return json_encode($ret);
}

6.4 GCM模式的安全特性

Impossible级别使用AES-256-GCM(Galois/Counter Mode) ,这是一种认证加密(Authenticated Encryption) 模式:

特性 说明
加密 + 认证 同时提供机密性和完整性保护
认证标签(Tag) 密文附带一个认证标签,任何篡改都会导致验证失败
随机IV 每次加密使用不同的随机初始化向量
抗篡改 攻击者无法在不破坏认证标签的情况下修改密文

6.5 为什么Impossible级别无法被绕过?

攻击方式 Impossible级别的防护 攻击者能否达成
ECB分组重放 GCM模式,块与块之间有关联 ❌ 无法单独提取或替换块
密文篡改 认证标签验证完整性 ❌ 任何修改都会导致标签验证失败
密钥猜测 AES-256,密钥空间巨大 ❌ 暴力破解不可行
Token伪造 无法在不被检测的情况下修改明文 ❌ 认证机制阻止了篡改

6.6 Impossible级别总结

防御层 技术手段 作用
第一层 AES-256-GCM认证加密 提供机密性 + 完整性双重保护
第二层 认证标签(Tag) 检测任何密文篡改
第三层 随机IV 相同明文产生不同密文

七、密码学安全的核心原则

通过DVWA四个级别的对比,我们可以总结出密码学安全的核心原则

7.1 必须遵循的原则

原则 说明 优先级
使用认证加密(AEAD) 如AES-GCM、ChaCha20-Poly1305,同时提供加密和完整性保护 ⭐⭐⭐⭐⭐
避免ECB模式 永远不要使用ECB模式加密任何数据 ⭐⭐⭐⭐⭐
密钥安全存储 密钥绝不能硬编码在源代码中 ⭐⭐⭐⭐⭐
使用安全的随机数 IV和盐值必须使用密码学安全的随机数生成器 ⭐⭐⭐⭐⭐
编码 ≠ 加密 Base64、Hex等是编码,不是加密 ⭐⭐⭐⭐⭐

7.2 常见误区

在实际开发中,以下做法不能提供有效的密码学安全

  • 使用ECB模式:可被分组重放攻击(如Medium/High级别)

  • 将编码当作加密:Base64不提供任何安全性(如Low级别)

  • 密钥硬编码:密钥暴露在代码中

  • 使用弱随机数:IV可预测导致安全性降低

  • 忽视完整性保护:仅加密不认证,密文可被篡改


八、实战工具推荐

8.1 CyberChef

CyberChef是GCHQ(英国政府通信总部)开发的"网络瑞士军刀",非常适合处理编码和加密相关的任务。

常用操作

  • From Base64

  • XOR

  • AES Decrypt

  • Hex

  • JSON格式化

8.2 Python密码学库

用途
pycryptodome AES、RSA等加密算法
cryptography 现代密码学库,支持AEAD
base64 Base64编码/解码

九、总结

本文完整梳理DVWA密码学模块全等级攻防逻辑:我们先厘清加密保障数据机密性、认证保障数据完整性的基础作用,依次完成各难度靶场实战:Low层级仅采用Base64与XOR组合编码而非真正加密,密钥硬编码极易逆向破解;Medium层级采用不安全的AES-ECB模式,该模式加密具备确定性,攻击者可通过剪切拼接密文块实施分组重放,自定义构造明文Token;High层级基于CBC模式存在填充预言漏洞,可借助响应差异解密Token、伪造越权凭证;Impossible层级采用AES-256-GCM认证加密AEAD方案,配套认证标签校验完整性,任意密文篡改都会触发校验失败,不存在可利用漏洞。文末归纳密码学开发核心规范:优先选用AES-GCM等AEAD认证加密、禁用ECB模式、妥善保管密钥、分清编码与加密本质。密码学算法强度有限,不安全的代码实现会直接引发安全风险,通过本模块实操,我们既能识别、利用各类密码学实现漏洞,也掌握了标准化安全落地思路,生产环境搭配AEAD加密、规范密钥管理、密码学安全随机数,即可搭建可靠的数据加密防护体系。


**重要声明:**本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。

如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享 ,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。

相关推荐
MartinYeung51 小时前
W3C Agent Identity 最新标准:从密码学视角的深度解析
密码学
糖果店的幽灵2 小时前
安全测试从入门到精通 - 环境搭建与基础工具选择
安全·web安全
风行南方6 小时前
弄懂有限域,AES加密核心GF(2⁸)数学原理详解
密码学
云水一下1 天前
DVWA从入门到精通(十七):Open HTTP Redirect(开放重定向)
web安全·dvwa·开放重定向
txg6661 天前
网络安全领域简报(2026年7月3日—10日)
安全·web安全·网络安全
Chengbei111 天前
SoloXSS:一款现代化的自托管 XSS平台
人工智能·安全·web安全·网络安全·自动化·xss·安全架构
2301_780303902 天前
网络安全、自动化运维、ERP、CRM、MES
运维·web安全·网络安全·自动化·安全威胁分析
技术不好的崎鸣同学2 天前
[GXYCTF2019]Ping Ping Ping 思路及解法
网络·安全·web安全
dehuisun2 天前
等保2.0实施方案
web安全