前段时间遇到一个挺有意思的题目,用到了padding oracle attack的相关知识,于是恶补了一下padding oracle attack相关内容,本着取之于民用之于民同时也可以方便自己以后复习的心态,我决定整理一下这几天的所学所得,也算是留下点什么hhh。

前面两篇文章简单介绍了padding oracle attack需要事先了解的一些知识,以便于理解,现在终于进入正题了hhh。下面我就我自己的理解说一下padding oracle attack的实现原理以及过程。

Padding Oracle Attack是针对CBC链接模式的攻击,和具体的加密算法无关,换句话说,这种攻击方式不是对加密算法的攻击,而是利用了算法的使用不当,进行的攻击。选择DES为例进行阐述,假设明文为: LittleHann(明文长度为10 8 < 10 < 16 即使用2个分组)经过DES加密(CBC模式)后,其密文为: EFC2807233F9D7C097116BB33E813C5E

如上图所示,padding oracle攻击其实就是通过服务器的返回值判断自己构建的IV值对不对,进而猜测出正确的中间值Intermediary Value,中间值再和获取到的原本的IV值异或便可得到明文,因此攻击成立的两个重要假设前提:
(1)  攻击者能够获得密文(Ciphertext),以及附带在密文前面的IV(初始化向量)
(2)  攻击者能够触发密文的解密过程,且能够知道密文的解密结果

这里有几个概念要先理清一下:
(1)基于密码学算法的攻击,往往第一个要搞清楚的是,我们在攻击谁,或者准确的说我们的攻击点在哪里?在一个密码学算法中,有很多的参数(指攻击者可以控制的参数),攻击者往往是针对其中某一个或某一些参数进行破解,穷举等攻击。在Padding Oracle Attack攻击中,攻击者输入的参数是IV+Cipher,我们要通过对IV的”穷举”来请求服务器端对我们指定的Cipher进行解密,并对返回的结果进行判断。
(2)和SQL注入中的Blind Inject思想类似。Padding Oracle Attack也是利用了这个二值逻辑的推理原理,或者说这是一种”边信道攻击(Side channel attack)”。这种漏洞不能算是密码学算法本身的漏洞,但是当这种算法在实际生产环境中使用不当就会造成问题。和盲注一样,这种二值逻辑的推理关键是要找到一个”区分点”,即能被攻击者用来区分这个的输入是否达到了目的(在这里就是寻找正确的IV)。 在web应用中,如果Padding不正确,则应用程序很可能会返回500的错误(程序执行错误);如果Padding正确,但解密出来的内容不正确,则可能会返回200的自定义错误,所以,这种区别就可以成为一个二值逻辑的”注入点”。
(4)明文分组和填充就是Padding Oracle Attack的根源所在,但是这些需要一个前提,那就是应用程序对异常的处理。当提交的加密后的数据中出现错误的填充信息时,不够健壮的应用程序解密时报错,直接抛出”填充错误”异常信息(这个错误信息在不同的应用中是不同的体现,在web一般是报500错误)。攻击者就是利用这个异常来做一些事情,假设有这样一个场景,一个WEB程序接受一个加密后的字符串作为参数,这个参数包含用户名、密码。参数加密使。攻击者只需要提交错误的密文,根据HTTP Code即可做出攻击。

下面就我做的这个题目说明一下padding oracle attack的大概思路:

首先,我们要明确目的——找到正确的中间值,进而得到明文。我们先回忆一下CBC模式解密的过程,如下图:

从图中我们可以看出,第n-1块密文是与第n块密文中间值异或的IV值。根据PKCS #5标准,我们知道,填充N位需在明文后面加上n个0xN,同时我们还知道明文最后一定有填充值,也就是说倒数第二块密文和最后一块密文的中间值异或得到的值最后N位(0<N<密文分组长度)是0xN,而服务器判断正误就是通过最后一组密文解密后的最后几位是不是0xN,如果是就会返回正确不是则会返回错误(总之是两种不同的返回值)。因此,我们可以先假设最后一组密文只填充了一位,也就是说最后明文的最后一位是0x1,我们只需随意构造一个IV值,对IV值的最后一位从0x01到0x10(这是以AES为例,AES每个分组的长度为16字节)逐个赋值并依次提交,当服务器返回值不是错误时,此时取到的最后一位IV值与最后一组密文中间值的最后一位相异或得到的明文是0x01,把这个IV值与0x01相异或即可得到最后一位中间值。然后假设填充了两位,先用得到的中间值和0x02异或得到IV值的最后一位,然后构造IV值的倒数第二位,取值范围也是0x01到0x10,服务器返回值不是错误的时候,倒数第二位IV值与最后一块密文中间值的倒数第二位异或得到的值是0x02,把倒数第二位IV值与0x02异或便可得到倒数第二位中间值。以此类推,逐位试出所有的中间值,把得到的中间值与倒数第二块密文相异或便可得到明文了。

这样说看上去很乱,下面我就题目再捋一下padding oracle attack的过程:

