Computer >> 컴퓨터 >  >> 네트워킹 >> 네트워크 보안

Drupal 사이트가 스팸 페이지로 리디렉션될 때: 증상, 원인부터 완벽한 복구 방법까지

Drupal은 뛰어난 보안성으로 널리 알려진 오픈소스 CMS입니다. 오픈소스 특성상 소스 코드가 공개되어 있어 버그 바운티 헌터들에게는 검증의 기회가 되지만, 동시에 공격자에게도 공격 벡터를 탐색할 여지를 제공합니다. 실제로 최근 몇 년간 Drupal은 악명 높은 '파르마 핵(Pharma Hack)'부터 '키티 크립토마이닝 멀웨어'에 이르기까지 다양한 공격에 노출되었습니다.

그중에서도 최근 급증하는 위협이 바로 Drupal 리디렉션 해킹(Drupal Hack Redirect)입니다. 이 공격은 방문자를 스팸 페이지로 강제로 이동시키는 수법으로, 피싱 사이트나 비아그라·포르노 등 성인용 페이지로 사용자를 유도하는 것이 특징입니다.

Drupal 리디렉션 해킹은 어떻게 나타날까?

공격자는 웹사이트의 취약점을 악용해 사이트 콘텐츠를 변조하고 멀웨어를 설치합니다. 그 결과 방문자는 스팸성·의심스러운 링크로 리디렉션됩니다. 이 감염에는 크게 두 가지 유형이 있습니다.

  1. 홈페이지에 접속하는 순간 스팸 페이지로 리디렉션되는 경우
  2. 버튼이나 링크를 클릭할 때마다 비아그라, 시알리스 등을 판매하는 가짜 약국 페이지로 이동하는 경우

두 번째 유형에 해당하는지 확인하려면 Google 검색 연산자(dork)를 활용할 수 있습니다. 아래 명령어를 입력해 보세요.

site:your-website.com "viagra"

이 검색 결과에 사이트가 표시된다면 비아그라 관련 페이지로 리디렉션되고 있을 가능성이 높습니다. 'viagra' 대신 poker, porn, loans 같은 키워드로 교체하여 추가 확인도 가능합니다.

검색된 링크를 클릭했을 때 오류가 발생한다면, 공격자가 이미 사이트를 침해해 리디렉션을 설정했다는 의미입니다. 다만 다른 요인으로 인해 현재는 리디렉션이 작동하지 않고 있을 수도 있습니다.

리디렉션 유형별 HTTP 상태 코드

리디렉션 해킹에 사용되는 HTTP 상태 코드는 다음과 같습니다.

  1. 301 리디렉션(영구 이동): URL이 새 위치로 영구적으로 이전되었음을 검색 엔진에 알립니다. 설정이 간단하기 때문에 공격자가 가장 선호하는 방식입니다.
  2. 302 리디렉션: 현재는 303으로 대체되어 거의 사용되지 않습니다. 문서가 일시적으로만 사용 가능함을 의미했습니다.
  3. 303 리디렉션: 302의 개선된 버전으로, 임시 페이지를 제공합니다. 향후 같은 주소에 존재하지 않을 수 있는 페이지(신용카드 정보 양식 등)에 사용됩니다. 정교한 공격이 아니라면 공격자가 잘 사용하지 않습니다.
  4. 307/308 리디렉션: 307은 303의 변형이며, 308은 실험적인 리디렉션입니다. 드물게 사용되지만 가능성 자체는 배제할 수 없습니다.

Drupal 멀웨어 리디렉션의 주요 징후

  • 비정상적으로 급증하는 웹사이트 트래픽
  • Drupal 사이트에 출처를 알 수 없는 파일이 생성됨
  • 관리자 권한을 가진 신규 사용자 계정이 발견됨
  • 홈페이지 링크 클릭 시 스팸 사이트로 이동
  • 악성 광고나 포르노 팝업이 사이트에 표시됨
  • 기존에 없던 노드(node)나 파일이 갑자기 나타남
  • 검색 엔진에 스팸 콘텐츠가 노출됨
  • Google, Bing 등 검색 엔진으로부터 보안 경고 또는 블랙리스트 등재

Drupal 리디렉션 해킹의 원인

원인은 매우 다양하지만, 대표적인 원인들을 살펴보겠습니다.

DNS 리디렉션

DNS 서버의 레코드가 변조되면 도메인 조회 시 공격자가 지정한 IP로 연결됩니다. Windows에서는 명령 프롬프트에 tracert www.your-site.com, Linux에서는 host www.your-site.com을 실행해 DNS 조회 결과를 확인하세요. 잘못된 IP가 반환된다면 문제는 웹사이트가 아닌 DNS에 있습니다.

파일 변조

공격자가 .htaccessindex.php 파일에 악성 코드를 삽입했을 수 있습니다. 다음과 같은 형태의 코드를 찾아보세요.

data:text/html,<html><meta http-equiv="refresh" content="0; url=https://malicious_site.com/process/route/1673246826.html?refresh=non-ie&bl=0"></html>

이 코드는 사이트 방문자를 malicious_site.com으로 강제 이동시키는 역할을 합니다.

코어 무결성(Core Integrity) 검증

모든 파일을 수동으로 검사하기는 어렵기 때문에, 먼저 설치된 파일의 무결성을 원본과 비교하는 것이 좋습니다. GitHub에서 순수 설치 파일을 내려받아 diff로 비교하는 방법입니다.

