Criminals Built a Fake Children's Charity to Hide a Card Skimmer

Criminals Built a Fake Children's Charity to Hide a Card Skimmer

If you spot an unfamiliar domain in your network traffic, you might open it in a browser and see what it is. Do that with chatshield.org and you land on a non-profit that protects children from grooming and harassment online, a noble cause. It has a 24/7 helpline, a team of counsellors and researchers, a donate button and a list of funders including UNESCO and the Mozilla Foundation. It seems legitimate so you'd probably close the tab and move on.

Sadly, that misdirection is exactly what this site is for. The same server hosts a credit card skimmer that we've found running on WooCommerce shops, and the fake charity exists to make sure nobody looks too closely at what's happening.

The "charity"

The homepage is a single page and every link in the menu (Mission, Team, Resources, Donate) jumps to a section further down the same page, but there's nothing else on the site. The page makes a lot of bold claims so we decided to verify some of them and see if they hold up. The site was clearly serving a credit-card skimmer. The question was whether a legitimate organisation had been compromised, or whether the charity site was built as cover for the operation.

"Nonprofit · 501(c)(3) · Est. 2018"
This sits at the top of the page, but the domain was registered on 3rd May 2026, and the page itself was last modified on 20th May, and the oldest archived copy of the homepage, from 4th May, is a 404.

The footer says the organisation is Stichting ChatShield, a Dutch foundation, and gives a Chamber of Commerce (KVK) number and an RSIN, the Dutch tax ID for organisations. The KVK number isn't in the Dutch business register, either as an active or a closed business, and neither is the name ChatShield. The RSIN isn't in the Dutch tax office's register of recognised charities. It passes the Dutch check-digit test, though, and when you search for it in the business register it belongs to a small, unrelated business in Amsterdam. Either it was borrowed, or someone generated a valid-looking number and it happened to be real.

The "Meet the Team" section has four people: an executive director who used to lead child protection at UNICEF, a clinical psychologist who runs the helpline, a research director who used to work in Trust & Safety at Meta, and a head of engineering. The photos are free stock images, loaded straight from Unsplash's CDN, and we couldn't find a real person matching any of the names and backgrounds.

The rest is the same where none of it checks out. The testimonials come from "Marta R." in Madrid and "James W." in Manchester, and the site claims to serve 42 countries in 14 languages. The offices are in a canal house in Amsterdam and a tower block in Toronto, both real buildings with lots of tenants, and nothing connects ChatShield to either of them. The linked GitHub and Mastodon accounts don't exist and none of the other social links work either. We couldn't find any registered charity called ChatShield, anywhere.

The skimmer

On an infected shop, the page loads what looks like jQuery:

https://chatshield.org/static/<id>/jquery.js?ver=6.4.3
https://chatshield.org/pub/static/<id>/jquery.js?ver=6.8.1

The ?ver= parameter is a familiar WordPress convention for scripts. Here, the values match WordPress release numbers, which helps the file blend in with the other scripts on the page. The <id> is 16 hex characters and is different for every shop. The file isn't jQuery. It's about 80KB of obfuscated JavaScript, and once you analyse it, this is what it does:

  1. It waits for the checkout. It looks for WooCommerce's Place order button and attaches its own click handler to it. It also re-enables the button if something has disabled it.
  2. It checks if anyone's watching. If the browser’s outer and inner heights differ by more than 160 pixels, a check typically used to detect developer tools docked in the window, it does nothing.
  3. It takes everything. When the shopper clicks Place order, it collects every input and select on the page: card number, expiry, CVC, name, address, email and phone.
  4. It encrypts it so only the operator can read it. The data is sealed with a public-key box using a fresh key pair per send and the attacker's public key, which is baked into the script. The traffic leaving the browser is then an opaque blob, but the attacker can recover everything with the associated private key.
  5. It sends it home. The newest copy we have opens a WebSocket to wss://chatshield.org/ws/<id>. Older copies, going as far back as May, sent it as a GET request to https://chatshield.org/<id>/<data> instead. In both versions the hostname isn't in the script as plain text; it's RC4-encrypted using the shop's ID as the key, so searching the file for "chatshield" finds nothing.

After that's done, it writes authorize_net-check to localStorage, named to look like it belongs to the Authorize.Net payment gateway, so the same browser is left alone for the next seven days. Finally, it removes its own script tag from the page.

A quick note for other defenders, the server definitely doesn't like being looked at. We fetched the homepage and a handful of the skimmer files over the course of a few days and it now doesn't accept connections from any of our IP addresses. Rotating to a new IP gets us access again but we get blocked even more quickly. I'm not sure if it's manual or automated, but it definitely responds if you appear to be analysing it.

How it gets onto the shops

In one approach, the page has a small inline script that does nothing unless the URL contains /checkout/. Both that path and the skimmer's URL are encoded, the path as base64 and the URL as a list of character codes, so neither appears in the source as readable text:

!function(e,t,n,r){if(!window.a)...}(document,0,"L2NoZWNrb3V0Lw==","104,116,116,112,115,...")

In the other, there's no inline script at all. The skimmer seems to be added through WordPress's own script loader, wp_enqueue_script, which means the code is running in PHP on the server, in a plugin or the theme's functions.php. The hint is that WordPress helpfully adds a dns-prefetch hint for the domain to the page <head> for enqueued scripts and styles.

If you’re cleaning up a WordPress site, search for the exact indicators above, including wp_head-js, par'.'ent_plu'.'gin-js, and references to chatshield.org. Review unfamiliar wp_enqueue_script() calls and the files that contain them. Then rotate admin, hosting and FTP credentials, because whoever added the code had write access.

Indicators of Compromise

These indicators may change and should be used alongside behavioural checks:

Domain and IP

chatshield.org
45.9.148.90

Skimmer paths

https://chatshield.org/static/<16 hex>/jquery.js
https://chatshield.org/pub/static/<16 hex>/jquery.js
wss://chatshield.org/ws/<16 hex>
https://chatshield.org/<16 hex>/<data>

Strings

  • localStorage key: authorize_net-check
  • Attacker public key: YJPgfAfSfQ1mBufiAEEXUYs5ArqCffEYH28RGNnUT1s=
  • Inline loader: L2NoZWNrb3V0Lw== (base64 for /checkout/) alongside a long comma-separated list of character codes
  • WordPress script handles: wp_head-js, par'.'ent_plu'.'gin-js

Read more