ctfshow
web21

爆破得到flag
web22
域名爆破,爆破ctfshow的子域名
用一个在线子域名查询工具vip


网上就是vip这个界面,鼠标在标签页悬停就会出现flag但是现在应该是环境出了问题没得了,不过这个网站还是好用的,但是我看有的wp用的Layer子域名挖掘机https://eclecticism.blog.csdn.net/article/details/135940447?fromshare=blogdetail&sharetype=blogdetail&sharerId=135940447&sharerefer=PC&sharesource=2401_88743143&sharefrom=from_link

用的这个,也能爆出来的
web23
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-03 11:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-03 11:56:11
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
include('flag.php');
if(isset($_GET['token'])){
$token = md5($_GET['token']);
if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1)){
if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
echo $flag;
}
}
}else{
highlight_file(__FILE__);
}
?>
get传一个token,然后对这个token进行md5加密
substr(string, start, length)
然后
条件一:token加密后的第2,15,18字符强相等
条件二:三位相加除以第二位与第32位强相等
这里要注意一下intval将数字转成整数,将字母一律看作0,注意intval(0/0)的时候会输出NAN
最好的办法是写个脚本遍历一下,我看了一下最简单的是写个php脚本
<?php
for($i=0; $i<10000; $i++){
$token = md5($i);
if(substr($token,1,1) === substr($token,14,1) && substr($token,14,1) === substr($token,17,1)){
if((intval(substr($token,1,1)) + intval(substr($token,14,1)) + substr($token,17,1)) / substr($token,1,1) == intval(substr($token,31,1))){
echo 'token=' . $i . ' md5=' . $token;
}
}
}
?>
直接加个循环逻辑和输出就行

得到token然后传参得到flag
嗯看了一下提示的脚本更麻烦一些
web24
这道题目考的最简单的随机种子
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
$r = $_GET['r'];
mt_srand(372619038);
if(intval($r)===intval(mt_rand())){
echo $flag;
}
}else{
highlight_file(__FILE__);
echo system('cat /proc/version');
}
?>
这道题的大致逻辑是这个随机种子生成的数与你传入的参数相等,就能输出flag,又因为在随机种子确定的情况下,输出序列相等

所以传入这个种子第一次生成的随机数就可以爆破出来的
好呢既然都做到了简单总结一下随机种子吧
其实主要涉及两个函数mt_srand和mt_rand两个函数,一个是生成随机种子,一个是生成随机数,
如果考察的话一般有两种形式,一种是确定随机种子,比如mt_srand(115488)在种子确定的情况下,随机数生成的序列也相。另一种是随机数已知,因为只有第一次生成随机数才会调用mt_srand()函数,已知第一个随机数就可以倒退随机种子(有一个问题就是不同版本的php生成的随机序列可能也不同),然后还有一个随机种子的工具

但是这个只有1-2两个参数能跑的出来,但他已经是最新版的了
web25
这个也是随机种子
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-03 13:56:57
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-03 15:47:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
$r = $_GET['r'];
mt_srand(hexdec(substr(md5($flag), 0,8)));
$rand = intval($r)-intval(mt_rand());
if((!$rand)){
if($_COOKIE['token']==(mt_rand()+mt_rand())){
echo $flag;
}
}else{
echo $rand;
}
}else{
highlight_file(__FILE__);
echo system('cat /proc/version');
}
这个就叫上一题复杂
这段代码的意思大概是取flag md5加密的前八位,转成十进制作为种子
!$rand
在 PHP 中,以下值被认为是假:
0(整数零)0.0(浮点零)""(空字符串)"0"(字符串零)nullfalse[](空数组)
所以让$rand=0即让r=mt_rand(No.1),这是条件一,条件二是token=mt_rand(No.2)+mt_rand(No.3)

