1719 lines
70 KiB
Python
1719 lines
70 KiB
Python
# coding: utf-8
|
||
# +-------------------------------------------------------------------
|
||
# | YakPanel
|
||
# +-------------------------------------------------------------------
|
||
# | Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||
# +-------------------------------------------------------------------
|
||
# | Author: hwliang <2020-08-04>
|
||
# +-------------------------------------------------------------------
|
||
|
||
import os, sys, json, time, datetime
|
||
os.chdir("/www/server/panel")
|
||
sys.path.append("class/")
|
||
import public
|
||
from public.validate import Param
|
||
|
||
class panelWarning:
|
||
__path = '/www/server/panel/data/warning'
|
||
__ignore = __path + '/ignore'
|
||
__result = __path + '/result'
|
||
__risk = __path + '/risk'
|
||
_vuln_ignore = __path + '/ignore.json'
|
||
_vuln_result = __path + '/result.json'
|
||
__repair_count = __path + '/repair_count.json'
|
||
__vul_list = __path + '/high_risk_vul-9.json' # 空i那么;皮的泡沫隔离
|
||
__report = '/www/server/panel/data/warning_report'
|
||
vul_num = 0
|
||
discov_count = 0 # 扫描中发现的漏洞数
|
||
score = 100 # 扫描中动态分数
|
||
yum_time = __path + '/yum_time.pl'
|
||
new_vul_list = __path + '/vul_centos7.json'
|
||
product_version = __path + '/product_version.json'
|
||
|
||
def __init__(self):
|
||
if not os.path.exists(self.__ignore):
|
||
os.makedirs(self.__ignore, 384)
|
||
if not os.path.exists(self.__result):
|
||
os.makedirs(self.__result, 384)
|
||
if not os.path.exists(self.__risk):
|
||
os.makedirs(self.__risk, 384)
|
||
if not os.path.exists(self.__path):
|
||
os.makedirs(self.__path, 384)
|
||
if not os.path.exists(self.__report):
|
||
os.makedirs(self.__report, 384)
|
||
|
||
if not os.path.exists(self._vuln_ignore):
|
||
result = []
|
||
public.WriteFile(self._vuln_ignore, json.dumps(result))
|
||
if not os.path.exists(self._vuln_result):
|
||
result = []
|
||
public.WriteFile(self._vuln_result, json.dumps(result))
|
||
self.new_system_result = []
|
||
# self.sys_version = self.get_sys_version()
|
||
# self.sys_product = self.new_get_sys_product()
|
||
|
||
def _get_list(self):
|
||
# 最终输出结果
|
||
self.data = {
|
||
'security': [],
|
||
'risk': [],
|
||
'ignore': [],
|
||
"is_autofix": [],
|
||
}
|
||
# 获取支持一键修复的列表
|
||
try:
|
||
is_autofix = public.read_config("safe_autofix")
|
||
except:
|
||
is_autofix = []
|
||
# 临时扫描结果,中断的时候返回
|
||
self.tmp_data = {
|
||
'security': [],
|
||
'risk': [],
|
||
'ignore': [],
|
||
'is_autofix': is_autofix,
|
||
'check_time': datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
|
||
}
|
||
context = {"status": "Ready to repair", "percentage": 0, "count": 0, "score": 100}
|
||
public.WriteFile(self.__path + '/bar.txt', json.dumps(context)) # 扫描进度条归零
|
||
bar_num = 0 # 进度条初始化
|
||
bar_limit = 0 # 进度条限制
|
||
self.discov_count = 0 # 扫描中发现漏洞数量初始化
|
||
self.score = 100 # 扫描中分数变化
|
||
sys_version = self.get_sys_version() # 获取系统版本
|
||
# self.compare_md5() # 比较漏洞库版本
|
||
# 下载新版漏洞库文件
|
||
if not self.download_new_vulns():
|
||
sys_version = None
|
||
# centos_7走新版漏洞扫描
|
||
if sys_version == 'centos_7' or sys_version == 'centos_8' or sys_version == 'centos_8_stream':
|
||
self.new_system_scan()
|
||
# ubuntu走新版2接口
|
||
elif sys_version == 'ubuntu_20.04' or sys_version == 'ubuntu_22.04' or sys_version == 'ubuntu_18.04' or sys_version == 'debian_12' or sys_version == 'debian_11' or sys_version == 'debian_10':
|
||
self.new_system_scan2()
|
||
# 旧版本漏洞检测
|
||
# else:
|
||
# self.system_scan() # 旧版本系统漏洞扫描
|
||
|
||
# 加载安全风险模块
|
||
p = public.get_modules('class_v2/safe_warning_v2')
|
||
for m_name in p.__dict__.keys():
|
||
ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
# 忽略的检查项
|
||
if p[m_name]._level == 0: continue
|
||
|
||
m_info = {
|
||
'title': p[m_name]._title,
|
||
'm_name': m_name,
|
||
'ps': p[m_name]._ps,
|
||
'version': p[m_name]._version,
|
||
'level': p[m_name]._level,
|
||
'ignore': p[m_name]._ignore,
|
||
'date': p[m_name]._date,
|
||
'tips': p[m_name]._tips,
|
||
'help': p[m_name]._help
|
||
}
|
||
try:
|
||
m_info['remind'] = p[m_name]._remind
|
||
except:
|
||
pass
|
||
result_file = self.__result + '/' + m_name + '.pl'
|
||
|
||
try:
|
||
s_time = time.time()
|
||
m_info['status'], m_info['msg'] = p[m_name].check_run()
|
||
m_info['taking'] = round(time.time() - s_time, 6)
|
||
m_info['check_time'] = int(time.time())
|
||
public.writeFile(result_file, json.dumps(
|
||
[m_info['status'], m_info['msg'], m_info['check_time'], m_info['taking']], ))
|
||
except:
|
||
continue
|
||
|
||
m_info['ignore'] = os.path.exists(ignore_file)
|
||
if m_info['ignore']:
|
||
self.data['ignore'].append(m_info)
|
||
self.tmp_data['ignore'].append(m_info) # 临时扫描结果
|
||
else:
|
||
if m_info['status']:
|
||
self.data['security'].append(m_info)
|
||
self.tmp_data['security'].append(m_info) # 临时扫描结果
|
||
else:
|
||
risk_file = self.__risk + '/' + m_name + '.pl'
|
||
public.writeFile(risk_file, json.dumps(m_info))
|
||
self.data['risk'].append(m_info)
|
||
self.tmp_data['risk'].append(m_info) # 临时扫描结果
|
||
self.discov_count += 1 # 扫描中发现风险数
|
||
self.score -= m_info['level']
|
||
if self.score < 0:
|
||
self.score = 0
|
||
|
||
bar = ("%.2f" % (float(bar_num) / float(len(p.__dict__.keys())) * 50 + 50))
|
||
# 通过进度条限制,防止写文件频繁占用高
|
||
if int(float(bar)) >= bar_limit:
|
||
context = {"status": "{}".format(m_info['title']), "percentage": int(float(bar)), "count": self.discov_count, "score": self.score}
|
||
public.WriteFile(self.__path + '/bar.txt', json.dumps(context))
|
||
self.dump_tmp_result() # 发现漏洞,先保存一份临时的
|
||
bar_limit += 10
|
||
bar_num += 1
|
||
|
||
# 新版漏洞检测无需读文件
|
||
# is_autofix被包含进tmp_data{}字典里,会动态增加
|
||
self.data['is_autofix'] = is_autofix
|
||
# self.data['is_autofix'] += is_autofix
|
||
|
||
# if sys_version == 'centos_7' or sys_version == 'ubuntu_20.04' or sys_version == 'ubuntu_22.04' or sys_version == 'ubuntu_18.04' or sys_version == 'debian_12' or sys_version == 'debian_11' or sys_version == 'debian_10':
|
||
# self.data['is_autofix'] += is_autofix
|
||
# 旧版本漏洞检测
|
||
# else:
|
||
# vuln_result = self.get_vuln_result()
|
||
# self.data['risk'] = self.data['risk'] + vuln_result['risk']
|
||
# self.data['ignore'] = self.data['ignore'] + vuln_result['ignore']
|
||
# vuln_is_autofix = []
|
||
# for vr in vuln_result['risk']:
|
||
# if not vr["reboot"]:
|
||
# vuln_is_autofix.append(vr["cve_id"])
|
||
# self.data['is_autofix'] = is_autofix + vuln_is_autofix
|
||
|
||
score = 100
|
||
for d in self.data['risk']:
|
||
score = score - d['level']
|
||
if score < 0:
|
||
self.data['score'] = 0
|
||
else:
|
||
self.data['score'] = score
|
||
self.data['risk'] = sorted(self.data['risk'], key=lambda x: x['level'], reverse=True)
|
||
self.data['security'] = sorted(self.data['security'], key=lambda x: x['level'], reverse=True)
|
||
self.data['ignore'] = sorted(self.data['ignore'], key=lambda x: x['level'], reverse=True)
|
||
self.data['check_time'] = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
|
||
# 将结果输出一份到报告目录下
|
||
with open("/www/server/panel/data/warning_report/data.json", "w") as f:
|
||
json.dump(self.data, f)
|
||
self.record_times()
|
||
context = {"status": "Detection completed", "percentage": 100, "count": self.discov_count, "score": self.score}
|
||
public.WriteFile(self.__path + '/bar.txt', json.dumps(context))
|
||
# public.WriteFile(self.__path + '/bar.txt', "100") # 扫描进度条归零
|
||
return self.data
|
||
|
||
def download_new_vulns(self):
|
||
'''
|
||
根据系统版本确定漏洞库名
|
||
'''
|
||
sys_version = self.get_sys_version()
|
||
zip_file = ""
|
||
if sys_version == "centos_7":
|
||
self.new_vul_list = self.__path + '/vul_centos7.json'
|
||
zip_file = "vul_centos7.zip"
|
||
elif sys_version == "centos_8":
|
||
self.new_vul_list = self.__path + '/vul_centos8.json'
|
||
zip_file = "vul_centos8.zip"
|
||
elif sys_version == "centos_8_stream":
|
||
self.new_vul_list = self.__path + '/vul_centos8stream.json'
|
||
zip_file = "vul_centos8stream.zip"
|
||
elif sys_version == "ubuntu_20.04":
|
||
self.new_vul_list = self.__path + '/vul_ubuntu2004.json'
|
||
zip_file = "vul_ubuntu2004.zip"
|
||
elif sys_version == "ubuntu_22.04":
|
||
self.new_vul_list = self.__path + '/vul_ubuntu2204.json'
|
||
zip_file = "vul_ubuntu2204.zip"
|
||
elif sys_version == "ubuntu_18.04":
|
||
self.new_vul_list = self.__path + '/vul_ubuntu1804.json'
|
||
zip_file = "vul_ubuntu1804.zip"
|
||
elif sys_version == "debian_12":
|
||
self.new_vul_list = self.__path + '/vul_debian12.json'
|
||
zip_file = "vul_debian12.zip"
|
||
elif sys_version == "debian_11":
|
||
self.new_vul_list = self.__path + '/vul_debian11.json'
|
||
zip_file = "vul_debian11.zip"
|
||
elif sys_version == "debian_10":
|
||
self.new_vul_list = self.__path + '/vul_debian10.json'
|
||
zip_file = "vul_debian10.zip"
|
||
# 检查漏洞库文件是否存在
|
||
if not os.path.exists(self.new_vul_list):
|
||
if zip_file != '':
|
||
downfile = self.__path+'/'+zip_file
|
||
public.downloadFile("/safe_warning/{}".format(public.get_url(),zip_file), downfile)
|
||
o, e = public.ExecShell("unzip -o {} -d {}".format(downfile, self.__path))
|
||
# 解压报错
|
||
if e != "":
|
||
return False
|
||
else:
|
||
return False
|
||
return True
|
||
# cve_id
|
||
def get_list(self, args):
|
||
'''
|
||
@name 开始扫描并返回结果
|
||
@param args:
|
||
@return:
|
||
'''
|
||
if 'force' in args:
|
||
# 校验参数
|
||
try:
|
||
args.validate([
|
||
Param('force').Integer(),
|
||
], [
|
||
public.validate.trim_filter(),
|
||
])
|
||
except Exception as ex:
|
||
public.print_log("error info: {}".format(ex))
|
||
return public.return_message(-1, 0, str(ex))
|
||
|
||
import subprocess
|
||
if hasattr(args, 'open') and args.open == "1":
|
||
public.set_module_logs("panel_warning_v2", "get_list")
|
||
public.WriteFile(self.__path + '/kill.pl', "False") # 用来判断这次的扫描是否被中断,默认没中断
|
||
command = "btpython /www/server/panel/class_v2/panel_warning_v2.py"
|
||
process = subprocess.Popen(command, shell=True)
|
||
# 获取进程ID
|
||
pid = process.pid
|
||
public.WriteFile(self.__path + "/pid.txt", str(pid))
|
||
process.wait()
|
||
result_file = self.__path + '/resultresult.json'
|
||
output = {
|
||
"score": 100,
|
||
"check_time": public.format_date(),
|
||
"interrupt": False,
|
||
"security": [],
|
||
"risk": [],
|
||
"ignore": [],
|
||
"is_autofix": []
|
||
}
|
||
if not os.path.exists(result_file):
|
||
return output
|
||
result_body = public.ReadFile(result_file)
|
||
if not result_body:
|
||
return output
|
||
try:
|
||
output = json.loads(result_body)
|
||
except:
|
||
return output
|
||
# 给前端判断这次的扫描结果是否中断
|
||
if public.ReadFile(self.__path + '/kill.pl') == "True":
|
||
output["interrupt"] = True
|
||
else:
|
||
output["interrupt"] = False
|
||
return public.return_message(0,0,output)
|
||
|
||
def sync_rule(self):
|
||
'''
|
||
@name 从云端同步规则
|
||
@author hwliang<2020-08-05>
|
||
@return void
|
||
'''
|
||
# try:
|
||
# dep_path = '/www/server/panel/class/safe_warning'
|
||
# local_version_file = self.__path + '/version.pl'
|
||
# last_sync_time = local_version_file = self.__path + '/last_sync.pl'
|
||
# if os.path.exists(dep_path):
|
||
# if os.path.exists(last_sync_time):
|
||
# if int(public.readFile(last_sync_time)) > time.time():
|
||
# return
|
||
# else:
|
||
# if os.path.exists(local_version_file): os.remove(local_version_file)
|
||
|
||
# download_url = public.get_url()
|
||
# version_url = download_url + '/install/warning/version.txt'
|
||
# cloud_version = public.httpGet(version_url)
|
||
# if cloud_version: cloud_version = cloud_version.strip()
|
||
|
||
# local_version = public.readFile(local_version_file)
|
||
# if local_version:
|
||
# if cloud_version == local_version:
|
||
# return
|
||
|
||
# tmp_file = '/tmp/bt_safe_warning.zip'
|
||
# public.ExecShell('wget -O {} {} -T 5'.format(tmp_file,download_url + '/install/warning/safe_warning.zip'))
|
||
# if not os.path.exists(tmp_file):
|
||
# return
|
||
|
||
# if os.path.getsize(tmp_file) < 2129:
|
||
# os.remove(tmp_file)
|
||
# return
|
||
|
||
# if not os.path.exists(dep_path):
|
||
# os.makedirs(dep_path,384)
|
||
# public.ExecShell("unzip -o {} -d {}/ >/dev/null".format(tmp_file,dep_path))
|
||
# public.writeFile(local_version_file,cloud_version)
|
||
# public.writeFile(last_sync_time,str(int(time.time() + 7200)))
|
||
# if os.path.exists(tmp_file): os.remove(tmp_file)
|
||
# public.ExecShell("chmod -R 600 {}".format(dep_path))
|
||
# except:
|
||
# pass
|
||
|
||
def set_ignore(self, args):
|
||
'''
|
||
@name 设置指定项忽略状态
|
||
@param dict_obj {
|
||
m_name<string> 模块名称
|
||
}
|
||
@return dict
|
||
'''
|
||
is_add_or_del = True
|
||
m_name = args.m_name.strip()
|
||
ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
if os.path.exists(ignore_file):
|
||
is_add_or_del = False
|
||
os.remove(ignore_file)
|
||
else:
|
||
public.writeFile(ignore_file, '1')
|
||
|
||
# 删除日志信息,避免重新扫描
|
||
result_file = self.__path + '/resultresult.json'
|
||
if not os.path.exists(result_file):
|
||
return public.return_message(-1, 0, 'Please perform a scan first!')
|
||
|
||
res = public.ReadFile(result_file)
|
||
res = json.loads(res)
|
||
ignore = None
|
||
|
||
# 如果是添加忽略,则从风险列表中删除
|
||
if is_add_or_del:
|
||
for r in res['risk']:
|
||
if r['m_name'] == m_name:
|
||
ignore = r
|
||
break
|
||
if ignore:
|
||
res['risk'].remove(ignore)
|
||
res['ignore'].append(ignore)
|
||
else:
|
||
for r in res['ignore']:
|
||
if r['m_name'] == m_name:
|
||
ignore = r
|
||
break
|
||
if ignore:
|
||
res['ignore'].remove(ignore)
|
||
res['risk'].append(ignore)
|
||
|
||
public.writeFile(result_file, json.dumps(res))
|
||
return public.return_message(0, 0, public.lang("successfully set!"))
|
||
|
||
def get_res_list(self, get):
|
||
'''
|
||
@name 检获取结果列表
|
||
@param dict_obj {
|
||
m_name<string> 模块名称
|
||
}
|
||
@return dict
|
||
'''
|
||
try:
|
||
result_file = self.__path + '/resultresult.json'
|
||
if not os.path.exists(result_file):
|
||
return public.return_message(-1,0,'Please perform a scan first!')
|
||
|
||
res = public.ReadFile(result_file)
|
||
res = json.loads(res)
|
||
return public.return_message(0,0,res)
|
||
except Exception as e:
|
||
return public.return_message(-1,0,'Please perform a scan first!')
|
||
|
||
def check_find(self, args):
|
||
'''
|
||
@name 检测指定项
|
||
@author hwliang<2020-08-04>
|
||
@param dict_obj {
|
||
m_name<string> 模块名称
|
||
}
|
||
@return dict
|
||
'''
|
||
# 校验参数
|
||
try:
|
||
args.validate([
|
||
Param('m_name').String(),
|
||
], [
|
||
public.validate.trim_filter(),
|
||
])
|
||
except Exception as ex:
|
||
public.print_log("error info: {}".format(ex))
|
||
return public.return_message(-1, 0, str(ex))
|
||
|
||
try:
|
||
m_name = args.m_name.strip()
|
||
p = public.get_modules('class_v2/safe_warning_v2')
|
||
m_info = {
|
||
'title': p[m_name]._title,
|
||
'm_name': m_name,
|
||
'ps': p[m_name]._ps,
|
||
'version': p[m_name]._version,
|
||
'level': p[m_name]._level,
|
||
'ignore': p[m_name]._ignore,
|
||
'date': p[m_name]._date,
|
||
'tips': p[m_name]._tips,
|
||
'help': p[m_name]._help
|
||
}
|
||
|
||
# 解决已经在忽略列表中,但是如果仍然需要检查的话可以检查
|
||
ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
if os.path.exists(ignore_file):
|
||
from cachelib import SimpleCache
|
||
cache = SimpleCache(5000)
|
||
ikey = 'warning_list'
|
||
cache.delete(ikey)
|
||
os.remove(ignore_file)
|
||
|
||
result_file = self.__result + '/' + m_name + '.pl'
|
||
s_time = time.time()
|
||
m_info['status'], m_info['msg'] = p[m_name].check_run()
|
||
m_info['taking'] = round(time.time() - s_time, 4)
|
||
m_info['check_time'] = int(time.time())
|
||
public.writeFile(result_file, json.dumps(
|
||
[m_info['status'], m_info['msg'], m_info['check_time'], m_info['taking']]))
|
||
return public.return_message(0, 0, public.lang("It has been retested."))
|
||
except:
|
||
return public.return_message(-1, 0, public.lang("Detection failed"))
|
||
|
||
|
||
def system_scan(self):
|
||
'''
|
||
一键扫描系统
|
||
:param get:
|
||
:return: dict
|
||
'''
|
||
self.compare_md5()
|
||
sys_version = self.get_sys_version()
|
||
|
||
# if sys_version == 'None':
|
||
# return public.returnMsg(False, public.lang("It is not supported by the current system"))
|
||
sys_product = self.get_sys_product()
|
||
# if not os.path.exists(self.__vul_list):
|
||
# return public.returnMsg(False, public.lang("The scan failed"))
|
||
vul_list = self.get_vul_list()
|
||
|
||
new_risk_list = []
|
||
new_ignore_list = []
|
||
# error_list = []
|
||
result_dict = {}
|
||
# cp_list = []
|
||
vul_count = 0
|
||
ignore_list = self.get_ignore_list()
|
||
reboot_count = 0
|
||
self.vul_num = len(vul_list)
|
||
bar_num = 0 # 进度条初始化
|
||
bar_limit = 0 # 进度条限制
|
||
for vul in vul_list:
|
||
bar = ("%.2f" % (float(bar_num)/float(self.vul_num)*50))
|
||
# 限制进度条,限制写文件频率
|
||
if int(float(bar)) >= bar_limit:
|
||
context = {"status": "{}".format(vul['cve_id']), "percentage": int(float(bar)), "count": self.discov_count, "score": self.score}
|
||
public.WriteFile(self.__path+'/bar.txt', json.dumps(context))
|
||
self.dump_tmp_result() # 发现漏洞,先保存一份临时的
|
||
bar_limit += 10
|
||
bar_num += 1
|
||
vul_count += 1
|
||
for v in vul["affected_list"]:
|
||
if v["manufacturer"] == sys_version:
|
||
tmp = 1 # 默认命中
|
||
if not 'affected' in v: continue
|
||
arr = v['affected'].split("Up to (excluding)\n ")
|
||
if len(arr) < 2: continue
|
||
vul_version = arr[1]
|
||
try:
|
||
for soft in v["softname"]:
|
||
compare_result = self.version_compare(sys_product[soft], vul_version)
|
||
if compare_result >= 0:
|
||
tmp = 0 # 当有一个软件包版本不在漏洞范围内,则不命中
|
||
break
|
||
if tmp == 1:
|
||
# softname_list = [soft+'-'+sys_product[soft] for soft in v["softname"]]
|
||
# softname_list = [{soft: sys_product[soft]} for soft in v["softname"]]
|
||
self.discov_count += 1 # 扫描中发现漏洞数
|
||
softname_dict = {}
|
||
for soft in v["softname"]:
|
||
softname_dict[soft] = sys_product[soft]
|
||
level = self.get_score_risk(vul["score"])
|
||
vul_dict = {key: vul[key] for key in ["cve_id", "vuln_name", "vuln_time", "vuln_solution"]}
|
||
vul_dict["level"] = level
|
||
self.score -= level # 扫描中的动态分数
|
||
if self.score < 0:
|
||
self.score = 0
|
||
vul_dict["soft_name"] = softname_dict
|
||
vul_dict["vuln_version"] = vul_version
|
||
vul_dict["check_time"] = int(time.time())
|
||
vul_dict["reboot"] = ""
|
||
if "kernel" in [k for k in v["softname"]]:
|
||
vul_dict["reboot"] = "This vulnerability is a kernel vulnerability, and you need to upgrade the kernel version yourself. It is recommended to make snapshots and backups before upgrading"
|
||
reboot_count += 1
|
||
if vul["cve_id"] in ignore_list:
|
||
new_ignore_list.append(vul_dict)
|
||
self.tmp_data['ignore'].append(vul_dict) # 添加到临时字典
|
||
break
|
||
new_risk_list.append(vul_dict)
|
||
self.tmp_data['risk'].append(vul_dict) # 添加到临时字典
|
||
if vul_dict["reboot"]:
|
||
self.tmp_data['is_autofix'].append(vul_dict["cve_id"])
|
||
break
|
||
# cp_list.append(vul["cve_id"]+': '+str([soft+'-'+sys_product[soft] for soft in v["softname"]])+' >= '+vul_version)
|
||
except Exception as e:
|
||
# error_list.append(vul["cve_id"]+': '+str(e))
|
||
break
|
||
result_dict["vul_count"] = vul_count
|
||
result_dict["risk"] = new_risk_list
|
||
result_dict["ignore"] = new_ignore_list
|
||
# result_dict["reboot"] = self.__need_reboot
|
||
# result_dict["error"] = error_list
|
||
# result_dict["compare"] = cp_list
|
||
public.WriteFile(self.__path + '/system_scan_time', str(int(time.time())))
|
||
public.WriteFile(self._vuln_result, json.dumps(result_dict))
|
||
# try:
|
||
# public.WriteFile(self._vuln_result, json.dumps(result_dict))
|
||
# return public.returnMsg(True, public.lang("扫描完成"))
|
||
# except:
|
||
# return public.returnMsg(False, public.lang("扫描失败"))
|
||
|
||
# 版本比较
|
||
def version_compare(self, ver_a, ver_b):
|
||
'''
|
||
比较版本大小
|
||
:param ver_a: 软件版本
|
||
:param ver_b: 漏洞版本
|
||
:return: int 大于等于返回1或0,小于返回-1
|
||
'''
|
||
sys_version = self.get_sys_version()
|
||
if "ubuntu" in sys_version or "debian" in sys_version:
|
||
if ver_b.startswith("1:"):
|
||
ver_b = ver_b[2:]
|
||
# if ver_a.startswith("1:"):
|
||
# ver_a = ver_a[2:]
|
||
result = public.ExecShell("dpkg --compare-versions " + ver_a + " ge " + ver_b + " && echo true")
|
||
if 'warning' in result[1].strip(): return None
|
||
if 'true' in result[0].strip():
|
||
return 1
|
||
else:
|
||
return -1
|
||
return self.vercmp(ver_a, ver_b)
|
||
|
||
def vercmp(self, first, second):
|
||
import re
|
||
R_NONALNUMTILDE = re.compile(br"^([^a-zA-Z0-9~]*)(.*)$")
|
||
R_NUM = re.compile(br"^([\d]+)(.*)$")
|
||
R_ALPHA = re.compile(br"^([a-zA-Z]+)(.*)$")
|
||
first = first.encode("ascii", "ignore")
|
||
second = second.encode("ascii", "ignore")
|
||
while first or second:
|
||
m1 = R_NONALNUMTILDE.match(first)
|
||
m2 = R_NONALNUMTILDE.match(second)
|
||
m1_head, first = m1.group(1), m1.group(2)
|
||
m2_head, second = m2.group(1), m2.group(2)
|
||
if m1_head or m2_head:
|
||
continue
|
||
|
||
if first.startswith(b'~'):
|
||
if not second.startswith(b'~'):
|
||
return -1
|
||
first, second = first[1:], second[1:]
|
||
continue
|
||
if second.startswith(b'~'):
|
||
return 1
|
||
|
||
if not first or not second:
|
||
break
|
||
|
||
m1 = R_NUM.match(first)
|
||
if m1:
|
||
m2 = R_NUM.match(second)
|
||
if not m2:
|
||
return 1
|
||
isnum = True
|
||
else:
|
||
m1 = R_ALPHA.match(first)
|
||
m2 = R_ALPHA.match(second)
|
||
isnum = False
|
||
|
||
if not m1:
|
||
return -1
|
||
if not m2:
|
||
return 1 if isnum else -1
|
||
|
||
m1_head, first = m1.group(1), m1.group(2)
|
||
m2_head, second = m2.group(1), m2.group(2)
|
||
|
||
if isnum:
|
||
m1_head = m1_head.lstrip(b'0')
|
||
m2_head = m2_head.lstrip(b'0')
|
||
|
||
m1hlen = len(m1_head)
|
||
m2hlen = len(m2_head)
|
||
if m1hlen < m2hlen:
|
||
return -1
|
||
if m1hlen > m2hlen:
|
||
return 1
|
||
if m1_head < m2_head:
|
||
return -1
|
||
if m1_head > m2_head:
|
||
return 1
|
||
continue
|
||
|
||
m1len = len(first)
|
||
m2len = len(second)
|
||
if m1len == m2len == 0:
|
||
return 0
|
||
if m1len != 0:
|
||
return 1
|
||
return -1
|
||
|
||
# 取系统版本
|
||
def get_sys_version(self):
|
||
'''
|
||
获取当前系统版本
|
||
:return: string
|
||
'''
|
||
sys_version = "None"
|
||
if os.path.exists("/etc/redhat-release"):
|
||
result = public.ReadFile("/etc/redhat-release")
|
||
if "CentOS Linux release 7" in result:
|
||
sys_version = "centos_7"
|
||
elif "CentOS Linux release 8" in result:
|
||
sys_version = "centos_8"
|
||
elif "CentOS Stream release 8" in result:
|
||
sys_version = "centos_8_stream"
|
||
elif os.path.exists("/etc/lsb-release"):
|
||
if "Ubuntu 20.04" in public.ReadFile("/etc/lsb-release"):
|
||
sys_version = "ubuntu_20.04"
|
||
elif "Ubuntu 22.04" in public.ReadFile("/etc/lsb-release"):
|
||
sys_version = "ubuntu_22.04"
|
||
elif "Ubuntu 18.04" in public.ReadFile("/etc/lsb-release"):
|
||
sys_version = "ubuntu_18.04"
|
||
elif os.path.exists("/etc/debian_version"):
|
||
result = public.ReadFile("/etc/debian_version")
|
||
if "10." in result:
|
||
sys_version = "debian_10"
|
||
elif "11." in result:
|
||
sys_version = "debian_11"
|
||
elif "12." in result:
|
||
sys_version = "debian_12"
|
||
return sys_version
|
||
|
||
def new_get_sys_product(self, flag=False):
|
||
'''
|
||
新版获取系统软件包及版本{"name":"version"}
|
||
@param flag bool 为True时直接扫一次
|
||
'''
|
||
# 修复完成需要重新获取一次软件包版本
|
||
if flag:
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
|
||
sys_version = self.get_sys_version()
|
||
if sys_version == "centos_7":
|
||
# 根据yum日志判断是否用软件包更新
|
||
yumlog = "/var/log/yum.log"
|
||
elif sys_version == "centos_8" or sys_version == "centos_8_stream":
|
||
yumlog = "/var/log/dnf.log"
|
||
else:
|
||
yumlog = "/var/log/apt/history.log"
|
||
try:
|
||
# 先判断有没有yum.log
|
||
if os.path.exists(yumlog):
|
||
# 第一次将yum.log修改时间记录在文件里
|
||
if not os.path.exists(self.yum_time):
|
||
new_modi_time = str(int(os.path.getmtime(yumlog)))
|
||
public.WriteFile(self.yum_time, new_modi_time)
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
else:
|
||
old_modi_time = public.ReadFile(self.yum_time)
|
||
new_modi_time = str(int(os.path.getmtime(yumlog)))
|
||
# 比较上一次记录的时间和这次获取的修改时间,相等则根据rpm文件的修改时间
|
||
if old_modi_time == new_modi_time:
|
||
if os.path.exists(self.product_version):
|
||
# 若rpm文件修改日期大于七天,则还是执行rpm检测
|
||
if self.is_file_too_old(self.product_version, 7):
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
else:
|
||
sys_product = json.loads(public.ReadFile(self.product_version))
|
||
else:
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
# 不相等证明最近有用yum安装过新软件,更新文件并检测
|
||
else:
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product)) # 将软件包版本写入文件
|
||
public.WriteFile(self.yum_time, new_modi_time)
|
||
# 没有yum.log,则直接根据rpm文件修改日期
|
||
else:
|
||
if os.path.exists(self.product_version):
|
||
if self.is_file_too_old(self.product_version, 7):
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
else:
|
||
sys_product = json.loads(public.ReadFile(self.product_version))
|
||
else:
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
except Exception as e:
|
||
sys_product = self.get_sys_product()
|
||
public.WriteFile(self.product_version, json.dumps(sys_product))
|
||
# 其他系统版本
|
||
return sys_product
|
||
|
||
# 取软件包版本
|
||
def get_sys_product(self):
|
||
"""
|
||
获取系统软件包及版本
|
||
{"name":"version"}
|
||
:return dict 如果系统不支持则返回str None
|
||
"""
|
||
product_version = {}
|
||
sys_version = self.get_sys_version()
|
||
|
||
# if sys_version == 'None':return public.returnMsg(False, public.lang("当前系统暂不支持"))
|
||
if "centos" in sys_version:
|
||
result = public.ExecShell('rpm -qa --qf \'%{NAME};%{VERSION}-%{RELEASE}\\n\'')[0].strip().split('\n')
|
||
elif "ubuntu" in sys_version:
|
||
# result1 = subprocess.check_output(['dpkg-query', '-W', '-f=${Package};${Version}\n']).decode('utf-8').strip().split('\n')
|
||
result = public.ExecShell('dpkg-query -W -f=\'${Package};${Version}\n\'')[0].strip().split('\n')
|
||
elif "debian" in sys_version:
|
||
result = public.ExecShell('dpkg-query -W -f=\'${Package};${Version}\n\'')[0].strip().split('\n')
|
||
elif sys_version == "None":
|
||
return None
|
||
else:
|
||
return None
|
||
for pkg in result:
|
||
try:
|
||
product_version[pkg.split(";")[0]] = pkg.split(";")[1]
|
||
except:
|
||
return None
|
||
# product_version["kernel"] = subprocess.check_output(['uname', '-r']).decode('utf-8').strip().replace(".x86_64", "")
|
||
product_version["kernel"] = public.ExecShell('uname -r')[0].strip()
|
||
return product_version
|
||
|
||
def get_vuln_result(self):
|
||
'''
|
||
获取上一次扫描结果
|
||
:param get:
|
||
:return: dict
|
||
'''
|
||
d_risk = 0
|
||
h_risk = 0
|
||
m_risk = 0
|
||
vul_list = []
|
||
if not os.path.exists(self.__vul_list):
|
||
self.vul_num = 0
|
||
else:
|
||
self.vul_num = len(self.get_vul_list())
|
||
if not os.path.exists(self._vuln_result):
|
||
tmp_dict = {"vul_count": self.vul_num, "risk": [], "ignore": [],
|
||
"count": {"serious": 0, "high_risk": 0, "moderate_risk": 0}, "msg": "",
|
||
"repair_count": {"all_count": 0, "today_count": 0}, "all_check_time": "", "ignore_count": 0}
|
||
if os.path.exists("/etc/redhat-release"):
|
||
result = public.ReadFile("/etc/redhat-release")
|
||
if "CentOS Linux release 8" in result:
|
||
# tmp_dict["msg"] = "当前系统【centos_8】官方已停止维护,为了安全起见,建议升级至centos 8 stream\n详情参考教程:https://www.yakpanel.com/bbs/thread-82931-1-1.html"
|
||
tmp_dict["msg"] = "The current system [centos_8] has been officially stopped maintenance, for security purposes, it is recommended to upgrade to centos 8 stream"
|
||
return tmp_dict
|
||
if public.ReadFile(self._vuln_result) == '[]':
|
||
tmp_dict = {"vul_count": self.vul_num, "risk": [], "ignore": [],
|
||
"count": {"serious": 0, "high_risk": 0, "moderate_risk": 0}, "msg": "",
|
||
"repair_count": {"all_count": 0, "today_count": 0}, "all_check_time": "", "ignore_count": 0}
|
||
if os.path.exists("/etc/redhat-release"):
|
||
result = public.ReadFile("/etc/redhat-release")
|
||
if "CentOS Linux release 8" in result:
|
||
# tmp_dict["msg"] = "当前系统【centos_8】官方已停止维护,为了安全起见,建议升级至centos 8 stream\n详情参考教程:https://www.yakpanel.com/bbs/thread-82931-1-1.html"
|
||
tmp_dict["msg"] = "The current system [centos_8] has been officially stopped maintenance, for security purposes, it is recommended to upgrade to centos 8 stream"
|
||
return tmp_dict
|
||
result_dict = json.loads(public.ReadFile(self._vuln_result))
|
||
old_risk_list = result_dict["risk"]
|
||
old_ignore_list = result_dict["ignore"]
|
||
new_risk_list = old_risk_list.copy()
|
||
new_ignore_list = old_ignore_list.copy()
|
||
tmp_ignore_list = self.get_ignore_list()
|
||
for cve in old_risk_list:
|
||
if cve["cve_id"] in tmp_ignore_list:
|
||
new_ignore_list.append(cve)
|
||
new_risk_list.remove(cve)
|
||
for cve_ig in old_ignore_list:
|
||
if cve_ig["cve_id"] not in tmp_ignore_list:
|
||
new_risk_list.append(cve_ig)
|
||
new_ignore_list.remove(cve_ig)
|
||
for vul in new_ignore_list + new_risk_list:
|
||
vul_list.append(vul["cve_id"])
|
||
if vul["cve_id"] in tmp_ignore_list:
|
||
continue
|
||
if vul["level"] == 3:
|
||
d_risk += 1
|
||
elif vul["level"] == 2:
|
||
h_risk += 1
|
||
elif vul["level"] == 1:
|
||
m_risk += 1
|
||
list_sort = [3, 2, 1] # 排序列表
|
||
# result_dict["risk"] = old_risk_list
|
||
result_dict["risk"] = sorted(new_risk_list, key=lambda x: list_sort.index(x.get("level")))
|
||
# result_dict["ignore"] = old_ignore_list
|
||
result_dict["ignore"] = sorted(new_ignore_list, key=lambda x: list_sort.index(x.get("level")))
|
||
# result_dict["reboot"] = self.__need_reboot
|
||
result_dict["count"] = {"serious": d_risk, "high_risk": h_risk, "moderate_risk": m_risk}
|
||
result_dict["msg"] = ""
|
||
result_dict["repair_count"] = self.count_repair(vul_list)
|
||
result_dict["all_check_time"] = public.ReadFile(self.__path + '/system_scan_time')
|
||
result_dict["ignore_count"] = len(tmp_ignore_list)
|
||
if os.path.exists("/etc/redhat-release"):
|
||
result = public.ReadFile("/etc/redhat-release")
|
||
if "CentOS Linux release 8" in result:
|
||
result_dict[
|
||
"msg"] = "The current system [centos_8] has been officially stopped maintenance, for security purposes, it is recommended to upgrade to centos 8 stream"
|
||
public.WriteFile(self._vuln_result, json.dumps(result_dict))
|
||
return result_dict
|
||
|
||
# 按分数评等级
|
||
def get_score_risk(self, score):
|
||
'''
|
||
拿到分数,返回危险等级
|
||
:param score:
|
||
:return: int 若没有符合的分数就报错,需要捕获异常
|
||
'''
|
||
if float(score) >= 9.0:
|
||
risk = 3
|
||
elif float(score) >= 7.0:
|
||
risk = 2
|
||
elif float(score) >= 6.0:
|
||
risk = 1
|
||
return risk
|
||
|
||
def get_vul_list(self):
|
||
return json.loads(public.ReadFile(self.__vul_list))
|
||
|
||
def get_ignore_list(self):
|
||
return json.loads(public.ReadFile(self._vuln_ignore))
|
||
|
||
def set_vuln_ignore(self, args):
|
||
'''
|
||
设置忽略指定cve,若已在列表里,则删除,不在列表里则添加
|
||
:param args:
|
||
:return: dict {status:true,msg:'设置成功/失败'}
|
||
'''
|
||
cve_list = json.loads(args.cve_list.strip())
|
||
ignore_list = self.get_ignore_list()
|
||
for cl in cve_list:
|
||
if cl in ignore_list:
|
||
ignore_list.remove(cl)
|
||
else:
|
||
ignore_list.append(cl)
|
||
|
||
public.WriteFile(self._vuln_ignore, json.dumps(ignore_list))
|
||
# public.WriteFile(self.__result, json.dumps(result_dict))
|
||
return public.return_message(0, 0, public.lang("successfully set!"))
|
||
|
||
|
||
def count_repair(self, now_list):
|
||
'''
|
||
获取总共修复漏洞的数量以及今日修复漏洞数量
|
||
:param now_list:
|
||
:return: dict
|
||
'''
|
||
cve_dict = {}
|
||
if not os.path.exists(self.__repair_count):
|
||
cve_dict["all_cve"] = now_list
|
||
cve_dict["today_cve"] = now_list
|
||
cve_dict["time"] = int(time.time())
|
||
public.WriteFile(self.__repair_count, json.dumps(cve_dict))
|
||
cve_dict = json.loads(public.ReadFile(self.__repair_count))
|
||
cve_dict["all_cve"].extend(set(now_list) - set(cve_dict["all_cve"]))
|
||
all_count = len(cve_dict["all_cve"]) - len(now_list)
|
||
cve_dict["today_cve"].extend(set(now_list) - set(cve_dict["today_cve"]))
|
||
today_count = len(cve_dict["today_cve"]) - len(now_list)
|
||
# if cve_dict["time"].split(" ")[0] != self.get_time().split(" ")[0]:
|
||
# cve_dict["today_cve"] = now_list
|
||
cve_dict["time"] = int(time.time())
|
||
public.WriteFile(self.__repair_count, json.dumps(cve_dict))
|
||
return {"all_count": all_count, "today_count": today_count}
|
||
|
||
def get_time(self):
|
||
return public.format_date()
|
||
|
||
def check_cve(self, args):
|
||
'''
|
||
检测单个漏洞
|
||
:param args:
|
||
:return: dict
|
||
'''
|
||
sys_product = self.get_sys_product()
|
||
if not sys_product:
|
||
return public.returnMsg(True, public.lang("Detection failed"))
|
||
cve_id = args.cve_id.strip()
|
||
result_dict = json.loads(public.ReadFile(self._vuln_result))
|
||
risk_list = result_dict["risk"]
|
||
ignore_list = result_dict["ignore"]
|
||
tmptmp = 1
|
||
for cve in risk_list:
|
||
if cve["cve_id"] == cve_id:
|
||
tmp = 1 # 默认命中漏洞
|
||
cve["check_time"] = int(time.time())
|
||
for soft in list(cve["soft_name"].keys()):
|
||
if self.version_compare(sys_product[soft], cve["vuln_version"]) >= 0:
|
||
tmp = 0 # 当有一个软件包不命中,则为已修复
|
||
tmptmp = 0
|
||
break
|
||
if tmp == 0:
|
||
risk_list.remove(cve)
|
||
for cve in ignore_list:
|
||
if cve["cve_id"] == cve_id:
|
||
tmp = 1 # 默认命中漏洞
|
||
cve["check_time"] = int(time.time())
|
||
for soft in list(cve["soft_name"].keys()):
|
||
if self.version_compare(sys_product[soft], cve["vuln_version"]) >= 0:
|
||
tmp = 0 # 当有一个软件包不命中,则为已修复
|
||
tmptmp = 0
|
||
break
|
||
if tmp == 0:
|
||
ignore_list.remove(cve)
|
||
result_dict["risk"] = risk_list
|
||
result_dict["ignore"] = ignore_list
|
||
public.WriteFile(self._vuln_result, json.dumps(result_dict))
|
||
if tmptmp == 0:
|
||
return public.returnMsg(True, public.lang("It has been retested."))
|
||
else:
|
||
return public.returnMsg(True, public.lang("It has been retested."))
|
||
|
||
def compare_md5(self):
|
||
'''
|
||
对比md5,更新漏洞库
|
||
:return:
|
||
'''
|
||
import requests
|
||
# try:
|
||
# new_md5 = requests.get("https://www.yakpanel.com/vulscan_d11ad1fe99a5f078548b0ea355db42dc.txt").text
|
||
# except:
|
||
# return 0
|
||
# old_md5 = public.FileMd5(self.__vul_list)
|
||
# if old_md5 != new_md5 or not os.path.exists(self.__vul_list):
|
||
if not os.path.exists(self.__vul_list):
|
||
try:
|
||
public.downloadFile("{}/install/src/high_risk_vul.zip".format(public.get_url()),
|
||
self.__path + "/high_risk_vul.zip")
|
||
public.ExecShell("unzip -o {}/high_risk_vul.zip -d {}/".format(self.__path, self.__path))
|
||
except:
|
||
return 0
|
||
return 1
|
||
|
||
def get_logs(self, get):
|
||
'''
|
||
获取升级日志
|
||
:param get:
|
||
:return: dict
|
||
'''
|
||
import files
|
||
return public.returnMsg(True, files.files().GetLastLine(self.__path + '/log.txt', 20))
|
||
|
||
def record_times(self):
|
||
'''
|
||
记录近七日扫描次数
|
||
'''
|
||
date_obj = datetime.datetime.now()
|
||
weekday = datetime.datetime.now().weekday()
|
||
if not os.path.exists("/www/server/panel/data/warning_report/record.json"):
|
||
tmp = {"scan": [], "repair": []}
|
||
for i in range(6, -1, -1):
|
||
last_date = (date_obj - datetime.timedelta(days=i)).strftime("%Y/%m/%d")
|
||
tmp["scan"].append({"date": last_date, "times": 0})
|
||
tmp["repair"].append({"date": last_date, "times": 0})
|
||
public.WriteFile("/www/server/panel/data/warning_report/record.json", json.dumps(tmp))
|
||
with open("/www/server/panel/data/warning_report/record.json", "r") as f:
|
||
record = json.load(f)
|
||
if record["scan"][weekday]["date"] == datetime.datetime.now().strftime("%Y/%m/%d"):
|
||
record["scan"][weekday]["times"] += 1
|
||
else:
|
||
record["scan"][weekday]["date"] = datetime.datetime.now().strftime("%Y/%m/%d")
|
||
record["scan"][weekday]["times"] = 1
|
||
public.WriteFile("/www/server/panel/data/warning_report/record.json", json.dumps(record))
|
||
|
||
def get_scan_bar(self, args):
|
||
'''
|
||
获取扫描进度条
|
||
@param args:
|
||
@return: int
|
||
'''
|
||
if not os.path.exists(self.__path + '/bar.txt'):return 0
|
||
data = json.loads(public.ReadFile(self.__path + '/bar.txt'))
|
||
return public.return_message(0,0,data)
|
||
|
||
def kill_get_list(self, args):
|
||
'''
|
||
杀掉扫描进程
|
||
@param args:
|
||
@return:
|
||
'''
|
||
if not os.path.exists(self.__path + '/pid.txt'):
|
||
return public.return_message(-1,0,"Interrupt failure")
|
||
pid = public.ReadFile(self.__path + '/pid.txt')
|
||
err = public.ExecShell("kill -9 {}".format(str(pid)))[1].strip()
|
||
if err:
|
||
return public.return_message(-1,0,"Interrupt failure")
|
||
else:
|
||
public.WriteFile(self.__path + '/kill.pl', "True")
|
||
return public.return_message(0,0,'Interrupt successfully')
|
||
|
||
|
||
def dump_tmp_result(self):
|
||
'''
|
||
动态保存结果
|
||
@param args:
|
||
@return:
|
||
'''
|
||
public.WriteFile(self.__path + '/tmp_result.json', json.dumps(self.tmp_data))
|
||
|
||
def get_tmp_result(self, args):
|
||
'''
|
||
获取中途中断结果
|
||
@param args:
|
||
@return:
|
||
'''
|
||
if not os.path.exists(self.__path + '/tmp_result.json'):
|
||
return "err"
|
||
return public.return_message(0,0,json.loads(public.ReadFile(self.__path + '/tmp_result.json')))
|
||
|
||
def new_system_scan2(self):
|
||
'''
|
||
新版系统dpkg软件包漏洞检测
|
||
'''
|
||
if not os.path.exists(self.new_vul_list):
|
||
return
|
||
# 加载漏洞库文件
|
||
try:
|
||
vul_json = json.loads(public.ReadFile(self.new_vul_list))
|
||
packages_rule = vul_json['Packages']
|
||
detail = vul_json['Detail']
|
||
except Exception as e:
|
||
return
|
||
sys_product = self.new_get_sys_product()
|
||
if sys_product is None:
|
||
return
|
||
|
||
dpkg = Dpkg # 获取DPKG对象
|
||
# 符合
|
||
systemscan_result = {}
|
||
# 开始检测
|
||
# 第一层遍历系统软件包
|
||
for pk, ver in sys_product.items():
|
||
# 跳过内核漏洞检测
|
||
# if pk.startswith("kernel"):
|
||
# continue
|
||
# 是否有历史漏洞
|
||
if pk in packages_rule:
|
||
# 第二层遍历比较软件包涉及的漏洞版本
|
||
for rule in packages_rule[pk]:
|
||
# 判断软件包版本是否存在主版本号,有则漏洞版本一起保留主版本号,否则去掉漏洞版本的主版本号
|
||
pk_ver, vul_ver = self.adjust_ver(ver, rule[0])
|
||
try:
|
||
cp_result = dpkg.compare_versions(pk_ver, vul_ver)
|
||
except:
|
||
continue
|
||
# 任意一个命中
|
||
if cp_result == -1:
|
||
if rule[1] not in systemscan_result:
|
||
systemscan_result[rule[1]] = detail[str(rule[1])]
|
||
systemscan_result[rule[1]]["impact"] = [{"package": pk, "version": pk_ver, "vul_ver": vul_ver}]
|
||
else:
|
||
systemscan_result[rule[1]]["impact"].append({"package": pk, "version": pk_ver, "vul_ver": vul_ver})
|
||
|
||
# 为了兼容旧版本再次做处理
|
||
for sr in systemscan_result.values():
|
||
one_risk = {}
|
||
one_risk["title"] = "【{}】Linux系统安全漏洞编号".format(sr["ref_id"])
|
||
one_risk["data"] = "2023-12-08"
|
||
one_risk["help"] = ""
|
||
one_risk["ignore"] = False
|
||
level = self.new_severity_to_num(sr["severity"])
|
||
one_risk["level"] = level
|
||
one_risk["m_name"] = sr["ref_id"]
|
||
pk_list = []
|
||
# 判断是否有内核漏洞在里面
|
||
is_kernel = False
|
||
soft_list = []
|
||
for impact in sr["impact"]:
|
||
if impact["package"].startswith("kernel"):
|
||
is_kernel = True
|
||
continue
|
||
soft_list.append("{} Versions below {}".format(impact["package"]+"-"+impact["version"], impact["vul_ver"]))
|
||
pk_list.append(impact["package"])
|
||
if is_kernel:
|
||
continue
|
||
one_risk["msg"] = "Security vulnerabilities are found in the following system software:<br>{}<br>Vulnerabilities involved:{}<br>Please refer to the official announcement for details:{}".format('<br>'.join(soft_list), '、'.join(sr["cve"]),sr["ref_url"])
|
||
one_risk["ps"] = "【{}】Linux system vulnerability security vulnerability number".format(sr["ref_id"])
|
||
one_risk["remind"] = "Fixing vulnerabilities has certain risks, so it is recommended to take a good system snapshot to prevent system operation from being affected."
|
||
one_risk["status"] = False
|
||
one_risk["taking"] = 0.000001
|
||
one_risk["tips"] = ["Update the software to a safe version according to the risk description", "Or click [One-click Repair] to solve all security issues"]
|
||
one_risk["version"] = 1
|
||
one_risk["type"] = "vulnerability"
|
||
one_risk["package"] = pk_list
|
||
|
||
# 存储结果
|
||
self.data["risk"].append(one_risk)
|
||
self.data["is_autofix"].append(one_risk["m_name"])
|
||
|
||
# 扫描中发现的漏洞数
|
||
self.discov_count += 1
|
||
# 扫描中的动态分数
|
||
self.score -= level
|
||
if self.score < 0:
|
||
self.score = 0
|
||
# 扫描中的动态风险
|
||
self.tmp_data['risk'].append(one_risk)
|
||
# 可修复项
|
||
self.tmp_data['is_autofix'].append(one_risk["m_name"])
|
||
|
||
def new_system_scan(self):
|
||
'''
|
||
新版系统rpm软件包漏洞检测
|
||
提升扫描速度
|
||
:param get:
|
||
:return: dict
|
||
'''
|
||
|
||
# 判断新漏洞库存不存在
|
||
if not os.path.exists(self.new_vul_list):
|
||
return
|
||
|
||
context = {"status": "Checking system software", "percentage": 0, "count": 0, "score": 100}
|
||
public.WriteFile(self.__path + '/bar.txt', json.dumps(context))
|
||
sys_product = self.new_get_sys_product()
|
||
# 加载漏洞库文件
|
||
try:
|
||
vul_json = json.loads(public.ReadFile(self.new_vul_list))
|
||
packages_rule = vul_json['Packages']
|
||
detail = vul_json['Detail']
|
||
except Exception as e:
|
||
return
|
||
if sys_product is None:
|
||
return
|
||
|
||
# 符合
|
||
systemscan_result = {}
|
||
# 开始检测
|
||
# 第一层遍历系统软件包
|
||
for pk, ver in sys_product.items():
|
||
# 跳过内核漏洞检测
|
||
# if pk.startswith("kernel"):
|
||
# continue
|
||
# 是否有历史漏洞
|
||
if pk in packages_rule:
|
||
# 第二层遍历比较软件包涉及的漏洞版本
|
||
for rule in packages_rule[pk]:
|
||
# 判断软件包版本是否存在主版本号,有则漏洞版本一起保留主版本号,否则去掉漏洞版本的主版本号
|
||
pk_ver, vul_ver = self.adjust_ver(ver, rule[0])
|
||
cp_result = self.vercmp(pk_ver, vul_ver)
|
||
if cp_result == -1:
|
||
if rule[1] not in systemscan_result:
|
||
systemscan_result[rule[1]] = detail[str(rule[1])]
|
||
systemscan_result[rule[1]]["impact"] = [{"package": pk, "version": pk_ver, "vul_ver": vul_ver}]
|
||
else:
|
||
systemscan_result[rule[1]]["impact"].append({"package": pk, "version": pk_ver, "vul_ver": vul_ver})
|
||
# public.WriteFile("/tmp/centos7_result.json", json.dumps(systemscan_result, indent=4))
|
||
|
||
# 为了兼容旧版本再次做处理
|
||
for sr in systemscan_result.values():
|
||
one_risk = {}
|
||
one_risk["title"] = "【{}】Linux system vulnerability security notice".format(sr["ref_id"])
|
||
one_risk["data"] = "2023-12-08"
|
||
one_risk["help"] = ""
|
||
one_risk["ignore"] = False
|
||
level = self.new_severity_to_num(sr["severity"])
|
||
one_risk["level"] = level
|
||
one_risk["m_name"] = sr["ref_id"]
|
||
pk_list = []
|
||
# 判断是否有内核漏洞在里面
|
||
is_kernel = False
|
||
soft_list = []
|
||
for impact in sr["impact"]:
|
||
if impact["package"].startswith("kernel"):
|
||
is_kernel = True
|
||
continue
|
||
soft_list.append("{} Versions below {}".format(impact["package"]+"-"+impact["version"], impact["vul_ver"]))
|
||
pk_list.append(impact["package"])
|
||
if is_kernel:
|
||
continue
|
||
one_risk["msg"] = "The following system software was found to have security vulnerabilities:<br>{}<br>Vulnerabilities involved:{}<br>Refer to the official announcement for details:{}".format('<br>'.join(soft_list), '、'.join(sr["cve"]),sr["ref_url"])
|
||
one_risk["ps"] = "【{}】Linux system vulnerability security notice".format(sr["ref_id"])
|
||
one_risk["remind"] = "Fixing vulnerabilities has certain risks, so it is recommended to take a good system snapshot to prevent system operation from being affected."
|
||
one_risk["status"] = False
|
||
one_risk["taking"] = 0.000001
|
||
one_risk["tips"] = ["Update the software to a safe version according to the risk description", "Or click [One-click Repair] to solve all security issues"]
|
||
one_risk["version"] = 1
|
||
one_risk["type"] = "vulnerability"
|
||
one_risk["package"] = pk_list
|
||
|
||
# 存储结果
|
||
self.data["risk"].append(one_risk)
|
||
self.data["is_autofix"].append(one_risk["m_name"])
|
||
|
||
# 扫描中发现的漏洞数
|
||
self.discov_count += 1
|
||
# 扫描中的动态分数
|
||
self.score -= level
|
||
if self.score < 0:
|
||
self.score = 0
|
||
# 扫描中的动态风险
|
||
self.tmp_data['risk'].append(one_risk)
|
||
# 可修复项
|
||
self.tmp_data['is_autofix'].append(one_risk["m_name"])
|
||
|
||
# result_json = {
|
||
# "vul_count": len(detail),
|
||
# "risk": [],
|
||
# "ignore": [],
|
||
# "all_check_time": "",
|
||
# "ignore_count": 0,
|
||
# "msg": "",
|
||
# "repair_count": {"all_count": 0, "today_vount": 0},
|
||
# }
|
||
# for sr in systemscan_result.values():
|
||
# one_risk = {
|
||
# "cve_id": "",
|
||
# "vuln_name": "",
|
||
# "vuln_time": "2021-12-16",
|
||
# "vuln_solution": "",
|
||
# "level": 1,
|
||
# "soft_name": {},
|
||
# "vuln_version": "",
|
||
# "check_time": 1701910962,
|
||
# "reboot": ""
|
||
# }
|
||
# one_risk["cve_id"] = sr["ref_id"]
|
||
# one_risk["vuln_name"] = "【{}】Linux软件安全公告".format(sr["ref_id"])
|
||
# one_risk["vuln_solution"] = "更新涉及软件补丁,具体信息参考官方公告{}".format(sr["ref_url"])
|
||
# level = self.new_severity_to_num(sr["severity"])
|
||
# one_risk["level"] = level
|
||
# # 处理受影响的软件包(为了兼容旧版本暂时这样)
|
||
# soft_name = {}
|
||
# vuln_version = ""
|
||
# for impact in sr["impact"]:
|
||
# soft_name[impact["package"]] = impact["version"]
|
||
# vuln_version = impact["vul_ver"]
|
||
# one_risk["soft_name"] = soft_name
|
||
# one_risk["vuln_version"] = vuln_version
|
||
# risk_list.append(one_risk)
|
||
#
|
||
# # 扫描中发现的漏洞数
|
||
# self.discov_count += 1
|
||
# # 扫描中的动态分数
|
||
# self.score -= level
|
||
# if self.score < 0:
|
||
# self.score = 0
|
||
# # 扫描中的动态风险
|
||
# self.tmp_data['risk'].append(one_risk)
|
||
# # 可修复项
|
||
# self.tmp_data['is_autofix'].append(one_risk["cve_id"])
|
||
#
|
||
# result_json["risk"] = risk_list
|
||
# public.WriteFile(self.__path + '/system_scan_time', int(time.time()))
|
||
# public.WriteFile(self._vuln_result, json.dumps(result_json))
|
||
|
||
def is_file_too_old(self, file_path, days):
|
||
"""
|
||
判断文件是否过于陈旧
|
||
:param file_path: 文件路径
|
||
:param days: 超过的天数
|
||
:return: bool
|
||
"""
|
||
mtime = os.path.getmtime(file_path)
|
||
# 不存在直接返回True
|
||
if mtime is None:
|
||
return True
|
||
mod_time = datetime.datetime.fromtimestamp(mtime)
|
||
days_old = datetime.datetime.now() - mod_time
|
||
return days_old.days > days
|
||
|
||
def adjust_ver(self, ver_a, ver_b):
|
||
'''
|
||
确保两个版本主版本号统一,一方存在另一方不存在则删除主版本,要么都有,要么都没有
|
||
'''
|
||
if ":" in ver_a:
|
||
if ":" in ver_b:
|
||
ver_1 = ver_a
|
||
else:
|
||
ver_1 = ver_a.split(":")[1]
|
||
ver_2 = ver_b
|
||
else:
|
||
if ":" in ver_b:
|
||
ver_2 = ver_b.split(":")[1]
|
||
else:
|
||
ver_2 = ver_b
|
||
ver_1 = ver_a
|
||
return ver_1, ver_2
|
||
|
||
def new_severity_to_num(self, severity):
|
||
'''
|
||
将漏洞级别转变成数字
|
||
'''
|
||
if severity == "Critical":
|
||
return 3
|
||
elif severity == "Important":
|
||
return 2
|
||
elif severity == "Moderate":
|
||
return 1
|
||
elif severity == "Low":
|
||
return 1
|
||
elif severity == "High":
|
||
return 3
|
||
elif severity == "Medium":
|
||
return 2
|
||
else:
|
||
return 2
|
||
|
||
# def new_rpmvercmp(self, sys_ver, vul_ver):
|
||
# output, err = public.ExecShell("rpmdev-vercmp {} {}".format(sys_ver, vul_ver))
|
||
# if err != '':
|
||
# return 1
|
||
# output = output.strip()
|
||
# if output == "{} > {}".format(sys_ver, vul_ver):
|
||
# return 1
|
||
# elif output == "{} == {}".format(sys_ver, vul_ver):
|
||
# return 0
|
||
# elif output == "{} < {}".format(sys_ver, vul_ver):
|
||
# return -1
|
||
# else:
|
||
# return 1
|
||
|
||
|
||
class Dpkg:
|
||
def __init__(self):
|
||
self._fileinfo = None
|
||
self._control_str = None
|
||
self._headers = None
|
||
self._message = None
|
||
self._upstream_version = None
|
||
self._debian_revision = None
|
||
self._epoch = None
|
||
|
||
@staticmethod
|
||
def get_epoch(version_str):
|
||
try:
|
||
e_index = version_str.index(":")
|
||
except ValueError:
|
||
return 0, version_str
|
||
|
||
try:
|
||
epoch = int(version_str[0:e_index])
|
||
except ValueError as ex:
|
||
print(f"Corrupt dpkg version '{version_str}': epochs can only be ints, and "
|
||
"epochless versions cannot use the colon character.")
|
||
return epoch, version_str[e_index + 1:]
|
||
|
||
@staticmethod
|
||
def get_upstream(version_str):
|
||
try:
|
||
d_index = version_str.rindex("-")
|
||
except ValueError:
|
||
return version_str, "0"
|
||
|
||
return version_str[0:d_index], version_str[d_index + 1:]
|
||
|
||
@staticmethod
|
||
def split_full_version(version_str):
|
||
epoch, full_ver = Dpkg.get_epoch(version_str)
|
||
upstream_rev, debian_rev = Dpkg.get_upstream(full_ver)
|
||
return epoch, upstream_rev, debian_rev
|
||
|
||
@staticmethod
|
||
def get_alphas(revision_str):
|
||
for i, char in enumerate(revision_str):
|
||
if char.isdigit():
|
||
if i == 0:
|
||
return "", revision_str
|
||
return revision_str[0:i], revision_str[i:]
|
||
return revision_str, ""
|
||
|
||
@staticmethod
|
||
def get_digits(revision_str):
|
||
if not revision_str:
|
||
return 0, ""
|
||
for i, char in enumerate(revision_str):
|
||
if not char.isdigit():
|
||
if i == 0:
|
||
return 0, revision_str
|
||
return int(revision_str[0:i]), revision_str[i:]
|
||
return int(revision_str), ""
|
||
|
||
@staticmethod
|
||
def listify(revision_str):
|
||
result = []
|
||
while revision_str:
|
||
rev_1, remains = Dpkg.get_alphas(revision_str)
|
||
rev_2, remains = Dpkg.get_digits(remains)
|
||
result.extend([rev_1, rev_2])
|
||
revision_str = remains
|
||
return result
|
||
|
||
@staticmethod
|
||
def dstringcmp(a, b):
|
||
if a == b:
|
||
return 0
|
||
try:
|
||
for i, char in enumerate(a):
|
||
if char == b[i]:
|
||
continue
|
||
if char == "~":
|
||
return -1
|
||
if b[i] == "~":
|
||
return 1
|
||
if char.isalpha() and not b[i].isalpha():
|
||
return -1
|
||
if not char.isalpha() and b[i].isalpha():
|
||
return 1
|
||
if ord(char) > ord(b[i]):
|
||
return 1
|
||
if ord(char) < ord(b[i]):
|
||
return -1
|
||
except IndexError:
|
||
if char == "~":
|
||
return -1
|
||
return 1
|
||
if b[len(a)] == "~":
|
||
return 1
|
||
return -1
|
||
|
||
@staticmethod
|
||
def compare_revision_strings(rev1, rev2):
|
||
if rev1 == rev2:
|
||
return 0
|
||
list1 = Dpkg.listify(rev1)
|
||
list2 = Dpkg.listify(rev2)
|
||
if list1 == list2:
|
||
return 0
|
||
try:
|
||
for i, item in enumerate(list1):
|
||
if i >= len(list2):
|
||
raise IndexError
|
||
if not isinstance(item, list2[i].__class__):
|
||
print(f"Cannot compare '{item}' to {list2[i]}, something has gone horribly awry.")
|
||
if item == list2[i]:
|
||
continue
|
||
if isinstance(item, int):
|
||
if item > list2[i]:
|
||
return 1
|
||
if item < list2[i]:
|
||
return -1
|
||
else:
|
||
return Dpkg.dstringcmp(item, list2[i])
|
||
except IndexError:
|
||
if list1[len(list2)][0][0] == "~":
|
||
return -1
|
||
return 1
|
||
if list2[len(list1)][0][0] == "~":
|
||
return 1
|
||
return -1
|
||
|
||
@staticmethod
|
||
def compare_versions(ver1, ver2):
|
||
if ver1 == ver2:
|
||
return 0
|
||
epoch1, upstream1, debian1 = Dpkg.split_full_version(str(ver1))
|
||
epoch2, upstream2, debian2 = Dpkg.split_full_version(str(ver2))
|
||
|
||
if epoch1 < epoch2:
|
||
return -1
|
||
if epoch1 > epoch2:
|
||
return 1
|
||
|
||
upstr_res = Dpkg.compare_revision_strings(upstream1, upstream2)
|
||
if upstr_res != 0:
|
||
return upstr_res
|
||
|
||
debian_res = Dpkg.compare_revision_strings(debian1, debian2)
|
||
if debian_res != 0:
|
||
return debian_res
|
||
|
||
return 0
|
||
|
||
if __name__ == "__main__":
|
||
# st = time.time()
|
||
panel = panelWarning()
|
||
# panel.new_system_scan()
|
||
public.WriteFile('/www/server/panel/data/warning/resultresult.json', json.dumps(panel._get_list()))
|
||
# et = time.time()
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# #coding: utf-8
|
||
# # +-------------------------------------------------------------------
|
||
# # | YakPanel
|
||
# # +-------------------------------------------------------------------
|
||
# # | Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||
# # +-------------------------------------------------------------------
|
||
# # | Author: hwliang <2020-08-04>
|
||
# # +-------------------------------------------------------------------
|
||
#
|
||
# import os,sys,json,time,public
|
||
#
|
||
# class panelWarning:
|
||
# __path = '/www/server/panel/data/warning'
|
||
# __ignore = __path + '/ignore'
|
||
# __result = __path + '/result'
|
||
# __risk = __path + '/risk'
|
||
# def __init__(self):
|
||
# if not os.path.exists(self.__ignore):
|
||
# os.makedirs(self.__ignore,384)
|
||
# if not os.path.exists(self.__result):
|
||
# os.makedirs(self.__result,384)
|
||
# if not os.path.exists(self.__risk):
|
||
# os.makedirs(self.__risk, 384)
|
||
#
|
||
# def get_list(self,args):
|
||
# p = public.get_modules('class/safe_warning')
|
||
# data = {
|
||
# 'security':[],
|
||
# 'risk':[],
|
||
# 'ignore':[]
|
||
# }
|
||
#
|
||
# for m_name in p.__dict__.keys():
|
||
# ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
# # 忽略的检查项
|
||
# if p[m_name]._level == 0: continue
|
||
#
|
||
# m_info = {
|
||
# 'title': p[m_name]._title,
|
||
# 'm_name': m_name,
|
||
# 'ps': p[m_name]._ps,
|
||
# 'version': p[m_name]._version,
|
||
# 'level': p[m_name]._level,
|
||
# 'ignore': p[m_name]._ignore,
|
||
# 'date': p[m_name]._date,
|
||
# 'tips': p[m_name]._tips,
|
||
# 'help': p[m_name]._help
|
||
# }
|
||
# result_file = self.__result + '/' + m_name + '.pl'
|
||
#
|
||
# try:
|
||
# s_time = time.time()
|
||
# m_info['status'],m_info['msg'] = p[m_name].check_run()
|
||
# m_info['taking'] = round(time.time() - s_time,6)
|
||
# m_info['check_time'] = int(time.time())
|
||
# public.writeFile(result_file,json.dumps([m_info['status'],m_info['msg'],m_info['check_time'],m_info['taking']],))
|
||
# except:
|
||
# continue
|
||
#
|
||
# m_info['ignore'] = os.path.exists(ignore_file)
|
||
# if m_info['ignore']:
|
||
# data['ignore'].append(m_info)
|
||
# else:
|
||
# if m_info['status']:
|
||
# data['security'].append(m_info)
|
||
# else:
|
||
# risk_file = self.__risk + '/' + m_name + '.pl'
|
||
# public.writeFile(risk_file, json.dumps(m_info))
|
||
# data['risk'].append(m_info)
|
||
#
|
||
# data['risk'] = sorted(data['risk'],key=lambda x: x['level'],reverse=True)
|
||
# data['security'] = sorted(data['security'],key=lambda x: x['level'],reverse=True)
|
||
# data['ignore'] = sorted(data['ignore'],key=lambda x: x['level'],reverse=True)
|
||
# # 获取支持一键修复的列表
|
||
# try:
|
||
# is_autofix = public.read_config("safe_autofix")
|
||
# except:
|
||
# is_autofix = []
|
||
# data['is_autofix'] = is_autofix
|
||
# return data
|
||
#
|
||
#
|
||
# def sync_rule(self):
|
||
# '''
|
||
# @name 从云端同步规则
|
||
# @author hwliang<2020-08-05>
|
||
# @return void
|
||
# '''
|
||
# # try:
|
||
# # dep_path = '/www/server/panel/class/safe_warning'
|
||
# # local_version_file = self.__path + '/version.pl'
|
||
# # last_sync_time = local_version_file = self.__path + '/last_sync.pl'
|
||
# # if os.path.exists(dep_path):
|
||
# # if os.path.exists(last_sync_time):
|
||
# # if int(public.readFile(last_sync_time)) > time.time():
|
||
# # return
|
||
# # else:
|
||
# # if os.path.exists(local_version_file): os.remove(local_version_file)
|
||
#
|
||
# # download_url = public.get_url()
|
||
# # version_url = download_url + '/install/warning/version.txt'
|
||
# # cloud_version = public.httpGet(version_url)
|
||
# # if cloud_version: cloud_version = cloud_version.strip()
|
||
#
|
||
# # local_version = public.readFile(local_version_file)
|
||
# # if local_version:
|
||
# # if cloud_version == local_version:
|
||
# # return
|
||
#
|
||
# # tmp_file = '/tmp/bt_safe_warning.zip'
|
||
# # public.ExecShell('wget -O {} {} -T 5'.format(tmp_file,download_url + '/install/warning/safe_warning.zip'))
|
||
# # if not os.path.exists(tmp_file):
|
||
# # return
|
||
#
|
||
# # if os.path.getsize(tmp_file) < 2129:
|
||
# # os.remove(tmp_file)
|
||
# # return
|
||
#
|
||
# # if not os.path.exists(dep_path):
|
||
# # os.makedirs(dep_path,384)
|
||
# # public.ExecShell("unzip -o {} -d {}/ >/dev/null".format(tmp_file,dep_path))
|
||
# # public.writeFile(local_version_file,cloud_version)
|
||
# # public.writeFile(last_sync_time,str(int(time.time() + 7200)))
|
||
# # if os.path.exists(tmp_file): os.remove(tmp_file)
|
||
# # public.ExecShell("chmod -R 600 {}".format(dep_path))
|
||
# # except:
|
||
# # pass
|
||
#
|
||
#
|
||
#
|
||
# def set_ignore(self,args):
|
||
# '''
|
||
# @name 设置指定项忽略状态
|
||
# @author hwliang<2020-08-04>
|
||
# @param dict_obj {
|
||
# m_name<string> 模块名称
|
||
# }
|
||
# @return dict
|
||
# '''
|
||
# m_name = args.m_name.strip()
|
||
# ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
# if os.path.exists(ignore_file):
|
||
# os.remove(ignore_file)
|
||
# else:
|
||
# public.writeFile(ignore_file,'1')
|
||
# return public.returnMsg(True, public.lang("Successfully set!"))
|
||
#
|
||
# def check_find(self, args):
|
||
# '''
|
||
# @name 检测指定项
|
||
# @author hwliang<2020-08-04>
|
||
# @param dict_obj {
|
||
# m_name<string> 模块名称
|
||
# }
|
||
# @return dict
|
||
# '''
|
||
# try:
|
||
# m_name = args.m_name.strip()
|
||
# p = public.get_modules('class/safe_warning')
|
||
# m_info = {
|
||
# 'title': p[m_name]._title,
|
||
# 'm_name': m_name,
|
||
# 'ps': p[m_name]._ps,
|
||
# 'version': p[m_name]._version,
|
||
# 'level': p[m_name]._level,
|
||
# 'ignore': p[m_name]._ignore,
|
||
# 'date': p[m_name]._date,
|
||
# 'tips': p[m_name]._tips,
|
||
# 'help': p[m_name]._help
|
||
# }
|
||
#
|
||
# # 解决已经在忽略列表中,但是如果仍然需要检查的话可以检查
|
||
# ignore_file = self.__ignore + '/' + m_name + '.pl'
|
||
# if os.path.exists(ignore_file):
|
||
# from cachelib import SimpleCache
|
||
# cache = SimpleCache(5000)
|
||
# ikey = 'warning_list'
|
||
# cache.delete(ikey)
|
||
# os.remove(ignore_file)
|
||
#
|
||
# result_file = self.__result + '/' + m_name + '.pl'
|
||
# s_time = time.time()
|
||
# m_info['status'], m_info['msg'] = p[m_name].check_run()
|
||
# m_info['taking'] = round(time.time() - s_time, 4)
|
||
# m_info['check_time'] = int(time.time())
|
||
# public.writeFile(result_file, json.dumps(
|
||
# [m_info['status'], m_info['msg'], m_info['check_time'], m_info['taking']]))
|
||
# return public.returnMsg(True, public.lang("Retested"))
|
||
# except:
|
||
# return public.returnMsg(False, public.lang("Detection failed"))
|