• bugku-login4-CBC字节翻转攻击


    CBC模式:Cipher Black Chaining mode(密码分组链接模式)

    CBC模式进行加解密是都需要一个随机初始向量iv,在第一轮进行加解密是都需要与iv进行xor的。


    1.加解密过程

    0x01:加密过程如下图(来自《图解密码技术》一书)

     0x02:解密过程(来自《图解密码技术》一书)

    CBC模式的加密过程主要分为这几步:

      1. 将明文分为若干组(16个字节为一组),最后一组不足则用特殊字符填充

      2.生成一个初始向量iv和密钥

      3.用iv与第一组明文异或(iv只影响第一组生成的密文)

      4. 然后再用前n组密文与后n+1组明文异或生成第n+1组密文,以次重复

      5.最后将生成的密文拼接起来,就成了最终密文

    CBC模式的解密过程主要分为这几步:

      1.将密文分组

      2.用iv与第一组密文xor,解密得到第一组明文

      3.用第n组密文与第n+1组密文xor,解密得到第n+1组明文,以此类推

      4.将各组的明文拼接在一起就是最终要得到的明文了

    这里注意一下:解密的时候前一组密文只影响后一组明文的结果,而不会影响其他组明文的结果,由图也可看得出,这个也是进行攻击的重要之处。

    2.CBC字节翻转攻击:

    我们需要改变前一组密文的一个字节,然后与下一组的密文异或,我们就可以得到一个不同的明文了,从而就能达到攻击的效果。如图:

    举个例子:

    我现在有个明文序列:helloworld,现在我以它2个字节为一组进行分组(一般是16个字节为一组,但是这里为了方便起见就以2个字节为一组了)

    第一组:he

    第二组:ll

    第三组:ow

    第四组:or

    第五组:ld

    现在我想把第三组 “ow”中的o翻转为x,那么我们就需要改变第二组的密文从而改变第三的明文

    phaintext="helloworld"

    enc=encrypt(phaintext)

    enc1=chr(ord(enc[5])^ord("o")^ord("x"))  #enc[5]即是与“o”相同比特位的密文,也就是说第三组只有"o"这个比特位受影响,而“w”不受影响

    result=decrypt(enc1)

    这里注意一下:任何字符与本身xor都是为0,任何字符与0xor都为本身,如A xor A=0,A xor 0=A

    3.实战—bugku-login4

    打开是一个登陆界面,随便输入一个账号密码就能登陆,但是admin不能登陆。

    抓包发现,有个iv和cipher,猜测是CBC模式的加密

    扫描一波发现有源码泄露

    vim -r index.php.swp恢复后得到源代码,审计关键代码

    这里对usernmae进行了检测只有admin才能看得到flag,但是admin又不允许登陆,这里看起来有点矛盾,但是我们再看看前面的代码,这个对登陆信息进行序列化然后用CBC模式的加密方式进行加密最后base64_encode,然后我们要做的是以admin的身份登陆,我们可以操作cookie中的iv和cipher进行CBC字节翻转攻击。

    然后我们以账号为admia,密码为12345登陆

    得到的明文是:a:2:{s:8:"username";s:5:"admia";s:8:"password";s:5:"12345"}

    然后16个字节分组得到

    s:2:{s:8:"userna

    me";s:5:"admia";

    s:8:"password";s

    :3:"12345";}

    所以我们要翻转的是第二组的“a”翻转为“n”,所以我们要改变第一组的密文从而达到攻击的效果

     代码如下

    1 import base64
    2 cipher="yQQeUDxlzRvPToe631KV1vcy8DyI4e0kz7Knb9K6GIH4yP8Q32kufQvWoD7oN3hzi2EpiBxx6t/7sfIH1pCExg=="
    3 plain=base64.b64decode(cipher)
    4 result=plain[0:13]+chr(ord(plain[13])^ord("n")^ord("a"))+plain[14:]
    5 print base64.b64encode(result)
    6 #print R0dGVia+fJ24Ei3t29NC90P5kRbHXnW+D690WNWHnATH3UHvC4h+btceizE5jotDgG0QZLa9LOdwSAg9LcsCdw==

      POST过去提示不能正常反序列化,因为我们修改了第一组的密文,导致第一组的密文与iv xor会出错,从而导致了第一组明文不能正常解密,所以我们还要对iv进行修改

    代码如下(由于我中途输入错了iv,所以代码中的iv和cipher和图中可能会不一样,但是思路是一样的):

    注意一下第二步不要修改cipher,只需要修改iv就行了,因为我两个图中的cipher是不一样的,所以我还是要说一下的,以免误人子弟

    1 import base64
    2 cipher="wRPT3VONV2zFV6D2PbHjIm1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9"
    3 plain=base64.b64decode(cipher)
    4 oldiv=base64.b64decode("uxrq4TtskqrNJh7JUZV9rg==")
    5 one='a:2:{s:8:"userna'
    6 iv=""
    7 for i in range(0,16):
    8     iv=iv+chr(ord(one[i])^ord(plain[i])^ord(oldiv[i]))
    9 print base64.b64encode(iv)#iv=GzMLBhOS//4yU8tMCVbw7Q==

    将新的iv POST过去成功getflag

    最后:写得不太好,若有师傅发现错误,望请斧正

  • 相关阅读:
    第十六节:类与对象基本概念
    dedecms源码分析:(1)index.php
    第十二节:控制结构foreachbreakcontinueswitch
    PHP的输出缓冲区(转)
    C 结构体小结
    指针参数在内存中的传递
    C typedef用途小结
    C语言考试2 题目整理
    MinGW 环境下 给hello.exe 自定义一个图标
    JavaEE程序设计快速入门小结
  • 原文地址:https://www.cnblogs.com/Byqiyou/p/9707711.html
Copyright © 2020-2023  润新知