起因

以前曾经在微博上看到过Html5的新特性可以用于新的Web攻击,其中提到文件夹上传可以用于欺骗。觉得有点意思,后来又看到蘑菇在创宇的官博上面写了一篇博客:

http://blog.knownsec.com/2015/11/html5-upload-folder-with-webkitdirectory-phishing/

感觉的该说的都被他说了,嘛,不过这个东西,可以拿出来逗大家玩玩消遣一下时间0w0,但是这个是PHP的,而且明显任意上传可以直接GetShell,不想在服务器上装PHP。于是想着用Python实现一番。

Python实现文件夹上传

主要问题在于先用的Python Web框架支不支持文件上传呢?写小玩意儿的时候我喜欢用flask,简单可定制强。于是调查了一番Flask对文件夹上传的支持,发现:其实对于后端来说,Html5的文件夹上传和以前的多文件上传并没有什么不一样,那就简单了-w-

直接上代码:(有点乱,我去整理整理)

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# -*- coding: utf-8 -*-

from flask import (
Flask,
request,
render_template,
send_from_directory,
url_for,
jsonify
)
from werkzeug import secure_filename
import logging
import os

import logging

logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)

fh = logging.FileHandler('log.txt')
fh.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh)
logger.addHandler(ch)

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)



app.config['ALLOWED_EXTENSIONS'] = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])


def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']


@app.context_processor
def override_url_for():
return dict(url_for=dated_url_for)


def dated_url_for(endpoint, **values):
if endpoint == 'js_static':
filename = values.get('filename', None)
if filename:
file_path = os.path.join(app.root_path,
'static/js', filename)
values['q'] = int(os.stat(file_path).st_mtime)
elif endpoint == 'css_static':
filename = values.get('filename', None)
if filename:
file_path = os.path.join(app.root_path,
'static/css', filename)
values['q'] = int(os.stat(file_path).st_mtime)
return url_for(endpoint, **values)


@app.route('/css/<path:filename>')
def css_static(filename):
return send_from_directory(app.root_path + '/static/css/', filename)


@app.route('/js/<path:filename>')
def js_static(filename):
return send_from_directory(app.root_path + '/static/js/', filename)


@app.route('/')
def index():
return render_template('index.html')

import os, errno

def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5 (except OSError, exc: for Python <2.5)
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise


@app.route('/xiazaizhong', methods=['POST'])
def upldfile():
print "########################"
filelist = request.files.getlist("file")
print request.remote_addr
print request.user_agent
for upload in filelist:
filename = upload.filename.encode('utf-8')
lpdir = upload.filename.rsplit("/")[0:-1]
if len(lpdir) is not 1:
pdir = '/'.join(lpdir)
elif len(lpdir) is 1:
pdir = lpdir[0]
mkdir_p(pdir)
upload.save(filename)
print "########################"
return "xiazaichenggong0w0"


if __name__ == '__main__':
app.run(host="0.0.0.0", debug=False, port=80)

结局和不足:

结局:

看到一大堆访问的IP不假,但是真实上传上来的文件夹却没有几个。不过大家 好像玩得挺开心的:

不足:

  1. 根据网速的不同,一般都上传不上来- -
  2. 阿里云的服务器还是有点渣啊
  3. Flask访问的人一多好像确实不给力
  4. 前端没改0w-感觉不好看(然而并没有什么关系

参考:

  1. http://sapphion.com/2011/11/21/html5-folder-upload-with-webkitdirectory/
  2. https://laike9m.com/blog/wen-jian-jia-shang-chuan-cong-qian-duan-dao-hou-duan,59/

本文URL: https://blog.neargle.com/2015/12/01/html5-file-upload-flask-ver-python-ver/index.html