mkdir drupal-8.3.5
cd drupal-8.3.5
wget https://github.com/drupal/core/archive/8.3.5.tar.gz
tar -zxvf core-8.3.5.tar.gz

이후 diff -r core-8.3.5 ./public_html 명령으로 원본 설치 파일과 현재 파일의 차이점을 확인하고, 이 방식으로 모든 파일을 점검하세요.

기타 원인

  • SQL 인젝션: 1998년 처음 공개된 이후 지금까지 웹사이트를 괴롭히는 고질적 취약점입니다. 입력값 검증(sanitization)을 소홀히 하면 단 하나의 세미콜론 누락만으로도 SQL 인젝션에 노출될 수 있습니다.
  • 수상한 모듈 파일: modules/system/wxeboa.php처럼 원본 설치에 없는 이름의 파일이 있다면 의심해야 합니다.
  • Google 투명성 보고서: Google Transparency Report를 활용하면 사이트의 보안 상태를 파악하는 데 큰 도움이 됩니다.
  • 취약한 비밀번호: FTP나 관리자 계정의 비밀번호가 약하거나 기본 설정값이라면 지금 즉시 변경하세요.

피해 확산 방지: .htaccess를 활용한 선제 차단

사이버 보안의 기본 원칙은 공격을 100% 막을 수 없다는 것입니다. 따라서 만약의 재감염에 대비해 .htaccess 파일을 미리 설정해 두면, 스팸 접근을 자동으로 차단해 검색 엔진의 블랙리스트 등재를 예방하고 검색 순위 하락을 최소화할 수 있습니다.

1. 리퍼러(Referrer) 키워드 기반 차단

<Limit GET>
order allow, deny
allow from all
deny from env = spammer
SetEnvIfNoCase Referer ".*(Poker|credit|money).*" Spammer
</Limit>

이 코드는 HTTP 리퍼러에 poker, credit 등의 키워드가 포함된 접근을 차단합니다. 정상적인 사이트에는 해당 키워드가 없으므로 안심하고 적용할 수 있습니다.

2. 식별자 기반 차단

RewriteEngine On
RewriteBase /
# allow referrals from search engines:
RewriteCond %{HTTP_REFERER} !.*xyz\.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^https://([^/]+)google\..*$ [NC]

google 부분을 yahoo, bing 등 허용하려는 검색 엔진으로 계속 추가하고, 차단할 스팸 키워드(viagra, porn, loans 등)도 마찬가지 방식으로 지정합니다. 단, 이 기능은 Apache의 ModRewrite가 활성화되어 있어야 작동합니다. 스팸으로 공개적으로 알려진 특정 IP를 직접 차단하는 것도 좋은 방법입니다.

감염된 사이트 정리하기

데이터베이스 정리

사용자 및 테이블 점검

먼저 SQL 인젝션 흔적을 찾습니다. show tables; 명령으로 전체 테이블을 조회하고, Sqlmap 같은 자동 침투 테스트 도구가 남긴 잔여 테이블이 있는지 확인하세요. 또한 공격자가 관리자 권한을 가진 신규 계정을 만들었을 수 있으므로 아래 쿼리로 확인합니다.

Select * from users as u
AND u.created > UNIX_TIMESTAMP(STR_TO_DATE('Oct 15 2018', '%M %d %Y'));

특정 날짜 이후 생성된 모든 사용자가 표시되며, 날짜는 필요에 따라 조정하세요. 수상한 사용자나 테이블이 발견되면 drop database database-name.dbo;로 삭제할 수 있습니다.

사용자 계정 잠금

모든 사용자의 비밀번호를 일괄 변경하려면 다음 명령을 사용합니다.

update users set pass = concat('ZZZ', sha(concat(pass, md5(rand()))));

이 SQL 문은 비밀번호를 MD5 해시 형태로 변환합니다. 평문 비밀번호 저장은 절대 금물입니다. 데이터베이스가 유출되면 평문은 곧바로 공격자에게 노출되지만, MD5와 같은 단방향 해시 함수는 역산이 어려워 추가적인 보안층을 제공합니다.

파일 정리 체크리스트

  • 백업본이 있다면 파일을 백업 시점으로 롤백
  • Hacked 모듈 같은 외부 스캐닝 모듈로 감염 여부 진단
  • 루트 디렉터리 외부에서 민감한 파일에 접근하지 못하도록 설정
  • 민감한 정보 노출을 막기 위해 에러 리포팅 비활성화
  • 설치 버전이 오래되었다면 즉시 업데이트 — Update! Update! Update!
  • 기존에 사용하던 API 키와 FTP 비밀번호를 모두 재설정하고 강력한 비밀번호 사용
  • 캐시 정리: Drupal 8은 drush cache-rebuild, Drupal 7은 drush cache-clear all 실행
  • WAF(Web Application Firewall) 솔루션을 도입해 추가 보안 계층 구축

그럼에도 불구하고 모든 원인을 스스로 찾기 어려울 수 있습니다. 수동 정리가 부담스럽다면 자동화 도구를 활용하거나 보안 전문가의 도움을 받는 것이 좋습니다. 또한 사용 중인 CMS에서 발견되는 취약점 정보를 블로그나 보안 사이트를 통해 꾸준히 확인하고 대응하는 습관이 무엇보다 중요합니다.