入侵检测脚本#
脚本说明#
入侵检测脚本用于检测系统入侵行为,包括异常登录、异常进程、异常文件等。
脚本代码#
#!/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 "$@"使用说明#
添加执行权限:
chmod +x intrusion_detection.sh基本用法:
# 创建系统基线 ./intrusion_detection.sh baseline # 比较系统基线 ./intrusion_detection.sh compare # 执行入侵检测 ./intrusion_detection.sh detect # 持续监控 ./intrusion_detection.sh monitor高级用法:
# 指定扫描间隔 ./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: 用于邮件告警
注意事项#
- 首次使用需要创建基线
- 持续监控建议使用systemd管理
- 告警功能需要配置邮件
- 定期更新基线以适应系统变化
- 某些检测可能产生误报