入侵检测脚本#

脚本说明#

入侵检测脚本用于检测系统入侵行为,包括异常登录、异常进程、异常文件等。

脚本代码#

#!/bin/bash

# 入侵检测脚本
# 功能:检测系统入侵行为
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
LOG_FILE="/var/log/intrusion_detection.log"
ALERT_LOG="/var/log/intrusion_alert.log"
BASELINE_FILE="/tmp/system_baseline.txt"
BASELINE_DIR="/tmp/baseline_files"
ALERT_EMAIL="admin@example.com"
SCAN_INTERVAL=300

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@" | tee -a "$LOG_FILE"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

log_warning() {
    log "WARNING" "$@"
}

# 创建基线
create_baseline() {
    log_info "创建系统基线"
    
    # 创建基线目录
    mkdir -p "$BASELINE_DIR"
    
    # 保存系统信息
    {
        echo "=== 系统信息 ==="
        echo "主机名: $(hostname)"
        echo "操作系统: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '\"')"
        echo "内核版本: $(uname -r)"
        echo "创建时间: $(date)"
        echo ""
        
        echo "=== 用户列表 ==="
        cat /etc/passwd
        echo ""
        
        echo "=== 组列表 ==="
        cat /etc/group
        echo ""
        
        echo "=== 安装的软件包 ==="
        if command -v dpkg &> /dev/null; then
            dpkg -l
        elif command -v rpm &> /dev/null; then
            rpm -qa
        fi
        echo ""
        
        echo "=== 网络配置 ==="
        ip addr show
        echo ""
        ip route show
        echo ""
        
        echo "=== 开放端口 ==="
        netstat -tuln
        echo ""
        
        echo "=== 运行的服务 ==="
        systemctl list-units --type=service --state=running
        echo ""
        
        echo "=== SUID文件 ==="
        find / -type f -perm -4000 2>/dev/null
        echo ""
        
        echo "=== SGID文件 ==="
        find / -type f -perm -2000 2>/dev/null
        echo ""
        
        echo "=== 重要文件哈希 ==="
        md5sum /etc/passwd /etc/shadow /etc/group /etc/sudoers 2>/dev/null
    } > "$BASELINE_FILE"
    
    # 保存重要文件
    cp /etc/passwd "$BASELINE_DIR/passwd.baseline"
    cp /etc/shadow "$BASELINE_DIR/shadow.baseline"
    cp /etc/group "$BASELINE_DIR/group.baseline"
    cp /etc/sudoers "$BASELINE_DIR/sudoers.baseline"
    
    log_info "系统基线创建完成: $BASELINE_FILE"
}

# 比较基线
compare_baseline() {
    log_info "比较系统基线"
    
    if [ ! -f "$BASELINE_FILE" ]; then
        log_error "基线文件不存在,请先创建基线"
        return 1
    fi
    
    local alerts=0
    
    # 比较用户列表
    log_info "比较用户列表"
    if ! diff "$BASELINE_DIR/passwd.baseline" /etc/passwd > /dev/null; then
        log_error "用户列表发生变化"
        diff "$BASELINE_DIR/passwd.baseline" /etc/passwd
        alerts=$((alerts + 1))
    fi
    
    # 比较组列表
    log_info "比较组列表"
    if ! diff "$BASELINE_DIR/group.baseline" /etc/group > /dev/null; then
        log_error "组列表发生变化"
        diff "$BASELINE_DIR/group.baseline" /etc/group
        alerts=$((alerts + 1))
    fi
    
    # 比较sudoers文件
    log_info "比较sudoers文件"
    if ! diff "$BASELINE_DIR/sudoers.baseline" /etc/sudoers > /dev/null; then
        log_error "sudoers文件发生变化"
        diff "$BASELINE_DIR/sudoers.baseline" /etc/sudoers
        alerts=$((alerts + 1))
    fi
    
    # 比较文件哈希
    log_info "比较文件哈希"
    local current_hashes=$(md5sum /etc/passwd /etc/shadow /etc/group /etc/sudoers 2>/dev/null)
    local baseline_hashes=$(grep "重要文件哈希" -A 4 "$BASELINE_FILE" | tail -n +2)
    
    if [ "$current_hashes" != "$baseline_hashes" ]; then
        log_error "文件哈希发生变化"
        alerts=$((alerts + 1))
    fi
    
    if [ $alerts -gt 0 ]; then
        log_error "发现 $alerts 个基线差异"
        return 1
    fi
    
    log_info "基线比较完成,没有发现差异"
    return 0
}

