Skip to content

log-analyzer.sh

Niveau : Intermรฉdiaire

Analyse des logs systรจme pour dรฉtecter les anomalies.


Description

Ce script analyse les logs systรจme : - Dรฉtection des tentatives de connexion failedes - Analyse des erreurs critiques - Statistiques d'accรจs - Rapport d'anomalies


Prรฉrequis

  • Systรจme : Linux (RHEL/Debian)
  • Permissions : Droits root ou sudo pour accรฉder aux logs systรจme
  • Dรฉpendances : grep, awk, journalctl (optionnel)

Cas d'Usage

  • Audit de sรฉcuritรฉ quotidien : Dรฉtection automatique de tentatives d'intrusion et activitรฉs suspectes
  • Investigation d'incidents : Analyse rapide des logs lors de problรจmes de sรฉcuritรฉ ou performance
  • Reporting rรฉgulier : Gรฉnรฉration de rapports pรฉriodiques sur l'activitรฉ systรจme et web
  • Dรฉtection d'anomalies : Identification de patterns suspects dans l'authentification et les accรจs

Script

#!/bin/bash
#===============================================================================
# Script Name: log-analyzer.sh
# Description: Analyse des logs systรจme
# Author: ShellBook
# Version: 1.0
#===============================================================================

set -euo pipefail

# Colors
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly CYAN='\033[0;36m'
readonly BOLD='\033[1m'
readonly NC='\033[0m'

# Configuration
LOG_DIR="/var/log"
HOURS=24
TOP_N=10
OUTPUT_FILE=""

usage() {
    cat << EOF
Usage: $(basename "$0") [OPTIONS]

Analyse des logs systรจme.

Options:
    -d, --dir PATH      Rรฉpertoire des logs (default: /var/log)
    -t, --time HOURS    Analyser les N lasts hours (default: 24)
    -n, --top NUM       Nombre de rรฉsultats top (default: 10)
    -o, --output FILE   Sauvegarder le rapport
    -h, --help          Show this help

Examples:
    $(basename "$0")                    # Analyse 24h
    $(basename "$0") -t 1               # Derniรจre heure
    $(basename "$0") -n 20 -o report.txt
EOF
}

print_header() {
    echo -e "\n${CYAN}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
    echo -e "${BOLD}  $1${NC}"
    echo -e "${CYAN}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
}