(1)待破解的密文为9F0B13944841A832B2421B9EAF6D9836813EC9D944A5C8347A7CA69AA34D8DC0DF70E343C4000A2AE35874CE75E64C31,采用了CBC模式下的AES算法加密,下面是服务器的登录程序(python):

s = Nonedef Oracle_Connect():import socketglobal ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)try:s.connect(('128.8.130.16', 49101))except socket.error as e:print (e)return -1print ("Connected to server successfully.")return 0def Oracle_Disconnect():if not s:print ("[WARNING]: You haven't connected to the server yet.")return -1s.close()print ("Connection closed successfully.")return 0# Packet Structure: < num_blocks(1) || ciphertext(16*num_blocks) || null-terminator(1) >
def Oracle_Send(ctext, num_blocks):if not s:print ("[WARNING]: You haven't connected to the server yet.")return -1msg = ctext[:]msg.insert(0, num_blocks)msg.append(0)s.send(bytearray(msg))recvbit = s.recv(2)try:return int(recvbit)except ValueError as e:return int(recvbit[0])

(2)首先根据AES算法的标准,我们把密文分组,每16字节为一组,可以分为三组,并且新建用于IV值构造的IV列表和用于存放明文的P列表

data = "9F0B13944841A832B2421B9EAF6D9836813EC9D944A5C8347A7CA69AA34D8DC0DF70E343C4000A2AE35874CE75E64C31"ctext = [(int(data[i:i+2],16)) for i in range(0, len(data), 2)]
C = [ctext[:16], ctext[16:32], ctext[-16:]]
P = [[0] * 16, [0] * 16, [0] * 16]
IV = [[0] * 16, [0] * 16, [0] * 16]

(3)重复向服务器提交密文,猜测正确的明文加密后的中间值(Intermediary Value),得到正确的中间值后,和已知的IV值互相异或便可以得到明文:

Oracle_Connect()
for bi in range(2):#循环两次,解密两个密文块(有一块密文块是IV值)b = 2 - bifor k in range(16):#K+1代表padding的个数,例如K=0时填充1位,服务器异或得到的值应该为0x01if b == 2:C1 = [C[0][:], C[1][:], C[2][:]]#解密C[2]对应的密文块,C[1]是IV值if b == 1:C1 = [C[0][:], C[1][:]]#解密C[1]对应的密文块,C[0]是IV值pos = 15 - k#pos对应的是IV值的第pos-1位for i in range(pos):            C1[b-1][i] = randrange(256)#构造IV值,从第0位到第pos—1位,随机填入0到255(即0x00到0xFF)中的一个数字#剩下K+1位用于循环猜测for i in range(pos + 1, 16):C1[b-1][i] = (k + 1) ^ IV[b][i]#得到正确的中间值后存入IV,并将正确的中间值和K+1异或,#保证每次只循环猜测第pos-1位IV值ii = -1for i in range(256):#循环猜测IV值,正确的IV值满足与正确中间值异或得到的数是0x(K+1)C1[b-1][pos] = iif b == 2:rc = Oracle_Send(C1[0][:] + C1[1][:] + C1[2][:], 3)if b == 1:rc = Oracle_Send(C1[0][:] + C1[1][:], 2)if rc == 1:ii = i#ii即正确的中间值与0x(K+1)异或得到的IV值breakIV[b][pos] = ii ^ (k + 1)#IV值与K+1异或便可得到正确的中间值P[b][pos] = C[b-1][pos] ^ IV[b][pos]#中间值与原来的IV值异或便可得到对应位的明文
Oracle_Disconnect()

这样我们便能得到正确的明文了:

完整的解题源码如下:

from oracle import *
import sys
from random import randrangedata = "9F0B13944841A832B2421B9EAF6D9836813EC9D944A5C8347A7CA69AA34D8DC0DF70E343C4000A2AE35874CE75E64C31"ctext = [(int(data[i:i+2],16)) for i in range(0, len(data), 2)]
C = [ctext[:16], ctext[16:32], ctext[-16:]]
P = [[0] * 16, [0] * 16, [0] * 16]
IV = [[0] * 16, [0] * 16, [0] * 16]Oracle_Connect()
for bi in range(2):#循环两次,解密两个密文块(有一块密文块是IV值)b = 2 - bifor k in range(16):#K+1代表padding的个数,例如K=0时填充1位,服务器异或得到的值应该为0x01if b == 2:C1 = [C[0][:], C[1][:], C[2][:]]#解密C[2]对应的密文块,C[1]是IV值if b == 1:C1 = [C[0][:], C[1][:]]#解密C[1]对应的密文块,C[0]是IV值pos = 15 - k#pos对应的是IV值的第pos-1位for i in range(pos):            C1[b-1][i] = randrange(256)#构造IV值,从第0位到第pos—1位,随机填入0到255(即0x00到0xFF)中的一个数字#剩下K+1位用于循环猜测for i in range(pos + 1, 16):C1[b-1][i] = (k + 1) ^ IV[b][i]#得到正确的中间值后存入IV,并将正确的中间值和K+1异或,#保证每次只循环猜测第pos-1位IV值ii = -1for i in range(256):#循环猜测IV值,正确的IV值满足与正确中间值异或得到的数是0x(K+1)C1[b-1][pos] = iif b == 2:rc = Oracle_Send(C1[0][:] + C1[1][:] + C1[2][:], 3)if b == 1:rc = Oracle_Send(C1[0][:] + C1[1][:], 2)if rc == 1:ii = i#ii即正确的中间值与0x(K+1)异或得到的IV值breakIV[b][pos] = ii ^ (k + 1)#IV值与K+1异或便可得到正确的中间值P[b][pos] = C[b-1][pos] ^ IV[b][pos]#中间值与原来的IV值异或便可得到对应位的明文
Oracle_Disconnect()
print (P[1])
print (P[2])
print (map(lambda x: str(unichr(x)), P[1]))
print (map(lambda x: str(unichr(x)), P[2]))a = ""
print (("the text is: %s") % a.join(text))

