实验吧 简单的登录题 之[ CBC翻转攻击 ] 详解

解题链接: http://ctf5.shiyanbar.com/web/jiandan/index.php
1)Burpsuite抓包
在这里插入图片描述
2)根据Tips,修改GET请求为test.php获得源码。
在这里插入图片描述

3)代码审计
这个是实验吧的源代码:

      define("SECRET_KEY", '***********');
       define("METHOD", "aes-128-cbc");
       error_reporting(0);
       include('conn.php');
       function sqliCheck($str){                  
       	if(preg_match("/\\\|,|-|#|=|~|union|like|procedure/i",$str)){
       		return 1;
       	}
       	return 0;
       }
       function get_random_iv(){
           $random_iv='';
           for($i=0;$i<16;$i++){
               $random_iv.=chr(rand(1,255));
           }
           return $random_iv;
       }
       function login($info){
       	$iv = get_random_iv();
       	$plain = serialize($info);
           $cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
           setcookie("iv", base64_encode($iv));
           setcookie("cipher", base64_encode($cipher));
       }
       function show_homepage(){
       	global $link;
           if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
               $cipher = base64_decode($_COOKIE['cipher']);
               $iv = base64_decode($_COOKIE["iv"]);
               if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
                   $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
                   $sql="select * from users limit ".$info['id'].",0";
                   $result=mysqli_query($link,$sql);
                   
                   if(mysqli_num_rows($result)>0  or die(mysqli_error($link))){
                   	$rows=mysqli_fetch_array($result);
       				echo '<h1><center>Hello!'.$rows['username'].'</center></h1>';
       			}
       			else{
       				echo '<h1><center>Hello!</center></h1>';
       			}
               }else{
                   die("ERROR!");
               }
           }
       }
       if(isset($_POST['id'])){
           $id = (string)$_POST['id'];
           if(sqliCheck($id))
       		die("<h1 style='color:red'><center>sql inject detected!</center></h1>");
           $info = array('id'=>$id);
           login($info);
           echo '<h1><center>Hello!</center></h1>';
       }else{
           if(isset($_COOKIE["iv"])&&isset($_COOKIE['cipher'])){
               show_homepage();
           }else{
               echo '<body class="login-body" style="margin:0 auto">
                       <div id="wrapper" style="margin:0 auto;width:800px;">
                           <form name="login-form" class="login-form" action="" method="post">
                               <div class="header">
                               <h1>Login Form</h1>
                               <span>input id to login</span>
                               </div>
                               <div class="content">
                               <input name="id" type="text" class="input id" value="id" onfocus="this.value=\'\'" />
                               </div>
                               <div class="footer">
                               <p><input type="submit" name="submit" value="Login" class="button" /></p>
                               </div>
                           </form>
                       </div>
                   </body>';
           }
       }

4) 以下是题目:http://118.89.219.210:49168/index.php 的源代码
因为正在学习CBC翻转攻击,查阅了csu_vc的文章
所以暂时先按他的文章的源代码来分析CBC翻转的题目。
实验吧的题目以后更新。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">;
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Login Form</title>
    <link href="static/css/style.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="static/js/jquery.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        $(".username").focus(function() {
            $(".user-icon").css("left","-48px");
        });
        $(".username").blur(function() {
            $(".user-icon").css("left","0px");
        });
        $(".password").focus(function() {
            $(".pass-icon").css("left","-48px");
        });
        $(".password").blur(function() {
            $(".pass-icon").css("left","0px");
        });
    });
    </script>
    </head>
    <?php
    define("SECRET_KEY", file_get_contents('/root/key'));
    define("METHOD", "aes-128-cbc");
    session_start();
    function get_random_iv(){
        $random_iv='';
        for($i=0;$i<16;$i++){
            $random_iv.=chr(rand(1,255));
        }
        return $random_iv;
    }
    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));
    }
    function check_login(){
        if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
            $cipher = base64_decode($_COOKIE['cipher']);
            $iv = base64_decode($_COOKIE["iv"]);
            if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
                $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
                $_SESSION['username'] = $info['username'];
            }else{
                die("ERROR!");
            }
        }
    }
    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>';
    }
    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();
        }
    }else{
        if(isset($_SESSION["username"])){
            check_login();
            show_homepage();
        }else{
            echo '<body class="login-body">
                    <div id="wrapper">
                        <div class="user-icon"></div>
                        <div class="pass-icon"></div>
                        <form name="login-form" class="login-form" action="" method="post">
                            <div class="header">
                            <h1>Login Form</h1>
                            <span>Fill out the form below to login to my super awesome imaginary control panel.</span>
                            </div>
                            <div class="content">
                            <input name="username" type="text" class="input username" value="Username" onfocus="this.value=\'\'" />
                            <input name="password" type="password" class="input password" value="Password" onfocus="this.value=\'\'" />
                            </div>
                            <div class="footer">
                            <input type="submit" name="submit" value="Login" class="button" />
                            </div>
                        </form>
                    </div>
                </body>';
        }
    }
    ?>

