워드프레스 악성코드를 삭제해도 다시 생기는 이유와 재감염 경로 확인 방법
악성 파일을 하나 찾아 삭제했는데 며칠 뒤 같은 파일이나 비슷한 코드가 다시 생긴다면, 단순히 삭제가 제대로 되지 않았다고만 보기는 어렵습니다. 공격자가 다시 들어올 수 있는 취약점이 남아 있거나, 서버 안에 설치된 백도어가 파일을 재생성하고 있을 수 있습니다.
워드프레스 보안 사고에서는 악성코드 제거와 재침입 원인 차단을 분리해서 봐야 합니다. 눈에 보이는 PHP 파일은 원인이 아니라 이미 발생한 침해의 결과일 가능성이 있기 때문입니다.
삭제한 악성 파일이 다시 생기는 구조
워드프레스 사이트가 감염되면 공격자가 파일 하나만 남긴다고 가정해서는 안 됩니다. 관리자 계정, 플러그인 디렉터리, 테마 파일, 업로드 폴더, 데이터베이스 등에 여러 개의 접근 지점을 만들어 둘 수 있습니다.
예를 들어 다음과 같은 흐름이 가능합니다.
취약한 플러그인으로 침입한 뒤 백도어를 설치하고, 관리자가 눈에 띄는 파일을 삭제하면 백도어가 다시 악성 파일을 생성하는 방식입니다. 또는 탈취된 관리자 계정이나 SFTP 계정으로 공격자가 며칠 뒤 다시 로그인해 파일을 올릴 수도 있습니다.
따라서 같은 파일이 반복해서 나타나는 현상은 다음 가능성을 함께 의미합니다.
- 다른 위치에 남은 백도어가 악성 파일을 다시 만들고 있음
- 취약한 플러그인이나 테마가 그대로 남아 있음
- 워드프레스 또는 서버 계정의 인증 정보가 탈취됨
- 데이터베이스에 악성 스크립트나 리디렉션 코드가 삽입됨
- 같은 호스팅 계정의 다른 사이트가 공격 통로로 사용됨
| 재감염 경로 | 남는 흔적 | 확인할 위치 |
|---|---|---|
| 남은 백도어 | 지운 파일이 같은 이름으로 재생성 | 업로드 폴더, 플러그인·테마 디렉터리 |
| 취약한 플러그인·테마 | 같은 취약점으로 재침입 | 버전과 유지보수 상태 |
| 탈취된 계정 | 며칠 뒤 정상 로그인처럼 보이는 접속 | 관리자 목록, SFTP·SSH 로그 |
| 데이터베이스 삽입 | 파일은 깨끗한데 리디렉션 발생 | 게시물 본문, 위젯, 옵션 값 |
| 같은 계정의 다른 사이트 | 복구한 사이트만 다시 감염 | 방치된 테스트·구 도메인 설치 |
관리자 비밀번호만 바꾸는 것도 필요한 조치지만, 침입 경로가 플러그인이나 서버 계정이었다면 문제는 계속될 수 있습니다.
먼저 확인할 파일과 위치
조사 전에 파일과 데이터베이스, 가능하다면 접근·오류 로그를 백업해 두는 것이 좋습니다. 처음부터 의심 파일을 전부 삭제하면 침입 시점과 공격 경로를 추적할 단서가 사라질 수 있습니다.
워드프레스 Core와 플러그인
워드프레스 Core 파일이 수정되었는지는 WP-CLI의 체크섬 검사로 비교할 수 있습니다.
wp core verify-checksums
wp plugin verify-checksums --all
이 명령은 설치된 파일이 WordPress.org에서 제공하는 공식 파일과 예상대로 일치하는지 확인하는 데 유용합니다. 변경된 파일을 찾는 도구이지, 사이트 전체가 안전하다는 것을 증명하는 검사는 아닙니다.
특히 wp-content 안의 업로드 파일, 데이터베이스, 유료 플러그인이나 외부에서 받은 플러그인은 검사 범위나 검증 가능 여부가 다를 수 있습니다. 체크섬이 다르다고 무조건 악성이라고 단정해서도 안 됩니다. 관리자가 직접 수정했거나 배포 과정에서 파일이 달라졌을 가능성도 있기 때문입니다.
wp-content/uploads와 설정 파일
wp-content/uploads는 보통 이미지와 문서 같은 미디어를 저장하는 위치입니다. 연도·월별 폴더 안에 정체를 설명하기 어려운 PHP 파일이 있다면 우선 조사 대상이 됩니다. 다만 PHP 확장자만 보고 정상 기능을 무조건 삭제하면 안 됩니다. 특정 플러그인이나 사용자 정의 기능이 별도의 실행 파일을 만들 수도 있으므로 생성 시점, 파일 내용, 해당 기능과의 관계를 함께 확인해야 합니다.
wp-config.php도 반드시 살펴봐야 합니다. 데이터베이스 접속 정보와 인증 관련 설정이 들어가는 핵심 파일이므로, 파일 앞뒤에 난독화된 코드나 출처를 알 수 없는 외부 파일 호출이 추가되지 않았는지 확인합니다. 호스팅 업체나 캐시·보안 솔루션이 정상 설정을 넣은 사례도 있으므로 익숙하지 않다는 이유만으로 바로 삭제하지 않는 편이 안전합니다.
Apache 서버라면 .htaccess도 확인해야 합니다. 이 파일이 변조되면 모든 방문자에게 문제가 나타나는 것이 아니라 검색엔진 유입이나 특정 브라우저에서만 다른 사이트로 이동하는 조건부 리디렉션이 생길 수 있습니다. 서버가 Nginx라면 .htaccess가 사용되지 않을 수 있으므로 웹 서버 구성을 먼저 확인해야 합니다.
손으로 훑지 말고 명령으로 좁힌다
감염된 사이트를 파일 관리자로 하나씩 열어 보는 방식은 시간도 오래 걸리고 놓치기도 쉽습니다. 서버에 접속할 수 있다면 몇 개의 명령으로 범위를 크게 줄일 수 있습니다. 아래는 실제로 돌려서 결과를 확인한 순서입니다.
1. 코어 파일이 변조됐는지부터 가른다
워드프레스는 배포된 코어 파일의 체크섬을 공개하고 있어서, 설치본이 원본과 같은지 기계적으로 비교할 수 있습니다. WP-CLI가 설치돼 있다면 한 줄이면 됩니다.
wp core verify-checksums
이상이 없으면 다음 한 줄만 나옵니다.
Success: WordPress installation verifies against checksums.
변조된 파일이 있으면 경로를 하나씩 나열해 줍니다. 이 검사가 통과했다면 코어는 건드려지지 않았다는 뜻이므로 조사 범위를 플러그인, 테마, 업로드 폴더로 좁힐 수 있습니다. 반대로 코어 파일이 걸려 나오면 재설치가 필요합니다.
2. 업로드 폴더의 PHP 파일을 센다
업로드 폴더에는 이미지와 문서만 있어야 합니다. PHP 파일이 있다면 정상적인 경우가 거의 없습니다.
find wp-content/uploads -name "*.php" | wc -l
정상이면 0이 나옵니다. 숫자가 0이 아니면 그 파일들이 최우선 조사 대상입니다.
3. 최근에 바뀐 파일만 뽑는다
재감염은 대개 최근에 일어납니다. 수정 시각을 기준으로 뽑으면 목록이 확 줄어듭니다.
find . -name "*.php" -mtime -1
최근 하루 안에 수정된 PHP 파일만 보여 줍니다. -mtime -7로 바꾸면 일주일입니다. 여기서 중요한 것은 결과에 나온 파일이 전부 범인은 아니라는 점입니다. 실제로 이 명령을 돌렸을 때 wp-config.php 한 개가 나왔는데, 그건 직전에 설정을 직접 손봤기 때문이었습니다. 내가 만진 기억이 있는 파일을 지우고 남는 것을 보는 방식입니다.
반대로 공격자가 수정 시각을 원래대로 돌려놓는 경우도 있습니다. 그래서 이 검사만 믿으면 안 되고, 앞의 체크섬 검사와 함께 봐야 합니다.
4. 난독화 흔적을 찾는다
악성코드는 내용을 감추기 위해 인코딩된 문자열을 실행하는 형태를 자주 씁니다. 대표적인 조합을 한 번에 검색할 수 있습니다.
grep -rlE "evals*(s*(base64_decode|gzinflate|str_rot13)" --include=*.php .
결과가 비어 있으면 그 유형은 없는 것입니다. 다만 이 패턴을 피해 가는 방식도 많으므로, 걸리면 확실한 신호지만 안 걸린다고 안전이 보장되지는 않습니다.
| 검사 | 정상일 때 | 걸렸을 때 뜻 |
|---|---|---|
| 코어 체크섬 | Success 한 줄 | 코어 변조 — 재설치 필요 |
| uploads의 PHP | 0 | 업로드 취약점으로 들어온 파일 |
| 최근 수정 파일 | 내가 만진 것만 | 기억에 없는 파일이 있으면 조사 |
| 난독화 패턴 | 결과 없음 | 거의 확실한 악성코드 |
5. 관리자 계정 목록을 확인한다
파일을 다 정리해도 관리자 계정이 하나 남아 있으면 재감염은 계속됩니다. 계정 목록과 가입 시각을 함께 봅니다.
wp user list --role=administrator --fields=ID,user_login,user_registered
가입 시각이 감염 시점과 겹치는 계정, 그리고 만든 기억이 없는 계정이 조사 대상입니다. 여기서 함께 볼 것이 아이디가 admin인 계정입니다. 공격 도구가 가장 먼저 시도하는 이름이라, 그대로 두면 비밀번호 하나만 뚫리면 됩니다. 재감염 조사와 별개로 정리해 두는 편이 안전합니다.
파일 밖의 재감염 경로도 조사해야 한다
사용자 계정
악성코드가 파일에만 존재한다고 생각하면 조사가 중간에 끝납니다. 워드프레스 사용자 목록에서 관리자 권한 계정을 확인하고, 직접 만들지 않은 계정이나 용도를 설명하기 어려운 계정이 있는지 살펴봐야 합니다. 여러 사람이 사이트를 관리한다면 삭제 전에 실제 담당자에게 확인하는 것이 좋습니다.
데이터베이스
데이터베이스에는 게시물 본문, 위젯, 옵션 값 등에 악성 스크립트나 스팸 문구가 들어갈 수 있습니다. 파일을 정리했는데도 방문자가 이상한 URL로 이동하거나 낯선 콘텐츠가 나타난다면 최근 수정하지 않은 게시물과 주요 옵션, 관리자 계정을 점검해야 합니다. 데이터베이스를 직접 수정할 때는 변경 전 백업이 필수입니다. 잘못된 SQL 쿼리 하나로 정상 콘텐츠까지 손상될 수 있습니다.
플러그인과 테마
플러그인과 테마의 상태도 함께 봐야 합니다. 오래된 구성 요소나 더 이상 유지보수되지 않는 플러그인은 악성 파일을 지운 뒤에도 같은 취약점을 통해 재공격을 받을 수 있습니다. 사용하지 않는 플러그인은 비활성화만 하는 것보다 실제 파일을 삭제하는 편이 공격 표면을 줄이는 데 유리할 수 있습니다. 다만 비활성화된 플러그인이 모든 환경에서 곧바로 공격에 이용된다고 단정할 수는 없으며, 삭제 전에는 해당 플러그인에 의존하는 기능과 복구 필요성을 확인해야 합니다.
침입 시점과 공격 계정을 추적하는 방법
파일 수정 시간은 침해 시점을 좁히는 단서가 됩니다. 문제가 처음 발견된 시간 전후로 평소 변경되지 않아야 할 PHP 파일이 동시에 수정되었는지 확인해 보십시오. 새벽 시간에 여러 파일이 바뀌었다면 조사 가치가 있지만, 워드프레스나 플러그인 업데이트 때도 많은 파일의 수정 시간이 변경될 수 있으므로 시간만으로 악성 여부를 결정해서는 안 됩니다.
웹 서버 접근 로그와 오류 로그에서는 의심스러운 PHP 파일에 반복적인 요청이 있었는지, 알 수 없는 POST 요청이나 관리자 로그인 시도가 있었는지 확인할 수 있습니다. 플러그인의 업로드 기능이나 특정 AJAX 엔드포인트가 공격에 이용된 흔적이 남을 수도 있습니다. 로그 보존 기간은 호스팅 업체마다 다르므로 사고를 알아챘다면 가능한 한 빨리 원본을 확보해야 합니다.
침입 경로가 워드프레스 관리자였다고 확정하지도 마십시오. 다음 인증 정보가 모두 영향을 받았을 수 있습니다.
- 워드프레스 관리자 계정
- 호스팅 패널과 SFTP·FTP 계정
- SSH 계정과 데이터베이스 계정
- 배포 도구 및 관리 서비스 계정
- 외부 서비스 API 키와 저장된 인증 토큰
비밀번호는 안전하다고 판단되는 기기에서 변경해야 합니다. 관리자 PC가 감염되어 키 입력이나 브라우저 저장 비밀번호가 다시 탈취되고 있다면 서버에서 비밀번호를 바꿔도 재침해가 반복될 수 있습니다. wp-config.php의 WordPress 보안 키와 Salt를 교체하면 기존 로그인 세션을 무효화하는 데 도움이 될 수 있지만, 이것이 백도어나 취약점 제거를 대신하지는 않습니다.
백업 복원만으로 해결되지 않는 이유
감염 이전의 정상 백업이 있다면 새로 설치한 깨끗한 환경으로 복구하는 데 유용합니다. 그러나 백업 시점과 백업 내용이 정말 안전한지 먼저 확인해야 합니다. 오랫동안 숨어 있던 백도어가 이미 포함된 백업이라면 복원 직후 문제가 재현될 수 있습니다.
또한 침입 원인이 취약한 플러그인이었다면 과거 백업에는 그 취약한 버전이 그대로 들어 있을 수 있습니다. 백업을 복원한 뒤에도 Core, 플러그인, 테마를 안전한 버전으로 업데이트하고, 유지보수가 중단된 구성 요소는 교체 여부를 검토해야 합니다.
복구 과정은 다음처럼 진행하는 편이 안전합니다.
- 현재 파일, 데이터베이스, 로그를 보존합니다.
- 필요하면 호스팅 업체와 협의해 사이트를 격리합니다.
- 관리자·서버 계정과 권한을 확인합니다.
- Core, 플러그인, 테마의 파일 변조와 버전을 검사합니다.
uploads,wp-config.php,.htaccess등 일반적으로 놓치기 쉬운 위치를 조사합니다.- 데이터베이스의 관리자 계정과 콘텐츠 변조를 확인합니다.
- 의심되는 취약점과 오래된 구성 요소를 제거하거나 업데이트합니다.
- 관련 인증 정보와 보안 키를 교체합니다.
- 깨끗한 상태에서 재검사한 뒤 사이트를 공개합니다.
- 복구 후 파일 변경과 새 관리자 계정 생성을 모니터링합니다.
사이트를 조사하기 전에 보안 플러그인부터 설치하거나 의심 파일 하나만 반복해서 삭제하는 방식은 원인 파악에 도움이 되지 않을 수 있습니다. 반대로 출처를 확인하지 않고 정상 파일을 대량 삭제하면 사이트 기능과 복구 가능성이 함께 훼손될 수 있습니다.
같은 호스팅 계정의 다른 사이트도 확인해야 한다
한 호스팅 계정에 운영 사이트, 테스트 사이트, 오래된 도메인을 함께 두는 경우가 많습니다. 현재 운영 중인 사이트만 복구했더라도 old-site나 몇 년째 방치된 테스트 워드프레스가 감염된 상태라면 서버 구성과 계정 권한에 따라 다시 공격받을 가능성을 검토해야 합니다.
사용하지 않는 워드프레스 설치와 오래된 테마·플러그인은 삭제하거나 별도로 격리하는 편이 낫습니다. 사이트 간 파일 권한과 계정이 과도하게 공유되고 있다면 한 사이트의 침해가 다른 사이트로 번질 위험도 커집니다. 호스팅 환경에서 사이트별 격리가 어떻게 구성되어 있는지 확인하기 어려운 경우에는 업체의 침해사고 대응 지원을 받는 것이 현실적일 수 있습니다.
재감염을 줄이는 운영 기준
복구가 끝난 뒤에는 업데이트, 계정, 백업, 로그를 따로 관리해야 합니다. 워드프레스 Core와 플러그인·테마를 정기적으로 업데이트하고, 출처가 불분명하거나 유지보수가 중단된 소프트웨어는 사용하지 않는 것이 기본입니다. 관리자는 각자 필요한 권한만 갖도록 줄이고, 가능한 환경에서는 다중 인증을 적용합니다.
백업은 만들어지는 것보다 실제로 복원 가능한지가 중요합니다. 파일과 데이터베이스가 함께 보존되는지, 여러 시점의 백업이 있는지, 백업 자체가 감염되지 않았는지를 주기적으로 확인해야 합니다. 접근 로그와 오류 로그의 보존 기간도 미리 알아두면 사고 조사에 필요한 시간을 벌 수 있습니다.
보안 플러그인은 탐지와 차단에 도움을 줄 수 있지만 모든 공격을 막는 장치는 아닙니다. 서버 계정이 탈취되었거나 이미 백도어가 설치된 경우에는 워드프레스 내부 기능만으로 해결하기 어렵습니다.
악성 파일이 삭제 후 다시 나타난다면 다음 세 가지를 우선 확인해야 합니다. 다른 백도어가 남아 있는지, 다시 침입할 취약점이나 탈취된 계정이 있는지, 같은 호스팅 환경에 감염된 다른 사이트가 있는지입니다. 이 원인을 확인하지 않은 채 파일만 지우면 사이트는 잠시 정상처럼 보일 뿐, 재감염 가능성은 그대로 남습니다.