前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Padding Oracle Attack

Padding Oracle Attack

作者头像
回天
发布2023-04-25 15:57:48
6210
发布2023-04-25 15:57:48
举报
文章被收录于专栏:Ga1@xy's W0r1dGa1@xy's W0r1d

CBC模式

CBC(Cipher Block Chaining)即密码分组链接,是一种加密模式。在CBC模式中,每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。

  • 加密流程图
img
img
  • 解密流程图
img
img

由流程图可以看出解密就是加密的逆过程,但有几点图中没有提到:

  1. 在加密前进行明文分组时,通常分为8字节(64bit)或16字节(128bit)一组,当明文长度不是8字节或16字节的整数倍时,在明文的最后会进行填充,通常采用 PKSC #5 或 PKCS #7 填充规则
  2. 我们通常把解密过程中密文与密钥进行 xor 后产生的字符串成为中间值 Intermediary Value,中间值与 IV 进行 xor 得到第一组明文,以此类推

PKCS #5 与 PKCS #7

PKCS #5 与 PKCS #7 的唯一不同就是前者只适用于8字节以内的填充,而后者填充范围包括 0x00~0xff

以 PKCS #5 为例,将明文填充到 8 字节的整数倍,如果明文已经满足 8 字节的整数倍,那就在明文的最后再添加 8 字节的填充,而填充的内容取决于需要填充的长度,如果需要填充 7 个字节,那就要填充 7 个 0x07,如果明文已经满足 8 字节的整数倍,那就在明文的最后再填充 8 个 0x08

DES算法进行加密时的填充规则是 PKCS #5、填充最多 8 位,而AES算法进行加密时的填充规则是 PKCS #7、填充最多 16 位。

Padding Oracle

Padding 意为填充,Oracle 在此意为提示,在对密文进行解密的过程中,如果解密得到的结果末尾不符合填充规则,那通常相应的解密库会抛出一个异常,提示填充不正确。简单来说,Padding Oracle 就是提示数据不符合填充规则的意思。

攻击详解

Padding Oracle Attack,顾名思义,就是根据返回给我们填充数据是否符合规则的提示进行攻击的方式,此种攻击方式有几个前提条件

  • 攻击者已知密文及初始向量 IV,并且已知服务端使用 CBC模式 进行加密
  • 攻击者能够向服务端提交密文数据并触发解密操作,攻击者能够根据服务端的返回值判断解密是否正常

基本原理

已知服务端可以根据检测填充是否正确来为我们返回不同的值,即可以实现 Padding Oracle,那么我们就可以根据其不同的返回值不断构造初始向量 IV 来爆破中间值(Intermediary Value),例如

  • 已知第一组密文:813EC9D944A5C8347A7CA69AA34D8DC0
  • 已知初始向量 IV:9F0B13944841A832B2421B9EAF6D9836

由于填充是在每个明文的末尾位置,所以我们构造 IV 需要从结尾开始,当填充为 0x01 时,按照填充规则,只填充末尾最后一位,此时如果服务器返回解密正确,则明文的形式应该为 ******************************01,那么我们从 0x00~0xff 爆破最后一位的 IV,得到当最后一位为 0x17 时解密正确,即

代码语言:javascript
复制
Padding: 0x01
iv:      00000000000000000000000000000017
plain:   ******************************01

此时我们利用填充位 xor 构造的 IV 对应位,即可得到正确的中间值,因为在密文不变的情况下,解密得到的中间值是始终不变的

代码语言:javascript
复制
Padding: 0x01
iv:      00000000000000000000000000000017
IValue:  00000000000000000000000000000016
plain:   ******************************01

经过第一轮的爆破,我们已知了中间值的最后一位,那当我们开始第二轮爆破时,就可以预先通过已知的中间值与本轮的填充计算出 IV 的已知位

代码语言:javascript
复制
Padding: 0x02
iv:      00000000000000000000000000000014
IValue:  00000000000000000000000000000016
plain:   ******************************02

再通过爆破倒数第二位的 IV,计算出倒数第二位的中间值

代码语言:javascript
复制
Padding: 0x02
iv:      0000000000000000000000000000f414
IValue:  0000000000000000000000000000f616
plain:   ****************************0202

依次类推,我们就可以爆破出完整的中间值

代码语言:javascript
复制
Padding: 0x10
iv:      d67a7aa57808d75782356efa9f1ce606
Ivalue:  c66a6ab56818c74792257eea8f0cf616
plain:   10101010101010101010101010101010

注:上述 plain 不是密文正确解密得到的明文,只是我们通过构造让服务器认为解密正确得到的明文