一开始反推种子得到四个
然后运行这个脚本来验证哪个种子能生成对应的第一个随机数,并生成对应的token
<?php
$target = 1778346834;
$seeds = [2754897542, 2754897543, 1857310316, 3422730783];
foreach ($seeds as $seed) {
mt_srand($seed);
$r1 = mt_rand(); // 第1次,匹配用
if ($r1 == $target) {
echo "seed: $seed ✓ 匹配!";
$r2 = mt_rand(); // 第2次,token 第一部分
$r3 = mt_rand(); // 第3次,token 第二部分
$token = $r2 + $r3;
echo " token = $token\n";
}
}


curl -v -b "token=2696463300" "https://f86dc8d3-caae-4a81-b28d-0d8fb87b3852.challenge.ctf.show/?r=1778346834"
或者curl一下发现是php7.3,因此可以选出两个来1857310316 和 3422730783

用kali里面的还要下载,我直接用在线沙盒子运行计算正确的token值,其实前面已经得到了,和上面得到的一样
<?php
mt_srand(1857310316);
mt_rand();
echo "token1: " . (mt_rand() + mt_rand()) . "\n";
mt_srand(3422730783);
mt_rand();
echo "token2: " . (mt_rand() + mt_rand()) . "\n";

就显示两个token值,然后分别进行curl测试得到flag
curl -v -b "token=2586953677" "https://f86dc8d3-caae-4a81-b28d-0d8fb87b3852.challenge.ctf.show/?r=1778346834"

web26


抓个包看看呢,直接爆破密码就行,但是他没给密码直接爆破很麻烦,我直接看了答案爆破

得到flag
polarisctf-wp
ECC
题目分析
题目实现了一个自定义的椭圆曲线加密系统,给出了曲线参数 a,b,c,d,e、生成元 G 和点 P = m*G,要求求出标量 m(即 flag)。
从代码中可以看出,曲线方程为:
text
y² + a*x*y + c*y = x³ + b*x² + d*x + e
其中 a = 0,简化了曲线形式。
解题步骤
1. 发现曲线奇异
首先尝试用 SageMath 定义曲线,发现曲线判别式为 0,说明曲线是奇异的(singular curve)。这意味着不能使用标准椭圆曲线的离散对数求解方法,但可以利用奇点的性质将问题转化为有限域上的离散对数问题。
2. 找到奇点
奇点满足偏导数为 0:
python
∂F/∂x = 0, ∂F/∂y = 0
解得:
- 从
∂F/∂y = 2y + c = 0得到y0 = -c * inv(2) mod p - 代入曲线方程求解 x,得到唯一的奇点
(x0, y0)
3. 分析奇点类型
将奇点平移到原点:u = x - x0, v = y - y0,展开曲线方程,观察二次项系数:
text
u²: 0
uv: 0
v²: 1
二次型为 v² = 0,判别式为 0,说明是 Cusp(尖点) 类型。
4. 构造同构映射
对于 cusp 型奇异曲线,群同构于加法群 (F_p, +)。通过参数化找到映射:
- 曲线在奇点附近的行为类似于
v² = u³的形式 - 正确的映射是
t = u / v(当 v ≠ 0) - 映射将曲线上的点
(x,y)映射到t = (x - x0) / (y - y0) mod p
5. 求解离散对数
在加法群中,点乘 m*G = P 转化为:
text
t_P = m * t_G (mod p)
因此:
text
m = t_P * (t_G)⁻¹ mod p
直接计算即可得到 m。
6. 获取 Flag
将 m 转换为字节串,得到 flag:
text
xmctf{A_s1ngu14r_Curv3_15_n0t_s3cur3!}
完整解题代码
python
from Crypto.Util.number import *
from sage.all import *
# 已知参数
p = 9259018534502783714631247560818133078409930397939705162361230465031580254504264713899169170790687716589100652406132800533397486109926387016562663961524649
a = 0
b = 6235467631650349040636525320446729529985562949423449382969614887116983248527693872546808737512375916974084741892428681798937790855872528526403738040908493
c = 4165903654767429195543540819098180314477702137507994424192636596518008877139978822038616746899053449640020812062736993008962585578921635697413459959685760
d = 1889382340373247565387211782596794283852946561870564309251998196824383297786878212641581641540685106266683503654620956037368416192796434147249748216284648
e = 3015564788819504594313842562882781366361783108618226049128986996153057550014499326419988348165744003693083108924831219996703133056523468396967900376388617
# 已知点
G = (1244884551970947614719458919805713649754289814760243366205012699871413235954279930743612403791919112394457579170253990713250052822262255880036254772609156,
4579639528751113977115209571728128585569082149696598770106934145500742785077382446292613925719404433141749168427443122707253164477493499731016883616496009)
P = (9039120379228240875764080238389949393433230267005269099421166553853462484353350917730468887801035670710981414900285176863179650428412616144755102163764906,
6266065680737729548475090556806928225106996606788926050268440244885398464756877886842570309216095272026404453765198968208595242208306240371310555394416694)
F = GF(p)
# 定义曲线方程
R.<x,y> = F[]
curve_eq = y^2 + a*x*y + c*y - (x^3 + b*x^2 + d*x + e)
# 找奇点
fx = diff(curve_eq, x)
fy = diff(curve_eq, y)
# 从 fy = 0 求 y0
y0 = -c * inverse_mod(2, p) % p
# 代入求 x0
x_poly = curve_eq(y=y0)
x_roots = x_poly.univariate_polynomial().roots(multiplicities=False)
for x_val in x_roots:
if fx(x=x_val, y=y0) == 0:
x0 = x_val
break
print(f"奇点: ({x0}, {y0})")
# 构造映射:对于 cusp 类型,t = u/v = (x-x0)/(y-y0)
def map_to_add(point):
x, y = point
u = (x - x0) % p
v = (y - y0) % p
if v == 0:
return None
return (u * pow(v, -1, p)) % p
# 映射 G 和 P
t_G = map_to_add(G)
t_P = map_to_add(P)
print(f"t_G = {t_G}")
print(f"t_P = {t_P}")
# 在加法群中求解:t_P = m * t_G (mod p)
if t_G is not None and t_G != 0:
m = (t_P * pow(t_G, -1, p)) % p
print(f"\nm = {m}")
# 转换为 flag
flag_bytes = long_to_bytes(int(m))
print(f"Flag: {flag_bytes.decode('utf-8')}")

