个人简介:
渣渣一枚,萌新一个,会划水,会喊六六
今天在bugku遇到关于CBC翻转攻击的题目,总结了一下关于CBC翻转攻击的原理,以及关于这道题目的解题思路
个人博客:https://www.cnblogs.com/lxz-1263030049/

CBC翻转攻击的主要目的:通过损坏密文字节来改变明文字节。(注:借助CBC内部的模式) 通过添加单引号等恶意字符来绕过过滤器,或通过将用户ID更改为admin来提升权限,或者更改应用程序所需的明文的任何其他后果。

加密过程:


上图CBC加密原理图
1:Plaintext:待加密的数据。
2:IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。
3:Ciphertext:加密后的数据
4:Key:分组加密使用的密钥
这里重要的一点是CBC在一个固定长度的位组上工作,称为块。在本文中,我们将使用每个16字节的块。
整个加密的过程简单说来就是:

  1. 首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
  2. 生成一个随机的初始化向量(IV)和一个密钥。
  3. 将IV和第一组明文异或。
  4. 用密钥对3中xor后产生的密文加密。
  5. 用4中产生的密文对第二组明文进行xor操作。
  6. 用密钥对5中产生的密文加密。
  7. 重复4-7,到最后一组明文。
  8. 将IV和加密后的密文拼接在一起,得到最终的密文。

从第一块开始,首先与一个初始向量IV异或(IV只在第一处作用),然后把异或的结果配合Key进行加密,得到第一块的密文,并且把加密的结果与下一块的明文进行异或,一直这样进行下去。因此这种模式最重要的特点就是:前一块的密文用来产生后一块的密文。

解密过程:

解密的过程其实只要理解了加密,反过来看解密过程就也很简单了,同样的,前一块密文参与下一块密文的还原。

  1. 从密文中提取出IV,然后将密文分组。
  2. 使用密钥对第一组的密文解密,然后和IV进行xor得到明文。
  3. 使用密钥对第二组密文解密,然后和2中的密文xor得到明文。
  4. 重复2-3,直到最后一组密文。

下图是为解释翻转攻击的原理图:

这里可以注意到前一块Ciphertext用来产生下一块明文,如果我们改变前一块Ciphertext中的一个字节,然后和下一块解密后的密文xor,就可以得到一个不同的明文,而这个明文是我们可以控制的。利用这一点,我们就欺骗服务端或者绕过过滤器
再解释一下:
根据解密方式我们可以知道,A=ciphertext(N-1),B=plaintext(N),C为第N块待异或且经过解密的字符,C'为我们经过翻转要得到的明文。
所以我们可以打得到关系:

A = B ^ C
C = A ^ B
A ^ B ^ C = 0
A ^ B ^ C ^ C' = C'

根据关系式可以得到:A' = A ^ C ^ C'
所以说我们只需要修改前一组密文所对应的本组明文相同位置的字符,即可得到想要的明文

下面就是关于Bugku的题目
http://118.89.219.210:49168/
这一题属于常规思路,可是不容易想到,我记得以前做过类似的题目,毕竟是萌新总会有很多知识点会忘记(QAQ)
使用备份文件脚本进行扫描就会得到:脚本代码:

