From 5949d7624ffd4b71f584289c9ebe45d053a09681 Mon Sep 17 00:00:00 2001 From: jose Date: Mon, 6 Jul 2020 10:33:41 +0800 Subject: [PATCH] 6.7.5 --- BTPanel/__init__.py | 20 +- BTPanel/static/css/site.css | 15 +- BTPanel/static/js/files.js | 14 +- BTPanel/static/js/public.js | 2 +- BTPanel/static/js/site.js | 13 +- BTPanel/static/js/soft.js | 187 +++++--- BTPanel/templates/default/layout.html | 2 +- class/ajax.py | 6 +- class/common.py | 2 +- class/config.py | 2 + class/data.py | 54 +-- class/database.py | 9 +- class/files.py | 42 +- class/jobs.py | 2 +- class/panelApi.py | 11 + class/panelPHP.py | 3 +- class/panelPlugin.py | 33 +- class/panelRedirect.py | 2 - class/panelSite.py | 43 +- class/public.py | 68 ++- class/ssh_security.py | 16 +- class/userlogin.py | 7 +- class/webshell_check.py | 638 +++++++++++++------------- class/wxapp.py | 44 +- config/config.json | 2 +- data/node.json | 42 +- 26 files changed, 730 insertions(+), 549 deletions(-) diff --git a/BTPanel/__init__.py b/BTPanel/__init__.py index ebbc1faf..e0029756 100644 --- a/BTPanel/__init__.py +++ b/BTPanel/__init__.py @@ -304,6 +304,7 @@ def login(): if session['login'] != False: session['login'] = False cache.set('dologin',True) + public.WriteLog('User LogOut','Client: {}, has manually exited the panel'.format(public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')))) session.clear() session_path = r'/dev/shm/session_py' + str(sys.version_info[0]) if os.path.exists(session_path): public.ExecShell("rm -f " + session_path + '/*') @@ -337,6 +338,7 @@ def login(): data['hosts'] = '[]' else: data['hosts'] = json.dumps(data['hosts']) + data['app_login'] = os.path.exists('data/app_login.pl') return render_template( 'login.html', data=data @@ -435,10 +437,10 @@ def database(pdata = None): def get_phpmyadmin_dir(): path = public.GetConfigValue('setup_path') + '/phpmyadmin' if not os.path.exists(path): return None - + phpport = '888' try: - import re; + import re if session['webserver'] == 'nginx': filename =public.GetConfigValue('setup_path') + '/nginx/conf/nginx.conf' conf = public.readFile(filename) @@ -446,13 +448,21 @@ def get_phpmyadmin_dir(): rtmp = re.search(rep,conf) if rtmp: phpport = rtmp.groups()[0] - else: + if session['webserver'] == 'apache': filename = public.GetConfigValue('setup_path') + '/apache/conf/extra/httpd-vhosts.conf' conf = public.readFile(filename) rep = "Listen\s+([0-9]+)\s*\n" rtmp = re.search(rep,conf) if rtmp: phpport = rtmp.groups()[0] + if session['webserver'] == 'openlitespeed': + filename = public.GetConfigValue('setup_path') + '/panel/vhost/openlitespeed/listen/888.conf' + public.writeFile('/tmp/2',filename) + conf = public.readFile(filename) + rep = "address\s*\*\:\s*(\d+)" + rtmp = re.search(rep,conf) + if rtmp: + phpport = rtmp.groups()[0] except: pass @@ -488,7 +498,7 @@ def api(pdata = None): if comReturn: return comReturn import panelApi api_object = panelApi.panelApi() - defs = ('get_token','check_bind','get_bind_status','get_apps','add_bind_app','remove_bind_app','set_token','get_tmp_token','get_app_bind_status') + defs = ('get_token','check_bind','get_bind_status','get_apps','add_bind_app','remove_bind_app','set_token','get_tmp_token','get_app_bind_status','login_for_app') return publicObject(api_object,defs,None,pdata) @app.route('/get_app_bind_status',methods=method_all) @@ -1309,7 +1319,7 @@ def get_pd(): 34, 98, 116, 46, 115, 111, 102, 116, 46, 117, 112, 100, 97, 116, 97, 95, 112, 114, 111, 40, 41, 34, 62, 32493, 36153, 60, 47, 97, 62, 60, 47, 115, 112, 97, 110, 62]) - elif tmp >= 0: + if tmp >= 0 and ltd in [-1,-2]: if tmp == 0: tmp2 = public.to_string([27704,20037,25480,26435]) tmp3 = public.to_string([60, 115, 112, 97, 110, 32, 99, 108, 97, 115, 115, 61, 34, 98, 116, diff --git a/BTPanel/static/css/site.css b/BTPanel/static/css/site.css index 18c3ac80..42a099d6 100644 --- a/BTPanel/static/css/site.css +++ b/BTPanel/static/css/site.css @@ -4925,11 +4925,11 @@ select[disabled]{ ::-webkit-scrollbar { /*滚动条整体样式*/ width : 10px; /*高宽分别对应横竖滚动条的尺寸*/ - height: 1px; + height: 10px; } ::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ - border-radius: 10px; + border-radius: 0; box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2); background : #999; } @@ -5382,7 +5382,7 @@ select[disabled]{ .ace_catalogue_list::-webkit-scrollbar { /*滚动条整体样式*/ width: 9px; /*高宽分别对应横竖滚动条的尺寸*/ - height: 1px; + height: 10px; } .ace_catalogue_list::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ @@ -5466,18 +5466,17 @@ select[disabled]{ .ace_scrollbar::-webkit-scrollbar { /*滚动条整体样式*/ width : 10px; /*高宽分别对应横竖滚动条的尺寸*/ - height: 1px; + height: 10px; } .ace_scrollbar::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); - background: #999; - border-radius: 10px; + background: #777; } .ace_scrollbar::-webkit-scrollbar-track{ /*滚动条里面轨道*/ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); - background: #ededed; + background: #333; border-radius: 10px; } .ace_editors.active { @@ -6769,7 +6768,7 @@ select[disabled]{ .dropUpLoadFile::-webkit-scrollbar { /*滚动条整体样式*/ width : 15px; /*高宽分别对应横竖滚动条的尺寸*/ - height: 1px; + height: 10px; } .dropUpLoadFile::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ diff --git a/BTPanel/static/js/files.js b/BTPanel/static/js/files.js index f043cb71..16cf739f 100644 --- a/BTPanel/static/js/files.js +++ b/BTPanel/static/js/files.js @@ -87,7 +87,7 @@ var fileDrop = { clearTimeout(time); return false; } - if(/^\.\w*/.test(filesAndDirs[i].name) ||/\/\.\w*/g.test(path)) continue; //排查隐藏文件目录和文件 + // if(/^\.\w*/.test(filesAndDirs[i].name) ||/\/\.\w*/g.test(path)) continue; //排查隐藏文件目录和文件 fileDrop.filesList.push({ file:filesAndDirs[i], path:bt.get_file_path(path +'/'+ filesAndDirs[i].name).replace('//','/'), @@ -160,7 +160,7 @@ var fileDrop = { $('').change(function(e){ var files = e.target.files,arry = []; for(var i=0;i\ \ " + cnametext + fileMsg + "\ @@ -2037,7 +2037,7 @@ function UnZip(fileName, type) { type = (type == 1) ? 'tar' : 'zip' var umpass = ''; if (type == 'zip') { - umpass = '
' + lan.files.zip_pass_title + '
' + umpass = '
' + lan.files.zip_pass_title + '
' } var layers = layer.open({ type: 1, @@ -2047,9 +2047,9 @@ function UnZip(fileName, type) { title: lan.files.unzip_title, content: '
' + '
' + - '' + lan.files.unzip_name + '
' + - '
' + lan.files.unzip_to + '
' + umpass + - '
' + lan.files.unzip_coding + '
' + + '
' + lan.files.unzip_to + '
' + umpass + + '
' + lan.files.unzip_coding + '' + diff --git a/BTPanel/static/js/public.js b/BTPanel/static/js/public.js index ebaf3610..df85a86d 100644 --- a/BTPanel/static/js/public.js +++ b/BTPanel/static/js/public.js @@ -651,7 +651,7 @@ var aceEditor = { $('.ace_dir_tools').on('click','.upper_level',function(){ var _paths = $(this).attr('data-menu-path'); _this.reader_file_dir_menu({path:_paths,is_empty:true}); - $('.ace_catalogue_title').html('目录:'+ _paths).attr('title',_paths); + $('.ace_catalogue_title').html('Directory: '+ _paths).attr('title',_paths); }); // 新建文件(文件目录主菜单) $('.ace_dir_tools').on('click','.new_folder',function(e){ diff --git a/BTPanel/static/js/site.js b/BTPanel/static/js/site.js index 43d9ea94..b97288e2 100644 --- a/BTPanel/static/js/site.js +++ b/BTPanel/static/js/site.js @@ -1404,11 +1404,11 @@ var site = { } }); $('#ols').on('click', function() { - private.toggle(); - checked = private.is(':hidden') ? false : true; + var loadT = bt.load(); bt.send('switch_ols_private_cache', 'config/switch_ols_private_cache', { id: web.id }, function(res) { - var loadT = bt.load(); loadT.close(); + private.toggle(); + checked = private.is(':hidden') ? false : true; bt.msg(res); if (checked) { bt.send('get_ols_private_cache', 'config/get_ols_private_cache', { id: web.id }, function(fdata) { @@ -1514,7 +1514,7 @@ var site = { callback: function(obj) { if (bt.os == 'Linux') { var spath = filename; - if (obj.val() != lan.site.rewritename) spath = '/www/server/panel/rewrite/' + webserver + '/' + obj.val() + '.conf'; + if (obj.val() != lan.site.rewritename) spath = '/www/server/panel/rewrite/' + (webserver == 'openlitespeed'?'apache':webserver) + '/' + obj.val() + '.conf'; bt.files.get_file_body(spath, function(ret) { editor.setValue(ret.data); }) @@ -1635,7 +1635,8 @@ var site = {
  • This is primary configuration file of the site, do NOT modify it at will if you do not know configuration rules.
  • \ '; $("#webedit-con").html(con); - var config = bt.aceEditor({ el: 'siteConfigBody', path: '/www/server/panel/vhost/' + bt.get_cookie('serverType') + '/' + web.name + '.conf' }) + var webserve = bt.get_cookie('serverType'), + config = bt.aceEditor({ el: 'siteConfigBody', path: '/www/server/panel/vhost/' + (webserve == 'openlitespeed' ? (webserve + '/detail') : webserve) + '/' + web.name + '.conf' }); $("#OnlineEditFileBtn").click(function(e) { bt.saveEditor(config); }); @@ -3141,7 +3142,7 @@ var site = { content: "
    " }) setTimeout(function() { - var webcache = bt.get_cookie('serverType') == 'openlitespeed' ? { title: 'LSCache', callback: site.edit.ols_cache } : ''; + var webcache = bt.get_cookie('serverType') == 'openlitespeed' ? { title: 'LS-Cache', callback: site.edit.ols_cache } : ''; var menus = [ { title: lan.site.domain_man, callback: site.edit.set_domains }, { title: lan.site.site_menu_1, callback: site.edit.set_dirbind }, diff --git a/BTPanel/static/js/soft.js b/BTPanel/static/js/soft.js index 2af2ff51..6a87bb1b 100644 --- a/BTPanel/static/js/soft.js +++ b/BTPanel/static/js/soft.js @@ -98,7 +98,31 @@ var soft = { click_opt += ' onclick="soft.set_soft_config(\'' + item.name + '\')" '; } } - if (rdata.apache22 && item.name.indexOf('php-') >= 0 && $.inArray(item.name, phps) == -1) click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; + var is_php5 = item.name.indexOf('php-5') >= 0, + webcache = bt.get_cookie('serverType') == 'openlitespeed' ? true : false, + distribution = bt.get_cookie('distribution'); + if (webcache) { + switch (distribution) { + case 'centos8': + if (is_php5 || item.name == 'php-7.0') { + click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; + } + break; + case 'centos7': + if (item.name == 'php-5.2') { + click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; + } + break; + default: + if (is_php5) { + click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; + } + break; + } + }else if (rdata.apache22 && item.name.indexOf('php-') >= 0 && $.inArray(item.name, phps) == -1){ + click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; + } + //if (rdata.apache22 && item.name.indexOf('php-') >= 0 && $.inArray(item.name, phps) == -1) click_opt = ' title="' + lan.soft.ap2_2_not_support + '"'; return '' + item.title + ' ' + version + ''; } }, @@ -254,73 +278,116 @@ var soft = { var is_php = item.name.indexOf('php-') >= 0, is_php5 = item.name.indexOf('php-5') >= 0, webcache = bt.get_cookie('serverType') == 'openlitespeed' ? true : false, - distribution = bt.get_cookie('distribution'), - redhat = rdata.Redhat; - if (rdata.apache22 && is_php && $.inArray(item.name, phps) == -1) { - if (item.setup) { - option = '' + lan.soft.uninstall + ''; - } else { + distribution = bt.get_cookie('distribution'); + if (webcache && is_php) { + if ((is_php5 || item.name == 'php-7.0') && distribution=='centos8') { option = '' + lan.soft.not_comp + ''; - } - } else if (rdata.apache24 && item.name == 'php-5.2') { - if (item.setup) { - option = '' + lan.soft.uninstall + ''; - } else { + }else if (distribution=='centos7'&&item.name == 'php-5.2') { option = '' + lan.soft.not_comp + ''; - } - } else { - if (item.setup && item.task == '1') { - if (pay_opt == '') { - if (item.versions.length > 1) { - for (var i = 0; i < item.versions.length; i++) { - var min_version = item.versions[i] - var ret = bt.check_version(item.version, min_version.m_version + '.' + min_version.version); - if (ret > 0) { - if (ret == 2) option += '' + lan.soft.update + ' | '; - break; + }else{ + if (is_php5) { + option = '' + lan.soft.not_comp + ''; + } else { + if (item.setup && item.task == '1') { + if (pay_opt == '') { + if (item.versions.length > 1) { + for (var i = 0; i < item.versions.length; i++) { + var min_version = item.versions[i] + var ret = bt.check_version(item.version, min_version.m_version + '.' + min_version.version); + if (ret > 0) { + if (ret == 2) option += '' + lan.soft.update + ' | '; + break; + } + } + } else { + var min_version = item.versions[0]; + var cloud_version = min_version.m_version + '.' + min_version.version; + if (item.version != cloud_version) option += '' + lan.soft.update + ' | '; } + if (item.admin) { + option += '' + lan.soft.setup + ' | '; + } else { + option += '' + lan.soft.setup + ' | '; + } + } else { + option = pay_opt + ' | ' + option; + } + option += '' + lan.soft.uninstall + ''; + } else if (item.task == '-1') { + option = '' + lan.soft.installing + ''; + soft.is_install = true; + } else if (item.task == '0') { + option = '' + lan.soft.wait_install + ''; + soft.is_install = true; + } else if (item.task == '-2') { + option = 'Updating'; + soft.is_install = true; + } else { + if (pay_opt) { + option = pay_opt; + } else { + option = '' + lan.soft.install + ''; + } + } + } + } + }else { + if (rdata.apache22 && is_php && $.inArray(item.name, phps) == -1) { + if (item.setup) { + option = '' + lan.soft.uninstall + ''; + } else { + option = '' + lan.soft.not_comp + ''; + } + } else if (rdata.apache24 && item.name == 'php-5.2') { + if (item.setup) { + option = '' + lan.soft.uninstall + ''; + } else { + option = '' + lan.soft.not_comp + ''; + } + } else { + if (item.setup && item.task == '1') { + if (pay_opt == '') { + if (item.versions.length > 1) { + for (var i = 0; i < item.versions.length; i++) { + var min_version = item.versions[i] + var ret = bt.check_version(item.version, min_version.m_version + '.' + min_version.version); + if (ret > 0) { + if (ret == 2) option += '' + lan.soft.update + ' | '; + break; + } + } + } else { + var min_version = item.versions[0]; + var cloud_version = min_version.m_version + '.' + min_version.version; + if (item.version != cloud_version) option += '' + lan.soft.update + ' | '; + } + if (item.admin) { + option += '' + lan.soft.setup + ' | '; + } else { + option += '' + lan.soft.setup + ' | '; } } else { - var min_version = item.versions[0]; - var cloud_version = min_version.m_version + '.' + min_version.version; - if (item.version != cloud_version) option += '' + lan.soft.update + ' | '; + option = pay_opt + ' | ' + option; } - if (item.admin) { - option += '' + lan.soft.setup + ' | '; + option += '' + lan.soft.uninstall + ''; + } else if (item.task == '-1') { + option = '' + lan.soft.installing + ''; + soft.is_install = true; + } else if (item.task == '0') { + option = '' + lan.soft.wait_install + ''; + soft.is_install = true; + } else if (item.task == '-2') { + option = 'Updating'; + soft.is_install = true; + } else { + if (pay_opt) { + option = pay_opt; } else { - option += '' + lan.soft.setup + ' | '; + option = '' + lan.soft.install + ''; } - } else { - option = pay_opt + ' | ' + option; - } - option += '' + lan.soft.uninstall + ''; - } else if (item.task == '-1') { - option = '' + lan.soft.installing + ''; - soft.is_install = true; - } else if (item.task == '0') { - option = '' + lan.soft.wait_install + ''; - soft.is_install = true; - } else if (item.task == '-2') { - option = 'Updating'; - soft.is_install = true; - } else { - if (pay_opt) { - option = pay_opt; - } else { - option = '' + lan.soft.install + ''; } } } - if (webcache && is_php5) { - if (!redhat) { - option = '' + lan.soft.not_comp + ''; - } else if (item.name == 'php-5.2'){ - option = '' + lan.soft.not_comp + ''; - } - } - if (distribution=='centos8' && item.name == 'php-7.0') { - option = '' + lan.soft.not_comp + ''; - } return option; } } @@ -2747,13 +2814,15 @@ var soft = { type: 'button', width: '62px', callback: function(ldata) { - var datal = {}; + var datal = {}, + loadP = bt.load(); delete ldata.btn_fresh; delete ldata.btn_save; ldata['enableGzipCompress']=$("#enableGzipCompress").prop('checked')?1:0; ldata = JSON.stringify(ldata); datal = { array: ldata }; bt.send('set_ols_value', 'config/set_ols_value', datal, function(res) { + loadP.close(); soft.get_tab_contents(key, obj); bt.msg(res); }); @@ -2877,7 +2946,7 @@ function soft_td_width_auto() { } else { thead_width = winWidth / 3.5; } - $('#softList thead th:eq(2)').width(thead_width); + //$('#softList thead th:eq(2)').width(thead_width); $('#softList tbody tr td:nth-child(8n+2)>span').width(thead_width + 75); } diff --git a/BTPanel/templates/default/layout.html b/BTPanel/templates/default/layout.html index b050f93e..286b2fa3 100644 --- a/BTPanel/templates/default/layout.html +++ b/BTPanel/templates/default/layout.html @@ -89,7 +89,7 @@ {% block content %}{% endblock %}
    diff --git a/class/ajax.py b/class/ajax.py index a4814fb9..96967d1e 100644 --- a/class/ajax.py +++ b/class/ajax.py @@ -654,7 +654,7 @@ class ajax: public.writeFile(p_file,'') phpinfo = public.request_php(get.version,'/phpinfo.php',p_file,'') if os.path.exists(p_file): os.remove(p_file) - return phpinfo.decode(); + return phpinfo.decode() #清理日志 def delClose(self,get): @@ -868,7 +868,7 @@ class ajax: if get.port in rulePort: return public.returnMsg(False,'AJAX_PHPMYADMIN_PORT_ERR') if public.get_webserver() == 'nginx': - rep = "listen\s+([0-9]+)\s*;" + rep = r"listen\s+([0-9]+)\s*;" oldPort = re.search(rep,conf).groups()[0] conf = re.sub(rep,'listen ' + get.port + ';\n',conf) elif public.get_webserver() == 'apache': @@ -937,7 +937,7 @@ class ajax: return public.returnMsg(True,'SOFT_PHPMYADMIN_STATUS',(msg,)) #except: #return public.returnMsg(False,'ERROR'); - + def ToPunycode(self,get): import re; get.domain = get.domain.encode('utf8') diff --git a/class/common.py b/class/common.py index 3f91b2a9..c2269524 100644 --- a/class/common.py +++ b/class/common.py @@ -34,7 +34,7 @@ class panelSetup: ua = ua.lower() if ua.find('spider') != -1 or ua.find('bot') != -1: return redirect('https://www.google.com') - g.version = '6.7.2' + g.version = '6.7.5' g.title = public.GetConfigValue('title') g.uri = request.path if not os.path.exists('data/debug.pl'): diff --git a/class/config.py b/class/config.py index ccce0ade..04f563e9 100644 --- a/class/config.py +++ b/class/config.py @@ -415,6 +415,8 @@ class config: ols_php_path = '/usr/local/lsws/lsphp' + get.version + '/etc/php.ini' if not os.path.exists(filename): return public.returnMsg(False,'PHP_NOT_EXISTS') for file in [filename,ols_php_path]: + if not os.path.exists(file): + continue phpini = public.readFile(file) rep = r"disable_functions\s*=\s*.*\n" phpini = re.sub(rep, 'disable_functions = ' + get.disable_functions + "\n", phpini) diff --git a/class/data.py b/class/data.py index 6746045a..afb368fa 100644 --- a/class/data.py +++ b/class/data.py @@ -45,34 +45,36 @@ class data: return result def get_site_ssl_info(self,siteName): - s_file = 'vhost/nginx/{}.conf'.format(siteName) - is_apache = False - if not os.path.exists(s_file): - s_file = 'vhost/apache/{}.conf'.format(siteName) - is_apache = True + try: + s_file = 'vhost/nginx/{}.conf'.format(siteName) + is_apache = False + if not os.path.exists(s_file): + s_file = 'vhost/apache/{}.conf'.format(siteName) + is_apache = True - if not os.path.exists(s_file): - return -1 + if not os.path.exists(s_file): + return -1 - s_conf = public.readFile(s_file) - if not s_conf: return -1 - ssl_file = None - if is_apache: - if s_conf.find('SSLCertificateFile') == -1: - return -1 - s_tmp = re.findall(r"SSLCertificateFile\s+(.+\.pem)",s_conf) - if not s_tmp: return -1 - ssl_file = s_tmp[0] - else: - if s_conf.find('ssl_certificate') == -1: - return -1 - s_tmp = re.findall(r"ssl_certificate\s+(.+\.pem);",s_conf) - if not s_tmp: return -1 - ssl_file = s_tmp[0] - ssl_info = public.get_cert_data(ssl_file) - if not ssl_info: return -1 - ssl_info['endtime'] = int(int(time.mktime(time.strptime(ssl_info['notAfter'], "%Y-%m-%d")) - time.time()) / 86400) - return ssl_info + s_conf = public.readFile(s_file) + if not s_conf: return -1 + ssl_file = None + if is_apache: + if s_conf.find('SSLCertificateFile') == -1: + return -1 + s_tmp = re.findall(r"SSLCertificateFile\s+(.+\.pem)",s_conf) + if not s_tmp: return -1 + ssl_file = s_tmp[0] + else: + if s_conf.find('ssl_certificate') == -1: + return -1 + s_tmp = re.findall(r"ssl_certificate\s+(.+\.pem);",s_conf) + if not s_tmp: return -1 + ssl_file = s_tmp[0] + ssl_info = public.get_cert_data(ssl_file) + if not ssl_info: return -1 + ssl_info['endtime'] = int(int(time.mktime(time.strptime(ssl_info['notAfter'], "%Y-%m-%d")) - time.time()) / 86400) + return ssl_info + except: return -1 #return "{}:{}".format(ssl_info['issuer'],ssl_info['notAfter']) diff --git a/class/database.py b/class/database.py index cf846167..81246b14 100644 --- a/class/database.py +++ b/class/database.py @@ -118,6 +118,7 @@ ssl-key=/www/server/data/server-key.pem if "ssl-ca" not in conf: conf = re.sub('\[mysqld\]','[mysqld]'+ssl_conf,conf) public.writeFile(conf_file,conf) + public.ExecShell('chown mysql.mysql /www/server/data/*.pem') return public.returnMsg(True,"Open successfully, take effect after manually restarting the database") # 检查mysqlssl状态 @@ -646,6 +647,11 @@ SetLink #设置数据库权限 def SetDatabaseAccess(self,get): + ssl = "" + if hasattr(get,'ssl'): + ssl = get.ssl + if ssl == "REQUIRE SSL" and not self.check_mysql_ssl_status(get): + return public.returnMsg(False,'SSL is not enabled in the database, please open it in the Mysql manager first') name = get['name'] db_name = public.M('databases').where('username=?',(name,)).getField('name') access = get['access'] @@ -657,9 +663,6 @@ SetLink users = mysql_obj.query("select Host from mysql.user where User='" + name + "' AND Host!='localhost'") for us in users: mysql_obj.execute("drop user '" + name + "'@'" + us[0] + "'") - ssl = "" - if hasattr(get,'ssl'): - ssl = get.ssl self.__CreateUsers(db_name,name,password,access,ssl) return public.returnMsg(True, 'SET_SUCCESS') diff --git a/class/files.py b/class/files.py index 96109edc..87550610 100644 --- a/class/files.py +++ b/class/files.py @@ -1742,27 +1742,27 @@ cd %s self.set_store_data(data) return public.returnMsg(True,'Successfully deleted!') - #单文件木马扫描 - def file_webshell_check(self,get): - if not 'filename' in get: return public.returnMsg(True, 'file does not exist!') - import webshell_check - if webshell_check.webshell_check().upload_file_url(get.filename.strip()): - return public.returnMsg(False,'This file is webshell [ %s ]'%get.filename.strip().split('/')[-1]) - else: - return public.returnMsg(True, 'no risk') - - #目录扫描木马 - def dir_webshell_check(self,get): - if not 'path' in get: return public.returnMsg(False, 'Please enter a valid directory!') - path=get.path.strip() - if os.path.exists(path): - #启动消息队列 - exec_shell = public.get_python_bin() + ' /www/server/panel/class/webshell_check.py dir %s mail'%path - task_name = "Scan Trojan files for directory %s"%path - import panelTask - task_obj = panelTask.bt_task() - task_obj.create_task(task_name, 0, exec_shell) - return public.returnMsg(True, 'Starting Trojan killing process. Details will be in the panel security log') + # #单文件木马扫描 + # def file_webshell_check(self,get): + # if not 'filename' in get: return public.returnMsg(True, 'file does not exist!') + # import webshell_check + # if webshell_check.webshell_check().upload_file_url(get.filename.strip()): + # return public.returnMsg(False,'This file is webshell [ %s ]'%get.filename.strip().split('/')[-1]) + # else: + # return public.returnMsg(True, 'no risk') + # + # #目录扫描木马 + # def dir_webshell_check(self,get): + # if not 'path' in get: return public.returnMsg(False, 'Please enter a valid directory!') + # path=get.path.strip() + # if os.path.exists(path): + # #启动消息队列 + # exec_shell = public.get_python_bin() + ' /www/server/panel/class/webshell_check.py dir %s mail'%path + # task_name = "Scan Trojan files for directory %s"%path + # import panelTask + # task_obj = panelTask.bt_task() + # task_obj.create_task(task_name, 0, exec_shell) + # return public.returnMsg(True, 'Starting Trojan killing process. Details will be in the panel security log') # 获取下载地址列表 def get_download_url_list(self, get): diff --git a/class/jobs.py b/class/jobs.py index c1c14f04..bfb81f28 100644 --- a/class/jobs.py +++ b/class/jobs.py @@ -100,7 +100,7 @@ def control_init(): public.ExecShell(c) p_file = 'class/plugin2.so' if os.path.exists(p_file): public.ExecShell("rm -f class/*.so") - public.ExecShell("chmod -R 600 /www/server/panel/data;chmod -R 600 /www/server/panel/config;chmod -R 700 /www/server/cron;chmod -R 600 /www/server/cron/*.log;chown -R root:root /www/server/panel/data;chown -R root:root /www/server/panel/config") + public.ExecShell("chmod -R 600 /www/server/panel/data;chmod -R 600 /www/server/panel/config;chmod -R 700 /www/server/cron;chmod -R 600 /www/server/cron/*.log;chown -R root:root /www/server/panel/data;chown -R root:root /www/server/panel/config;chown -R root:root /www/server/phpmyadmin;chmod -R 755 /www/server/phpmyadmin") #disable_putenv('putenv') clean_session() #set_crond() diff --git a/class/panelApi.py b/class/panelApi.py index 17959070..02cd56a7 100644 --- a/class/panelApi.py +++ b/class/panelApi.py @@ -30,6 +30,17 @@ class panelApi: del(data['key']) return data + + def login_for_app(self,get): + from BTPanel import cache + tid = get.tid + if(len(tid) != 12): return public.returnMsg(False,'Invalid login key') + session_id = cache.get(tid) + if not session_id: return public.returnMsg(False,'The specified key does not exist or has expired') + if(len(session_id) != 64): return public.returnMsg(False,'Invalid login key') + cache.set(session_id,'True',120) + return public.returnMsg(True,'Scan code successfully, log in!') + def get_api_config(self): tmp = public.ReadFile(self.save_path) if not tmp or not os.path.exists(self.save_path): diff --git a/class/panelPHP.py b/class/panelPHP.py index 3fadaf92..5e3793f0 100644 --- a/class/panelPHP.py +++ b/class/panelPHP.py @@ -90,7 +90,8 @@ class panelPHP: shutil.copy(src_php_ini,php_ini) #解除所有禁用函数 php_ini_body = public.readFile(php_ini) - php_ini_body = re.sub("disable_functions\s*=.*","disable_functions = ",php_ini_body) + php_ini_body = re.sub(r"disable_functions\s*=.*","disable_functions = ",php_ini_body) + php_ini_body = re.sub(r".*bt_filter.+","",php_ini_body) public.writeFile(php_ini,php_ini_body) return php_path + php_v + '/bin/php -c ' + php_ini diff --git a/class/panelPlugin.py b/class/panelPlugin.py index 5de234d6..7aaadb65 100644 --- a/class/panelPlugin.py +++ b/class/panelPlugin.py @@ -153,26 +153,6 @@ class panelPlugin: check_result = self.check_install_limit(get) if check_result: return check_result - # p_node = '/www/server/panel/install/public.sh' - # if os.path.exists(p_node): - # if len(public.readFile(p_node)) < 100: os.remove(p_node) - # if not pluginInfo: return public.returnMsg(False,'INIT_PLUGIN_NOT_EXISTS') - # if not self.check_mutex(pluginInfo['mutex']): return public.returnMsg(False,'UNINSTALL_FIRST' , (pluginInfo['mutex'],)) - # if not hasattr(get,'id'): - # if not self.check_dependnet(pluginInfo['dependnet']): return public.returnMsg(False,'DEP_PAGE' , (pluginInfo['dependnet'],)) - # if 'version' in get: - # for versionInfo in pluginInfo['versions']: - # if versionInfo['m_version'] != get.version: continue - # if not 'type' in get: get.type = '0' - # if int(get.type) > 4: get.type = '0' - # if get.type == '0': - # if not self.check_cpu_limit(versionInfo['cpu_limit']): return public.returnMsg(False,'At least [{0}] CPU cores are required to install'.format(versionInfo['cpu_limit'])) - # if not self.check_mem_limit(versionInfo['mem_limit']): return public.returnMsg(False,'At least [{0} MB] memory is required to install'.format(versionInfo['mem_limit'])) - # if not self.check_os_limit(versionInfo['os_limit']): - # m_ps = {0:public.GetMsg("ALL"),1:"Centos",2:"Ubuntu/Debian"} - # return public.returnMsg(False,'ONLY_SUP_SYS' , (m_ps[int(versionInfo['os_limit'])],)) - # if not hasattr(get,'id'): - # if not self.check_dependnet(versionInfo['dependnet']): return public.returnMsg(False,'DEP_PAGE' , (versionInfo['dependnet'],)) if pluginInfo['type'] != 5: result = self.install_sync(pluginInfo,get) @@ -235,7 +215,7 @@ class panelPlugin: if get.version == '1.8': return public.returnMsg(False,'NOT_SUP_NG1.8') if get.sName.find('php-') != -1:get.sName = get.sName.split('-')[0] ols_execstr = "" - if "php" == get.sName: + if "php" == get.sName and os.path.exists('/usr/local/lsws'): ols_sName = 'php-ols' ols_version = get.version.replace('.','') ols_execstr = " &> /tmp/panelExec.log && /bin/bash install_soft.sh {} {} " + ols_sName + " " + ols_version @@ -255,7 +235,7 @@ class panelPlugin: ols_execstr = ols_execstr.format(get.type,mtype) execstr = "cd /www/server/panel/install && /bin/bash install_soft.sh {} {} {} {} {}".format(get.type,mtype,get.sName,get.version,ols_execstr) if get.sName == "phpmyadmin": - execstr += "&> /tmp/panelExec.log && /usr/local/lsws/bin/lswsctrl restart" + execstr += "&> /tmp/panelExec.log && sleep 1 && /usr/local/lsws/bin/lswsctrl restart" public.M('tasks').add('id,name,type,status,addtime,execstr',(None, mmsg + '['+get.sName+'-'+get.version+']','execshell','0',time.strftime('%Y-%m-%d %H:%M:%S'),execstr)) cache.delete('install_task') public.writeFile('/tmp/panelTask.pl','True') @@ -700,16 +680,21 @@ class panelPlugin: if not os.path.exists(self.__index): public.writeFile(self.__index,'[]') indexList = json.loads(public.ReadFile(self.__index)) if sName in indexList: return public.returnMsg(False,'DONT_ADD_AGAIN') - if len(indexList) >= 12: softList = self.get_cloud_list(get)['list'] for softInfo in softList: + # return softList + if softInfo['name'] == 'php': + for i in softInfo['versions']: + php_v = 'php-'+ i['m_version'] + if not os.path.exists('/www/server/php/{}'.format(i['m_version']))\ + and php_v in indexList: + indexList.remove(php_v) if softInfo['name'] in indexList: new_softInfo = self.check_status(softInfo) if not new_softInfo['setup']: indexList.remove(softInfo['name']) public.writeFile(self.__index,json.dumps(indexList)) if len(indexList) >= 12: return public.returnMsg(False,'HP_DIS_MOST') - indexList.append(sName) public.writeFile(self.__index,json.dumps(indexList)) return public.returnMsg(True,'ADD_SUCCESS') diff --git a/class/panelRedirect.py b/class/panelRedirect.py index 902fee29..a7036e6d 100644 --- a/class/panelRedirect.py +++ b/class/panelRedirect.py @@ -154,11 +154,9 @@ class panelRedirect: #检测名称是否重复 if sys.version_info.major < 3: if len(get.redirectname) < 3 or len(get.redirectname) > 15: - print("NAME_LEN") return public.returnMsg(False, 'NAME_LEN') else: if len(get.redirectname.encode("utf-8")) < 3 or len(get.redirectname.encode("utf-8")) > 15: - print("NAME_LEN") return public.returnMsg(False, 'NAME_LEN') if self.__CheckRedirect(get.sitename,get.redirectname): return public.returnMsg(False, 'REDIRECT_EXIST') diff --git a/class/panelSite.py b/class/panelSite.py index c9f5ee6c..32d59768 100644 --- a/class/panelSite.py +++ b/class/panelSite.py @@ -329,7 +329,7 @@ extprocessor BTSITENAME { } phpIniOverride { -php_admin_value open_basedir "/tmp:$VH_ROOT" +php_admin_value open_basedir "/tmp/:BT_RUN_PATH" } expires { @@ -346,6 +346,10 @@ rewrite { } include /www/server/panel/vhost/openlitespeed/proxy/BTSITENAME/*.conf ''' + open_base_path = self.sitePath + if self.sitePath[-1] != '/': + open_base_path = self.sitePath + '/' + conf = conf.replace('BT_RUN_PATH',open_base_path) conf = conf.replace('BT_EXTP_NAME',self.siteName) conf = conf.replace('BTPHPV',self.phpVersion) conf = conf.replace('BTSITENAME',self.siteName) @@ -1128,7 +1132,7 @@ listener Default%s{ result = self.GetSiteRunPath(get) if 'runPath' in result: return result['runPath'] - return False + return result # 创建Let's Encrypt免费证书 @@ -2109,20 +2113,6 @@ listener SSL443 { public.writeFile(file,conf301) else: public.ExecShell('rm -f {}*'.format(file)) - # mconf = public.readFile(filename) - # if mconf == False: return public.returnMsg(False,'The specified configuration file does not exist!') - # if type == '1': - # if(srcDomain == 'all'): - # conf301 = "\n\t#301-START\n\tRewriteEngine on\n\tRewriteRule ^(.*)$ "+toDomain+"$1 [L,R=301]\n\t#301-END\n" - # else: - # conf301 = "\n\t#301-START\n\tRewriteEngine on\n\tRewriteCond %{HTTP_HOST} ^"+srcDomain+" [NC]\n\tRewriteRule ^(.*) "+toDomain+"$1 [L,R=301]\n\t#301-END\n" - # rep = "autoLoadHtaccess\s*1" - # mconf = mconf.replace(rep,rep + "\n\t" + conf301) - # else: - # rep = "\n\s+#301-START(.|\n){1,300}#301-END\n*" - # mconf = re.sub(rep, '\n\n', mconf,1) - # mconf = re.sub(rep, '\n\n', mconf,1) - # public.writeFile(filename,mconf) isError = public.checkWebConfig() if(isError != True): @@ -2501,10 +2491,12 @@ server public.writeFile(file,conf) # OLS - file = self.setupPath + '/panel/vhost/apache/' + Name + '.conf' + file = self.setupPath + '/panel/vhost/openlitespeed/' + Name + '.conf' conf = public.readFile(file) if conf: - sitname = Path.split('/')[-2] + reg = 'vhRoot.*' + conf = re.sub(reg,'vhRoot '+Path,conf) + public.writeFile(file,conf) #创建basedir userIni = Path + '/.user.ini' @@ -3026,11 +3018,6 @@ extprocessor %s { } """ % (get.proxyname,get.proxysite) public.writeFile(file_path,reverse_proxy_conf) - # detail_file = "%s/panel/vhost/openlitespeed/detail/%s.conf" % (self.setupPath,get.sitename) - # detail_conf = public.readFile(detail_file) - # if detail_conf: - # include_conf = "\ninclude %s/panel/vhost/openlitespeed/proxy/%s/*.conf" % (self.setupPath,get.sitename) - # public.writeFile(detail_file,include_conf,"a+") # 添加urlrewrite dir_path = "%s/panel/vhost/openlitespeed/proxy/%s/urlrewrite/" % (self.setupPath, get.sitename) if not os.path.exists(dir_path): @@ -3040,16 +3027,6 @@ extprocessor %s { RewriteRule ^%s(.*)$ http://%s/$1 [P,E=Proxy-Host:%s] """ % (get.proxydir,get.proxyname,get.todomain) public.writeFile(file_path,reverse_urlrewrite_conf) - # detail_file = "%s/panel/vhost/openlitespeed/detail/%s.conf" % (self.setupPath,get.sitename) - # detail_conf = public.readFile(detail_file) - # if detail_conf: - # include_conf = "\n include %s/panel/vhost/openlitespeed/proxy/%s/urlrewrite/*.conf" % (self.setupPath,get.sitename) - # rep = "autoLoadHtaccess\s+1" - # tmp = re.search(rep,detail_conf).group() - # tmp = tmp + include_conf - # detail_conf = re.sub(rep,tmp,detail_conf) - # public.writeFile(detail_file,detail_conf) - # 检查伪静态、主配置文件是否有location冲突 def CheckLocation(self,get): diff --git a/class/public.py b/class/public.py index d33ae040..17fb4720 100644 --- a/class/public.py +++ b/class/public.py @@ -533,19 +533,43 @@ def phpReload(version): else: ExecShell('/etc/init.d/php-fpm-' + version + ' reload') +def get_timeout(url,timeout=3): + try: + start = time.time() + result = int(httpGet(url,timeout)) + return result,int((time.time() - start) * 1000 - 500) + except: return 0,False + def get_url(timeout = 0.5): import json try: nodeFile = 'data/node.json' node_list = json.loads(readFile(nodeFile)) - mnode = None + mnode1 = [] + mnode2 = [] + mnode3 = [] for node in node_list: - node['ping'] = get_timeout(node['protocol'] + node['address'] + ':' + node['port'] + '/check.txt') + node['net'],node['ping'] = get_timeout(node['protocol'] + node['address'] + ':' + node['port'] + '/net_test',1) if not node['ping']: continue - if not mnode: mnode = node - if node['ping'] < mnode['ping']: mnode = node - if mnode['ping'] < 50: break - return mnode['protocol'] + mnode['address'] + ':' + mnode['port'] + if node['ping'] < 100: #当响应时间<100ms且可用带宽大于1500KB时 + if node['net'] > 1500: + mnode1.append(node) + elif node['net'] > 1000: + mnode3.append(node) + else: + if node['net'] > 1000: #当响应时间>=100ms且可用带宽大于1000KB时 + mnode2.append(node) + if node['ping'] < 100: + if node['net'] > 3000: break #有节点可用带宽大于3000时,不再检查其它节点 + if mnode1: #优选低延迟高带宽 + mnode = sorted(mnode1,key= lambda x:x['net'],reverse=True) + elif mnode3: #备选低延迟,中等带宽 + mnode = sorted(mnode3,key= lambda x:x['net'],reverse=True) + else: #终选中等延迟,中等带宽 + mnode = sorted(mnode2,key= lambda x:x['ping'],reverse=False) + + if not mnode: return 'http://download.bt.cn' + return mnode[0]['protocol'] + mnode[0]['address'] + ':' + mnode[0]['port'] except: return 'http://download.bt.cn' @@ -840,14 +864,6 @@ def hasPwd(password): import crypt return crypt.crypt(password,password) -def get_timeout(url,timeout=3): - try: - start = time.time() - result = httpGet(url,timeout) - if result != 'True': return False - return int((time.time() - start) * 1000) - except: return False - def getDate(format='%Y-%m-%d %X'): # 取格式时间 return time.strftime(format, time.localtime()) @@ -1723,6 +1739,30 @@ def get_linux_distribution(): distribution = 'centos7' return distribution +def long2ip(ips): + ''' + @name 将整数转换为IP地址 + @author hwliang<2020-06-11> + @param ips string(ip地址整数) + @return ipv4 + ''' + i1 = int(ips / (2 ** 24)) + i2 = int((ips - i1 * ( 2 ** 24 )) / ( 2 ** 16 )) + i3 = int(((ips - i1 * ( 2 ** 24 )) - i2 * ( 2 ** 16 )) / ( 2 ** 8)) + i4 = int(((ips - i1 * ( 2 ** 24 )) - i2 * ( 2 ** 16 )) - i3 * ( 2 ** 8)) + return "{}.{}.{}.{}".format(i1,i2,i3,i4) + +def ip2long(ip): + ''' + @name 将IP地址转换为整数 + @author hwliang<2020-06-11> + @param ip string(ipv4) + @return long + ''' + ips = ip.split('.') + if len(ips) != 4: return 0 + iplong = 2 ** 24 * int(ips[0]) + 2 ** 16 * int(ips[1]) + 2 ** 8 * int(ips[2]) + int(ips[3]) + return iplong #取通用对象 class dict_obj: diff --git a/class/ssh_security.py b/class/ssh_security.py index 418e2b23..790c0992 100644 --- a/class/ssh_security.py +++ b/class/ssh_security.py @@ -244,6 +244,12 @@ class ssh_security: 'addtime desc').select() return data + def get_server_ip(self): + if os.path.exists('/www/server/panel/data/iplist.txt'): + data=public.ReadFile('/www/server/panel/data/iplist.txt') + return data.strip() + else:return '127.0.0.1' + #登陆的情况下 def login(self): @@ -256,10 +262,14 @@ class ssh_security: ip = ["127.0.0.1"] if len(ip[0])==0:return False try: + import time + mDate = time.strftime('%Y-%m-%d %X', time.localtime()) if ip[0] in self.__ip_data: + if public.M('logs').where('type=? addtime', ('SSH security',mDate,)).count():return False public.WriteLog('SSH security', 'The server {} login IP is {}, login user is root'.format(public.GetLocalIp(),ip[0])) return False else: + if public.M('logs').where('type=? addtime', ('SSH security', mDate,)).count(): return False self.send_mail_data('Server {} login alarm'.format(public.GetLocalIp()),'There is a login alarm on the server {}, the login IP is {}, the login user is root'.format(public.GetLocalIp(),ip[0])) public.WriteLog('SSH security','There is a login alarm on the server {}, the login IP is {}, login user is root'.format(public.GetLocalIp(),ip [0])) return True @@ -438,7 +448,9 @@ if __name__ == '__main__': import sys type = sys.argv[1] if type=='login': - aa = ssh_security() - aa.login() + try: + aa = ssh_security() + aa.login() + except:pass else: pass diff --git a/class/userlogin.py b/class/userlogin.py index 8368dba2..2ad2154e 100644 --- a/class/userlogin.py +++ b/class/userlogin.py @@ -30,7 +30,7 @@ class userlogin: userInfo = u_info if 'code' in session: if session['code'] and not 'is_verify_password' in session: - if not hasattr(post, 'code'): return public.returnMsg(False,'Verification code can not be empty!') + if not hasattr(post, 'code'): return public.returnJson(False,'Verification code can not be empty!') if not public.checkCode(post.code): public.WriteLog('TYPE_LOGIN','LOGIN_ERR_CODE',('****','****',public.GetClientIp())) return public.returnJson(False,'CODE_ERR'),json_header @@ -218,7 +218,7 @@ class userlogin: session['login'] = True session['username'] = userInfo['username'] session['uid'] = userInfo['id'] - public.WriteLog('TYPE_LOGIN','LOGIN_SUCCESS',(userInfo['username'],public.GetClientIp())) + public.WriteLog('TYPE_LOGIN','LOGIN_SUCCESS',(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')))) self.limit_address('-') cache.delete('panelNum') cache.delete('dologin') @@ -226,6 +226,9 @@ class userlogin: public.writeFile(sess_input_path,str(int(time.time()))) self.set_request_token() self.login_token() + login_type = 'data/app_login.pl' + if os.path.exists(login_type): + os.remove(login_type) return public.returnJson(True,'LOGIN_SUCCESS'),json_header except Exception as ex: stringEx = str(ex) diff --git a/class/webshell_check.py b/class/webshell_check.py index bddfab85..efbfb59b 100644 --- a/class/webshell_check.py +++ b/class/webshell_check.py @@ -1,319 +1,319 @@ -# coding: utf-8 -# +------------------------------------------------------------------- -# | 宝塔Linux面板 x6 -# +------------------------------------------------------------------- -# | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved. -# +------------------------------------------------------------------- -# | Author: lkqiang -# +------------------------------------------------------------------- -# +-------------------------------------------------------------------- -# | 宝塔webshell 内置扫描 -# +-------------------------------------------------------------------- - -import public, hashlib, os, sys, json, time, re -import send_mail - - -class webshell_check: - __PATH = '/www/server/panel/data/' - __mail_config = '/www/server/panel/data/stmp_mail.json' - __mail_list_data = '/www/server/panel/data/mail_list.json' - __dingding_config = '/www/server/panel/data/dingding.json' - __mail_list = [] - __weixin_user = [] - - def __init__(self): - self.mail = send_mail.send_mail() - if not os.path.exists(self.__mail_list_data): - ret = [] - public.writeFile(self.__mail_list_data, json.dumps(ret)) - else: - try: - mail_data = json.loads(public.ReadFile(self.__mail_list_data)) - self.__mail_list = mail_data - except: - ret = [] - public.writeFile(self.__mail_list_data, json.dumps(ret)) - if not os.path.exists(self.__PATH + 'webshell_rule.json'): - rule = ["@\\$\\_\\(\\$\\_", "\\$\\_=\"\"", "\\${'\\_'", - "@preg\\_replace\\((\")*\\/(\\S)*\\/e(\")*,\\$_POST\\[\\S*\\]", "base64\\_decode\\(\\$\\_", - "'e'\\.'v'\\.'a'\\.'l'", "\"e\"\\.\"v\"\\.\"a\"\\.\"l\"", "\"e\"\\.\"v\"\\.\"a\"\\.\"l\"", - "\\$(\\w)+\\(\"\\/(\\S)+\\/e", "\\(array\\)\\$_(POST|GET|REQUEST|COOKIE)", "\\$(\\w)+\\(\\${", - "@\\$\\_=", "\\$\\_=\\$\\_", "chr\\((\\d)+\\)\\.chr\\((\\d)+\\)", "phpjm\\.net", "cha88\\.cn", - "c99shell", "phpspy", "Scanners", "cmd\\.php", "str_rot13", "webshell", "EgY_SpIdEr", - "tools88\\.com", "SECFORCE", "eval\\(('|\")\\?>", "preg_replace\\(\"\\/\\.\\*\\/e\"", - "assert\\(('|\"|\\s*)\\$", "eval\\(gzinflate\\(", "gzinflate\\(base64_decode\\(", - "eval\\(base64_decode\\(", "eval\\(gzuncompress\\(", "ies\",gzuncompress\\(\\$", - "eval\\(gzdecode\\(", "eval\\(str_rot13\\(", "gzuncompress\\(base64_decode\\(", - "base64_decode\\(gzuncompress\\(", "eval\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "assert\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "require\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "require_once\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "include\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "include_once\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", "call_user_func\\((\"|')assert(\"|')", - "call_user_func\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "\\$_(POST|GET|REQUEST|COOKIE)\\[([^\\]]+)\\]\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[", - "echo\\(file_get_contents\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "file_put_contents\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[([^\\]]+)\\],('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", - "fputs\\(fopen\\((.+),('|\")w('|\")\\),('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[", - "SetHandlerapplication\\/x-httpd-php", "php_valueauto_prepend_file", "php_valueauto_append_file"] - public.WriteFile(self.__PATH + 'webshell_rule.json', json.dumps(rule)) - - # 返回配置邮件地址 - def return_mail_list(self): - return self.__mail_list - - # 查看自定义邮箱配置 - def get_user_mail(self): - qq_mail_info = json.loads(public.ReadFile(self.__mail_config)) - if len(qq_mail_info) == 0: - return False - return qq_mail_info - - # 查看钉钉 - def get_dingding(self): - qq_mail_info = json.loads(public.ReadFile(self.__dingding_config)) - if len(qq_mail_info) == 0: - return False - return qq_mail_info - - # 查看能使用的告警通道 - def get_settings(self): - qq_mail_info = json.loads(public.ReadFile(self.__mail_config)) - if len(qq_mail_info) == 0: - user_mail = False - else: - user_mail = True - dingding_info = json.loads(public.ReadFile(self.__dingding_config)) - if len(dingding_info) == 0: - dingding = False - else: - dingding = True - ret = {} - ret['user_mail'] = {"user_name": user_mail, "mail_list": self.__mail_list, "info": self.get_user_mail()} - ret['dingding'] = {"dingding": dingding, "info": self.get_dingding()} - return ret - - # 返回站点 - def return_site(self): - data = public.M('sites').field('name,path').select() - ret = {} - for i in data: - ret[i['name']] = i['path'] - return public.returnMsg(True, ret) - - # 获取规则 - def get_rule(self): - ret = [] - if os.path.exists(self.__PATH + 'webshell_rule.json'): - try: - data = json.loads(public.ReadFile(self.__PATH + 'webshell_rule.json')) - return data - except: - return False - else: - return False - - def get_dir(self, path): - return_data = [] - data2 = [] - [[return_data.append(os.path.join(root, file)) for file in files] for root, dirs, files in os.walk(path)] - for i in return_data: - if str(i.lower())[-4:] == '.php': - data2.append(i) - return data2 - - # 目录 - def getdir_list(self, path_data): - if os.path.exists(str(path_data)): - return self.get_dir(path_data) - else: - return False - - # 扫描 - def scan(self, filelist, rule): - import time - time_data = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) - ret = [] - data2 = [] - for file in filelist: - try: - data = open(file).read() - for r in rule: - if re.compile(r).findall(data): - result = {} - result[file] = r - ret.append(result) - data = ("%s [!] %s %s \n" % (time_data, file, r)) - data2.append(file) - except:print('%s File opening failed! !! Skipping'%file) - return data2 - - # 上传webshell - def upload_shell(self, data): - if len(data) == 0: return [] - return_data = [] - for i in data: - if self.upload_file_url(i): - return_data.append(i) - return return_data - - def san_dir(self, path, send='mail'): - file = self.getdir_list(path) - if not file: return exit( "Directory does not exist") - rule = self.get_rule() - if not rule: return exit("Rule is empty or rule file is wrong") - result = self.scan(file, rule) - return_data = self.upload_shell(result) - tongdao = self.get_settings() - if len(return_data) >= 1: - if send == 'dingding': - if tongdao['dingding']: - msg="Webshell killing found the Trojan in the % s directory as follows:%s"%(path,return_data) - self.mail.dingding_send(msg) - elif send == 'mail': - if tongdao['user_mail']: - - title = "Webshell killing found the Trojan in the % s directory as follows" % (path) - body = "Webshell search and found that the Trojan exists in the %s directory as follows: %s" % (path, return_data) - if len(self.__mail_list)==0: - if tongdao['user_mail']['user_name']: - self.mail.qq_smtp_send(str(tongdao['user_mail']['info']['qq_mail']), title=title, body=body) - else: - for i in self.__mail_list: - if tongdao['user_mail']['user_name']: - self.mail.qq_smtp_send(str(i), title=title, body=body) - return return_data - - def send_san_dir(self, path, send): - file = self.getdir_list(path) - if not file: return exit( "Directory does not exist") - rule = self.get_rule() - if not rule: return exit("Rule is empty or rule file is wrong") - result = self.scan(file, rule) - return_data = self.upload_shell(result) - tongdao = self.get_settings() - if len(return_data) >= 1: - if send == 'dingding': - if tongdao['dingding']: - msg="Webshell search and found that the Trojan exists in the %s directory as follows: %s"%(path,return_data) - self.mail.dingding_send(msg) - elif send == 'mail': - if tongdao['user_mail']: - title = "Webshell killing found the Trojan in the %s directory as follows" % (path) - body = "Webshell search and found that the Trojan exists in the %s directory as follows: %s" % (path, return_data) - if len(self.__mail_list)==0: - self.mail.qq_smtp_send(str(tongdao['user_mail']['info']['qq_mail']), title=title, body=body) - else: - for i in self.__mail_list: - self.mail.qq_smtp_send(str(i), title=title, body=body) - return return_data - - def upload_file_url(self, filename): - try: - if os.path.exists(filename): - data = public.ExecShell( - '/usr/local/curl/bin/curl https://scanner.baidu.com/enqueue -F archive=@%s' % filename) - data = json.loads(data[0]) - time.sleep(3) - import http_requests - default_headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' - } - data_list = http_requests.get(url=data['url'], headers=default_headers, verify=False) - data2 = data_list.json() - if 'data' in data2[0]: - if len(data2[0]['data']) >= 1: - if 'descr' in data2[0]['data'][0]: - if 'WebShell' in data2[0]['data'][0]['descr']: - print('%s file is a Trojan'%filename) - self.send_baota2(filename) - return True - return False - else: - return False - except: - return False - - def read_file_md5(self, filename): - if os.path.exists(filename): - with open(filename, 'rb') as fp: - data = fp.read() - file_md5 = hashlib.md5(data).hexdigest() - return file_md5 - else: - return False - - def send_baota2(self, filename): - cloudUrl = 'http://www.bt.cn/api/panel/btwaf_submit' - pdata = {'codetxt': public.ReadFile(filename), 'md5': self.read_file_md5(filename), 'type': '0', - 'host_ip': public.GetLocalIp(), 'size': os.path.getsize(filename)} - ret = public.httpPost(cloudUrl, pdata) - return True - - def send_baota(self, filename): - if not os.path.exists(filename): return False - cloudUrl = 'http://www.bt.cn/api/panel/btwaf_submit' - pdata = {'codetxt': public.ReadFile(filename), 'md5': self.read_file_md5(filename), 'type': '0', - 'host_ip': public.GetLocalIp(), 'size': os.path.getsize(filename)} - ret = public.httpPost(cloudUrl, pdata) - if ret == '1': - return self.check_webshell(filename) - elif ret == '-1': - return self.check_webshell(filename) - else: - return False - - def check_webshell(self, filename): - if not os.path.exists(filename): return False - cloudUrl = 'http://www.bt.cn/api/panel/btwaf_check_file' - pdata = {'md5': self.read_file_md5(filename), 'size': os.path.getsize(filename)} - ret = public.httpPost(cloudUrl, pdata) - if ret == '0': - return False - elif ret == '1': - return False - elif ret == '-1': - return False - else: - return False - - def __get_md5(self, s): - m = hashlib.md5() - m.update(s.encode('utf-8')) - return m.hexdigest() - - -if __name__ == "__main__": - public.WriteFile('/www/server/panel/data/webshell_data.json', json.dumps([])) - type = sys.argv[1] - path = sys.argv[2] - send = sys.argv[3] - os.chdir("/www/server/panel") - import sys - sys.path.append('class') - import public - aa = webshell_check() - print('Start scanning webshell') - start_time=time.time() - if type == 'dir': - data = aa.san_dir(path) - public.WriteFile('/www/server/panel/data/webshell_data.json', json.dumps(data)) - localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) - if len(data) >= 1: - public.WriteLog('aaPanel built-in webshell killing','Killing the %s directory found the following Trojan %s'%(path,data)) - else: - public.WriteLog('aaPanel built-in webshell killing','Checking and killing [ %s ] directory did not find any risks'%(path)) - elif type=='site': - data = public.M('sites').where('name=?', (path,)).field('name,id,path').select() - localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) - if len(data) >= 1: - path = data[0]['path'] - ##木马返回在这里 - data = aa.send_san_dir(path, send) - if len(data) >= 1: - public.WriteLog('aaPanel built-in webshell killing', 'Killing the %s directory found the following Trojan %s' % (path, data)) - else: - public.WriteLog('aaPanel built-in webshell killing','Checking and killing [ %s ] directory did not find any risks'%(path)) - - +# # coding: utf-8 +# # +------------------------------------------------------------------- +# # | 宝塔Linux面板 x6 +# # +------------------------------------------------------------------- +# # | Copyright (c) 2015-2017 宝塔软件(http://bt.cn) All rights reserved. +# # +------------------------------------------------------------------- +# # | Author: lkqiang +# # +------------------------------------------------------------------- +# # +-------------------------------------------------------------------- +# # | 宝塔webshell 内置扫描 +# # +-------------------------------------------------------------------- +# +# import public, hashlib, os, sys, json, time, re +# import send_mail +# +# +# class webshell_check: +# __PATH = '/www/server/panel/data/' +# __mail_config = '/www/server/panel/data/stmp_mail.json' +# __mail_list_data = '/www/server/panel/data/mail_list.json' +# __dingding_config = '/www/server/panel/data/dingding.json' +# __mail_list = [] +# __weixin_user = [] +# +# def __init__(self): +# self.mail = send_mail.send_mail() +# if not os.path.exists(self.__mail_list_data): +# ret = [] +# public.writeFile(self.__mail_list_data, json.dumps(ret)) +# else: +# try: +# mail_data = json.loads(public.ReadFile(self.__mail_list_data)) +# self.__mail_list = mail_data +# except: +# ret = [] +# public.writeFile(self.__mail_list_data, json.dumps(ret)) +# if not os.path.exists(self.__PATH + 'webshell_rule.json'): +# rule = ["@\\$\\_\\(\\$\\_", "\\$\\_=\"\"", "\\${'\\_'", +# "@preg\\_replace\\((\")*\\/(\\S)*\\/e(\")*,\\$_POST\\[\\S*\\]", "base64\\_decode\\(\\$\\_", +# "'e'\\.'v'\\.'a'\\.'l'", "\"e\"\\.\"v\"\\.\"a\"\\.\"l\"", "\"e\"\\.\"v\"\\.\"a\"\\.\"l\"", +# "\\$(\\w)+\\(\"\\/(\\S)+\\/e", "\\(array\\)\\$_(POST|GET|REQUEST|COOKIE)", "\\$(\\w)+\\(\\${", +# "@\\$\\_=", "\\$\\_=\\$\\_", "chr\\((\\d)+\\)\\.chr\\((\\d)+\\)", "phpjm\\.net", "cha88\\.cn", +# "c99shell", "phpspy", "Scanners", "cmd\\.php", "str_rot13", "webshell", "EgY_SpIdEr", +# "tools88\\.com", "SECFORCE", "eval\\(('|\")\\?>", "preg_replace\\(\"\\/\\.\\*\\/e\"", +# "assert\\(('|\"|\\s*)\\$", "eval\\(gzinflate\\(", "gzinflate\\(base64_decode\\(", +# "eval\\(base64_decode\\(", "eval\\(gzuncompress\\(", "ies\",gzuncompress\\(\\$", +# "eval\\(gzdecode\\(", "eval\\(str_rot13\\(", "gzuncompress\\(base64_decode\\(", +# "base64_decode\\(gzuncompress\\(", "eval\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "assert\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "require\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "require_once\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "include\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "include_once\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", "call_user_func\\((\"|')assert(\"|')", +# "call_user_func\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "\\$_(POST|GET|REQUEST|COOKIE)\\[([^\\]]+)\\]\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[", +# "echo\\(file_get_contents\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "file_put_contents\\(('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[([^\\]]+)\\],('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)", +# "fputs\\(fopen\\((.+),('|\")w('|\")\\),('|\"|\\s*)\\$_(POST|GET|REQUEST|COOKIE)\\[", +# "SetHandlerapplication\\/x-httpd-php", "php_valueauto_prepend_file", "php_valueauto_append_file"] +# public.WriteFile(self.__PATH + 'webshell_rule.json', json.dumps(rule)) +# +# # 返回配置邮件地址 +# def return_mail_list(self): +# return self.__mail_list +# +# # 查看自定义邮箱配置 +# def get_user_mail(self): +# qq_mail_info = json.loads(public.ReadFile(self.__mail_config)) +# if len(qq_mail_info) == 0: +# return False +# return qq_mail_info +# +# # 查看钉钉 +# def get_dingding(self): +# qq_mail_info = json.loads(public.ReadFile(self.__dingding_config)) +# if len(qq_mail_info) == 0: +# return False +# return qq_mail_info +# +# # 查看能使用的告警通道 +# def get_settings(self): +# qq_mail_info = json.loads(public.ReadFile(self.__mail_config)) +# if len(qq_mail_info) == 0: +# user_mail = False +# else: +# user_mail = True +# dingding_info = json.loads(public.ReadFile(self.__dingding_config)) +# if len(dingding_info) == 0: +# dingding = False +# else: +# dingding = True +# ret = {} +# ret['user_mail'] = {"user_name": user_mail, "mail_list": self.__mail_list, "info": self.get_user_mail()} +# ret['dingding'] = {"dingding": dingding, "info": self.get_dingding()} +# return ret +# +# # 返回站点 +# def return_site(self): +# data = public.M('sites').field('name,path').select() +# ret = {} +# for i in data: +# ret[i['name']] = i['path'] +# return public.returnMsg(True, ret) +# +# # 获取规则 +# def get_rule(self): +# ret = [] +# if os.path.exists(self.__PATH + 'webshell_rule.json'): +# try: +# data = json.loads(public.ReadFile(self.__PATH + 'webshell_rule.json')) +# return data +# except: +# return False +# else: +# return False +# +# def get_dir(self, path): +# return_data = [] +# data2 = [] +# [[return_data.append(os.path.join(root, file)) for file in files] for root, dirs, files in os.walk(path)] +# for i in return_data: +# if str(i.lower())[-4:] == '.php': +# data2.append(i) +# return data2 +# +# # 目录 +# def getdir_list(self, path_data): +# if os.path.exists(str(path_data)): +# return self.get_dir(path_data) +# else: +# return False +# +# # 扫描 +# def scan(self, filelist, rule): +# import time +# time_data = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +# ret = [] +# data2 = [] +# for file in filelist: +# try: +# data = open(file).read() +# for r in rule: +# if re.compile(r).findall(data): +# result = {} +# result[file] = r +# ret.append(result) +# data = ("%s [!] %s %s \n" % (time_data, file, r)) +# data2.append(file) +# except:print('%s File opening failed! !! Skipping'%file) +# return data2 +# +# # 上传webshell +# def upload_shell(self, data): +# if len(data) == 0: return [] +# return_data = [] +# for i in data: +# if self.upload_file_url(i): +# return_data.append(i) +# return return_data +# +# def san_dir(self, path, send='mail'): +# file = self.getdir_list(path) +# if not file: return exit( "Directory does not exist") +# rule = self.get_rule() +# if not rule: return exit("Rule is empty or rule file is wrong") +# result = self.scan(file, rule) +# return_data = self.upload_shell(result) +# tongdao = self.get_settings() +# if len(return_data) >= 1: +# if send == 'dingding': +# if tongdao['dingding']: +# msg="Webshell killing found the Trojan in the % s directory as follows:%s"%(path,return_data) +# self.mail.dingding_send(msg) +# elif send == 'mail': +# if tongdao['user_mail']: +# +# title = "Webshell killing found the Trojan in the % s directory as follows" % (path) +# body = "Webshell search and found that the Trojan exists in the %s directory as follows: %s" % (path, return_data) +# if len(self.__mail_list)==0: +# if tongdao['user_mail']['user_name']: +# self.mail.qq_smtp_send(str(tongdao['user_mail']['info']['qq_mail']), title=title, body=body) +# else: +# for i in self.__mail_list: +# if tongdao['user_mail']['user_name']: +# self.mail.qq_smtp_send(str(i), title=title, body=body) +# return return_data +# +# def send_san_dir(self, path, send): +# file = self.getdir_list(path) +# if not file: return exit( "Directory does not exist") +# rule = self.get_rule() +# if not rule: return exit("Rule is empty or rule file is wrong") +# result = self.scan(file, rule) +# return_data = self.upload_shell(result) +# tongdao = self.get_settings() +# if len(return_data) >= 1: +# if send == 'dingding': +# if tongdao['dingding']: +# msg="Webshell search and found that the Trojan exists in the %s directory as follows: %s"%(path,return_data) +# self.mail.dingding_send(msg) +# elif send == 'mail': +# if tongdao['user_mail']: +# title = "Webshell killing found the Trojan in the %s directory as follows" % (path) +# body = "Webshell search and found that the Trojan exists in the %s directory as follows: %s" % (path, return_data) +# if len(self.__mail_list)==0: +# self.mail.qq_smtp_send(str(tongdao['user_mail']['info']['qq_mail']), title=title, body=body) +# else: +# for i in self.__mail_list: +# self.mail.qq_smtp_send(str(i), title=title, body=body) +# return return_data +# +# def upload_file_url(self, filename): +# try: +# if os.path.exists(filename): +# data = public.ExecShell( +# '/usr/local/curl/bin/curl https://scanner.baidu.com/enqueue -F archive=@%s' % filename) +# data = json.loads(data[0]) +# time.sleep(3) +# import http_requests +# default_headers = { +# 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' +# } +# data_list = http_requests.get(url=data['url'], headers=default_headers, verify=False) +# data2 = data_list.json() +# if 'data' in data2[0]: +# if len(data2[0]['data']) >= 1: +# if 'descr' in data2[0]['data'][0]: +# if 'WebShell' in data2[0]['data'][0]['descr']: +# print('%s file is a Trojan'%filename) +# self.send_baota2(filename) +# return True +# return False +# else: +# return False +# except: +# return False +# +# def read_file_md5(self, filename): +# if os.path.exists(filename): +# with open(filename, 'rb') as fp: +# data = fp.read() +# file_md5 = hashlib.md5(data).hexdigest() +# return file_md5 +# else: +# return False +# +# def send_baota2(self, filename): +# cloudUrl = 'http://www.bt.cn/api/panel/btwaf_submit' +# pdata = {'codetxt': public.ReadFile(filename), 'md5': self.read_file_md5(filename), 'type': '0', +# 'host_ip': public.GetLocalIp(), 'size': os.path.getsize(filename)} +# ret = public.httpPost(cloudUrl, pdata) +# return True +# +# def send_baota(self, filename): +# if not os.path.exists(filename): return False +# cloudUrl = 'http://www.bt.cn/api/panel/btwaf_submit' +# pdata = {'codetxt': public.ReadFile(filename), 'md5': self.read_file_md5(filename), 'type': '0', +# 'host_ip': public.GetLocalIp(), 'size': os.path.getsize(filename)} +# ret = public.httpPost(cloudUrl, pdata) +# if ret == '1': +# return self.check_webshell(filename) +# elif ret == '-1': +# return self.check_webshell(filename) +# else: +# return False +# +# def check_webshell(self, filename): +# if not os.path.exists(filename): return False +# cloudUrl = 'http://www.bt.cn/api/panel/btwaf_check_file' +# pdata = {'md5': self.read_file_md5(filename), 'size': os.path.getsize(filename)} +# ret = public.httpPost(cloudUrl, pdata) +# if ret == '0': +# return False +# elif ret == '1': +# return False +# elif ret == '-1': +# return False +# else: +# return False +# +# def __get_md5(self, s): +# m = hashlib.md5() +# m.update(s.encode('utf-8')) +# return m.hexdigest() +# +# +# if __name__ == "__main__": +# public.WriteFile('/www/server/panel/data/webshell_data.json', json.dumps([])) +# type = sys.argv[1] +# path = sys.argv[2] +# send = sys.argv[3] +# os.chdir("/www/server/panel") +# import sys +# sys.path.append('class') +# import public +# aa = webshell_check() +# print('Start scanning webshell') +# start_time=time.time() +# if type == 'dir': +# data = aa.san_dir(path) +# public.WriteFile('/www/server/panel/data/webshell_data.json', json.dumps(data)) +# localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +# if len(data) >= 1: +# public.WriteLog('aaPanel built-in webshell killing','Killing the %s directory found the following Trojan %s'%(path,data)) +# else: +# public.WriteLog('aaPanel built-in webshell killing','Checking and killing [ %s ] directory did not find any risks'%(path)) +# elif type=='site': +# data = public.M('sites').where('name=?', (path,)).field('name,id,path').select() +# localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +# if len(data) >= 1: +# path = data[0]['path'] +# ##木马返回在这里 +# data = aa.send_san_dir(path, send) +# if len(data) >= 1: +# public.WriteLog('aaPanel built-in webshell killing', 'Killing the %s directory found the following Trojan %s' % (path, data)) +# else: +# public.WriteLog('aaPanel built-in webshell killing','Checking and killing [ %s ] directory did not find any risks'%(path)) +# +# diff --git a/class/wxapp.py b/class/wxapp.py index 9f98478a..229acf49 100644 --- a/class/wxapp.py +++ b/class/wxapp.py @@ -15,7 +15,7 @@ import json import time import binascii import base64 -from BTPanel import session,cache +from BTPanel import session,cache,request class ScanLogin(object): # 扫码登录面板 @@ -32,15 +32,25 @@ class ScanLogin(object): self.app_path+'login.pl').split(':') if time.time() - float(init_time) < 60: return public.returnMsg(True, key) + session_id = public.get_session_id() + if cache.get(session_id) == 'True': + return public.returnMsg(True, 'Scan QRCORE successfully') return public.returnMsg(False, '') # 返回二维码地址 def login_qrcode(self, get): - qrcode_str = 'https://app.bt.cn/app.html?&panel_url='+public.getPanelAddr()+'&v=' + public.GetRandomString(3)+'?login'; + tid = public.GetRandomString(12) + qrcode_str = 'https://app.bt.cn/app.html?&panel_url='+public.getPanelAddr()+'&v=' + public.GetRandomString(3)+'?login&tid=' + tid + cache.set(tid,public.get_session_id(),360) + cache.set(public.get_session_id(),tid,360) return public.returnMsg(True, qrcode_str) # 设置登录状态 def set_login(self, get): + session_id = public.get_session_id() + if cache.get(session_id) == 'True': + return self.check_app_login(get) + if os.path.exists(self.app_path+"login.pl"): data = public.readFile(self.app_path+'login.pl') public.ExecShell('rm ' + self.app_path+"login.pl") @@ -53,10 +63,32 @@ class ScanLogin(object): session['username'] = userInfo['username'] cache.delete('panelNum') cache.delete('dologin') - public.WriteLog('TYPE_LOGIN', 'LOGIN_SUCCESS1', - (public.GetMsg("WECHAT_SCAN_QRCORE"), public.GetClientIp())) - return public.returnMsg(True, 'LOGIN_SUCCESS') - return public.returnMsg(False, 'LOGIN_FAIL') + public.WriteLog('TYPE_LOGIN', 'LOGIN_SUCCESS', + ('WeChat scan code login', public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')))) + login_type = 'data/app_login.pl' + public.writeFile(login_type,'True') + return public.returnMsg(True, 'login successful') + return public.returnMsg(False, 'Login failed') + + + #验证APP是否登录成功 + def check_app_login(self,get): + session_id = public.get_session_id() + if cache.get(session_id) != 'True': + return public.returnMsg(False,'Wait for the app to scan the code and log in') + cache.delete(session_id) + userInfo = public.M('users').where("id=?",(1,)).field('id,username').find() + session['login'] = True + session['username'] = userInfo['username'] + session['tmp_login'] = True + public.WriteLog('TYPE_LOGIN','APP scan code login, account: {}, login IP: {}'.format(userInfo['username'],public.GetClientIp()+ ":" + str(request.environ.get('REMOTE_PORT')))) + cache.delete('panelNum') + cache.delete('dologin') + sess_input_path = 'data/session_last.pl' + public.writeFile(sess_input_path,str(int(time.time()))) + login_type = 'data/app_login.pl' + public.writeFile(login_type,'True') + return public.returnMsg(True,'login successful!') class SelfModule(): ''' diff --git a/config/config.json b/config/config.json index d5228ae4..ffa66a58 100644 --- a/config/config.json +++ b/config/config.json @@ -1 +1 @@ -{"product": "Linux panel", "setup_path": "/www/server", "openlitespeed_path": "/usr/local", "language": "English", "title": "aaPanel Linux panel", "brand": "aaPanel", "root_path": "/www", "template": "default", "logs_path": "/www/wwwlogs", "home": "http://www.bt.cn", "recycle_bin": true} +{"product": "Linux panel", "setup_path": "/www/server", "openlitespeed_path": "/usr/local", "language": "English", "title": "aaPanel Linux panel", "brand": "aaPanel", "root_path": "/www", "template": "default", "logs_path": "/www/wwwlogs", "home": "https://console.aapanel.com", "recycle_bin": true} diff --git a/data/node.json b/data/node.json index cdf0becc..54be8df0 100644 --- a/data/node.json +++ b/data/node.json @@ -1,10 +1,46 @@ [ + { + "protocol": "http://", + "address": "128.1.164.196", + "port": "80", + "ping": 500 + }, { "protocol": "http://", "address": "103.224.251.67", "port": "80", "ping": 500 }, + { + "protocol": "http://", + "address": "45.76.53.20", + "port": "80", + "ping": 500 + }, + { + "protocol": "http://", + "address": "dg2.bt.cn", + "port": "80", + "ping": 500 + }, + { + "protocol": "http://", + "address": "dg1.bt.cn", + "port": "80", + "ping": 500 + }, + { + "protocol": "http://", + "address": "125.88.182.172", + "port": "5880", + "ping": 500 + }, + { + "protocol": "http://", + "address": "123.129.198.197", + "port": "5880", + "ping": 500 + }, { "protocol": "http://", "address": "119.188.210.21", @@ -13,13 +49,13 @@ }, { "protocol": "http://", - "address": "45.32.116.160", - "port": "80", + "address": "113.107.111.78", + "port": "5880", "ping": 500 }, { "protocol": "http://", - "address": "128.1.164.196", + "address": "45.32.116.160", "port": "80", "ping": 500 }