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/wp_checksum_verify.sh
#!/bin/bash
# ============================================================
#  πŸ”‘ WordPress μ½”μ–΄ 체크섬 검증 (WP Checksum Verify)
#  μ„œλ²„ 배포 경둜: /home/altablue/wp_checksum_verify.sh
#
#  WordPress.org 곡식 APIμ—μ„œ μ œκ³΅ν•˜λŠ” 체크섬과
#  둜컬 μ½”μ–΄ 파일의 MD5 ν•΄μ‹œλ₯Ό λΉ„κ΅ν•˜μ—¬ λ³€μ‘°λ₯Ό νƒμ§€ν•©λ‹ˆλ‹€.
#
#  μ‚¬μš©λ²•:
#    ./wp_checksum_verify.sh --verify     # λͺ¨λ“  μ‚¬μ΄νŠΈ μ½”μ–΄ 파일 검증
#    ./wp_checksum_verify.sh --cache      # 체크섬 μΊμ‹œ κ°±μ‹ 
#    ./wp_checksum_verify.sh --status     # 검증 μƒνƒœ 확인
# ============================================================

set -uo pipefail

# ── μ„€μ • λ‘œλ“œ ─────────────────────────────────────
CONFIG_FILE="${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}/wp_checksum.log"
VERIFIED_FILES_LIST="${BASELINE_DIR}/wp_verified_files.txt"

# μΊμ‹œ 유효 μ‹œκ°„ (초) β€” 24μ‹œκ°„
CACHE_MAX_AGE=86400

mkdir -p "$LOG_DIR" "$BASELINE_DIR"

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