[hide]import requests
import sys
url = 'http://118.89.219.210:49168/'
import threading
a = ['bak','zip','rar','tar.gz','txt']
b = ['swp','swo','swn']
c = ['index.php', 'flag.php', 'profile.php','login.php']
s = requests.session()
proxies = {
    'http':None,
    'https':None
}
headers = {"Cookie": "PHPSESSID=sclfgjri76captre7cvq6g4170","Accept": "text/html,application/xhtml+xml,application/xml;", "Accept-Encoding": "gzip", "Accept-Language": "zh-CN,zh;q=0.8",
           "Referer": "http://www.example.com/", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"}
for i in c:
    nurl = url +i+ '~'
    r = s.get(nurl,proxies=proxies)
    if str(r) != '<Response [404]>':
        print nurl
        sys.stdout.flush()
    for j in range(0,len(a)):
        nurl = url + i +'.'+ a[j]
        r = s.get(nurl, proxies=proxies)
        if str(r) != '<Response [404]>':
            print nurl
            sys.stdout.flush()
    for j in range(0, len(b)):
        nurl = url + '.'+ i +'.'+ b[j]
        r = s.get(nurl, proxies=proxies)
        if str(r) != '<Response [404]>':
            print nurl
            sys.stdout.flush()
print 'finish'[/hide]

运行之后就会得到:

打开链接发现是应该可以下载的文件并且文件是以.swp为后缀名
关于.swp文件:
使用vi,经常可以看到.swp这个文件。那这个文件是怎么产生的呢,当打开一个文件,vi就会生成这么一个.(filename)swp文件 以备不测(比如非正常退出),如果你正常退出,那么这个这个.swp文件将会自动删除
怎么恢复.swp
可以使用

 vim -r:命令来查看当前目录下的所有swp文件
vi -r {your file name} :命令恢复文件
rm .{your file name}.swp:命令删除swp文件,不然每一次编辑时总是有这个提示。


就会得到html文档:

看到该题的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">;
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Login Form</title>
<link href="static/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="static/js/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
    $(".username").focus(function() {
        $(".user-icon").css("left","-48px");
    });
    $(".username").blur(function() {
        $(".user-icon").css("left","0px");
    });
    $(".password").focus(function() {
        $(".pass-icon").css("left","-48px");
    });
    $(".password").blur(function() {
        $(".pass-icon").css("left","0px");
    });
});
</script>
</head>
<?php
define("SECRET_KEY", file_get_contents('/root/key'));
define("METHOD", "aes-128-cbc");
session_start();
function get_random_iv(){
    $random_iv='';
    for($i=0;$i<16;$i++){
        $random_iv.=chr(rand(1,255));
    }
    return $random_iv;
}
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));
}
function check_login(){
    if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
        $cipher = base64_decode($_COOKIE['cipher']);
        $iv = base64_decode($_COOKIE["iv"]);
        if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
            $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
            $_SESSION['username'] = $info['username'];
        }else{
            die("ERROR!");
        }
    }
}
function show_homepage(){
    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>';
}
if(isset($_POST['username']) && isset($_POST['password'])){
    $username = (string)$_POST['username'];
    $password = (string)$_POST['password'];
    if($username === 'admin'){
        exit('<p>admin are not allowed to login</p>');
    }else{
        $info = array('username'=>$username,'password'=>$password);
        login($info);
        show_homepage();
    }
}else{
    if(isset($_SESSION["username"])){
        check_login();
        show_homepage();
    }else{
        echo '<body class="login-body">
                <div id="wrapper">
                    <div class="user-icon"></div>
                    <div class="pass-icon"></div>
                    <form name="login-form" class="login-form" action="" method="post">
                        <div class="header">
                        <h1>Login Form</h1>
                        <span>Fill out the form below to login to my super awesome imaginary control panel.</span>
                        </div>
                        <div class="content">
                        <input name="username" type="text" class="input username" value="Username" />
                        <input name="password" type="password" class="input password" value="Password" />
                        </div>
                        <div class="footer">
                        <input type="submit" name="submit" value="Login" class="button" />
                        </div>
                    </form>
                </div>
            </body>';
    }
}
?>
</html>


GO一下可以看到cookie中返回的ivcipher

将输入序列化得s:2:{s:8:"username";s:5:"adcin";s:8:"password";s:3:"123";}
然后每16字节分组得

1: a : 2 : { s : 8 : " u s e r n a
2: m e " ; s : 5 : " a d c i n " ;
3: s : 8 : " p a s s w o r d " ; s
4: 3 : " 1 2 3 " ; }

可见,如果我们想要将2中的c变成m就需要对1中的s进行改变,使用脚本:

[hide]# -*- coding: utf-8 -*-
import base64,urllib def get_newCipher():
    cipher = ''#输入所得cipher
    cipher = base64.b64decode(urllib.unquote(cipher))
    newCipher = cipher[0:x] + chr(ord(cipher[x])^ord('')^ord('')) + cipher[x+1:]#x为需要改变值所在的字节数,第二个ord中为输入值,第三个ord中为目标值
    print urllib.quote(base64.b64encode(newCipher)) def get_newIV():
    cipher = ''#get_newCipher提交后所得的无法反序列化密文
    iv = ''#所得iv
    #cipher = urllib.unquote(cipher)
    cipher = base64.b64decode(cipher)
    iv = base64.b64decode(urllib.unquote(iv))
    newIv = ''
    right = ''#被损坏前正确的明文
    for i in range(16):
        newIv += chr(ord(right[i])^ord(iv[i])^ord(cipher[i]))
    print urllib.quote(base64.b64encode(newIv)) if __name__ == '__main__':
    #get_newCipher()
    #get_newIV()[/i][/i][/i][/hide][i][i][i]


发现新密文无法反序列化,这是因为,我们将c修改成m时破坏1中的结构
于是我们将新得到的密文复制,通过base64解密过后的iv与新密文解密的明文与原1中数据对应异或


提交新的iv和刚才得到的cipher即可

大家有任何问题可以提问,更多文章可到i春秋论坛阅读哟~

