Web Security

Charity Hacked: Web Skimmer Infected Caritas Spain Websites for Over a Year

April 23rd, 2025 | By Pedro Fortuna | 20 min read

with David Alves and Pedro Marrucho


This research documents Jscrambler’s investigation into a stealthy web skimming campaign that infiltrated multiple Caritas Spain websites of Caritas Internationalis, a confederation of over 160 Catholic relief, development, and social service organizations operating in more than 200 countries and territories.
 

All targeted Caritas Spain websites were running WooCommerce, the popular e-commerce plugin for WordPress. The attack chain consisted of two distinct stages, carefully designed to remain undetected while intercepting sensitive payment data.

This campaign reinforces a broader trend that has been observed: web skimming infections are increasingly driven by modular kits. These toolkits enable attackers to mix and match various delivery mechanisms, support multiple communication channels within their infrastructure, and deploy flexible combinations of loader and skimmer scripts. Jscrambler was able to confirm that the threat actors' automated validation and use of the stolen cards occurs soon after they are captured.


What makes this case especially concerning is the nature of the victim: Caritas is a non-profit dedicated to helping vulnerable communities. Still, attackers were happy to keep their skimming operation going on seventeen Caritas España sites for over a year until it was shut down recently. 


How the attack works


The skimming campaign, like many, was executed in two stages. Stage one served as the loader, laying the groundwork for the attack. Stage two held the skimmer logic itself, injected a fake payment form, and exfiltrated sensitive data.


Stage 1: Entry point and loader

The initial infection vector remains unknown. It could have been an exploited vulnerability, a misconfigured server, a compromised plugin, or credentials theft.  In this type of infection, threat actors usually ensure they can retain access even if the initial vulnerability or misconfiguration is patched or fixed in the meantime.

It was observed that the Stage 1 loader was injected as a one-liner at the bottom of the minified WooCommerce JavaScript: cart-fragments.min.js, which runs on the homepage.

https://www.caritas.es/main-files/plugins/woocommerce/assets/js/frontend/cart-fragments.min.js?ver=6.1.2


Here’s what that one-liner looks like:

Entry-point-and-loaderListing 1 - Sample stage 1 loader


This one-liner (lightly obfuscated) executes the following logic:


  1. Clears a key (XsuHCYmfbgVSRFVx7SHRnU7DfapjFpaf) from localStorage (this entry is associated with a potential web socket connection);

  2. Checks for another key (QIQWJJnh1Ckclw0jFr5KPME2M3kYHTyq) to avoid multiple skimming attacks on the same device;

  3. Dynamically constructs a URL using String.fromCharCode — in this case, https://categorywishlist.com;

  4. Sends a POST request to that endpoint;

  5. If the response is successful, the loader:

    • gets a JSON response that, among other things, includes a property called response.data containing the following subproperties:

  • “script”: the URL from where the stage2 script must be loaded,

  • “handler”: the URL to where skimmed data will be exfiltrated by the Fetch method,

  • “Socket”: an alternative exfil channel using Web Sockets


sample-jscon-returnedListing 2 - Sample JSON returned by the categorywishlist.com endpoint


The arrays above are strings using the same obfuscation technique as before. Using String.fromCharCode, you get:


json-after-decoding-string-elementsListing 3 - JSON after decoding string elements


  • Then “socket” and “handler” are saved, respectively, into Local Storage items “XsuHCYmfbgVSRFVx7SHRnU7DfapjFpaf” and “XsuHCYmfbgVSRFVx7SHRnU7DfapjFpaf_handler”

6. Loads a stage 2 script from https://newsasssets\.com/caritas\.js by appending it to the head section of the DOM.


Any errors are caught by the script so as to avoid triggering errors that could lead to an earlier discovery of the attack.


Stage 2: Fake payment form and exfiltration


donor-form-caritas-spainImage 1 - Donor form


Once loaded, the second-stage script monitors for the selection of the Tarjeta (payment card) payment option. When detected, it injects a fake Continuar (Proceed) submit button and hides the real one.

