403Webshell
Server IP : 119.195.102.159  /  Your IP : 216.73.217.134
Web Server : nginx/1.18.0
System : Linux picell 5.15.0-181-generic #191-Ubuntu SMP Fri May 22 19:09:02 UTC 2026 x86_64
User : altablue ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/altablue/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/altablue/integrity_baseline.sh
#!/bin/bash
# ============================================================
#  πŸ” ν•΄μ‹œ 기반 파일 무결성 검증 (Integrity Baseline)
#  μ„œλ²„ 배포 경둜: /home/altablue/integrity_baseline.sh
#
#  WordPress μ½”μ–΄ 파일 λ“±μ˜ SHA256 ν•΄μ‹œ λ² μ΄μŠ€λΌμΈμ„ μƒμ„±ν•˜κ³ 
#  주기적으둜 λΉ„κ΅ν•˜μ—¬ λ³€μ‘°λ₯Ό κ°μ§€ν•©λ‹ˆλ‹€.
#
#  μ‚¬μš©λ²•:
#    ./integrity_baseline.sh --init          # 베이슀라인 졜초 생성
#    ./integrity_baseline.sh --verify        # 베이슀라인 λŒ€λΉ„ 검증
#    ./integrity_baseline.sh --update        # 베이슀라인 κ°±μ‹ 
#    ./integrity_baseline.sh --status        # ν˜„μž¬ μƒνƒœ 확인
# ============================================================

set -uo pipefail

# ── μ„€μ • λ‘œλ“œ ─────────────────────────────────────
CONFIG_FILE="/etc/security-watchdog/config"
if [ ! -f "$CONFIG_FILE" ]; then
    echo "❌ μ„€μ • νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€: $CONFIG_FILE"
    exit 1
fi
source "$CONFIG_FILE"

# ── 경둜 μ„€μ • ─────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
NOTIFY="$SCRIPT_DIR/telegram_notify.sh"
LOG_FILE="${LOG_DIR}/integrity.log"

mkdir -p "$LOG_DIR" "$BASELINE_DIR"

# ── 둜그 ν•¨μˆ˜ ─────────────────────────────────────
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

