您当前的位置: 首页 > 

合天网安实验室

暂无认证

  • 0浏览

    0关注

    748博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

通过一道题了解CBC翻转攻击

合天网安实验室 发布时间:2018-03-16 17:32:43 ,浏览量:0

走过路过,不要错过这个公众号哦!

CBC翻转攻击方法的精髓在于:

 

通过损坏密文字节来改变明文字节。(注:借助CBC内部的模式)借由此可以绕过过滤器,或者改变用户权限提升至管理员,又或者改变应用程序预期明文以尽猥琐之事。

 

下面介绍一下CBC字节翻转攻击的原理:

这是CBC加密的原理图:

Plaintext:待加密的。

IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。

Key:被一些如AES的对称加密算法使用。

Ciphertext:加密后的数据。

在这里重要的一点是,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,就可以得到一个不同的明文,而这个明文是我们可以控制的。利用这一点,我们就欺骗服务端或者绕过过滤器。

 

具体怎么翻转呢,因为涉及到异或,这里稍微介绍下异或的概念:

当我们的一个值C是由A和B异或得到

C = A XOR B

那么

A XOR B XOR C很明显是=0的

当我们知道B和C之后,想要得到A的值也很容易

A = B XOR C

因此,A XOR B XOR C等于0。有了这个公式,我们可以在XOR运算的末尾处设置我们自己的值,即可改变。

下面以一道例题作为说明

http://118.89.219.210:49168/index.php

首先,尝试用常见的用户名测试一下,root,user,admin等

当登录其他的用户名时,返回来了提示only admin can see flag

当尝试用admin登录时,却说admin不允许登录

接着尝试看看是否存在注入,可是都返回一样的信息,这时候思路需要转换一下,肯定有条路走,不然这道题做不下去,这时候要考虑是不是存在某些提示,比如源码,扫一遍常见的敏感路径,最后发现.index.php.swp存在,下载下来。

关于swp文件:

使用vi,经常可以看到swp这个文件。那这个文件是怎么产生的呢,当打开一个文件,vi就会生成这么一个.(filename)swp文件 以备不测(比如非正常退出),如果你正常退出,那么这个这个swp文件将会自动删除 。

 

怎么恢复.swp:

可以使用

vi -r {your file name}

来恢复文件,然后用下面的命令删除swp文件,不然每一次编辑时总是有这个提示。

rm .{your file name}.swp

输入7,即可恢复

看到该题的代码

;

Login Form

$(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");

    });

});

从代码中可以看出考察的是cbc字节反转攻击,而且是用了及其简单的CBC。

 

仔细审计代码

我们先发送正常请求

username=zdmin&password=12345

bp查看返回包

把里面的cipher进行翻转下面是自己写的脚本

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Date    : 2018-03-15 11:45:57

# @Author  : Mr.zhang(s4ad0w.protonmail.com)

# @Link    : http://blog.csdn.net/csu_vc

import base64

import requests

import urllib

iv_raw='%2F8iEm4jh%2BjbgVGwlQ31ycg%3D%3D'  #这里填写第一次返回的iv值

cipher_raw='8WdhbPxjZy9xYAgoCeghiOUQu0ri1Y3dv7cX44MbvOfIC6zZxCbR%2FPFpeMatL5qIgT%2BYA66tIdCBpxtWsWxV9Q%3D%3D'  #这里填写第一次返回的cipher值

print "[*]原始iv和cipher"

print "iv_raw:  " + iv_raw

print "cipher_raw:  " + cipher_raw

print "[*]对cipher解码,进行反转"

cipher = base64.b64decode(urllib.unquote(cipher_raw))

#a:2:{s:8:"username";s:5:"zdmin";s:8:"password";s:5:"12345"}

#s:2:{s:8:"userna

#me";s:5:"zdmin";

#s:8:"password";s

#:3:"12345";}

xor_cipher = cipher[0:9] +  chr(ord(cipher[9]) ^ ord('m') ^ ord('a')) + cipher[10:]  #请根据你的输入自行更改,原理看上面的介绍

xor_cipher=urllib.quote(base64.b64encode(xor_cipher))

print "反转后的cipher:" + xor_cipher

然后再bp中的cookie中设置iv和翻转后的cipher,注意,这里要把post的数据清空,否则会重复开始的流程,就进不了这个流程了

服务器提示反序列化失败,但是其实我们这个时候只要对这个进行base64解码就会发现,我们的username已经变成了admin

 原因是在我们为了修改mdmin为admin的时候,是通过修改第一块数据来修改的,所以第一个块数据(16字节)被破坏了。因为程序中要求username要等于admin所以不能利用文章里的说的填充字符。 又因为是第一个块数据被破坏,第一个块数据是和IV有关,所以只要将在CBC字符翻转攻击,得到新的IV就可以修复第一块数据。

具体办法如下

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Date    : 2018-03-15 11:56:20

# @Author  : csu_vc(s4ad0w.protonmail.com)

# @Link    : http://blog.csdn.net/csu_vc

import base64

import urllib

cipher = 'Bc6oENSSAEPpPdv/rbqRZG1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9'#填写提交后所得的无法反序列化密文

iv = '%2F8iEm4jh%2BjbgVGwlQ31ycg%3D%3D'#一开始提交的iv

#cipher = urllib.unquote(cipher)

cipher = base64.b64decode(cipher)

iv = base64.b64decode(urllib.unquote(iv))

newIv = ''

right = 'a:2:{s:8:"userna'#被损坏前正确的明文

for i in range(16):

    newIv += chr(ord(right[i])^ord(iv[i])^ord(cipher[i])) #这一步相当于把原来iv中不匹配的部分修改过来

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

把得到的新的修复的iv值替换掉,cipher仍然为翻转后的cipher

提交,就可以成功进去

至于序列化的知识:

因为不是这个主题的内容就,不详细介绍了,感兴趣可以百度。

后记:

这道题涉及到的一些密码学的概念和序列化的知识。本人也是通过反复测试,对照代码,查看自己进入到了哪一步的流程,尝试了很多次,一步一步才得到最终答案,过程虽然麻烦,但是很有意思。菜鸡上路,各位大佬勿喷,只是记录下自己的思路,欢迎大佬们指出错误。

声明:

本文章是为了普及网络安全知识,提高小伙伴的密码学的概念和序列化的知识等,若读者因此做出危害网络安全的行为后果自负,与合天智汇以及本文作者无关,特此声明!

看不过瘾?合天2017年度干货精华请点击《【精华】2017年度合天网安干货集锦》

别忘了投稿哟!!!

合天公众号开启原创投稿啦!!!

大家有好的技术原创文章。

欢迎投稿至邮箱:edu@heetian.com;

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予100元-500元不等的稿费哟。

有才能的你快来投稿吧!

重金悬赏 | 合天原创投稿等你来!(点击了解投稿详情)

    合天智汇

网址 : www.heetian.com

电话:4006-123-731

长按图片,据说只有颜值高的人才能识别哦→

关注
打赏
1665306545
查看更多评论
立即登录/注册

微信扫码登录

0.0411s