当我们得到一整个完整的中间值时,根据 CBC模式 的解密流程,我们将中间值 xor IV 即可得到正确的明文

代码语言:javascript
复制
IValue:  c66a6ab56818c74792257eea8f0cf616
IV:      9F0B13944841A832B2421B9EAF6D9836
plain:   5961792120596F752067657420616E20
text:    "Yay! You get an "

代码实现

爆破 IValue 部分

代码语言:javascript
复制
    for l in range(length / 2): # 爆破每一位 Ivalue (0~15),总长度依次叠加
        iv = ''
        padding = l + 1 # 1~16
        for ll in range(l): # 根据已知 Ivalue 修改 iv
            iv += hex(ord(Ivalue.decode('hex')[ll]) ^ padding)[2:].zfill(2)
        
        for iv_test in range(256):
            iv = iv[0 : l * 2]
            iv += hex(iv_test)[2:].zfill(2)
            #print iv
            iv = iv.ljust(length, '0')
            #print iv
            data = iv.decode('hex')[::-1].encode('hex') + Cry[flag] 
            ctext = [(int(data[i:i+2],16)) for i in range(0, len(data), 2)]
            rc = Oracle_Send(ctext, 2)
            if str(rc) == '1': # padding 正确。根据 padding 值和此时 iv 计算 对应位置 Ivalue
                Ivalue += hex(padding ^ iv_test)[2:].zfill(2)
                print "Ivalue: ", Ivalue.ljust(length, '0').decode('hex')[::-1].encode('hex')
                break
        print "iv:     ", iv.decode('hex')[::-1].encode('hex')
        print '-' * 50

由于实际解密时填充从末尾开始,我们为了方便字符串操作选择先正向叠加,在和需要解密的密文拼接在一起之前再逆序(题目背景是给服务器上传一段16进制字符串密文,服务器会将前一半密文当做后一半密文解密的IV,当服务端返回值为 '1' 时,意为解密正确,即明文填充无误)

完整代码

代码语言:javascript
复制
# coding=utf-8
from oracle import *

c = '9F0B13944841A832B2421B9EAF6D9836813EC9D944A5C8347A7CA69AA34D8DC0DF70E343C4000A2AE35874CE75E64C31'
block_num = 3
length = len(c) / block_num
Cry = []
for i in range(block_num):
    Cry.append(c[i * length : (i + 1) * length])
#print Cry[0], Cry[1], Cry[2]
Oracle_Connect()
# iv = ‘9F0B13944841A832B2421B9EAF6D9836’
# cry1 = '813EC9D944A5C8347A7CA69AA34D8DC0'
# cry2 = 'DF70E343C4000A2AE35874CE75E64C31'
mess = ''
flag = 1
for i in range(1, block_num):
    IV = Cry[i - 1].decode('hex')
    Ivalue = ''
    for l in range(length / 2): # 爆破每一位 Ivalue (0~15),总长度依次叠加
        iv = ''
        padding = l + 1 # 1~16
        for ll in range(l): # 根据已知 Ivalue 修改 iv
            iv += hex(ord(Ivalue.decode('hex')[ll]) ^ padding)[2:].zfill(2)
        
        for iv_test in range(256):
            iv = iv[0 : l * 2]
            iv += hex(iv_test)[2:].zfill(2)
            #print iv
            iv = iv.ljust(length, '0')
            #print iv
            data = iv.decode('hex')[::-1].encode('hex') + Cry[flag] 
            ctext = [(int(data[i:i+2],16)) for i in range(0, len(data), 2)]
            rc = Oracle_Send(ctext, 2)
            if str(rc) == '1': # padding 正确。根据 padding 值和此时 iv 计算 对应位置 Ivalue
                Ivalue += hex(padding ^ iv_test)[2:].zfill(2)
                print "Ivalue: ", Ivalue.ljust(length, '0').decode('hex')[::-1].encode('hex')
                break
        print "iv:     ", iv.decode('hex')[::-1].encode('hex')
        print '-' * 50
    Ivalue = Ivalue.decode('hex')[::-1]
    mess += "".join(chr(ord(x) ^ ord(y)) for x, y in zip(Ivalue, IV))
    print '=' * 70, '\n', mess, '\n', '=' * 70
    flag += 1

Oracle_Disconnect()
print mess

完整输出