5)可以简单地画一个流程图:
在这里插入图片描述

解题思路:
1)在于考察aes-128-cbc算法的“CBC翻转攻击“漏洞

2)由源代码我们可知:
2.1)Flag只有Session = admin可以查看
2.2)我们不可以通过POST传参的方式Set Session = admin
2.3)我们可以通过CBC算法的翻转攻击漏洞 Set Session = admin

3)CBC翻转攻击原理:
在这里插入图片描述
上图CBC加密的原理图
1.Plaintext: 待加密的数据。
2.IV: 用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。
3.Ciphertext: 加密后的数据。

在这里重要的一点是,CBC工作于一个固定长度的比特组,将其称之为块。在本文中,我们将使用包含16字节的块。

整个加密的过程简单说来就是:

1.首先将明文分组(常见的以16字节为一组),位数不足的使用特殊字符填充。
2.生成一个随机的初始化向量(IV)和一个密钥。
3.将IV和第一组明文异或。
4.用密钥对3中xor后产生的密文加密。
5.用4中产生的密文对第二组明文进行xor操作。
6.用密钥对5中产生的密文加密。
7.重复4-7,到最后一组明文。
8.将IV和加密后的密文拼接在一起,得到最终的密文。

从第一块开始,首先与一个初始向量iv异或(iv只在第一处作用),然后把异或的结果配合key进行加密,得到第一块的密文,并且把加密的结果与下一块的明文进行异或,一直这样进行下去。因此这种模式最重要的特点就是:前一块的密文用来产生后一块的密文。

在这里插入图片描述
这是解密过程,解密的过程其实只要理解了加密,反过来看解密过程就也很简单了,同样的,前一块密文参与下一块密文的还原。

1.从密文中提取出IV,然后将密文分组。
2.使用密钥对第一组的密文解密,然后和IV进行xor得到明文。
3.使用密钥对第二组密文解密,然后和2中的密文xor得到明文。
4.重复2-3,直到最后一组密文。

假设我们修改了第一个密文块的第 4 个字节,那么根据 CBC 模式的解密,它将影响下一个密文块的解密结果,如图标红部分。

上述的影响过程中,只涉及到异或运算,这里异或运算的特性就十足重要了!

4)异或的概念:

1)异或的运算方法是一个二进制运算: 1^1=0 0^0=0 1^0=1 0^1=1 两者相等为0,不等为1.
这样我们发现交换两个整数的值时可以不用第三个参数。 如a=11,b=9.以下是二进制 a=a^ b=1011^1001=0010; b=b^
a=1001^0010=1011; a=a^ b=0010^1011=1001; 这样一来a=9,b=11了。

2)异或是可逆的。
已知A=B^ C
可以得到结论B=A^ C
并且也能得到A^ C^B= B ^ B=0

上述结论拿到这里的 CBC 翻转攻击假设中看

设第一块密文中的第4个字节设为变量A,在第二块密文的第4个字节设为变量B,第二块的明文中第4个字节设为变量C
因为A ^ B=C,根据结论有B=A^C
如果人为令A变量值改变为A^ C,那么原本的A^B将变成A ^ C ^ B=B ^ B=0,第二个产生的明文的第4个字节将变为0
如果认为将A改变为A ^ C^ X(这里X是任意字符),那么参与运算后,A ^ B将等于A ^ C ^ X ^ B=B ^ X ^ B=X,
第二个产生的明文的第4个字节将变为X字符,这样,第二块密文块解密的结果就可控了!

1、根据CBC算法的原理,此题中:
Plaintext1:s:2:{s:8:“u serna
Plaintext2:me”;s:5:“z dmin”;
Plaintext3:s:8:“password”;s
Plaintext4::3:“12345”;}XXX

2、不妨设
①②③④代表Plaintext1、2、3、4
(1)(2)(3)(4)分别代表Ciphertext1、2、3、4

3、CBC加密前:
plaintext = ①②③④
4、CBC加密后:
Ciphertext = (1)(2)(3)(4)

CBC加密:
iv ⊕① =(1)
(1)⊕② =(2)
(2)⊕③ =(3)
(3)⊕④ =(4)

CBC解密
(1)⊕iv = ①
(1)⊕(2)=②
(2)⊕(3)=③
(3)⊕(4)=④

5)攻击流程:
1、修改能够得到的密文的第一块(前16个字节),使得第二块密文块结果的字符中zdmin能变成admin
cipher[9] = u

 xor_cipher = cipher[0:9] +  chr(ord(cipher[9]) ^ ord('z') ^ ord('a')) + cipher[10:]  