# ── μ‚¬μ΄νŠΈ 루트 디렉토리 μžλ™ 탐지 ───────────────
# nginx μ„€μ •μ—μ„œ root 디렉토리 μΆ”μΆœ
get_site_roots() {
    local roots=()

    # 방법 1: nginx μ„€μ • νŒŒμΌμ—μ„œ root μΆ”μΆœ
    if [ -d "/etc/nginx/sites-enabled" ]; then
        while IFS= read -r root; do
            root=$(echo "$root" | sed 's/;$//' | xargs)
            if [ -d "$root" ]; then
                roots+=("$root")
            fi
        done < <(grep -rh '^\s*root\s' /etc/nginx/sites-enabled/ 2>/dev/null | awk '{print $2}' | sort -u)
    fi

    # 방법 2: WATCH_DIRS λ‚΄ WordPress μ‚¬μ΄νŠΈ μžλ™ 탐지
    if [ ${#roots[@]} -eq 0 ]; then
        for dir in "${WATCH_DIRS[@]}"; do
            if [ ! -d "$dir" ]; then
                continue
            fi
            while IFS= read -r wp_config; do
                roots+=("$(dirname "$wp_config")")
            done < <(find "$dir" -maxdepth 2 -name "wp-config.php" -type f 2>/dev/null)
        done
    fi

    printf '%s\n' "${roots[@]}" | sort -u
}

# ── μ‚¬μ΄νŠΈλ³„ 베이슀라인 파일 경둜 ─────────────────
get_baseline_file() {
    local site_root="$1"
    local site_name
    site_name=$(echo "$site_root" | sed 's|/|_|g' | sed 's|^_||')
    echo "${BASELINE_DIR}/${site_name}.baseline"
}

# ── 파일 ν•΄μ‹œ 생성 ────────────────────────────────
generate_hash() {
    local file="$1"
    if [ -f "$file" ] && [ -r "$file" ]; then
        sha256sum "$file" 2>/dev/null | cut -d' ' -f1
    fi
}

# ── 베이슀라인 μ΄ˆκΈ°ν™” ─────────────────────────────
init_baseline() {
    log "πŸ” 베이슀라인 μ΄ˆκΈ°ν™” μ‹œμž‘"

    local site_count=0
    local file_count=0

    while IFS= read -r site_root; do
        if [ -z "$site_root" ]; then
            continue
        fi

        ((site_count++))
        local baseline_file
        baseline_file=$(get_baseline_file "$site_root")
        local site_name
        site_name=$(basename "$site_root")

        log "  πŸ“‚ μ‚¬μ΄νŠΈ: $site_name ($site_root)"

        # 베이슀라인 파일 μ΄ˆκΈ°ν™”
        cat > "$baseline_file" << EOF
# Integrity Baseline
# Site: $site_root
# Created: $(date '+%Y-%m-%d %H:%M:%S')
# Format: SHA256_HASH|FILE_PATH|FILE_SIZE|FILE_PERMS|MODIFIED_TIME
EOF

        # WordPress μ½”μ–΄ 파일 ν•΄μ‹œ
        for pattern in "${INTEGRITY_PATTERNS[@]}"; do
            while IFS= read -r -d '' file; do
                local hash size perms mtime
                hash=$(generate_hash "$file")
                size=$(stat -c%s "$file" 2>/dev/null || echo "0")
                perms=$(stat -c%a "$file" 2>/dev/null || echo "000")
                mtime=$(stat -c%Y "$file" 2>/dev/null || echo "0")

                if [ -n "$hash" ]; then
                    echo "${hash}|${file}|${size}|${perms}|${mtime}" >> "$baseline_file"
                    ((file_count++))
                fi
            done < <(find "$site_root" -path "*/$pattern" -type f -print0 2>/dev/null)
        done

        # μΆ”κ°€: 루트 λ””λ ‰ν† λ¦¬μ˜ .php 파일
        while IFS= read -r -d '' file; do
            local hash size perms mtime
            hash=$(generate_hash "$file")
            size=$(stat -c%s "$file" 2>/dev/null || echo "0")
            perms=$(stat -c%a "$file" 2>/dev/null || echo "000")
            mtime=$(stat -c%Y "$file" 2>/dev/null || echo "0")

            if [ -n "$hash" ]; then
                echo "${hash}|${file}|${size}|${perms}|${mtime}" >> "$baseline_file"
                ((file_count++))
            fi
        done < <(find "$site_root" -maxdepth 1 -name "*.php" -type f -print0 2>/dev/null)

        # μΆ”κ°€: .htaccess 파일
        if [ -f "$site_root/.htaccess" ]; then
            local hash size perms mtime
            hash=$(generate_hash "$site_root/.htaccess")
            size=$(stat -c%s "$site_root/.htaccess" 2>/dev/null || echo "0")
            perms=$(stat -c%a "$site_root/.htaccess" 2>/dev/null || echo "000")
            mtime=$(stat -c%Y "$site_root/.htaccess" 2>/dev/null || echo "0")
            echo "${hash}|${site_root}/.htaccess|${size}|${perms}|${mtime}" >> "$baseline_file"
            ((file_count++))
        fi

        log "    βœ… 베이슀라인 생성 μ™„λ£Œ: $(grep -c '|' "$baseline_file" 2>/dev/null)개 파일"

    done < <(get_site_roots)

    log "πŸ” 베이슀라인 μ΄ˆκΈ°ν™” μ™„λ£Œ: ${site_count}개 μ‚¬μ΄νŠΈ, ${file_count}개 파일"

    "$NOTIFY" "INFO" "πŸ” <b>무결성 베이슀라인 생성 μ™„λ£Œ</b>

πŸ“‚ μ‚¬μ΄νŠΈ: ${site_count}개
πŸ“„ 파일: ${file_count}개
πŸ“ μ €μž₯ 경둜: ${BASELINE_DIR}"
}

# ── 무결성 검증 ───────────────────────────────────
verify_baseline() {
    log "πŸ” 무결성 검증 μ‹œμž‘"

    local total_checked=0
    local modified_count=0
    local missing_count=0
    local new_count=0
    local modified_files=()
    local missing_files=()

    # 베이슀라인 파일 순회
    for baseline_file in "${BASELINE_DIR}"/*.baseline; do
        if [ ! -f "$baseline_file" ]; then
            continue
        fi

        local site_root
        site_root=$(grep "^# Site:" "$baseline_file" | head -1 | sed 's/^# Site: //')

        if [ -z "$site_root" ] || [ ! -d "$site_root" ]; then
            log "  ⚠️ μ‚¬μ΄νŠΈ 디렉토리 μ—†μŒ: $site_root"
            continue
        fi

        local site_name
        site_name=$(basename "$site_root")

        # 베이슀라인 μ—”νŠΈλ¦¬ 검증
        while IFS='|' read -r expected_hash filepath expected_size expected_perms expected_mtime; do
            # 주석 및 빈 쀄 κ±΄λ„ˆλ›°κΈ°
            [[ "$expected_hash" =~ ^#.*$ ]] && continue
            [ -z "$expected_hash" ] && continue

            ((total_checked++))

            if [ ! -f "$filepath" ]; then
                # 파일 λˆ„λ½ (μ‚­μ œλ¨)
                ((missing_count++))
                missing_files+=("$filepath")
                log "  ❌ 파일 λˆ„λ½: $filepath"
                continue
            fi

            # ν˜„μž¬ ν•΄μ‹œ 계산
            local current_hash
            current_hash=$(generate_hash "$filepath")

            if [ "$current_hash" != "$expected_hash" ]; then
                # ν•΄μ‹œ 뢈일치 (변쑰됨)
                ((modified_count++))
                local current_size
                current_size=$(stat -c%s "$filepath" 2>/dev/null || echo "0")
                local current_perms
                current_perms=$(stat -c%a "$filepath" 2>/dev/null || echo "000")

                modified_files+=("$filepath (크기: ${expected_size}β†’${current_size}, κΆŒν•œ: ${expected_perms}β†’${current_perms})")
                log "  πŸ”΄ λ³€μ‘° 감지: $filepath"
                log "      원본 ν•΄μ‹œ: $expected_hash"
                log "      ν˜„μž¬ ν•΄μ‹œ: $current_hash"
            fi

        done < "$baseline_file"

        # μƒˆλ‘œ μƒμ„±λœ 파일 확인 (λ² μ΄μŠ€λΌμΈμ— μ—†λŠ” 파일)
        while IFS= read -r -d '' file; do
            local in_baseline=false
            if grep -q "|${file}|" "$baseline_file" 2>/dev/null; then
                in_baseline=true
            fi

            if [ "$in_baseline" = "false" ]; then
                ((new_count++))
                log "  πŸ†• μƒˆ 파일: $file"
            fi
        done < <(find "$site_root" -maxdepth 1 -name "*.php" -type f -print0 2>/dev/null)

    done

    log "πŸ” 검증 μ™„λ£Œ: ${total_checked}개 확인, ${modified_count}개 λ³€μ‘°, ${missing_count}개 λˆ„λ½, ${new_count}개 μ‹ κ·œ"

    # κ²°κ³Ό μ•Œλ¦Ό
    if [ "$modified_count" -gt 0 ] || [ "$missing_count" -gt 0 ]; then
        local alert_level="WARNING"
        if [ "$modified_count" -gt 0 ]; then
            alert_level="CRITICAL"
        fi

        local detail_msg=""

        if [ "$modified_count" -gt 0 ]; then
            detail_msg="${detail_msg}
πŸ”΄ <b>λ³€μ‘°λœ 파일 (${modified_count}개):</b>"
            local count=0
            for f in "${modified_files[@]}"; do
                ((count++))
                if [ "$count" -le 10 ]; then
                    detail_msg="${detail_msg}
  β€’ <code>${f}</code>"
                fi
            done
            if [ "$count" -gt 10 ]; then
                detail_msg="${detail_msg}
  ... μ™Έ $((count - 10))개"
            fi
        fi

        if [ "$missing_count" -gt 0 ]; then
            detail_msg="${detail_msg}

❌ <b>μ‚­μ œλœ 파일 (${missing_count}개):</b>"
            local count=0
            for f in "${missing_files[@]}"; do
                ((count++))
                if [ "$count" -le 10 ]; then
                    detail_msg="${detail_msg}
  β€’ <code>${f}</code>"
                fi
            done
            if [ "$count" -gt 10 ]; then
                detail_msg="${detail_msg}
  ... μ™Έ $((count - 10))개"
            fi
        fi

        "$NOTIFY" "$alert_level" "πŸ” <b>무결성 검증 κ²°κ³Ό</b>

πŸ“Š <b>검증 μš”μ•½:</b>
━━━━━━━━━━━━━━━━━━━━
πŸ“„ 검사 파일: ${total_checked}개
πŸ”΄ λ³€μ‘°: ${modified_count}개
❌ λˆ„λ½: ${missing_count}개
πŸ†• μ‹ κ·œ: ${new_count}개
${detail_msg}"
    else
        log "βœ… λͺ¨λ“  파일 무결성 확인"
        # 정상일 λ•ŒλŠ” 별도 μ•Œλ¦Ό μ•ˆ 보냄 (둜그만 기둝)
    fi
}

# ── 베이슀라인 κ°±μ‹  ───────────────────────────────
update_baseline() {
    log "πŸ”„ 베이슀라인 κ°±μ‹  μ‹œμž‘"

    # κΈ°μ‘΄ 베이슀라인 λ°±μ—…
    local backup_dir="${BASELINE_DIR}/backup_$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$backup_dir"
    cp "${BASELINE_DIR}"/*.baseline "$backup_dir/" 2>/dev/null

    log "  πŸ“¦ κΈ°μ‘΄ 베이슀라인 λ°±μ—…: $backup_dir"

    # μƒˆ 베이슀라인 생성
    init_baseline

    "$NOTIFY" "INFO" "πŸ”„ <b>베이슀라인 κ°±μ‹  μ™„λ£Œ</b>
πŸ“¦ 이전 베이슀라인 λ°±μ—…: <code>${backup_dir}</code>"
}

# ── μƒνƒœ 확인 ─────────────────────────────────────
show_status() {
    echo "πŸ” 무결성 베이슀라인 μƒνƒœ"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "πŸ“ μ €μž₯ 경둜: $BASELINE_DIR"
    echo ""

    if [ ! "$(ls -A "$BASELINE_DIR"/*.baseline 2>/dev/null)" ]; then
        echo "⚠️ 베이슀라인이 μƒμ„±λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."
        echo "   μƒμ„±ν•˜λ €λ©΄: $0 --init"
        return
    fi

    for baseline_file in "${BASELINE_DIR}"/*.baseline; do
        local site_root
        site_root=$(grep "^# Site:" "$baseline_file" | head -1 | sed 's/^# Site: //')
        local created
        created=$(grep "^# Created:" "$baseline_file" | head -1 | sed 's/^# Created: //')
        local file_count
        file_count=$(grep -c '|' "$baseline_file" 2>/dev/null || echo 0)

        echo "πŸ“‚ μ‚¬μ΄νŠΈ: $(basename "$site_root")"
        echo "   경둜: $site_root"
        echo "   생성: $created"
        echo "   파일: ${file_count}개"
        echo ""
    done
}

# ── 메인 ──────────────────────────────────────────
case "${1:-}" in
    --init|-i)
        init_baseline
        ;;
    --verify|-v)
        verify_baseline
        ;;
    --update|-u)
        update_baseline
        ;;
    --status|-s)
        show_status
        ;;
    --help|-h)
        echo "πŸ” ν•΄μ‹œ 기반 파일 무결성 검증"
        echo ""
        echo "μ‚¬μš©λ²•:"
        echo "  $0 --init      베이슀라인 졜초 생성"
        echo "  $0 --verify    베이슀라인 λŒ€λΉ„ 검증"
        echo "  $0 --update    베이슀라인 κ°±μ‹  (λ°±μ—… ν›„)"
        echo "  $0 --status    ν˜„μž¬ μƒνƒœ 확인"
        echo "  $0 --help      도움말"
        ;;
    *)
        echo "❌ μ˜΅μ…˜μ„ μ§€μ •ν•΄μ£Όμ„Έμš”. --help 둜 μ‚¬μš©λ²• 확인"
        exit 1
        ;;
esac

Youez - 2016 - github.com/yon3zu
LinuXploit