WP-CLI와 SQL로 워드프레스 은폐 백도어 찾는 법

AI/미래기술8분 읽기

TuBrief 편집팀 원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다. 원본 영상: 이것이 워드프레스 역사상 최악의 해킹일까? · Better Stack

외주로 만든 워드프레스 사이트의 코어 업데이트 버튼을 누르기는 꽤나 망설여집니다. 테마나 커스텀 플러그인이 꼬여서 화면이 하얗게 질릴까 봐 미루다 보면 어느새 사이트는 취약점 투성이가 됩니다. 이미 털렸을지도 모른다는 불안감이 엄습할 때, 가장 빠르게 데이터베이스와 서버를 털어보는 실무 점검 절차입니다.

은폐된 관리자 계정과 파일 검색하기

공격자는 보통 티 나지 않게 들어옵니다. 데이터베이스의 wp_usermeta 테이블을 직접 건드려 기존 계정에 은근슬쩍 관리자 권한을 부여하는 식입니다. 일반적인 로그인 목록에는 잘 안 보이지만 DB를 직접 찌르면 바로 나옵니다.

SELECT 
    u.ID, 
    u.user_login, 
    u.user_email, 
    u.user_registered, 
    m.meta_value AS capabilities
FROM 
    wp_users u
INNER JOIN 
    wp_usermeta m ON u.ID = m.user_id
WHERE 
    m.meta_key = 'wp_capabilities' 
    AND (
        m.meta_value LIKE '%"administrator"%' 
        OR m.meta_value LIKE '%"administrator":true%'
    )
ORDER BY 
    u.user_registered DESC;

그 다음은 파일 시스템입니다. 이미지나 문서만 들어있어야 할 wp-content/uploads 디렉토리에 PHP 파일이 굴러다닌다면 십중팔구 백도어입니다. SSH 터미널을 열고 위험한 파일이 있는지 훑어봅니다.

# 1. uploads 디렉토리 내 PHP 파일 수색
find wp-content/uploads/ -type f -name "*.php" -ls

# 2. 난독화 함수(eval, base64_decode 등)를 품은 파일 감지
find . -type f -name "*.php" -exec grep -HnE "(eval\(|base64_decode\(|gzinflate\(|passthru\(|shell_exec\()" {} \;

# 3. 코어 파일이 변질됐는지 체크섬 검증
wp core verify-checksums --include-root

로그도 봐야 합니다. REST API를 노린 공격은 보통 짧은 시간에 POST 요청을 쏟아내며 200이나 201 응답을 받아냅니다. Nginx access.log에서 수상한 반응을 보인 요청을 뽑아냅니다.

grep -E "POST|PUT" /var/log/nginx/access.log | grep -E "/wp-json/|rest_route=" | awk '$9 ~ /^(200|201|207)$/ {print $1, $4, $6, $7, $9}' | sort | uniq -c | sort -nr | head -n 30

스테이징 환경에서 안전하게 검증하기

운영 중인 사이트에 바로 패치를 지르는 건 배짱이 아니라 무모함에 가깝습니다. 데이터베이스와 파일 시스템을 통째로 복제한 스테이징 환경을 먼저 만듭니다.

# DB 백업 및 파일 복제
wp db export production_backup.sql --add-drop-table
rsync -avz --exclude='wp-content/cache' /var/www/html/ staging:/var/www/staging/

# 스테이징 서버 접속 후 DB 밀어넣기 및 도메인 교체
wp db import production_backup.sql
wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid

# 호환성 안 맞는 플러그인 확인
wp plugin list --update=available --fields=name,version,update_version,requires_php --format=table

복제가 끝나면 업데이트를 치고 딱 5분만 주요 기능을 눌러봅니다. 회원가입, 로그인, 장바구니 담기, 결제 창 호출, 문의 양식 제출까지 직접 해봐야 마음이 편합니다.

코어 업데이트를 미뤄야 할 때 쳐두는 방화벽

플러그인 개발사가 업데이트를 안 해줘서 코어를 바로 못 올리는 답답한 상황도 있습니다. 그럴 땐 서버 레벨이나 WAF에서 특정 경로의 접근을 막아두는 걸로 시간을 벌어야 합니다. Nginx를 쓴다면 nginx.conf에 REST API 유저 생성 및 배치 처리 엔드포인트를 내 IP 제외하고 막아버립니다.

location ~* ^/wp-json/(batch/v1|wp/v2/users) {
    limit_except GET {
        allow 192.0.2.1;
        deny all;
    }
    try_files $uri $uri/ /index.php?$args;
}

혹시 모를 사태를 대비해 DB와 업로드 폴더를 S3로 올려두는 백업 스크립트도 덤으로 걸어둡니다.

#!/bin/bash
WP_PATH="/var/www/html"
BACKUP_DIR="/tmp/wp_backups"
DATE=$(date +%Y%m%d_%H%M%S)
S3_BUCKET="s3://my-wordpress-secure-backups"

mkdir -p $BACKUP_DIR
wp db export $BACKUP_DIR/db_$DATE.sql --path=$WP_PATH --quiet
tar -czf $BACKUP_DIR/files_$DATE.tar.gz -C $WP_PATH wp-content/uploads/

aws s3 cp $BACKUP_DIR/db_$DATE.sql $S3_BUCKET/db_$DATE.sql
aws s3 cp $BACKUP_DIR/files_$DATE.tar.gz $S3_BUCKET/files_$DATE.tar.gz
find $BACKUP_DIR -type f -mtime +7 -delete

세션 강제 종료와 스크립트 수정 차단

악성 코드를 지우고 보안 패치를 마쳤다고 끝이 아닙니다. 공격자가 훔쳐낸 세션 쿠키로 다시 들어올 수 있으니까요. 세션을 털어내고 wp-config.php 솔트 키를 전부 갈아엎습니다.

# 모든 계정의 활성 세션 한번에 날리기
wp user list --field=ID | xargs -n 1 wp user session destroy --all

# 솔트 키 재발급
wp config shuffle-salts

관리자 페이지 안에서 플러그인이나 테마 파일을 직접 수정하는 기능도 끕니다. 공격자가 권한을 잡더라도 코드 주입을 못 하게 막는 최소한의 안전장치입니다. wp-config.php에 아래 두 줄을 넣습니다.

define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );

마지막으로 로그인 안 한 사용자가 REST API로 유저 목록을 훔쳐보지 못하게 mu-plugins 디렉토리에 전용 필터를 하나 던져넣습니다.

<?php
/**
 * Plugin Name: REST API Security Hardening
 */
add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) return $result;
    if ( ! is_user_logged_in() ) {
        if ( strpos( $_SERVER['REQUEST_URI'], '/wp/v2/users' ) !== false ) {
            return new WP_Error( 'rest_cannot_access', '접근이 거부되었습니다.', array( 'status' => 401 ) );
        }
    }
    return $result;
});
add_filter( 'xmlrpc_enabled', '__return_false' );

관련 영상

이것이 워드프레스 역사상 최악의 해킹일까?

Better Stack5:04

커뮤니티의 다른 글

댓글

로그인하고 댓글을 남겨 보세요.

아직 댓글이 없습니다.