0x00:前记

XMAN第二天,密码学大手子太强了,web选手听了一天还是不听8懂,膜一下1phan师傅.


0x01:CBC字节反转攻击

原理:乌云知识库
这里以bugkuCTF-login4为例子讲一下CBC字节反转攻击
.index.php.swp泄露源码,拿到源码后,先看一下关键部分的代码.

  1. 获取flag部分的代码:
function show_homepage(){
    if ($_SESSION["username"]==='admin'){
        echo '<p>Hello admin</p>';
        echo '<p>Flag is $flag</p>';
    }else{
        echo '<p>hello '.$_SESSION['username'].'</p>';
        echo '<p>Only admin can see flag</p>';
    }
    echo '<p><a href="loginout.php">Log out</a></p>';
}

可以看到当登陆的用户名为admin时候即可获取flag

  1. 登陆部分的代码
if(isset($_POST['username']) && isset($_POST['password'])){
    $username = (string)$_POST['username'];
    $password = (string)$_POST['password'];
    if($username === 'admin'){
        exit('<p>admin are not allowed to login</p>');
    }else{
        $info = array('username'=>$username,'password'=>$password);
        login($info);
        show_homepage();
    }
function login($info){
    $iv = get_random_iv();
    $plain = serialize($info);
    $cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
    $_SESSION['username'] = $info['username'];
    setcookie("iv", base64_encode($iv));
    setcookie("cipher", base64_encode($cipher));
}

登陆部分要求用户名不能为admin,并且将用户名和密码反序列化后加密.并设置为cookie.
解题思路:
注册一个名字为bdmin的账户,并且通过cbc字节反转攻击字符b修改bdmin为admin并反序列化成功.

  1. 注册账号后反序列化的明文为:
a:2:{s:8:"userna
me";s:5:"bdmin";
s:8:"password";s
:3:"admin";}

我们要修改的字符b在第二行的第十个位置,即b[9],
而使用cbc字节反转攻击所修改的地方即为a[9].

攻击cipher的脚本:

# -*- coding: utf-8 -*-
# Author:Sheldon
import base64 as bs64
import urllib
cipher = "hFykIH7P9Zdh5FoDRdfDpnap7C5SLsKA%2FTEyev3d8n5Tp%2FknZg52AunNuk5ovtjILCsTrRf%2Ffbl48IA3xRWYWQ%3D%3D"  #注册后的Cookie中的cipher
cipher = urllib.unquote(cipher)
cipher = bs64.b64decode(cipher)
new_cip = cipher[:9] + chr(ord(cipher[9]) ^ ord("b") ^ ord("a")) + cipher[10:]   # new_cipher[9] = old_cipher[9] ^ {原来明文的字符} ^ {你想修改的字符}
print "new ciper: " + urllib.quote(bs64.b64encode(new_cip))

但是修改之后发现提示反序列化错误,原因是因为第一组密文解密的时候是使用IV,但是密文已经被我们修改了,导致第一组密文解密出来的时候并不是a:2:{s:8:"userna
,所以我们需要伪造IV,使得我们修改后的密文解密后的明文为a:2:{s:8:"userna
伪造IV的脚本:

# -*- coding: utf-8 -*-
# Author:Sheldon
import base64 as bs64
import urllib
cipher = "8C/h2gPjbXOiBBkGU0m4t21lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjM6IjEyMyI7fQ=="  #攻击后的cipher
cipher=bs64.b64decode(cipher)
IV = "QzbE2bhhJv9F6VTgR4Fc3Q%3D%3D"    #初始Cookie中的IV
IV = bs64.b64decode(urllib.unquote(IV))
s = 'a:2:{s:8:"userna'   #正确的明文
new_IV = ""
for i in range(16):
    new_IV += chr(ord(s[i]) ^ ord(IV[i]) ^ ord(cipher[i]))
new_IV = urllib.quote(bs64.b64encode(new_IV))
print new_IV

修改Cookie中的IV和cipher后访问网页即可获取flag