题目分析
题目给出了一个 RSA 加密系统,但增加了一个特殊的多项式约束:
python
def get_poly(k):
x,a,b = sympy.symbols('x a b')
poly = x**3 - a * x**2 + b * x - c - k*n
deriv1 = sympy.diff(poly, x)
a1 = random.randint(2**119,2**120)
b1 = random.randint(2**119,2**120)
x1 = random.randint(2**510,2**511)
deriv1_num = deriv1.subs({
x: x1,
a: a1,
b: b1
})
return x1,deriv1_num
已知参数:
n:RSA 模数x1:随机的大整数deriv1_num:多项式在(x1, a1, b1)处的导数值cipher:加密后的 flag
需要求解的是 c(RSA 中的秘密指数相关参数),然后用它解密得到 flag。
神秘学
解题思路
1. 建立方程
设多项式:
P(x)=x3−ax2+bx−c−knP(x)=x3−ax2+bx−c−kn
其导数为:
P′(x)=3x2−2ax+bP′(x)=3x2−2ax+b
已知在 (x1, a1, b1) 处:
P′(x1)=3x12−2a1x1+b1=deriv1_numP′(x1)=3x12−2a1x1+b1=deriv1_num
令:
R=3x12−deriv1_num=2a1x1−b1(1)R=3x12−deriv1_num=2a1x1−b1(1)
同时,虽然题目没有直接给出 P(x1) 的值,但我们可以假设 P(x1) = 0(这是合理的,因为 a1, b1 是随机选取的,x1 是多项式的根)。于是:
x13−a1x12+b1x1−c−kn=0(2)x13−a1x12+b1x1−c−kn=0(2)
2. 消元求解
由 (1) 得:
b1=2a1x1−Rb1=2a1x1−R
代入 (2):
x13−a1x12+(2a1x1−R)x1−c−kn=0x13−a1x12+(2a1x1−R)x1−c−kn=0x13−a1x12+2a1x12−Rx1−c−kn=0x13−a1x12+2a1x12−Rx1−c−kn=0x13+a1x12−Rx1−c−kn=0x13+a1x12−Rx1−c−kn=0
因此:
c=x13+a1x12−Rx1−kn(3)c=x13+a1x12−Rx1−kn(3)
3. 利用范围约束
已知 a1 和 b1 都在 [2^{119}, 2^{120}] 范围内。
由 (1) 得:
b1=2a1x1−Rb1=2a1x1−R
b1 的范围给出:
2119≤2a1x1−R≤21202119≤2a1x1−R≤2120
解得:
2119+R2x1≤a1≤2120+R2x12x12119+R≤a1≤2x12120+R
同时 a1 本身也在 [2^{119}, 2^{120}] 范围内,取交集得到 a1 的搜索范围。
4. 枚举 k
k 是 8 位素数,只有有限个可能值(2-251 之间的素数)。对于每个可能的 k:
- 计算
R = 3x1^2 - deriv1_num - 根据
b1的范围计算a1的候选范围 - 由于
x1非常大(约 511 位),2x1也很大,因此a1的范围实际上非常窄(通常只有几个整数值) - 对每个候选
a1,用公式 (3) 计算c - 用
c作为解密指数尝试解密:m = pow(cipher, c, n) - 检查解密结果是否包含 flag 标识
5. 关键观察
在 RSA 中,由于 e = inverse(c, φ),所以解密指数 d ≡ c (mod φ)。如果 c < φ(通常成立),那么 d = c,可以直接用 c 解密。
解题脚本
python
from Crypto.Util.number import *
import sympy
# 给定的数据
n = 63407394080105297388278430339692150920405158535377818019441803333853224630295862056336407010055412087494487003367799443217769754070745006473326062662322624498633283896600769211094059989665020951007831936771352988585565884180663310304029530702695576386164726400928158921458173971287469220518032325956366276127
x1 = 3481408902400626584294863390184557833125008467348169645656825368985677578418186933223051810792813745190000132321911937970968840332589150965113386330575858
deriv1_num = 36360623837143006554133449776905822223850034204333042340303731846698251185379183585401025894584873826284649058526470710038176516677326058549625930550928515944115160614909195746688504416967586844354012895944251800672195553936202084073217078119494546421088598245791873936703883718926122761577400400368341859847
cipher = 17359360992646515022812225990358117265652240629363564764503325024700251560440679272576574598620940996876220276588413345495658258508097150181947839726337961689195064024953824539654084620226127592330054674517861032601638881355220119605821814412919221685287567648072575917662044603845424779210032794782725398473
# 计算 R
R = 3 * x1 * x1 - deriv1_num
# 获取 8 位素数
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
primes_8bit = [i for i in range(2, 256) if is_prime(i)]
print("开始搜索...")
found = False
for k in primes_8bit:
# 根据 b1 范围计算 a1 的范围
b1_min = 2**119
b1_max = 2**120
a1_min_from_b1 = (b1_min + R) // (2 * x1)
a1_max_from_b1 = (b1_max + R) // (2 * x1)
# a1 本身的范围
a1_abs_min = 2**119
a1_abs_max = 2**120
# 取交集
search_min = max(a1_min_from_b1, a1_abs_min)
search_max = min(a1_max_from_b1, a1_abs_max)
# 由于 x1 很大,范围通常只有几个整数
for a1 in range(search_min, search_max + 1):
# 计算 b1 验证
b1 = 2 * a1 * x1 - R
if b1 < b1_min or b1 > b1_max:
continue
# 计算 c
c_val = x1**3 + a1 * x1**2 - R * x1 - k * n
if c_val <= 0:
continue
# 尝试解密
try:
m = pow(cipher, c_val, n)
flag = long_to_bytes(m)
# 检查是否为 flag
if b'flag' in flag or b'CTF' in flag:
print(f"\n成功!k = {k}")
print(f"a1 = {a1}")
print(f"b1 = {b1}")
print(f"c = {c_val}")
print(f"flag: {flag.decode()}")
found = True
break
except:
continue
if found:
break
if not found:
print("未找到 flag")