payment-card-option-selected-on-the-donor-formImage 2 - Payment Card option selected on the donor's form


fake-button-inject-functionImage  3 - Fake button inject function (deobfuscated for improved readability)


Once the user submits the initial form, it overlays it with a fake payment form on the same domain (caritas.es) that visually resembles the legitimate payment gateway (Redsys on behalf of Santander).   The skimmed data — cardholder name, number, expiry, and CVV — is collected and exfiltrated via a covert Image.src request to https://hotjarws\.com/b\.php, base64 encoded.


user-submits-the-initial-form


Collected data:

  • Cardholder data:

    • User Agent

    • Email

    • First Name

    • Last Name

    • Address

    • City And Postcode

    • Cardholder name

    • Phone

    • DNI

    • Payment card number

    • Expiry date

    • CVV

  • Collected from:

    • website

fake-payment-form-running-caritas-spainImage 3 - Fake payment form running at Caritas.es


exfiltrated-dataImage 4 - Exfiltrated data


exfiltrated-data-example


After the user submits the fake payment form, the overlay is removed, and a loading spinner is shown for a few seconds. Then, the donor form is shown again. At this point, provided that the user does not deselect the target (card), if the user clicks Continuar (submit), they are redirected to the legitimate PSP site to proceed with the donation.

legitimate-payment-form

Image 5 - Legitimate payment form on sis.redsys.es


While the visual representation is convincing, the differences become obvious after the user is taken to the second payment form.  By comparing Images 3 and 5, they are easily spotted.  The question is whether these differences are sufficient to prompt users to report them to Caritas, and, if so, how those reports are being processed.


Infected websites


The team checked all Caritas related websites and we found the same skimming campaign affecting the following 17 websites:


  • caritas.es

  • caritasespanola.org

  • caritasdtr.org

  • caritasoa.org

  • caritastortosa.org

  • caritas-sc.org

  • caritasmalaga.es

  • caritasmallorca.org

  • caritasmeba.es

  • caritasplasencia.org

  • caritasvalencia.org

  • caritas-zaragoza.org

  • caritasbi.org

  • caritasbisbatvic.cat

  • caritasjaen.es

  • caritasregiondemurcia.org

  • diocesanaterrassa.caritas.es


Most websites were hosted under the same IP address, indicating centralized management or a shared infrastructure. A few exceptions exist (3), but the majority were under the same IP, and they are likely being managed using a common backend administration panel.

infected-websites-infrastructure-graph

Image 6 - Infected websites infrastructure graph


Research timelines


This campaign was first detected on March 16th, 2025. Soon enough, all seventeen infected websites from Caritas in Spain were found, along with all domains and IP addresses involved. Then, between April 1st and 3rd, 2025, the stage 1 categorywishlist\.com and the C2 domain newassets\.com went offline, but the websites were still infected with Stage 1. On April 3rd at 1 am, the C2 domain came back with a new IP:


research-timelines


At this point, Jscrambler started reaching out to victims. The team reached out to Caritas on April 4th. All Caritas-infected websites were down for maintenance shortly after. 


websites-under-maintenanceImage 7 - Websites under maintenance


When they returned online, few things had changed. All websites were still infected, but the point of infection was now on a different WooCommerce script:


woocommerce-script


The Jscrambler Research Team couldn’t confirm whether the previous script was cleaned by Caritas or if the threat actors had simply changed the infection point elsewhere, perhaps as an evasion tactic. Evidence suggests that the threat actors have persistent access to the WooCommerce installation. 


Besides that change, the skimmer stack remained the same, except that a skimmer-related domain changed. Instead of using categorywishlist\.com for the Stage 1 JSON request, it was now using assetssafepay\.com. All other skimmer-related domains remained unchanged.


Jscrambler reached out again to Caritas, and by April 11th, 2025, we confirmed the infection had been removed.  


Other targets and skimming insights