padding oracle attack相关之padding oracle attack相关推荐

  1. oracle wallet相关的bug|oracle wallet使用注意事项|ORA-28374: typed master key not found in wa

    ### Code Reference URL:https://blog.csdn.net/cpongo6/article/details/88793610 DESC:oracle wallet相关的b ...

  2. Oracle 性能相关常用脚本(SQL)

    在缺乏的可视化工具来监控数据库性能的情形下,常用的脚本就派上用场了,下面提供几个关于Oracle性能相关的脚本供大家参考.以下脚本均在Oracle 10g测试通过,Oracle 11g可能要做相应调整 ...

  3. oracle查看相关用户表

    oracle查看相关用户表 select TABLE_NAME from user_tables  //当前用户表 select TABLE_NAME from dba_tables  //所有用户表 ...

  4. oracle数据库各组件介绍,Oracle 数据库 组件相关说明【第一部分】

    参考MOS文档: Information On Installed Database Components and Schemas (文档 ID 472937.1) Oracle 组件可以通过下面的S ...

  5. oracle adjusting parallel,Oracle 并行相关的初始化参数

    Oracle数据库并行操作,特别是在RAC环境,一定程度上能够提升数据库的性能,所以对相关的初始化参数的了解是必要的,这篇文章将根据实际的案例讨论Oracle数据库的部分并行参数. Oracle数据库 ...

  6. Zabbix如何通过ODBC对接Oracle获取相关数据

    转载来源 :https://mp.weixin.qq.com/s/PNl3c8frgqIYjDnVsQALHA 目 录 什么是ODBC及其主要功能 安装Oracle-instantclient 配置S ...

  7. Oracle序列相关命令

    Oracle序列相关命令 1.Oracle创建序列命令 2.Oracle序列查询命令 3.Oracle序列删除命令 4.Oracle序列实际应用 5.注意事项 1.Oracle创建序列命令 CREAT ...

  8. 关于 Oracle ACFS 相关知识的简单学习

    作者 | JiekeXu 来源 | JiekeXu之路(ID: JiekeXu_IT) 转载请联系授权 | (微信ID:xxq1426321293) 大家好,我是 JiekeXu,很高兴又和大家见面了 ...

  9. Oracle字符集相关知识

    Oracle的字符集命名遵循以下命名规则: <Language><bit size><encoding>     AL32UTF8/AL16UTF16/ZHS16G ...

最新文章

  1. php增删改查前后端分离,前后端分离之前端增删改查
  2. PHP使用文件锁解决高并发问题示例
  3. Akka实战:HTTP大文件断点上传、下载,秒传
  4. 树莓派3b python3.6.1 SSL模块调用不起来的坑
  5. Quadratic equation(二次剩余)2019牛客多校第九场
  6. android 本地图片分享,Android 把图片保存到本地相册
  7. 算法学习总结(八):计数排序
  8. Decision Tree(DT)决策树
  9. Spark 异步Action
  10. 虚拟地球原理与实现(转载)
  11. SQL63 刷题通过的题目排名
  12. Screaming Frog SEO Spider for Mac进行网页抓取和数据提取的技巧
  13. mysql用binlog回复_mysql binlog回复数据,亲测
  14. IEEE Access模板caption无法换行
  15. 多线段几何图形—— 简单几何图形(求几何图形面积)
  16. SFP+光纤模块使用
  17. Set集合:求交集、并集和差集
  18. PHP 出现 The requested URL was not found on this server 怎么办?
  19. html5拼图游戏canvas,canvas拼图游戏
  20. IP协议详解之IPv6头部结构简介

热门文章

  1. 基于PaddleHub的QQ聊天机器人
  2. grub启动iso,img
  3. office办公软件有哪些:试试OnlyOffice(Office办公软件)官网中文版吧 | 使用简单无需onlyoffice使用教程
  4. ArcGIS基础:相同空间人口图层的人口数量字段转移至小区图层(核心:相交操作)及制作人口密度专题图
  5. 基于stm32单片机单相用电器分析电流电压功率因子监测装置
  6. 高级sql学习——with子句!!!
  7. android apk 反编译,修改version后重新打包
  8. log4jdbc简介
  9. Python爬虫学习,批量爬取下载抖音视频
  10. 蓝牙电话之PBAP同步电话簿的安卓实现