于bugku中游荡意外得到关于CBC翻转攻击思路的更多相关文章

  1. CBC翻转攻击(实验吧_简单的登陆题)

    题目链接 http://ctf5.shiyanbar.com/web/jiandan/index.php 有源码在test.php页面 分析代码过程 如果post id,将id转字符串,然后进入sql ...

  2. Padding Oracle 和 CBC字节翻转攻击学习

    以前一直没时间来好好研究下这两种攻击方式,虽然都是很老的点了= =! 0x01:Padding oracle CBC加密模式为分组加密,初始时有初始向量,密钥,以及明文,明文与初始向量异或以后得到中间 ...

  3. SQL SERVER 2008:内部查询处理器错误: 查询处理器在执行过程中遇到意外错误

       今天一个同事突然告诉我,以前跑得很正常的一个SQL语句,执行时突然报如下错误:         消息1222,级别16,状态18,第1 行         已超过了锁请求超时时段.        ...

  4. 关于“System.Data.OleDb.OleDbException,外部数据库驱动程序 (1) 中的意外错误。”的解决方案

    网站之前运行一直很正常,但有一次用户在导入格式为xls的excel文件,发生了错误,跟踪错误后抛出如下的异常: 错误提示: 未处理System.Data.OleDb.OleDbException HR ...

  5. “在注释中遇到意外的文件结束”--记一个令人崩溃的bug

    下午写程序,写的好好的,突然报错"在注释中遇到意外的文件结束". 下面是官方给出的错误原因是缺少注释终结器 (* /). // C1071.cpp int main() { } / ...

  6. 用友u8各版本在输出的时候报错提示:外部数据库驱动程序(1)中的意外错误

    从10月12日起很多U8用户反馈,在各版本U8中输出报表时软件报错,报错内容“外部数据库驱动程序(1)中的意外错误”,经初步分析有以下解决方案:1.卸载微软的补丁:(1)如果是PC操作系统(一般是客户 ...

  7. CBC字节翻转攻击

    iscc2018线上赛开始两周多了,学到了很多,写几篇文章总结一下遇到的知识点,做一个归纳,方便以后查找. web300-----CBC字节翻转攻击 cbc是AES加密的cbc模式 即密码分组链模式: ...

  8. 切记ajax中要带上AntiForgeryToken防止CSRF攻击

    在程序项目中经常看到ajax post数据到服务器没有加上防伪标记,导致CSRF被攻击,下面小编通过本篇文章给大家介绍ajax中要带上AntiForgeryToken防止CSRF攻击,感兴趣的朋友一起 ...

  9. 【转载】【翻译】Breaking things is easy///机器学习中安全与隐私问题(对抗性攻击)

    原文:Breaking things is easy 译文:机器学习中安全与隐私问题(对抗性攻击) 我是通过Infaraway的那篇博文才发现cleverhans-blog的博客的,这是一个很有意思的 ...

随机推荐

  1. linux-kernel-4.4 移植 (3) 网卡移植

    开发环境:win10 64位 + VMware12 + Ubuntu14.04 32位 工具链:linaro提供的gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-g ...

  2. 《笨方法学Python》加分题32

    注意一下 range 的用法.查一下 range 函数并理解它在第 22 行(我的答案),你可以直接将 elements 赋值为 range(0, 6) ,而无需使用 for 循环?在 python ...

  3. 摹客iDoc 新功能“柔性工作流”,让设计随需而动

    摹客iDoc推出了全新“柔性工作流”,让协作设计自由流动,随需而动. 更高效.更自由的协作方式,赶快告诉你的团队吧~ “柔性工作流” VS “普通工作流” 普通工作流往往是将很多东西混杂在一起,并施以 ...

  4. gitlab 修改root密码

    [root@svr34 bin]# gitlab-rails console production Loading production environment (Rails 4.2.5.2) irb ...

  5. ssh多台主机之间不用密码远程

    二.多台服务器相互无密码访问 多台服务器相互无密码访问,与两台服务器单向无密码访问的原理是一样的,只不过由于是多台服务器之间相互无密码访问,不能象两台服务器无密码登录那样直接上传,步骤如下: 1.在需 ...

  6. 关于python,完善我计算机知识的一步。

    因为身为理科男,所以特别喜欢涉及其他领域的知识.而对我来说,计算机是很有诱惑力的--尤其是程序语言设计,懂得一门“外语”是多么的重要.大一时候接触过包括有计算机的基本知识,c语言,这个新的学期也开始接 ...

  7. Chapter5_初始化与清理_数组初始化与可变参数列表

    一.数组初始化 数组是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列.编译器是不允许指定数组的长度的,当使用语句int[] a时,拥有的只是一个符号名,即一个数组的引用,并不拥 ...

  8. node 项目中 koa2 环境搭建 以及项目发布

    环境搭建: 1.Koa 必须使用 7.6 以上的版本.如果你的版本低于这个要求,就要先升级 Node. 查看node版本方法:node -v 2.使用koa-generator生成器生成项目 安装ko ...

  9. JS-MD5加密

    首先,下载MD5文件压缩包 点击下载MD5压缩包 然后,在需要加密的页面引用MD5脚本文件 <script src="js/md5.js" type="text/j ...

  10. IOS 获取系统相册和拍照使用HXPhotoPicker 返回页面时页面上移被nav遮住问题

    解决: - (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated]; self.automaticallyAdj ...