在网络安全应急响应(Incident Response)中,现场环境往往复杂且受限。安全工程师需要在不破坏现场证据的前提下,快速收集系统状态、分析日志并定位恶意文件。

虽然有许多成熟的 EDR 和商业工具,但在紧急情况下,轻量级、可定制的 Python 或 Shell 脚本往往是最好用的“瑞士军刀”。本文提供三个应急响应中最常用的实战脚本示例。

场景一:系统信息“快照”收集 (System Info Collector)

目标:快速获取当前系统的进程列表、网络连接、用户信息和计划任务,用于后续离线分析。 特点:使用 Python 标准库 subprocess,无需安装 psutil,兼容性强。

import subprocess
import os
import datetime

def run_command(cmd, description):
    print(f"[*] 正在收集: {description}...")
    try:
        # 使用 shell=True 允许使用管道符,但需注意安全风险(此处为内部工具,相对可控)
        result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
        return f"\n=== {description} ===\n" + result.decode('utf-8', errors='ignore')
    except subprocess.CalledProcessError as e:
        return f"\n=== {description} (ERROR) ===\n" + str(e.output)

def collect_linux_info():
    report = f"系统信息收集报告 - 时间: {datetime.datetime.now()}\n"
    
    # 1. 当前登录用户
    report += run_command("w", "当前登录用户")
    
    # 2. 异常网络连接 (关注 ESTABLISHED 和 LISTEN)
    # -p: 显示进程PID, -n: 不解析域名 (加速)
    report += run_command("netstat -antlp", "网络连接与对应进程")
    
    # 3. 进程列表 (按 CPU/内存排序)
    report += run_command("ps -aux --sort=-pcpu | head -20", "Top 20 CPU 占用进程")
    
    # 4. 检查定时任务
    report += run_command("cat /etc/crontab", "系统级 Crontab")
    report += run_command("ls -la /var/spool/cron/", "用户级 Crontab 目录")
    
    # 5. 检查最近修改的敏感文件 (如 /etc/passwd, /etc/shadow)
    # 查找 7 天内修改过的 /etc 下的文件
    report += run_command("find /etc -type f -mtime -7 2>/dev/null", "最近7天修改的配置")

    # 保存报告
    filename = f"ir_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
    with open(filename, "w") as f:
        f.write(report)
    print(f"\n[+] 收集完成,报告已保存至: {filename}")

if __name__ == "__main__":
    if os.name == 'posix':
        collect_linux_info()
    else:
        print("此示例脚本主要针对 Linux 环境,Windows 建议使用 PowerShell 或 WMIC。")

场景二:Web 日志攻击特征分析 (Log Analyzer)

目标:从海量的 Web 访问日志(Apache/Nginx)中筛选出 SQL 注入、XSS 或 Webshell 连接的痕迹。 特点:基于正则匹配,快速定位攻击源 IP。

import re
import sys

# 定义常见的攻击特征正则
ATTACK_PATTERNS = {
    'SQL_Injection': r"(union.*select|select.*from|information_schema|waitfor.*delay|sleep\()",
    'XSS': r"(<script>|alert\(|javascript:|onerror=)",
    'Webshell_Connect': r"(cmd=|eval\(|whoami|exec\(|system\()",
    'Directory_Traversal': r"(\.\./\.\./|/etc/passwd|c:\\windows)",
    'Struts2_RCE': r"(org\.apache\.struts2|ognl)"
}