2、由于操作1导致第一块密文块解密后得到错误结果,修正IV初始化向量,将第一块的明文结果还原成a:2:{s:8:"userna

通俗点说就是:
我们需要更改(1),使得(1)⊕(2)后,得到②中的zdmin变成admin
因为(1)被更改,所以(1)⊕iv得到的①会被更改,导致无法反序列化。
所以我们需要适当更改iv使得(1)⊕iv 仍然等于①。

Realfirstblk = 'a:2:{s:8:"userna'#被损坏前正确的明文
for i in range(16):
    newIv += chr(ord(iv[i])^ord(cipher[i])^ord(Realfirstblk[i])) #这一步相当于把原来iv中不匹配的部分修改过来

iv ⊕ ① =(1)
(1)⊕(2)= ②

令iv =A ,①=B , (1)=C
(1)⊕(2)=② 等价于A ^ B =C
可控点(A^C ^X) ^B = X
等价于iv ^ (1) ^ RealFirstBlock = RealFirstBlock
iv = oldiv
(1) = cipher[0:16]
所以newIv[i] = chr(ord(iv[i])^ ord(cipher[i])^ord(Realfirstblk[i]))

6)攻击流程1的Exp

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Date    : 2018-03-15 11:45:57
    # @Author  : Mr.zhang(s4ad0w.protonmail.com)
    # @Link    : http://blog.csdn.net/csu_vc
    import base64
    import requests
    import urllib
    iv_raw='%2F8iEm4jh%2BjbgVGwlQ31ycg%3D%3D'  #这里填写第一次返回的iv值
    cipher_raw='8WdhbPxjZy9xYAgoCeghiOUQu0ri1Y3dv7cX44MbvOfIC6zZxCbR%2FPFpeMatL5qIgT%2BYA66tIdCBpxtWsWxV9Q%3D%3D'  #这里填写第一次返回的cipher值
    print "[*]原始iv和cipher"
    print "iv_raw:  " + iv_raw
    print "cipher_raw:  " + cipher_raw
    print "[*]对cipher解码,进行反转"
    cipher = base64.b64decode(urllib.unquote(cipher_raw))
    #a:2:{s:8:"username";s:5:"zdmin";s:8:"password";s:5:"12345"}
    #s:2:{s:8:"userna
    #me";s:5:"zdmin";
    #s:8:"password";s
    #:3:"12345";}
    xor_cipher = cipher[0:9] +  chr(ord(cipher[9]) ^ ord('z') ^ ord('a')) + cipher[10:]  
    xor_cipher=urllib.quote(base64.b64encode(xor_cipher))
    print "反转后的cipher:" + xor_cipher

7)攻击流程2的Exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-03-15 11:56:20
# @Author  : csu_vc(s4ad0w.protonmail.com)
# @Link    : http://blog.csdn.net/csu_vc
import base64
import urllib
cipher = 'Bc6oENSSAEPpPdv/rbqRZG1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9'#填写提交后所得的无法反序列化密文
iv = '%2F8iEm4jh%2BjbgVGwlQ31ycg%3D%3D'#会报”无法反序列化“错的iv
#cipher = urllib.unquote(cipher)
cipher = base64.b64decode(cipher)
iv = base64.b64decode(urllib.unquote(iv))
newIv = ''
Realfirstblk = 'a:2:{s:8:"userna'#被损坏前正确的明文
for i in range(16):
    newIv += chr(ord(iv[i])^ord(cipher[i])^ord(Realfirstblk[i])) #这一步相当于把原来iv中不匹配的部分修改过来
print "oldIv: " + iv
print "newIv:" + urllib.quote(base64.b64encode(newIv))

最终得到计算得到的 cipher 和 iv:

root@localhost:~/Desktop# python 1.py 
[*]原始iv和cipher
iv_raw:  %2F8iEm4jh%2BjbgVGwlQ31ycg%3D%3D
cipher_raw:  8WdhbPxjZy9xYAgoCeghiOUQu0ri1Y3dv7cX44MbvOfIC6zZxCbR%2FPFpeMatL5qIgT%2BYA66tIdCBpxtWsWxV9Q%3D%3D
[*]对cipher解码,进行反转
反转后的cipher:8WdhbPxjZy9xewgoCeghiOUQu0ri1Y3dv7cX44MbvOfIC6zZxCbR/PFpeMatL5qIgT%2BYA66tIdCBpxtWsWxV9Q%3D%3D

root@localhost:~/Desktop# python 2.py 
oldIv: �Ȅ����6�Tl%C}rr
newIv:mzwesScAwE0zS8Kpi7WNdw%3D%3D

8)访问并GetFlag
在这里插入图片描述

发布了92 篇原创文章 · 获赞 57 · 访问量 5万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 终极编程指南 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览