# 检测异常登录
detect_abnormal_login() {
    log_info "检测异常登录"
    
    local alerts=0
    
    # 检查失败的登录尝试
    local failed_logins=$(grep "Failed password" /var/log/auth.log 2>/dev/null | tail -100 || \
                          grep "Failed password" /var/log/secure 2>/dev/null | tail -100)
    
    if [ -n "$failed_logins" ]; then
        # 统计每个IP的失败次数
        local ip_counts=$(echo "$failed_logins" | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn)
        
        echo "$ip_counts" | while read count ip; do
            if [ $count -gt 10 ]; then
                log_error "检测到暴力破解尝试: $ip ($count 次失败)"
                alerts=$((alerts + 1))
            fi
        done
    fi
    
    # 检查异常时间登录
    local abnormal_time_logins=$(date +%H)
    if [ $abnormal_time_logins -lt 6 ] || [ $abnormal_time_logins -gt 22 ]; then
        local recent_logins=$(last -n 10 | grep "still logged in")
        if [ -n "$recent_logins" ]; then
            log_warning "检测到异常时间登录"
            echo "$recent_logins"
        fi
    fi
    
    # 检查新用户登录
    local new_users=$(last -n 100 | awk '{print $1}' | sort -u | grep -v "reboot\|wtmp\|root")
    if [ -n "$new_users" ]; then
        log_info "最近登录的用户: $new_users"
    fi
    
    return $alerts
}

# 检测异常进程
detect_abnormal_process() {
    log_info "检测异常进程"
    
    local alerts=0
    
    # 检查可疑进程
    local suspicious_processes=$(ps aux | grep -E "(nc|netcat|telnet|ftp|wget|curl.*sh)" | grep -v grep)
    
    if [ -n "$suspicious_processes" ]; then
        log_error "检测到可疑进程"
        echo "$suspicious_processes"
        alerts=$((alerts + 1))
    fi
    
    # 检查隐藏进程
    local hidden_processes=$(ps aux | awk '{print $11}' | grep -E "^\." | grep -v "^\.\./")
    
    if [ -n "$hidden_processes" ]; then
        log_error "检测到隐藏进程"
        echo "$hidden_processes"
        alerts=$((alerts + 1))
    fi
    
    # 检查高CPU使用进程
    local high_cpu_processes=$(ps aux --sort=-%cpu | awk 'NR>1 && $3>80 {print}')
    
    if [ -n "$high_cpu_processes" ]; then
        log_warning "检测到高CPU使用进程"
        echo "$high_cpu_processes"
    fi
    
    # 检查网络连接的进程
    local network_processes=$(netstat -tulnp | grep LISTEN | awk '{print $7}' | cut -d/ -f1 | sort -u)
    
    if [ -n "$network_processes" ]; then
        log_info "监听端口的进程: $network_processes"
    fi
    
    return $alerts
}

# 检测异常文件
detect_abnormal_file() {
    log_info "检测异常文件"
    
    local alerts=0
    
    # 检查最近修改的系统文件
    local recent_system_files=$(find /etc -type f -mtime -1 2>/dev/null)
    
    if [ -n "$recent_system_files" ]; then
        log_warning "检测到最近修改的系统文件"
        echo "$recent_system_files"
    fi
    
    # 检查可执行文件
    local executable_files=$(find /tmp -type f -executable 2>/dev/null)
    
    if [ -n "$executable_files" ]; then
        log_error "检测到/tmp目录的可执行文件"
        echo "$executable_files"
        alerts=$((alerts + 1))
    fi
    
    # 检查SUID文件
    local suid_files=$(find / -type f -perm -4000 2>/dev/null | grep -v "^/proc")
    
    if [ -n "$suid_files" ]; then
        log_info "SUID文件:"
        echo "$suid_files"
    fi
    
    # 检查SGID文件
    local sgid_files=$(find / -type f -perm -2000 2>/dev/null | grep -v "^/proc")
    
    if [ -n "$sgid_files" ]; then
        log_info "SGID文件:"
        echo "$sgid_files"
    fi
    
    # 检查大文件
    local large_files=$(find / -type f -size +100M 2>/dev/null | grep -v "^/proc")
    
    if [ -n "$large_files" ]; then
        log_warning "检测到大文件"
        echo "$large_files" | head -20
    fi
    
    return $alerts
}

# 检测异常网络
detect_abnormal_network() {
    log_info "检测异常网络"
    
    local alerts=0
    
    # 检查异常网络连接
    local established_connections=$(netstat -an | grep ESTABLISHED | wc -l)
    
    if [ $established_connections -gt 1000 ]; then
        log_error "检测到大量网络连接: $established_connections"
        alerts=$((alerts + 1))
    fi
    
    # 检查可疑端口
    local suspicious_ports=$(netstat -tuln | grep -E ":(31337|12345|54321|4444)" | grep LISTEN)
    
    if [ -n "$suspicious_ports" ]; then
        log_error "检测到可疑端口"
        echo "$suspicious_ports"
        alerts=$((alerts + 1))
    fi
    
    # 检查异常DNS查询
    local dns_queries=$(grep "query" /var/log/syslog 2>/dev/null | tail -100)
    
    if [ -n "$dns_queries" ]; then
        log_info "最近的DNS查询:"
        echo "$dns_queries" | tail -20
    fi
    
    return $alerts
}

