Padding oracle attack!

1 篇文章 0 订阅

终于补题补到了这个题目!这个也是非常经典的问题了,但是一直没有搞明白,之前鸡哥的讲解已经非常清楚了,忍不住还是想佩服一下4ction。下面还是大概讲一下这个Padding oracle attack到底是个啥,这里采用白帽子上的讲解方式就很好了!

1.基础知识

(1)padding

由于CBC是块密码工作模式, 所以要求明文长度必须是块长度的整数倍.
对于不满足的数据, 会进行数据填充到满足整数倍. 即 padding,格式如下

** ** ** ** ** ** ** 01
** ** ** ** ** ** 02 02
** ** ** ** ** 03 03 03
** ** ** ** 04 04 04 04
** ** ** 05 05 05 05 05
** ** 06 06 06 06 06 06
** 07 07 07 07 07 07 07
08 08 08 08 08 08 08 08

当然这里是64位为一块的情况,其他的情况自行分析

(2)CBC分组密码的链接模式

这里写图片描述

CBC模式加密流程图

这里写图片描述

CBC模式解密流程图

理解以上两张图以后还需要知道以下这张图中的IV的意思,中间值,也是我们解密过程中最后的需要抑或的地方

这里写图片描述

这个的认识非常关键!下买你讲一下攻击的原理

    在Padding Oracle Attack攻击中,攻击者输入的参数是IV+Cipher,我们要通过对IV的”穷举”来请求服务器端对我们指定的Cipher进行解密,并对返回的结果进行判断。

    和SQL注入中的Blind Inject思想类似。我觉得Padding Oracle Attack也是利用了这个二值逻辑的推理原理,或者说这是一种”边信道攻击(Side channel attack)”

2.攻击条件

二者缺一不可

1.可以控制密文 或者 IV
2.如果解密后不满足 padding 服务端会报错.

然后这里需要搞清楚到底是怎样猜解,具体比较复杂,不多讲了。总之就是控制IV在解密的过程中寻找成功解密的IV值,并且根据填充的内容确定中间值。至于我们需要的明文只要中间值和原有的IV抑或一下就有了(本人就坑在这几个变量的关系上)

3.一个例子

题目来自于第三届上海大学生网络安全大赛中的is_aes_secure密码题目,题目中明显就是了利用此漏洞,给定一个rb,贴一下代码如下

#!/usr/bin/ruby -w
require 'openssl'
require 'base64'

def banner()
    puts ' ____________________________________________'
    puts '|                                            |'
    puts '| Welcome to our secure communication system |'
    puts '| Our system is secured by AES               |'    
    puts '| So...No key! No Message!                   |'
    puts '|____________________________________________|'
    puts ''
end

def option()
    puts '1. Get the secret message.'
    puts '2. Encrypt the message'
    puts '3. Decrypt the message.'
    puts 'Give your option:'
    STDOUT.flush
    op=gets
    return op.to_i
end

def init()
    file_key=File.new("./aeskey","r")
    $key=file_key.gets
    file_key.close()
end
def aes_encrypt(iv,data)
    cipher = OpenSSL::Cipher::AES.new(256, :CBC)
    cipher.encrypt
    cipher.key = $key
    cipher.iv  =  iv
    cipher.update(data) << cipher.final
end

def aes_decrypt(iv,data)
    cipher = OpenSSL::Cipher::AES.new(256, :CBC)
    cipher.decrypt
    cipher.key = $key
    cipher.iv  = iv
    data = cipher.update(data) << cipher.final
end

def output_secret()
    file_secret=File.new("./flag","r")
    secret=file_secret.gets
    puts secret
    file_secret.close
    secret_enc=aes_encrypt("A"*16,secret)
    secret_enc_b64=Base64.encode64(secret_enc)
    puts secret_enc_b64 
    STDOUT.flush
end

init
banner
while true do
    begin
        op=option
        if op==1
            output_secret
        elsif op==2
            puts "IV:"
            STDOUT.flush
            iv=Base64.decode64(gets)
            puts "Data:"
            STDOUT.flush
            data=Base64.decode64(gets)
            data_enc=aes_encrypt iv,data
            puts Base64.encode64(data_enc)
            puts "Encrytion Done"    
            STDOUT.flush
        elsif op==3
            puts "IV:"
            STDOUT.flush
            iv=Base64.decode64(gets)
            puts "Data:"
            STDOUT.flush
            data=Base64.decode64(gets)
            data_dec=aes_decrypt iv,data
            puts "233"
            puts data_dec
            puts "Decrpytion Done"
            STDOUT.flush
        else
            puts 'Wrong Option'
            STDOUT.flush
        end
    rescue Exception => e  
        puts e.message
        STDOUT.flush
        retry
    end
end

代码的逻辑非常清楚,然后我们需要进行一些设置将服务挂起来