代码语言:javascript
复制
Connected to server successfully.
Ivalue:  00000000000000000000000000000016
iv:      00000000000000000000000000000017
--------------------------------------------------
Ivalue:  0000000000000000000000000000f616
iv:      0000000000000000000000000000f414
--------------------------------------------------
Ivalue:  000000000000000000000000000cf616
iv:      000000000000000000000000000ff515
--------------------------------------------------
Ivalue:  0000000000000000000000008f0cf616
iv:      0000000000000000000000008b08f212
--------------------------------------------------
Ivalue:  0000000000000000000000ea8f0cf616
iv:      0000000000000000000000ef8a09f313
--------------------------------------------------
Ivalue:  000000000000000000007eea8f0cf616
iv:      0000000000000000000078ec890af010
--------------------------------------------------
Ivalue:  000000000000000000257eea8f0cf616
iv:      0000000000000000002279ed880bf111
--------------------------------------------------
Ivalue:  000000000000000092257eea8f0cf616
iv:      00000000000000009a2d76e28704fe1e
--------------------------------------------------
Ivalue:  000000000000004792257eea8f0cf616
iv:      000000000000004e9b2c77e38605ff1f
--------------------------------------------------
Ivalue:  000000000000c74792257eea8f0cf616
iv:      000000000000cd4d982f74e08506fc1c
--------------------------------------------------
Ivalue:  000000000018c74792257eea8f0cf616
iv:      000000000013cc4c992e75e18407fd1d
--------------------------------------------------
Ivalue:  000000006818c74792257eea8f0cf616
iv:      000000006414cb4b9e2972e68300fa1a
--------------------------------------------------
Ivalue:  000000b56818c74792257eea8f0cf616
iv:      000000b86515ca4a9f2873e78201fb1b
--------------------------------------------------
Ivalue:  00006ab56818c74792257eea8f0cf616
iv:      000064bb6616c9499c2b70e48102f818
--------------------------------------------------
Ivalue:  006a6ab56818c74792257eea8f0cf616
iv:      006565ba6717c8489d2a71e58003f919
--------------------------------------------------
Ivalue:  c66a6ab56818c74792257eea8f0cf616
iv:      d67a7aa57808d75782356efa9f1ce606
--------------------------------------------------
====================================================================== 
Yay! You get an  
======================================================================
Ivalue:  000000000000000000000000000000cb
iv:      000000000000000000000000000000ca
--------------------------------------------------
Ivalue:  000000000000000000000000000086cb
iv:      000000000000000000000000000084c9
--------------------------------------------------
Ivalue:  000000000000000000000000004686cb
iv:      000000000000000000000000004585c8
--------------------------------------------------
Ivalue:  000000000000000000000000a84686cb
iv:      000000000000000000000000ac4282cf
--------------------------------------------------
Ivalue:  000000000000000000000091a84686cb
iv:      000000000000000000000094ad4383ce
--------------------------------------------------
Ivalue:  00000000000000000000ad91a84686cb
iv:      00000000000000000000ab97ae4080cd
--------------------------------------------------
Ivalue:  00000000000000000077ad91a84686cb
iv:      00000000000000000070aa96af4181cc
--------------------------------------------------
Ivalue:  00000000000000007177ad91a84686cb
iv:      0000000000000000797fa599a04e8ec3
--------------------------------------------------
Ivalue:  000000000000003f7177ad91a84686cb
iv:      0000000000000036787ea498a14f8fc2
--------------------------------------------------
Ivalue:  000000000000c33f7177ad91a84686cb
iv:      000000000000c9357b7da79ba24c8cc1
--------------------------------------------------
Ivalue:  0000000000aec33f7177ad91a84686cb
iv:      0000000000a5c8347a7ca69aa34d8dc0
--------------------------------------------------
Ivalue:  000000006daec33f7177ad91a84686cb
iv:      0000000061a2cf337d7ba19da44a8ac7
--------------------------------------------------
Ivalue:  000000e46daec33f7177ad91a84686cb
iv:      000000e960a3ce327c7aa09ca54b8bc6                                                                                       
--------------------------------------------------                                                                               
Ivalue:  0000e9e46daec33f7177ad91a84686cb
iv:      0000e7ea63a0cd317f79a39fa64888c5
--------------------------------------------------
Ivalue:  0010e9e46daec33f7177ad91a84686cb
iv:      001fe6eb62a1cc307e78a29ea74989c4
--------------------------------------------------
Ivalue:  c010e9e46daec33f7177ad91a84686cb
iv:      d000f9f47dbed32f6167bd81b85696db
--------------------------------------------------
====================================================================== 
Yay! You get an A. =)
======================================================================
Connection closed successfully.
Yay! You get an A. =)

参考文章

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CBC模式
  • PKCS #5 与 PKCS #7
  • Padding Oracle
  • 攻击详解
    • 基本原理
      • 代码实现
      • 参考文章
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档