def analyze_log(log_file):
    print(f"[*] 开始分析日志文件: {log_file}")
    
    suspicious_count = 0
    ip_stats = {}
    
    try:
        with open(log_file, 'r', encoding='utf-8', errors='ignore') as f:
            for line in f:
                # 简单的 Nginx/Apache 日志解码
                # 假设格式: IP - - [Date] "Request" Status Bytes ...
                # 这里只做简单的全文匹配,实际场景可精细化解析
                
                is_suspicious = False
                for attack_type, pattern in ATTACK_PATTERNS.items():
                    if re.search(pattern, line, re.IGNORECASE):
                        print(f"[!] 发现疑似 {attack_type} 攻击:")
                        print(f"    {line.strip()[:200]}...") # 只打印前200字符
                        is_suspicious = True
                        suspicious_count += 1
                        break # 一行只报一次
                
                if is_suspicious:
                    # 尝试提取 IP (简单正则,匹配行首 IP)
                    ip_match = re.match(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", line)
                    if ip_match:
                        ip = ip_match.group(1)
                        ip_stats[ip] = ip_stats.get(ip, 0) + 1

    except FileNotFoundError:
        print("[-] 错误:找不到日志文件。")
        return

    print(f"\n[*] 分析结束。共发现 {suspicious_count} 条可疑记录。")
    if ip_stats:
        print("\n[+] 可疑 IP TOP 5:")
        sorted_ips = sorted(ip_stats.items(), key=lambda x: x[1], reverse=True)[:5]
        for ip, count in sorted_ips:
            print(f"    IP: {ip} - 触发次数: {count}")

if __name__ == "__main__":
    # 使用方式: python log_analyzer.py /var/log/nginx/access.log
    if len(sys.argv) < 2:
        print("Usage: python log_analyzer.py <logfile_path>")
    else:
        analyze_log(sys.argv[1])

场景三:Webshell 与变动文件扫描 (File Scanner)

目标:扫描 Web 目录,找出最近被修改的文件(可能是攻击者上传的马)以及包含危险函数的文件。 特点:结合时间戳和文件内容特征。

import os
import time

# 配置扫描目录和敏感扩展名
SCAN_DIR = "/var/www/html"  # 修改为实际 Web 根目录
EXTENSIONS = ['.php', '.jsp', '.asp', '.aspx']

# 危险函数特征 (PHP示例)
WEBSHELL_SIGNATURES = [
    b'eval($_POST', 
    b'system($_GET', 
    b'shell_exec', 
    b'base64_decode', 
    b'assert('
]

def scan_files(directory):
    print(f"[*] 开始扫描目录: {directory}")
    print(f"[*] 查找最近 24 小时内修改过的脚本文件...")
    
    now = time.time()
    one_day_ago = now - (24 * 60 * 60)
    
    for root, dirs, files in os.walk(directory):
        for filename in files:
            filepath = os.path.join(root, filename)
            _, ext = os.path.splitext(filename)
            
            if ext.lower() not in EXTENSIONS:
                continue
            
            try:
                # 1. 检查文件修改时间 (mtime)
                file_stats = os.stat(filepath)
                mtime = file_stats.st_mtime
                
                if mtime > one_day_ago:
                    print(f"[Time] 最近修改: {filepath} (时间: {time.ctime(mtime)})")
                
                # 2. 检查文件内容特征
                with open(filepath, 'rb') as f:
                    content = f.read()
                    for sig in WEBSHELL_SIGNATURES:
                        if sig in content:
                            print(f"[Danger] 发现危险特征 '{sig.decode()}': {filepath}")
                            break
                            
            except Exception as e:
                print(f"[-] 无法读取文件: {filepath} - {e}")

if __name__ == "__main__":
    if os.path.exists(SCAN_DIR):
        scan_files(SCAN_DIR)
    else:
        print(f"[-] 目录不存在: {SCAN_DIR}")

应急响应工具箱推荐

除了上述自编脚本,以下现成工具也是应急响应的标准配置:

  1. Sysinternals Suite (Windows):
    • Process Explorer: 查看进程层级、加载的 DLL。
    • Autoruns: 最全的启动项检查工具。
    • TCPView: 实时查看端口连接。
  2. BusyBox (Linux):
    • 如果系统命令(如 ls, ps)被植入 rootkit 替换了,上传一个静态编译的 busybox 可以使用干净的指令集。
  3. GScan / Chkrootkit / Rkhunter:
    • Linux 自动化排查脚本,能自动检测 rootkit 和常见的后门配置。
  4. Wireshark / Tcpdump:
    • 全流量抓包分析,用于捕捉 C2(Command & Control)通信流量。

结语

工具只是辅助,核心在于分析思路。在执行上述脚本时,请务必注意:

  1. 最小化影响:不要在业务高峰期运行高负载扫描。
  2. 证据保全:任何操作前,最好对关键日志和文件进行哈希备份。
  3. 隔离优先:确认主机受陷后,第一时间断网(物理拔线或虚拟隔离)是防止扩散的最有效手段。