# 检测Rootkit
detect_rootkit() {
    log_info "检测Rootkit"
    
    local alerts=0
    
    # 检查修改过的系统二进制文件
    local modified_binaries=$(rpm -Va 2>/dev/null | grep "^..5" || \
                              dpkg --verify 2>/dev/null | grep "^..5")
    
    if [ -n "$modified_binaries" ]; then
        log_error "检测到修改过的系统文件"
        echo "$modified_binaries"
        alerts=$((alerts + 1))
    fi
    
    # 检查隐藏的模块
    local hidden_modules=$(lsmod | grep -v "^Module")
    
    if [ -n "$hidden_modules" ]; then
        log_info "加载的内核模块:"
        lsmod
    fi
    
    # 检查可疑的启动项
    local suspicious_startup=$(grep -r "exec\|sh\|bash" /etc/init.d/ 2>/dev/null | grep -v "^Binary")
    
    if [ -n "$suspicious_startup" ]; then
        log_warning "检测到可疑的启动项"
        echo "$suspicious_startup" | head -20
    fi
    
    return $alerts
}

# 发送入侵告警
send_intrusion_alert() {
    local message=$1
    
    log_error "发送入侵告警: $message"
    
    # 记录到告警日志
    echo "[$(date)] $message" >> "$ALERT_LOG"
    
    # 发送邮件告警
    if command -v mail &> /dev/null; then
        echo "$message" | mail -s "入侵检测告警" "$ALERT_EMAIL"
    fi
    
    # 记录到系统日志
    logger -p auth.warning "Intrusion Detection Alert: $message"
}

# 执行完整入侵检测
run_full_detection() {
    log_info "开始完整入侵检测"
    
    local total_alerts=0
    
    # 执行各项检测
    detect_abnormal_login || total_alerts=$((total_alerts + $?))
    detect_abnormal_process || total_alerts=$((total_alerts + $?))
    detect_abnormal_file || total_alerts=$((total_alerts + $?))
    detect_abnormal_network || total_alerts=$((total_alerts + $?))
    detect_rootkit || total_alerts=$((total_alerts + $?))
    
    # 比较基线
    compare_baseline || total_alerts=$((total_alerts + $?))
    
    # 发送告警
    if [ $total_alerts -gt 0 ]; then
        send_intrusion_alert "检测到 $total_alerts 个入侵迹象"
        return 1
    fi
    
    log_info "入侵检测完成,没有发现入侵迹象"
    return 0
}

# 持续监控
continuous_monitoring() {
    log_info "开始持续监控"
    
    while true; do
        log_info "执行入侵检测"
        run_full_detection
        
        log_info "等待 $SCAN_INTERVAL 秒后再次检测"
        sleep $SCAN_INTERVAL
    done
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] [命令]"
    echo ""
    echo "选项:"
    echo "  -i <间隔>        扫描间隔(秒,默认: 300)"
    echo "  -e <邮箱>        告警邮箱"
    echo "  -h               显示帮助信息"
    echo ""
    echo "命令:"
    echo "  baseline          创建系统基线"
    echo "  compare           比较系统基线"
    echo "  detect            执行入侵检测(默认)"
    echo "  monitor           持续监控"
    echo ""
    echo "示例:"
    echo "  $0 baseline"
    echo "  $0 compare"
    echo "  $0 detect"
    echo "  $0 monitor"
    echo "  $0 -i 60 monitor"
}

# 主函数
main() {
    # 解析选项
    while getopts "i:e:h" opt; do
        case $opt in
            i)
                SCAN_INTERVAL="$OPTARG"
                log_info "扫描间隔: $SCAN_INTERVAL 秒"
                ;;
            e)
                ALERT_EMAIL="$OPTARG"
                log_info "告警邮箱: $ALERT_EMAIL"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查命令
    local command=${1:-detect}
    
    # 执行命令
    case $command in
        baseline)
            create_baseline
            ;;
        compare)
            compare_baseline
            ;;
        detect)
            run_full_detection
            ;;
        monitor)
            continuous_monitoring
            ;;
        *)
            log_error "无效的命令: $command"
            show_help
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x intrusion_detection.sh
  2. 基本用法:

    # 创建系统基线
    ./intrusion_detection.sh baseline
    
    # 比较系统基线
    ./intrusion_detection.sh compare
    
    # 执行入侵检测
    ./intrusion_detection.sh detect
    
    # 持续监控
    ./intrusion_detection.sh monitor
  3. 高级用法:

    # 指定扫描间隔
    ./intrusion_detection.sh -i 60 monitor
    
    # 指定告警邮箱
    ./intrusion_detection.sh -e admin@example.com detect
    
    # 结合crontab定时检测
    */5 * * * * /path/to/intrusion_detection.sh detect

功能特点#

  • 系统基线创建和比较
  • 异常登录检测
  • 异常进程检测
  • 异常文件检测
  • 异常网络检测
  • Rootkit检测
  • 持续监控
  • 告警功能

依赖项#

  • netstat: 用于网络检查
  • ps: 用于进程检查
  • find: 用于文件检查
  • mail: 用于邮件告警

注意事项#

  1. 首次使用需要创建基线
  2. 持续监控建议使用systemd管理
  3. 告警功能需要配置邮件
  4. 定期更新基线以适应系统变化
  5. 某些检测可能产生误报