安装socat,这个可以看我前面的介绍
socat安装使用指南
还需要配置几个文件

1.创建flag文件输入flag
flag{flag_is_here_but_you_cannont_see}
2.创建aeskey输入密码
因为这个我们在做题中不可得,填入任意的32字节长的字符串

然后我们挂载起来服务即可

之后就是做题了,首先我们输入1得到经过加密的flag内容,然后大概分析一下b64解密后长度为48,需要将之分为3组,然后就比较简单了,直接上程序,我写的程序可能比较乱,但是思路尽可能写清楚
ps:这里注意owntools的使用,这里在接收东西的时候用recvuntil远远比recv要稳定的多!!!之前做不出来就是因为这个!!!长见识了!!!

# coding:utf-8
from pwn import *

using_words=''  #从0-255的字符
flag = ''   #最终的flag
temp_flag=''    #获取的每一块的flag值
def make_using_words():
    global using_words
    for i in range(0,255):
        using_words+=chr(i)

def make_new(ans,sigal,pos):    #这个函数生成爆破的IV向量,我们尤其需要注意ans值,和下面的的return值理清关系
    ret=''
    for i in range(pos):    #添加前导零
        ret+="0"
    ret+=sigal
    for i in range(len(ans)):
        ret+=chr(ord(ans[i])^(16-pos))  #加入要填充nbyte,保证后n-1byte是0xn
    return ret

def decode_sigal_word(conn,iv,block,ans,pos):   #爆破一个byte
    global using_words
    for sigal in using_words:
        padding = make_new(ans,sigal,pos)  #NO.16-pos word
        conn.send('3\n')
        conn.recvuntil('IV:\n')     #注意用recvuntil比较稳定
        conn.send(base64.b64encode(padding)+"\n")   #注意用\n才会进入下一步
        conn.recvuntil('Data:\n')
        conn.send(base64.b64encode(block)+"\n")
        content =  conn.recv()
        #print content
        if "Decrpytion Done"  in content:   #我们在文章中描述的二叉值的来源,Decrpytion Done说明解密成功了
            global temp_flag 
            temp_flag+= chr(ord(sigal)^(16-pos)^ord(iv[pos]))   #抑或原来的IV,得到直接是flag的值
            return chr(ord(sigal)^(16-pos))     #注意这里不需要抑或原来的IV,后面只要num^(16-pos)^(15-pos),自己想清楚!!!

def decode_words(conn,iv,block):    #爆破一整串
    global temp_flag
    temp_flag = ''
    ans=''
    for i in range(15,-1,-1):   #从尾向头爆破
        ans+=decode_sigal_word(conn,iv,block,ans[::-1],i)
        #print ans
    #return ans



if __name__=='__main__':
    decode_total = 'zCGS96d+kbkerCze6RFPRz+0+0Lg6NzXbdhmLgXtliGJyJuoW4aAQT18u6AGkmFR' #我们按下1得到的密文
    IV = "QUFBQUFBQUFBQUFBQUFBQQ==" #"A"×16的base64加密值
    make_using_words()
    decode = base64.b64decode(IV)+base64.b64decode(decode_total)    #链接起来
    conn = remote('127.0.0.1',3333)
    print conn.recvuntil('option:\n')
    global flag
    global temp_flag
    for i in range(1,4):    #按照位置分片,前一个为IV值后一个为密文
        iv = decode[i*16-16:i*16]
        decode_block = decode[i*16:i*16+16]
        decode_words(conn,iv,decode_block)
        flag+=temp_flag[::-1]
    print flag

这里写图片描述

学习到了,开心啊,再膜4ction师傅














  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Padding Oracle attack is a type of cryptographic attack that exploits the behavior of cryptographic systems using block ciphers with padding. The attack allows an attacker to decrypt the contents of encrypted data by sending specially crafted ciphertexts to a server that uses the encryption algorithm. The attack works by exploiting the server's ability to detect whether a ciphertext is properly padded or not. Padding is commonly used in block ciphers to ensure that the input block is a fixed length. If the padding is incorrect, the server will reject the ciphertext and return an error message. However, by analyzing the error messages, an attacker can infer information about the plaintext and eventually decrypt it. To carry out the attack, the attacker sends many modified ciphertexts to the server, each with a different block of the ciphertext modified. By analyzing the responses from the server, the attacker can determine whether the modified block of ciphertext was properly padded or not. This information can be used to gradually determine the value of each byte of the plaintext. Padding Oracle attack is a serious threat to many cryptographic systems that use block ciphers with padding. To prevent this attack, it is important to use authenticated encryption modes, such as AES-GCM or ChaCha20-Poly1305, that provide both encryption and authentication of the ciphertext. Additionally, servers should be configured to return a generic error message, rather than specific error messages that reveal information about the encryption process.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值