| |
| |
|
|
| import os, sys, public |
| import re |
|
|
| _title = '检查nginx配置文件是否被挂马' |
| _version = 1.0 |
| _ps = "检查nginx配置文件是否被挂马" |
| _level = 3 |
| _date = '2023-11-21' |
| _ignore = os.path.exists("data/warning/ignore/sw_nginx_malware.pl") |
| _tips = [ |
| "根据提示,找到nginx配置文件,删除js挂马内容,或点击【修复】按钮", |
| "重启nginx服务" |
| ] |
| _help = '' |
| _remind = '手动修复之前建议先把该配置文件做备份,以防操作失误导致服务无法启动;或者使用一键修复' |
|
|
|
|
| def check_run(): |
| ''' |
| @name 开始检测 |
| @author lwh<2023-11-21> |
| @return tuple (status<bool>,msg<string>) |
| ''' |
| try: |
| import glob |
| path = '/www/server/panel/vhost/nginx/' |
| if not os.path.exists(path): |
| return True, '无风险' |
| risk_files = [] |
| |
| malware_patterns = [ |
| r'(?mi)^\s*(?!#)\s*sub_filter\s+.*<script.*?;' |
| ] |
| patterns = [re.compile(pattern) for pattern in malware_patterns] |
|
|
| for filename in glob.glob(os.path.join(path, '*.conf')): |
| try: |
| if os.path.isdir(filename): |
| continue |
| content = public.ReadFile(filename) |
| if not content: |
| continue |
| |
| if len(content) > 10 * 1024 * 1024: |
| continue |
| |
| for pattern in patterns: |
| matches = pattern.findall(content) |
| if matches: |
| risk_files.append({ |
| 'file': filename, |
| 'content': matches[0].strip() |
| }) |
| break |
| |
| |
| |
| except Exception as e: |
| continue |
| if risk_files: |
| |
| report = ["发现{}个配置文件存在可疑内容:".format(len(risk_files))] |
|
|
| for i, risk in enumerate(risk_files, 1): |
| report.append("{}. 文件: {} ".format( |
| i, |
| risk['file'] |
| |
| )) |
|
|
| return False, '<br />' + ('<br />'.join(report)) |
|
|
| |
| |
| return True, '无风险' |
| except Exception as e: |
| return True, '无风险' |
|
|
|
|
| def _get_context(content, match, context_lines=2): |
| """获取匹配内容的上下文""" |
| try: |
| lines = content.split('\n') |
| for i, line in enumerate(lines): |
| if match in line: |
| start = max(0, i - context_lines) |
| end = min(len(lines), i + context_lines + 1) |
| return '\n'.join(lines[start:end]) |
| except: |
| return match |
| return match |