# ── ν•„μˆ˜ 도ꡬ 확인 ────────────────────────────────
check_dependencies() {
    local missing=()

    if ! command -v curl &>/dev/null; then
        missing+=("curl")
    fi
    if ! command -v python3 &>/dev/null; then
        missing+=("python3")
    fi
    if ! command -v md5sum &>/dev/null; then
        missing+=("md5sum")
    fi

    if [ ${#missing[@]} -gt 0 ]; then
        log "❌ ν•„μˆ˜ 도ꡬ가 μ„€μΉ˜λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€: ${missing[*]}"
        echo "❌ ν•„μˆ˜ 도ꡬ가 μ„€μΉ˜λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€: ${missing[*]}"
        echo "   μ„€μΉ˜: sudo apt install ${missing[*]}"
        exit 1
    fi
}

# ── WordPress 버전 μΆ”μΆœ ───────────────────────────
# wp-includes/version.php μ—μ„œ $wp_version 값을 μΆ”μΆœ
get_wp_version() {
    local site_root="$1"
    local version_file="${site_root}/wp-includes/version.php"

    if [ ! -f "$version_file" ]; then
        log "  ⚠️ version.php μ—†μŒ: $version_file"
        return 1
    fi

    local version
    version=$(grep -oP "\\\$wp_version\s*=\s*'[^']+'" "$version_file" | grep -oP "'[^']+'" | tr -d "'")

    if [ -z "$version" ]; then
        log "  ⚠️ WordPress 버전을 μΆ”μΆœν•  수 μ—†μŠ΅λ‹ˆλ‹€: $version_file"
        return 1
    fi

    echo "$version"
}

# ── 체크섬 λ‹€μš΄λ‘œλ“œ 및 μΊμ‹œ ───────────────────────
# WordPress.org APIμ—μ„œ 체크섬 JSON을 λ‹€μš΄λ‘œλ“œν•˜κ³  μΊμ‹œμ— μ €μž₯
fetch_checksums() {
    local version="$1"
    local cache_file="${BASELINE_DIR}/wp_checksums_${version}.json"

    # μΊμ‹œ μœ νš¨μ„± 확인 (24μ‹œκ°„)
    if [ -f "$cache_file" ]; then
        local cache_mtime
        cache_mtime=$(stat -c%Y "$cache_file" 2>/dev/null || echo 0)
        local now
        now=$(date +%s)
        local age=$(( now - cache_mtime ))

        if [ "$age" -lt "$CACHE_MAX_AGE" ]; then
            log "  πŸ’Ύ μΊμ‹œ μ‚¬μš© (${age}초 κ²½κ³Ό): $cache_file"
            echo "$cache_file"
            return 0
        fi
        log "  πŸ”„ μΊμ‹œ 만료 (${age}초 κ²½κ³Ό), μž¬λ‹€μš΄λ‘œλ“œ"
    fi

    # APIμ—μ„œ 체크섬 λ‹€μš΄λ‘œλ“œ
    local api_url="https://api.wordpress.org/core/checksums/1.0/?version=${version}&locale=ko_KR"
    log "  🌐 체크섬 λ‹€μš΄λ‘œλ“œ: $api_url"

    local http_code
    http_code=$(curl -s -o "$cache_file" -w "%{http_code}" --connect-timeout 10 --max-time 30 "$api_url" 2>/dev/null)

    if [ "$http_code" != "200" ]; then
        log "  ❌ API μš”μ²­ μ‹€νŒ¨ (HTTP $http_code): $api_url"
        rm -f "$cache_file" 2>/dev/null
        return 1
    fi

    # JSON μœ νš¨μ„± κΈ°λ³Έ 검증
    if ! python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$cache_file" 2>/dev/null; then
        log "  ❌ μœ νš¨ν•˜μ§€ μ•Šμ€ JSON 응닡: $cache_file"
        rm -f "$cache_file" 2>/dev/null
        return 1
    fi

    log "  βœ… 체크섬 λ‹€μš΄λ‘œλ“œ μ™„λ£Œ: $cache_file"
    echo "$cache_file"
    return 0
}

# ── μΊμ‹œ κ°±μ‹  (λͺ¨λ“  μ‚¬μ΄νŠΈ) ───────────────────────
refresh_cache() {
    log "πŸ”„ 체크섬 μΊμ‹œ κ°±μ‹  μ‹œμž‘"

    check_dependencies

    local refreshed=0
    local failed=0
    local versions_done=()

    for dir in "${WATCH_DIRS[@]}"; do
        if [ ! -d "$dir" ]; then
            continue
        fi

        while IFS= read -r wp_config; do
            local site_root
            site_root=$(dirname "$wp_config")
            local version
            version=$(get_wp_version "$site_root") || continue

            # 동일 버전 쀑볡 κ°±μ‹  λ°©μ§€
            local already_done=false
            for v in "${versions_done[@]+"${versions_done[@]}"}"; do
                if [ "$v" = "$version" ]; then
                    already_done=true
                    break
                fi
            done
            if [ "$already_done" = "true" ]; then
                continue
            fi

            # κΈ°μ‘΄ μΊμ‹œ μ‚­μ œ ν›„ κ°•μ œ μž¬λ‹€μš΄λ‘œλ“œ
            rm -f "${BASELINE_DIR}/wp_checksums_${version}.json" 2>/dev/null

            if fetch_checksums "$version" >/dev/null; then
                ((refreshed++))
                versions_done+=("$version")
            else
                ((failed++))
            fi
        done < <(find "$dir" -maxdepth 3 -name "wp-config.php" -type f 2>/dev/null)
    done

    log "πŸ”„ μΊμ‹œ κ°±μ‹  μ™„λ£Œ: ${refreshed}개 버전 κ°±μ‹ , ${failed}개 μ‹€νŒ¨"

    if [ "$failed" -gt 0 ]; then
        "$NOTIFY" "WARNING" "πŸ”„ <b>체크섬 μΊμ‹œ κ°±μ‹ </b>

βœ… 성곡: ${refreshed}개 버전
❌ μ‹€νŒ¨: ${failed}개 버전"
    else
        log "  βœ… λͺ¨λ“  μΊμ‹œ κ°±μ‹  성곡"
    fi
}

# ── κ°œλ³„ μ‚¬μ΄νŠΈ 검증 ──────────────────────────────
verify_site() {
    local site_root="$1"
    local site_name
    site_name=$(basename "$site_root")

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

    # WordPress 버전 μΆ”μΆœ
    local version
    version=$(get_wp_version "$site_root")
    if [ $? -ne 0 ] || [ -z "$version" ]; then
        log "  ⚠️ WordPress 버전 확인 λΆˆκ°€, κ±΄λ„ˆλœ€: $site_root"
        return 1
    fi
    log "    πŸ“Œ WordPress 버전: $version"

    # 체크섬 JSON κ°€μ Έμ˜€κΈ° (μΊμ‹œ λ˜λŠ” λ‹€μš΄λ‘œλ“œ)
    local cache_file
    cache_file=$(fetch_checksums "$version")
    if [ $? -ne 0 ] || [ -z "$cache_file" ] || [ ! -f "$cache_file" ]; then
        log "  ❌ 체크섬을 κ°€μ Έμ˜¬ 수 μ—†μŠ΅λ‹ˆλ‹€ (v$version)"
        return 1
    fi

    # JSONμ—μ„œ 체크섬 νŒŒμ‹±: "MD5ν•΄μ‹œ 파일경둜" ν˜•μ‹μœΌλ‘œ 좜λ ₯
    local checksum_list
    checksum_list=$(python3 -c "
import json, sys
d = json.load(open(sys.argv[1]))
checksums = d.get('checksums', {})
for k, v in checksums.items():
    print(f'{v} {k}')
" "$cache_file" 2>/dev/null)

    if [ -z "$checksum_list" ]; then
        log "  ❌ 체크섬 νŒŒμ‹± μ‹€νŒ¨: $cache_file"
        return 1
    fi

    local total_files=0
    local matched_count=0
    local modified_count=0
    local missing_count=0
    local modified_files=()
    local missing_files=()
    local verified_paths=()

    # 각 파일의 MD5 체크섬 비ꡐ
    while IFS=' ' read -r expected_md5 rel_path; do
        [ -z "$expected_md5" ] && continue
        [ -z "$rel_path" ] && continue

        ((total_files++))

        local full_path="${site_root}/${rel_path}"

        if [ ! -f "$full_path" ]; then
            ((missing_count++))
            missing_files+=("$rel_path")
            continue
        fi

        # 둜컬 파일 MD5 ν•΄μ‹œ 계산
        local local_md5
        local_md5=$(md5sum "$full_path" 2>/dev/null | cut -d' ' -f1)

        if [ "$local_md5" = "$expected_md5" ]; then
            ((matched_count++))
            verified_paths+=("$full_path")
        else
            ((modified_count++))
            modified_files+=("$rel_path")
            log "    πŸ”΄ λ³€μ‘° 감지: $rel_path"
            log "       곡식 MD5: $expected_md5"
            log "       둜컬 MD5: $local_md5"
        fi
    done <<< "$checksum_list"

    # wp-admin, wp-includes λ‚΄ 곡식 λͺ©λ‘μ— μ—†λŠ” μΆ”κ°€ 파일 탐지
    local extra_count=0
    local extra_files=()

    for check_dir in "wp-admin" "wp-includes"; do
        local abs_dir="${site_root}/${check_dir}"
        if [ ! -d "$abs_dir" ]; then
            continue
        fi

        while IFS= read -r -d '' file; do
            local rel
            rel="${file#${site_root}/}"

            # 체크섬 λͺ©λ‘μ— μžˆλŠ”μ§€ 확인
            if ! echo "$checksum_list" | grep -qF " ${rel}"; then
                ((extra_count++))
                extra_files+=("$rel")
            fi
        done < <(find "$abs_dir" -type f -name "*.php" -print0 2>/dev/null)
    done

    # κ²€μ¦λœ 파일 λͺ©λ‘ 기둝 (λ‹€λ₯Έ μŠ€ν¬λ¦½νŠΈμ—μ„œ ν™œμš©)
    for vp in "${verified_paths[@]+"${verified_paths[@]}"}"; do
        echo "$vp" >> "$VERIFIED_FILES_LIST"
    done

    log "    πŸ“Š κ²°κ³Ό: 전체=${total_files}, 일치=${matched_count}, λ³€μ‘°=${modified_count}, λˆ„λ½=${missing_count}, μΆ”κ°€=${extra_count}"

    # κ²°κ³Όλ₯Ό stdout으둜 λ°˜ν™˜ (ν˜ΈμΆœμžμ—μ„œ μ§‘κ³„μš©)
    echo "SITE:${site_name}"
    echo "ROOT:${site_root}"
    echo "VERSION:${version}"
    echo "TOTAL:${total_files}"
    echo "MATCHED:${matched_count}"
    echo "MODIFIED:${modified_count}"
    echo "MISSING:${missing_count}"
    echo "EXTRA:${extra_count}"

    if [ ${#modified_files[@]} -gt 0 ]; then
        echo "MODIFIED_FILES:"
        for f in "${modified_files[@]}"; do
            echo "  ${f}"
        done
    fi

    if [ ${#missing_files[@]} -gt 0 ]; then
        echo "MISSING_FILES:"
        for f in "${missing_files[@]}"; do
            echo "  ${f}"
        done
    fi

    if [ ${#extra_files[@]} -gt 0 ]; then
        echo "EXTRA_FILES:"
        for f in "${extra_files[@]}"; do
            echo "  ${f}"
        done
    fi

    echo "---"
}

# ── 체크섬 검증 μ™„λ£Œ μ—¬λΆ€ 확인 ────────────────────
# λ‹€λ₯Έ 슀크립트(malware_scanner.sh λ“±)μ—μ„œ ν˜ΈμΆœν•˜μ—¬
# νŠΉμ • 파일이 곡식 μ½”μ–΄ νŒŒμΌμΈμ§€ λΉ λ₯΄κ²Œ νŒλ³„
is_checksum_verified() {
    local filepath="$1"

    if [ ! -f "$VERIFIED_FILES_LIST" ]; then
        return 1
    fi

    if grep -qxF "$filepath" "$VERIFIED_FILES_LIST" 2>/dev/null; then
        return 0
    fi

    return 1
}

# ── 전체 검증 μ‹€ν–‰ ────────────────────────────────
verify_all() {
    log "πŸ”‘ WordPress μ½”μ–΄ 체크섬 검증 μ‹œμž‘"

    check_dependencies

    local scan_start
    scan_start=$(date +%s)

    # 검증 λͺ©λ‘ μ΄ˆκΈ°ν™”
    > "$VERIFIED_FILES_LIST"

    local site_count=0
    local total_modified=0
    local total_missing=0
    local total_extra=0
    local total_matched=0
    local all_modified_details=""
    local overall_status="CLEAN"

    # WATCH_DIRS λ‚΄ WordPress μ‚¬μ΄νŠΈ 탐색
    for dir in "${WATCH_DIRS[@]}"; do
        if [ ! -d "$dir" ]; then
            continue
        fi

        while IFS= read -r wp_config; do
            local site_root
            site_root=$(dirname "$wp_config")
            ((site_count++))

            # μ‚¬μ΄νŠΈ 검증 μ‹€ν–‰
            local result
            result=$(verify_site "$site_root")

            # κ²°κ³Ό νŒŒμ‹±
            local modified
            modified=$(echo "$result" | grep "^MODIFIED:" | head -1 | cut -d: -f2)
            local missing
            missing=$(echo "$result" | grep "^MISSING:" | head -1 | cut -d: -f2)
            local extra
            extra=$(echo "$result" | grep "^EXTRA:" | head -1 | cut -d: -f2)
            local matched
            matched=$(echo "$result" | grep "^MATCHED:" | head -1 | cut -d: -f2)
            local site_name
            site_name=$(echo "$result" | grep "^SITE:" | head -1 | cut -d: -f2)
            local version
            version=$(echo "$result" | grep "^VERSION:" | head -1 | cut -d: -f2)

            modified=${modified:-0}
            missing=${missing:-0}
            extra=${extra:-0}
            matched=${matched:-0}

            total_modified=$((total_modified + modified))
            total_missing=$((total_missing + missing))
            total_extra=$((total_extra + extra))
            total_matched=$((total_matched + matched))

            # λ³€μ‘°λœ 파일 상세 μˆ˜μ§‘ (ν…”λ ˆκ·Έλž¨ μ•Œλ¦Όμš©)
            if [ "$modified" -gt 0 ]; then
                overall_status="CRITICAL"
                local mod_files
                mod_files=$(echo "$result" | sed -n '/^MODIFIED_FILES:/,/^---$\|^[A-Z_]*:/p' | grep "^  " | head -10)
                all_modified_details="${all_modified_details}
πŸ“‚ <b>${site_name}</b> (v${version}):
${mod_files}"
            elif [ "$missing" -gt 0 ] && [ "$overall_status" = "CLEAN" ]; then
                overall_status="WARNING"
            fi

        done < <(find "$dir" -maxdepth 3 -name "wp-config.php" -type f 2>/dev/null)
    done

    local scan_end
    scan_end=$(date +%s)
    local duration=$((scan_end - scan_start))

    # κ²€μ¦λœ 파일 λͺ©λ‘ μ •λ ¬ 및 쀑볡 제거
    if [ -f "$VERIFIED_FILES_LIST" ]; then
        sort -u "$VERIFIED_FILES_LIST" -o "$VERIFIED_FILES_LIST"
        local verified_total
        verified_total=$(wc -l < "$VERIFIED_FILES_LIST")
        log "  πŸ“‹ 검증 λͺ©λ‘ 생성: ${verified_total}개 파일 β†’ $VERIFIED_FILES_LIST"
    fi

    log "πŸ”‘ 검증 μ™„λ£Œ: ${site_count}개 μ‚¬μ΄νŠΈ, 일치=${total_matched}, λ³€μ‘°=${total_modified}, λˆ„λ½=${total_missing}, μΆ”κ°€=${total_extra} (${duration}초)"

    # 결과에 λ”°λ₯Έ μ•Œλ¦Ό
    if [ "$overall_status" = "CRITICAL" ]; then
        # λ³€μ‘° 파일 발견 β€” CRITICAL μ•Œλ¦Ό
        "$NOTIFY" "CRITICAL" "πŸ”‘ <b>WordPress μ½”μ–΄ λ³€μ‘° 감지!</b>

πŸ“Š <b>검증 κ²°κ³Ό:</b>
━━━━━━━━━━━━━━━━━━━━
πŸ“‚ μ‚¬μ΄νŠΈ: ${site_count}개
βœ… 일치: ${total_matched}개
πŸ”΄ λ³€μ‘°: ${total_modified}개
❌ λˆ„λ½: ${total_missing}개
πŸ†• μΆ”κ°€: ${total_extra}개
⏱️ μ†Œμš”: ${duration}초

πŸ”΄ <b>λ³€μ‘°λœ 파일:</b>
${all_modified_details}"

    elif [ "$overall_status" = "WARNING" ]; then
        # λˆ„λ½ 파일만 있음 β€” WARNING μ•Œλ¦Ό
        "$NOTIFY" "WARNING" "πŸ”‘ <b>WordPress μ½”μ–΄ 파일 λˆ„λ½ 감지</b>

πŸ“Š <b>검증 κ²°κ³Ό:</b>
━━━━━━━━━━━━━━━━━━━━
πŸ“‚ μ‚¬μ΄νŠΈ: ${site_count}개
βœ… 일치: ${total_matched}개
❌ λˆ„λ½: ${total_missing}개
πŸ†• μΆ”κ°€: ${total_extra}개
⏱️ μ†Œμš”: ${duration}초"

    else
        # λͺ¨λ‘ 정상 β€” 둜그만 기둝 (ν…”λ ˆκ·Έλž¨ μ•Œλ¦Ό μ—†μŒ, λ…Έμ΄μ¦ˆ κ°μ†Œ)
        log "  βœ… λͺ¨λ“  μ½”μ–΄ 파일 체크섬 일치"
    fi

    # μ‚¬μ΄νŠΈλ₯Ό μ°Ύμ§€ λͺ»ν•œ 경우
    if [ "$site_count" -eq 0 ]; then
        log "  ⚠️ WordPress μ‚¬μ΄νŠΈλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€"
        echo "⚠️ WATCH_DIRS λ‚΄μ—μ„œ wp-config.phpλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
        echo "   κ°μ‹œ λŒ€μƒ: ${WATCH_DIRS[*]}"
    fi
}

# ── μƒνƒœ 확인 ─────────────────────────────────────
show_status() {
    echo "πŸ”‘ WordPress μ½”μ–΄ 체크섬 검증 μƒνƒœ"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""

    # μΊμ‹œλœ 체크섬 파일 ν‘œμ‹œ
    echo "πŸ“¦ μΊμ‹œλœ 체크섬:"
    local cache_count=0
    for cache_file in "${BASELINE_DIR}"/wp_checksums_*.json; do
        if [ ! -f "$cache_file" ]; then
            continue
        fi
        ((cache_count++))

        local version
        version=$(basename "$cache_file" | sed 's/wp_checksums_//;s/\.json//')
        local cache_mtime
        cache_mtime=$(stat -c%Y "$cache_file" 2>/dev/null || echo 0)
        local now
        now=$(date +%s)
        local age=$(( now - cache_mtime ))
        local age_hours=$(( age / 3600 ))
        local age_status="βœ…"
        if [ "$age" -ge "$CACHE_MAX_AGE" ]; then
            age_status="⚠️ 만료"
        fi

        local file_count
        file_count=$(python3 -c "
import json, sys
d = json.load(open(sys.argv[1]))
print(len(d.get('checksums', {})))
" "$cache_file" 2>/dev/null || echo "?")

        echo "   ${age_status} v${version} β€” ${file_count}개 파일, ${age_hours}μ‹œκ°„ μ „ κ°±μ‹ "
    done
    if [ "$cache_count" -eq 0 ]; then
        echo "   (μ—†μŒ) β€” --cache λ˜λŠ” --verify 둜 μƒμ„±ν•˜μ„Έμš”"
    fi
    echo ""

    # 검증 λͺ©λ‘ μƒνƒœ
    echo "πŸ“‹ 검증 λͺ©λ‘:"
    if [ -f "$VERIFIED_FILES_LIST" ]; then
        local verified_count
        verified_count=$(wc -l < "$VERIFIED_FILES_LIST" 2>/dev/null || echo 0)
        local list_mtime
        list_mtime=$(stat -c%Y "$VERIFIED_FILES_LIST" 2>/dev/null || echo 0)
        local list_date
        list_date=$(date -d "@${list_mtime}" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "μ•Œ 수 μ—†μŒ")
        echo "   βœ… ${verified_count}개 파일 검증 μ™„λ£Œ"
        echo "   πŸ“… λ§ˆμ§€λ§‰ κ°±μ‹ : ${list_date}"
        echo "   πŸ“ 경둜: $VERIFIED_FILES_LIST"
    else
        echo "   (μ—†μŒ) β€” --verify 둜 μƒμ„±ν•˜μ„Έμš”"
    fi
    echo ""

    # κ°μ§€λœ μ‚¬μ΄νŠΈ λͺ©λ‘
    echo "πŸ“‚ WordPress μ‚¬μ΄νŠΈ:"
    local found_sites=0
    for dir in "${WATCH_DIRS[@]}"; do
        if [ ! -d "$dir" ]; then
            continue
        fi
        while IFS= read -r wp_config; do
            local site_root
            site_root=$(dirname "$wp_config")
            local site_name
            site_name=$(basename "$site_root")
            local version
            version=$(get_wp_version "$site_root" 2>/dev/null) || version="확인 λΆˆκ°€"
            ((found_sites++))
            echo "   πŸ“‚ ${site_name} β€” v${version} (${site_root})"
        done < <(find "$dir" -maxdepth 3 -name "wp-config.php" -type f 2>/dev/null)
    done
    if [ "$found_sites" -eq 0 ]; then
        echo "   (μ—†μŒ)"
    fi
    echo ""

    # 졜근 둜그
    echo "πŸ“ 졜근 검증 둜그:"
    if [ -f "$LOG_FILE" ]; then
        tail -5 "$LOG_FILE" | sed 's/^/   /'
    else
        echo "   (둜그 μ—†μŒ)"
    fi
}

# ── 메인 ──────────────────────────────────────────
case "${1:-}" in
    --verify|-v)
        verify_all
        ;;
    --cache|-c)
        refresh_cache
        ;;
    --status|-s)
        show_status
        ;;
    --help|-h)
        echo "πŸ”‘ WordPress μ½”μ–΄ 체크섬 검증"
        echo ""
        echo "μ‚¬μš©λ²•:"
        echo "  $0 --verify    λͺ¨λ“  μ‚¬μ΄νŠΈ μ½”μ–΄ 파일 검증"
        echo "  $0 --cache     체크섬 μΊμ‹œ κ°•μ œ κ°±μ‹ "
        echo "  $0 --status    ν˜„μž¬ μƒνƒœ 확인"
        echo "  $0 --help      도움말"
        ;;
    *)
        echo "❌ μ˜΅μ…˜μ„ μ§€μ •ν•΄μ£Όμ„Έμš”. --help 둜 μ‚¬μš©λ²• 확인"
        exit 1
        ;;
esac

Youez - 2016 - github.com/yon3zu
LinuXploit