Ez_Python
漏洞点 :该函数递归合并用户输入的 JSON 数据到目标对象,但没有对键名进行过滤,允许设置任意属性。
危险路由 /read
@app.route('/read')
def read():
return open(instance.config.
filename).read()
读取 instance.config.filename 指定的文件,如果能控制这个属性,就能读取任意文件。
- 攻击链
用户输入 JSON → merge() 污染属性 → 修改 filename → /read 读取任意文件

only real
信息泄露 :在首页HTML源码中发现注释泄露了登录凭据:
```
<!-- xmuser/123456 -->
```
-
登录系统 :使用凭据 xmuser/123456 登录 login.php
-
获取JWT Token :登录成功后获得JWT cookie:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV
CJ9.
eyJzdWIiOiIxIiwicm9sZSI6InVzZXIiL
CJleHAiOjE3NzQ3Mjc3MjR9.
1bk2GNll05r0ezVt746c7hGFdjYzVLV5G
P697S92rCk
```
- 访问flag页面 :登录后访问 flag.php 直接获得flag
ezpollute
攻击链:
-
原型链污染绕过 :代码过滤了 proto ,但可以通过 constructor.prototype 绕过
-
NODE_OPTIONS注入 :
-
代码过滤了 --require 、 --import 等关键词
-
但 没有过滤 -r ( --require 的简写形式)
- 利用过程 :
```
{"constructor":{"prototype":
{"NODE_OPTIONS":"-r /flag"}}}
```
- 触发执行 :访问 /api/status 时, for...in 遍历 process.env 会遍历到原型链上污染的 NODE_OPTIONS ,子进程尝试 require('/flag') 导致flag内容在错误信息中泄露
关键点:
-
-r 是 --require 的简写,绕过了正则过滤 --(require|import|...)
-
/flag 文件被当作JS模块加载,因语法错误在报错信息中暴露了flag内容
AutoPypy
1. 漏洞类型:路径遍历 + Python 自动加载机制
2. 攻击链:
```
上传恶意文件 → 路径遍历到
site-packages → server.py 启动新
Python 进程 → 自动加载 usercustomize.
py → 在宿主机执行代码 → 绕过 proot 沙箱
```
3. 关键点:
组件 问题 server.py:26-28 文件名未过滤,允许 ../ 路径遍历 server.py:43 打印 site.getsitepackages() 作为提示 Python 机制 启动时自动加载 site-packages/usercustomize.py proot 沙箱 只限制用户代码,无法限制宿主机的 Python 进程
4. 攻击原理:
当 server.py 执行 subprocess.run([sys.executable, launcher_path, ...]) 时,会在 宿主机 上启动一个新的 Python 解释器。这个 Python 解释器会自动加载 site-packages/usercustomize.py ,而这个文件已经被我们通过路径遍历上传了恶意代码。
恶意代码在宿主机执行,完全绕过了 proot 沙箱,可以读取 /flag 文件。
Broken Trust
这道题目包含两个关键漏洞:
- SQL注入漏洞
在 /api/profile 接口中, uid 参数存在SQL注入漏洞。通过发送:
```
{"uid": "' OR '1'='1"}
```
可以获取到admin用户的信息,包括其UID: 5c3a88831c09410a87403815a4f57504
- 路径遍历漏洞
在 /api/admin?action=backup&file= 接口中存在路径遍历漏洞。虽然系统过滤了 ../ 和绝对路径,但可以使用 ....// 绕过过滤:
-
....// 会被处理成 ../ (先去掉 ../ 后剩余 ../ )
-
最终payload: ....//....//....//flag
完整攻击流程
-
注册普通用户获取UID
-
利用SQL注入获取admin的UID
-
使用admin UID登录获得管理员权限
-
利用路径遍历漏洞读取flag文件