The same campaign targeted several websites beyond Caritas. The Jscrambler Research Team discovered that this particular threat actor was leveraging an unusually high number of domains, totaling 61, most of which were hosted under the same IP address that had recently been assigned to their C2 server (see Image 7).

When an attacker uses such a large volume of domains, attempting to take them down individually is often ineffective. Taking down the IP address — for example, by reporting it to the hosting provider — is typically a more impactful countermeasure, especially when many sites are hosted on the same infrastructure.


Other-targets-skimming-insights

Image 8 - Domains used by the Threat Actor


Across other victim websites, we observed variations of the same attack. These differences appeared in both the loader scripts (Stage 1) and the main skimmer logic (Stage 2):


  • Stage 1 loaders: varied in location and method. Some were injected into different plugins or scripts, including those loaded via a legitimate Google Tag Manager (GTM) or through scripts pretending to be GTM. The loader code itself also showed multiple variations.

  • Stage 2 scripts: clearly generated by a tool, all very similar, usually obfuscated. In some cases, we saw a comment header typically associated with Google Closure Compiler: Copyright The Closure Library Authors. SPDX-License-Identifier: Apache-2.0. While the team cannot confirm whether Closure Compiler was actually used, it is plausible that the attacker inserted this comment deliberately to make the script appear more legitimate. If Closure Compiler was used at some point, its traces may have been overwritten by subsequent layers of obfuscation. It's worth noting that Closure Compiler is intended for minification, not obfuscation; however, the distinction may be lost on defenders performing a quick analysis.


Interestingly, some victims appeared aware that something was wrong, but lacked the means or knowledge to properly address it. On one merchant’s site, there was an attempt to block the skimmer by injecting a script designed to prevent the stage 2 payload from loading from paysafeprocess\.com.

merchant-attempt-fix-the-problemImage 9 - A merchant’s attempt to fix the problem


How fast is stolen data used?


The Jscrambler Research Team wanted to understand how quickly stolen payment data from this campaign was being used. To do so, a canary payment card was deployed from Thinkst — a specially generated card number intended for use as a decoy and not for legitimate transactions. If this card is used or even tested for authorization, it triggers an alert, confirming that it has been compromised. Think of it as a payment card honeypot.


Using a canary card service, a card was created and submitted through the fake form on caritas\.es. Within just 10 minutes, an alert was received.

incident-info-canary-payment-card-triggered-alert

Image 10 - Canary Payment Card triggered alert


Given how quickly the card was tested, it's likely that the threat actor’s infrastructure is automated to validate stolen cards soon after they are captured.


Highly persistent infection


As stated above, the Jscrambler Research Team first detected this infection in mid-March 2025. However, by examining historical snapshots from Archive.org and other web-crawling services, the initial infection was traced back to February 22nd, 2024.

highly-persistent-infection



first-sign-of-infection

Image 11 - First sign of infection on February 22nd, 2024



Over time, it was observed that different scripts were being infected, multiple skimming techniques were deployed, and there were periods of dormancy. These signs strongly suggest that the threat actors had persistent access to the WooCommerce environments, allowing them to reintroduce or modify the skimming code at will, shift infection points, and rotate infrastructure domains as needed.

As of April 11th, 2025, Jscrambler confirmed that the skimmer was no longer active. However, from our external vantage point, we cannot determine whether the attacker still retains any level of access to the affected systems.

How to protect against web skimming


To mitigate the risk of web skimming, organizations that accept online payments should consider implementing robust security solutions. Merchants accepting payment card payments are already contractually obligated to comply with security standards such as PCI DSS.

Specifically, the following requirements apply:

  • Requirement 6.4.3: Merchants must ensure that all payment page scripts are authorized and have a method to assure their integrity. This means cataloging which scripts are expected to run on the payment page, validating their sources, and implementing integrity checks.

  • Requirement 11.6.1: Merchants must implement a change- and tamper-detection mechanism to alert on unauthorized modifications to HTTP headers and the contents of payment pages as received by the consumer browser. This requires the ability to detect if a skimmer or rogue script is injected post-deployment.