print_section() {
    echo -e "\n${YELLOW}โ–ถ $1${NC}"
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ANALYSE AUTH/SSH
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
analyze_auth_logs() {
    print_header "ANALYSE AUTHENTIFICATION"

    local auth_log=""
    for log in "$LOG_DIR/auth.log" "$LOG_DIR/secure" "$LOG_DIR/auth.log.1"; do
        [[ -f "$log" ]] && auth_log="$log" && break
    done

    if [[ -z "$auth_log" ]]; then
        echo "Aucun ficyesterday de log d'authentification trouvรฉ"
        return
    fi

    # Tentatives failedes SSH
    print_section "Tentatives SSH ร‰chouรฉes (Top $TOP_N IPs)"
    grep -h "Failed password" "$auth_log" "$LOG_DIR/auth.log.1" 2>/dev/null | \
        grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count ip; do
            printf "  ${RED}%-6s${NC} %s\n" "$count" "$ip"
        done

    # Utilisateurs invalides
    print_section "Utilisateurs Invalides Tentรฉs"
    grep -h "Invalid user" "$auth_log" 2>/dev/null | \
        grep -oP "Invalid user \K\w+" | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count user; do
            printf "  ${YELLOW}%-6s${NC} %s\n" "$count" "$user"
        done

    # Connections succeededes
    print_section "Connections SSH Rรฉussies"
    local success_count=$(grep -c "Accepted" "$auth_log" 2>/dev/null || echo "0")
    echo "  Total: $success_count"

    grep -h "Accepted" "$auth_log" 2>/dev/null | \
        awk '{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}' | \
        sort | uniq -c | sort -rn | head -n 5 | \
        while read -r count ip; do
            printf "  ${GREEN}%-6s${NC} %s\n" "$count" "$ip"
        done

    # Sudo
    print_section "Commandes Sudo"
    grep -h "sudo:" "$auth_log" 2>/dev/null | \
        grep "COMMAND" | \
        awk -F'COMMAND=' '{print $2}' | \
        sort | uniq -c | sort -rn | head -n 5 | \
        while read -r count cmd; do
            printf "  ${CYAN}%-6s${NC} %s\n" "$count" "${cmd:0:60}"
        done
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ANALYSE SYSLOG
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
analyze_syslog() {
    print_header "ANALYSE SYSLOG"

    local syslog=""
    for log in "$LOG_DIR/syslog" "$LOG_DIR/messages"; do
        [[ -f "$log" ]] && syslog="$log" && break
    done

    if [[ -z "$syslog" ]]; then
        echo "Aucun ficyesterday syslog trouvรฉ"
        return
    fi

    # Erreurs critiques
    print_section "Erreurs Critiques"
    grep -iE "(error|critical|emergency|alert)" "$syslog" 2>/dev/null | \
        tail -n 20 | \
        while read -r line; do
            echo "  ${line:0:80}"
        done

    # Services avec erreurs
    print_section "Services avec Erreurs"
    grep -i "error" "$syslog" 2>/dev/null | \
        awk '{print $5}' | \
        sed 's/\[.*//; s/:$//' | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count service; do
            printf "  ${RED}%-6s${NC} %s\n" "$count" "$service"
        done

    # Kernel messages
    print_section "Messages Kernel"
    grep -i "kernel" "$syslog" 2>/dev/null | \
        grep -iE "(error|warning|fail)" | \
        tail -n 5 | \
        while read -r line; do
            echo "  ${line:0:80}"
        done
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ANALYSE NGINX/APACHE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
analyze_web_logs() {
    print_header "ANALYSE SERVEUR WEB"

    local access_log=""
    local error_log=""

    # Chercher les logs web
    for log in "$LOG_DIR/nginx/access.log" "$LOG_DIR/apache2/access.log" "$LOG_DIR/httpd/access_log"; do
        [[ -f "$log" ]] && access_log="$log" && break
    done

    for log in "$LOG_DIR/nginx/error.log" "$LOG_DIR/apache2/error.log" "$LOG_DIR/httpd/error_log"; do
        [[ -f "$log" ]] && error_log="$log" && break
    done

    if [[ -z "$access_log" ]]; then
        echo "Aucun log de serveur web trouvรฉ"
        return
    fi

    # Top IPs
    print_section "Top $TOP_N IPs (Requรชtes)"
    awk '{print $1}' "$access_log" 2>/dev/null | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count ip; do
            printf "  ${CYAN}%-8s${NC} %s\n" "$count" "$ip"
        done

    # Codes HTTP
    print_section "Codes HTTP"
    awk '{print $9}' "$access_log" 2>/dev/null | \
        grep -E "^[0-9]{3}$" | \
        sort | uniq -c | sort -rn | head -n 10 | \
        while read -r count code; do
            local color=$GREEN
            [[ "$code" == 4* ]] && color=$YELLOW
            [[ "$code" == 5* ]] && color=$RED
            printf "  ${color}%-8s${NC} HTTP %s\n" "$count" "$code"
        done

    # URLs les plus demandรฉes
    print_section "Top URLs"
    awk '{print $7}' "$access_log" 2>/dev/null | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count url; do
            printf "  ${GREEN}%-8s${NC} %s\n" "$count" "${url:0:50}"
        done

    # Erreurs 4xx/5xx
    print_section "Erreurs HTTP (4xx/5xx)"
    awk '$9 ~ /^[45]/ {print $9, $7}' "$access_log" 2>/dev/null | \
        sort | uniq -c | sort -rn | head -n "$TOP_N" | \
        while read -r count code url; do
            printf "  ${RED}%-6s${NC} %s %s\n" "$count" "$code" "${url:0:40}"
        done

    # User agents suspects
    print_section "User Agents Suspects"
    grep -iE "(sqlmap|nikto|nmap|scanner|bot|crawler)" "$access_log" 2>/dev/null | \
        awk -F'"' '{print $6}' | \
        sort | uniq -c | sort -rn | head -n 5 | \
        while read -r count ua; do
            printf "  ${YELLOW}%-6s${NC} %s\n" "$count" "${ua:0:50}"
        done
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ANALYSE JOURNALD
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
analyze_journald() {
    print_header "ANALYSE JOURNALD"

    if ! command -v journalctl &>/dev/null; then
        echo "journalctl non disponible"
        return
    fi

    local since="$HOURS hours ago"

    # Erreurs systรจme
    print_section "Erreurs Systรจme (lasts ${HOURS}h)"
    journalctl --since "$since" -p err --no-pager 2>/dev/null | \
        tail -n 20 | \
        while read -r line; do
            echo "  ${line:0:80}"
        done

    # Services faileds
    print_section "Services ร‰chouรฉs"
    journalctl --since "$since" | \
        grep -i "failed" | \
        awk '{print $5}' | \
        sed 's/\[.*//; s/:$//' | \
        sort | uniq -c | sort -rn | head -n 5 | \
        while read -r count svc; do
            printf "  ${RED}%-6s${NC} %s\n" "$count" "$svc"
        done

    # Boot messages
    print_section "Dernier Boot"
    local boot_time=$(journalctl --list-boots 2>/dev/null | tail -1 | awk '{print $3, $4}')
    echo "  Dรฉmarrรฉ: $boot_time"
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STATISTIQUES Gร‰Nร‰RALES
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
show_statistics() {
    print_header "STATISTIQUES Gร‰Nร‰RALES"

    # Taille des logs
    print_section "Taille des Logs"
    du -sh "$LOG_DIR"/* 2>/dev/null | sort -rh | head -n 10 | \
        while read -r size path; do
            printf "  %-10s %s\n" "$size" "$(basename "$path")"
        done

    # Logs modifiรฉs rรฉcemment
    print_section "Logs Modifiรฉs (last heure)"
    find "$LOG_DIR" -type f -mmin -60 2>/dev/null | head -n 10 | \
        while read -r log; do
            echo "  $(basename "$log")"
        done
}

show_summary() {
    print_header "Rร‰SUMร‰"

    echo "  Pรฉriode analysรฉe: lasts ${HOURS}h"
    echo "  Rรฉpertoire logs: $LOG_DIR"
    echo "  Date rapport: $(date '+%Y-%m-%d %H:%M:%S')"

    if [[ -n "$OUTPUT_FILE" ]]; then
        echo "  Rapport sauvegardรฉ: $OUTPUT_FILE"
    fi
}

main() {
    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            -d|--dir)
                LOG_DIR="$2"
                shift 2
                ;;
            -t|--time)
                HOURS="$2"
                shift 2
                ;;
            -n|--top)
                TOP_N="$2"
                shift 2
                ;;
            -o|--output)
                OUTPUT_FILE="$2"
                shift 2
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done

    # Redirection vers ficyesterday si demandรฉ
    if [[ -n "$OUTPUT_FILE" ]]; then
        exec > >(tee "$OUTPUT_FILE")
    fi

    echo -e "${CYAN}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
    echo -e "${BOLD}${GREEN}          ANALYSEUR DE LOGS SYSTรˆME${NC}"
    echo -e "${CYAN}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${NC}"
    echo -e "  Date: $(date '+%Y-%m-%d %H:%M:%S')"
    echo -e "  Host: $(hostname)"
    echo -e "  Pรฉriode: lasts ${HOURS}h"

    analyze_auth_logs
    analyze_syslog
    analyze_web_logs
    analyze_journald
    show_statistics
    show_summary
}

main "$@"

Usage

# Rendre exรฉcutable
chmod +x log-analyzer.sh

# Analyse standard (24h)
sudo ./log-analyzer.sh

# Derniรจre heure
sudo ./log-analyzer.sh -t 1

# Top 20 avec rapport
sudo ./log-analyzer.sh -n 20 -o report.txt

# Rรฉpertoire personnalisรฉ
sudo ./log-analyzer.sh -d /var/log/myapp

Sortie Exemple

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
          ANALYSEUR DE LOGS SYSTรˆME
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  Date: 2024-01-15 14:30:22
  Host: webserver01
  Pรฉriode: lasts 24h

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  ANALYSE AUTHENTIFICATION
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

โ–ถ Tentatives SSH ร‰chouรฉes (Top 10 IPs)
  1523   203.0.113.45
  892    198.51.100.23
  456    192.0.2.100

โ–ถ Utilisateurs Invalides Tentรฉs
  234    admin
  189    root
  145    test
  98     user

โ–ถ Connections SSH Rรฉussies
  Total: 45
  23     192.168.1.10
  15     10.0.0.5
  7      192.168.1.20

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  ANALYSE SERVEUR WEB
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

โ–ถ Codes HTTP
  125000   HTTP 200
  3500     HTTP 304
  890      HTTP 404
  23       HTTP 500

โ–ถ Erreurs HTTP (4xx/5xx)
  890    404 /wp-admin/
  234    404 /phpmyadmin/
  23     500 /api/users

Voir Aussi