赛博协会新生测验 Web Writeup
昨晚补完刀剑后又看了一会手机,睡得有点晚。今天早上十点多才起,想起赛博今天有新生测验,马上跑下床打开电脑。 嘛,还是挺有意思的,学到了不少东西。虽然刚开始跑偏了,差点想放弃2333 那么,我们来看看这些题吧:
Web1
这是一个搞逆向的学长出的 web 题。嘛,确实有些地方有点不太“安全“吧,之后我会提到。
假的杭电认证
进入题目,输入1
进入第一题,然后直接跳到了连接校内 Wifi 的登录认证界面。这个是最骚的。我整整在这里耗了两个小时……各种尝试都用尽了,还是什么都没有出来。正当想放弃去写代码的时候,开 F12 随便看了一眼——发现他这边的 302 跳转用了两次。从confirm.php
跳到了easiest.php
再到check_login.html
的。
嗯,感觉这个easiest.php
有那么点小问题。开 Burp Suite 抓一波包,果然:
flag{Th1s_is_7eh_easiest_Eo2}
嘛,想太复杂了,被自己蠢哭。哈哈哈哈
这边有个小插曲,学长之前把 flag 中的 he
写成了 eh
,也就是我拿到的这个,导致进不去下一题,改回去就好了。我还以为自己拿到了假的 flag。
首先你得有一个亿
原以为这个是那种很弱智的把文本框的maxlength
改一下就好的,结果发现不行 QAQ
然后连蒙带猜瞎尝试,最后被我试出来:
这个必须要输入科学计数法,比如1e999
然后就可以了!
土豪俱乐部
直接一个do not click me
连接,点一下跳到:http://111.231.107.65/exam/flag.php?file=useless.php
,页面内容是QXJlIHlvdSBibGluZD8=
,根据文件名useless.php
以及页面内容base64_decode
后得出的信息,我们可以知道这个页面只是为了告诉你这里存在一个文件包含。
我刚开始只是随意填了几个当前目录下的文件,发现仅仅是单纯的包含进来,并没有什么用。
搜了一波,发现居然可以用php://
来读取文件源代码!哇!学到了!
直接访问:
http://111.231.107.65/exam/flag.php?file=php://filter/read=convert.base64-encode/resource=flag.php
拿到 base64 后的网站源代码,然后解码一下就出来 flag 了:
flag{8ec2re_0F_1NcIu6e}
三道代码审计
后面就是三道代码审计了,套路都是一样的:
第一题
第一题就是在看你学没学过 PHP,哈哈
flag_1="xxx"
$temp = $_GET['number'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
die('第一段:'.$flag_1);
传入一个 GET 参数number
,然后要比 1336 大,但又不能是数字。我记得很久之前的协会培训,就讲到了 GET 参数传数组进去的骚套路。传数组总会出现一样不到的东西。这里就用上了:
http://111.231.107.65/exam/innocent.php?number[]=2333
得到第一段 flag:
1nN0c3nt_
第二题
$flag_2 = 'xxx';
if (isset($_GET['username']) and isset($_GET['password'])) {
if ($_GET['username'] == $_GET['password'])
print 'Your password can not be your username.';
else if (md5($_GET['username']) === md5($_GET['password']))
die('第二段:'.$flag_2);
else
print 'Invalid password';
}
这里要求 GET 请求传进去的username
和password
参数不能相等,但是他们的 md5 要相等。就是协会之前培训的原题,传数组!!
http://111.231.107.65/exam/innocent.php?id=2&username[]=1&password[]=2
拿到第二段 flag:
phPcOde_
第三题
$flag_3 = 'xxx';
if (isset($_GET['flag_3'])) {
if (strcmp($_GET['flag_3'], $flag_3) == 0)
die('第三段:'.$flag_3);
else
print 'No';
}
这里就是对比传进去的flag_3
和$flag_3
变量是否相等,相等出 flag,但我们并不知道$flag_3
的值,怎么办呢?三个字,传数组!!
http://111.231.107.65/exam/innocent.php?id=3&flag_3[]=233
拿到第三段 flag:
aUd17
三段拼起来,拿到最终的 flag:
flag{1nN0c3nt_phPcOde_aUd17}
后面这三道题其实都是 PHP 弱类型比较的,都是用了==
而不是===
所引发的问题。之前司大哥在看我 GitHub 上的项目时也指出了我疯狂用弱类型比较的问题。
然后 web1 就做完了!开心!
Web2
这题嘛,就是单纯的代码审计啦~
但是满满的干货呢!学到了不少东西!
首先直接访问149.28.199.89:2223
就 302 跳转到了 4399。(话说这个靠 Flash 吃饭的网站居然还没倒闭?!)
Burp Suite 抓包看一下 302 跳转前原页面的内容:
这边的注释里面告诉我们可以以任何请求方式传一个名字为source
的参数
传参后就看到了网站的源码,太长了就不贴了。我一段一段来分析吧:
if(strcmp($_GET['password'], $password) == 0)){
...
又是strcmp
和一个不知道的变量比较,用 web1 的套路,传数组!!
password[]=1
拿到第一段 flag:
Cyber{
if($b != $c & md5($b) == md5($c)) {
...
这个就是很常见的弱类型比较了,$b
和$c
不能相等,但是他们的 md5 要相等。碰撞是不可能的。这里就是用科学计数法啦~
只要让md5($b)
和md5($c)
的值都是0e
开头即可,这样弱类型比较都会把两个值当成数字,然后0==0
为true
,搞定!
百度一波0e
开头的 md5,随便挑两个传进去就行。
equal_md5_1=s878926199a&equal_md5_2=s155964671a
拿到第二段 flag:
Aud1t_
if($data=="web_1s_rea1_funny"&& preg_match("/^lalala$/m", $_GET['fake'])&& $_GET['fake']!=="lalala") {
这个有点意思。
我们首先看这个$data
,上面有一句$data = @file_get_contents($_GET['data'],'r');
。一直是做的 PHP 开发,所以不知道file_get_contents
还可这样用。
上网找了下,又是说我们可以传data=php://input
进去,然后$data
变量就可以读取自我们 POST 进去的数据了。
再把web_1s_rea1_funny
POST 过去即可。
后面的正则比较,临时抱佛脚现场学了下正则,发现问题在/m
这里,定义中是这么说的:
如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 “\n” 或 “\r” 之前的位置
也就是说会多匹配一个换行符或回车符。这就好办了,我们只需要在fake
后面加个换行符就好了。但是问题来了,怎样在 GET 的参数里,也就是 URL 里加上换行符呢?
直接在 URL 里面换行肯定不对,我们只需要找到了换行符 urlencode 编码后的东西就好了,是%0a
。
那么就是fake=lalala%0a
拿到第三段 flag:
1s_re0l_
if(!(substr($_GET['boom'], 32) === md5($_GET['boom']))){
又是比较,又有 md5,那么怎么办呢?大声喊出那三个字!传数组!!
轻轻松松 boom[]=1
拿到第四段 flag:
InTerest1ng}
拼在一起就是:
Cyber{Aud1t_1s_re0l_InTerest1ng}
整个 Web2 的 payload:
curl 'http://149.28.199.89:2223/?source=1&password%5B%5D=1&equal_md5_1=s878926199a&equal_md5_2=s155964671a&data=php%3A%2F%2Finput&fake=lalala%0a&boom%5B%5D=1' -H 'Pragma: no-cache' -H 'Origin: chrome-extension://aejoelaoggembcahagimdiliamlcdmfm' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36' -H 'Content-Type: text/plain' -H 'Accept: */*' -H 'Cache-Control: no-cache' -H 'Connection: keep-alive' --data-binary 'web_1s_rea1_funny' --compressed
我做的时候是用部长之前推荐的 Chrome 插件:Restlet Client,可以直接发送 GET / POST 请求。我之前写微信小程序时后端的各种接口都是拿这个测试的。十分的舒服。
总结一下
以上两道题就是这样。真的是学到了不少东西啊。
那么我就来简单总结一下吧,首先是 Web1,学长出这个题的时候装 XAMPP 环境的时候没搞干净啊。直接访问 IP 进入 XAMPP 默认的欢迎界面,然后右上角直接进入看phpinfo()
刺不刺激?看到 MySQL 那边都是一片空,我大概推测这题一路下来应该没什么 SQL 注入。
如果绑了数据库,看到了账号密码,想想看会有多刺激2333。
然后 Web1 之前一直耗在那个登录界面,F12 看到页面中被注释掉的 JS 原本是要转到login.php
。试了下,发现它会把userName
和pwd
强制转换成数字,然后输出它们相加的结果。一个计算器哈哈哈。
我也尝试了传科学计数法的数字,它同样也会计算。所以我在之后的“首先你得有一个亿”才会想到也传科学计数法试试。
嘛,总之第一题当时很懵逼,不知道该怎么办才好,抱怨这题怎么这么奇葩。302 跳转抓包后才发现我真的就是想太多。
Web2 满满的干货,让我涨了不少见识。以后开发中也要多注意安全问题啊!
玩得很开心。学长们都很棒!只是菜鸡的我只会做 web 题。QAQ
喜欢这篇文章?为什么不打赏一下呢?