Implementing script behavior-based monitoring solutions, such as Jscrambler Webpage Integrity, can detect unauthorized script injections and enforce PCI DSS requirements 6.4.3 and 11.6.1.  

Given that small merchants often lack the expertise or resources to fully implement the stringent requirements of PCI DSS, these automated solutions provide an essential layer of protection. Equally important is having an incident response plan in place that includes how to communicate with users and restore trust after an incident.

Web skimming prevention requires a combination of technical controls, process rigor, and continuous visibility into what is executing on your users' browsers during checkout.


Conclusion

Losing payment card numbers to threat actors is always a serious matter, regardless of the context. When it happens in a typical online shopping scenario, the impact is significant. However, when someone visits a website solely to make a donation to a charitable cause and their cardholder data is stolen in the process, it feels especially disheartening.

This incident serves as a powerful reminder that web skimming is a threat that transcends organization size, mission, or industry. Threat actors don’t discriminate — if a website processes cardholder data, it’s a viable target.


Skimming operations are increasingly relying on automation. From searching and infecting victims, to validating and using the stolen data. There is a market for skimming kits, which invites new threat actors to set up their skimming operations. This attack also demonstrates that these attacks can persist for extended periods, making web skimming a highly profitable activity for threat actors.


If your organization processes online payments, ensuring the integrity of what users see in their browsers is critical. To learn how Webpage Integrity can help you detect and stop web skimming attacks before they cause harm, get in touch with us — we're here to help.




Indicators of Compromise (IOCs):
GTM IDs

GTM

GTM-KJJ3BFKC



Indicators of Compromise (IOCs):
Malicious Domains

C2

IP

ASN

ASN-NAME

ASN-COUNTRY

paysafeprocess[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

analysiscache[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

analysisdoubleclick[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

assets-token[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

assetshotjar[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

assetssafepay[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

bundlereferrer[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

analysistoken[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

notificationfeedback[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cachereferrer[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

campaigntransaction[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

categorywishlist[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cdn-secure[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cdnmozilla[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cdnnewassets[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

explorerstripe[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

gravatargo[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

platformwebsite[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

heure-planification[.]com

185[.]208[.]158[.]121

42624

SWISSNETWORK02, SC

Seychelles

hipaye[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

hotjarmultisafe[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

interfaceuser-friendly[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

locationchrome[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

ratingrecommendation[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

recommendationtrend[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

inventoryvoucher[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

timestampcdn[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

referrerlocation[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

refundpurchase[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

safepaymultisafe[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

securedata-ns[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

securi-analitycs[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

staticreview[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

stockbarcode[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

jguery-web[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

web-jguery[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

stripehotjar[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

tag-secure[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

user-friendlyexperience[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

webjguery[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

webjquery[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

wishlistnotification[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

ads-advertise[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

multisafebundle[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

paysafeprocess[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

analysis-ns[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

hotjarws[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

mozillastatus[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

firefoxcaptcha[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

experienceresponsive[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

newsassets[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

checkoutcache[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cdnweb2analytics[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cdnsafepay[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

bundle-referrer[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cloudsolutio[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

cachecaptcha[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

assets-tokens[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

advertcheckout[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

token-analysis[.]com

86[.]54[.]42[.]111

42624

SWISSNETWORK02, SC

Seychelles

approvalreceipt[.]com

-

-

-

-

stripepayway[.]com

-

-

-

-

Jscrambler

The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Web Security

Stripe API Skimming Campaign: Additional Victims and Insights

A recently discovered web skimming campaign has introduced a novel technique that leverages a legacy Stripe API to validate stolen payment details before exfiltrating them.

April 2, 2025 | By Pedro Fortuna | 13 min read

Web Security

Stealing Seconds: Web Skimmer Compromises Casio UK and Growing Number of Websites

Jscrambler just uncovered a new batch of web skimmer infections affecting multiple websites, including casio.co.uk. So far, 17 victim websites are confirmed, though this number will likely increase...

January 31, 2025 | By Pedro Fortuna | 10 min read

Section Divider