Elementor Malware: Finding Code Hidden in _elementor_data
By Glenn Lyvers · Updated · 7 min read
Elementor stores the layout of every page it builds as JSON in the database, in the _elementor_data field of wp_postmeta. Attackers who get in through a vulnerable add-on often inject their script there, or into an HTML widget, a popup or a Custom Code snippet, rather than into a PHP file. File scanners never look at it, so the site keeps serving malware after every “clean” scan. You find it with a few targeted database queries and remove it without breaking the page’s JSON.
Where Elementor keeps your pages
A page built with Elementor has two copies of its content. post_content in wp_posts holds a plain fallback version. The real layout — every section, column, widget and setting — is a JSON document in wp_postmeta under the key _elementor_data. Elementor renders from that JSON, and it writes generated stylesheets to wp-content/uploads/elementor/css/.
That split matters for cleanup. Someone who checks the post in the classic editor, or searches post_content, sees nothing wrong. The injected script sits inside the JSON, often inside an HTML widget that looks empty in the editor because the code has no visible output.
The other places I check on every Elementor site:
- Templates, headers, footers and popups. These are posts in the Elementor template library (the
elementor_librarypost type) with their own_elementor_data. A malicious global footer runs on every page. - Elementor Pro Custom Code. Under Elementor › Custom Code, snippets can be injected into the head or body sitewide. It is a legitimate feature and an ideal hiding place.
- Page and site settings stored in other
_elementor_*meta keys and inwp_options. - Revisions. Every revision carries its own copy of
_elementor_data, so restoring an old revision can put the malware straight back.
How it gets there
Elementor itself has had serious bugs — versions 3.6.0 to 3.6.2 had a remote code execution flaw in its onboarding module (CVE-2022-1329) — but the entry point I see far more often is an add-on pack. In May 2023 Essential Addons for Elementor, installed on over a million sites, shipped a fix for an unauthenticated privilege escalation (CVE-2023-32243, versions 5.4.0 to 5.7.1) that let anyone reset an administrator’s password. Sucuri reported a mass infection campaign exploiting it within days. Once an attacker is an administrator, writing a script into a page layout is one API call.
Other routes are the usual ones: a reused admin password, a nulled copy of Elementor Pro from a download site (see nulled themes and fake plugins), or a contributor account on a site with too many of them. If you don’t know which one it was, how did my WordPress site get hacked covers how to work it out from logs and timestamps.
Finding the injection with SQL
Take a database backup first. Then look for script-like content in Elementor data. Adjust the wp_ prefix to match yours.
SELECT post_id, LENGTH(meta_value) AS size
FROM wp_postmeta
WHERE meta_key = '_elementor_data'
AND (meta_value LIKE '%<script%'
OR meta_value LIKE '%atob(%'
OR meta_value LIKE '%fromCharCode%'
OR meta_value LIKE '%eval(%'
OR meta_value LIKE '%document.write%'
OR meta_value LIKE '%iframe%');
Remember the content is JSON, so slashes and quotes are escaped — a closing tag appears as <\/script> and a URL as https:\/\/. Search for a suspicious domain without its slashes. Not every hit is malicious: a real site may legitimately embed a booking widget or a map. The question for each one is whether you, or someone you trust, put it there.
Then list every Elementor post type on the site and check those too, including anything that looks like a code snippet type:
SELECT post_type, post_status, COUNT(*)
FROM wp_posts
WHERE post_type LIKE '%elementor%'
GROUP BY post_type, post_status;
Finally, search wp_options for the same patterns. The broader method, including the other tables worth checking, is in my guide to WordPress database malware. If the hit contains an external domain, look it up properly before deciding — how to check a strange domain in your site’s code explains how to do that without visiting it.
Removing it without breaking the page
Use the editor where you can. If the injection is in a widget you can open, delete the widget in Elementor and update the page. Elementor rewrites the JSON correctly for you.
Edit the JSON only if you must. When the code is buried in a setting the editor won’t show, export the meta_value, remove the malicious fragment in a text editor, and check the result is still valid JSON before writing it back. A missing comma or unescaped quote will blank the page. Never run a blind search-and-replace across wp_postmeta: other meta keys are PHP-serialized, and changing a string length inside them corrupts the data.
Clean the rest. Delete malicious Custom Code snippets and templates, delete infected revisions of affected pages, then regenerate Elementor’s generated files (Elementor › Tools, the regenerate files and data button) and purge every page cache and CDN. The uploads/elementor/css/ folder is rebuilt from the database, so once the database is clean it will be too.
Close the door. Update Elementor and every add-on, remove add-ons you don’t use, review administrator accounts for ones you didn’t create (see hidden admin users), and change passwords. Then check the file system for a backdoor, because attackers who can write to the database usually leave one; WordPress backdoor removal covers where they go.
Rather hand it to me?
Every job is done by me personally, at a flat price per site, with written findings.
Not sure which? Ask me first — I’ll tell you honestly if you can handle it yourself.
Divi, WPBakery and other builders
The same principle applies elsewhere: the content lives somewhere a file scanner doesn’t read. Divi keeps layouts as shortcodes in post_content, and its Theme Options have an Integration tab with fields for code in the head and body — check them. WPBakery’s Raw HTML and Raw JS elements store their content encoded rather than as readable HTML, which means a naive search for <script finds nothing and a scanner looking for encoded strings raises false alarms on legitimate content. Decode and read those elements rather than trusting either result.
Why your scanner said the site was clean
Most free and plugin-based scanners are built to find malicious files. A script stored as one string inside a large JSON document in wp_postmeta is neither a file nor a recognisable signature, and many scanners skip meta values entirely for performance. I explain the wider problem in why free scanners miss backdoors. The practical takeaway: on a page-builder site, a clean file scan tells you very little. My free site checker looks at what the pages actually serve, which is where this kind of injection shows itself.
If you would rather not edit JSON in phpMyAdmin on a live store or a site with hundreds of pages, that is the right instinct. Database cleanups of builder data are routine work for me, and they are included in every cleanup rather than billed as extra.
Common questions
Can malware hide inside Elementor?
Yes. Elementor stores page layouts as JSON in the _elementor_data field of wp_postmeta, and attackers inject scripts into that JSON, into HTML widgets, templates, popups or Elementor Pro Custom Code. Because none of those are files, a file-based malware scan usually reports the site as clean while the pages keep serving the script.
How do I search Elementor data for malicious code?
Back up the database, then query wp_postmeta where meta_key is _elementor_data for patterns such as script tags, atob, eval, fromCharCode and unfamiliar domains. Remember the JSON escapes slashes, so search domains without them. Check Elementor template posts, Custom Code snippets, revisions and wp_options as well.
Is it safe to edit _elementor_data directly in phpMyAdmin?
Only with care. Prefer deleting the infected widget in the Elementor editor. If you must edit the raw value, copy it out, remove the malicious fragment, validate that it is still valid JSON, and write it back. Never run a bulk search-and-replace across wp_postmeta, because serialized values elsewhere will be corrupted.
Why did the malware come back after I restored a revision?
Revisions keep their own copies of _elementor_data. If the injection happened before the revision you restored, or the attacker edited several revisions, restoring one simply brings the script back. Clean the current version, delete infected revisions, and remove the backdoor or vulnerable plugin that allowed the change.
Is Elementor itself insecure?
Elementor has had serious vulnerabilities, such as the 2022 remote code execution flaw in versions 3.6.0 to 3.6.2, but in practice add-on packs and outdated or nulled copies cause most of the infections I see. Keep Elementor and every add-on updated, remove add-ons you do not use, and never install nulled Pro versions.
More than malware
Most people meet me in an emergency. It isn’t all I do.
I’ve been building and repairing systems since 1995. Whatever brought you here, there’s a good chance I can help with the rest of it too — and you’ll be dealing with the same person either way.
Hacked, but not WordPress?
Joomla, Drupal, Magento, Shopify, PrestaShop, Laravel, Node, IIS and plain HTML — cleaned the same way, priced the same way.
Take a look →Custom builds & AI systems
Plugins, custom applications, website chatbots and automation — built to do exactly what you need, maintained by the person who wrote them.
Take a look →Servers, speed, SEO & accessibility
Migrations, faster load times, technical SEO and accessibility fixes. Measured improvements, with the numbers to show you.
Take a look →Better web hosting
Fast, secure hosting with SSL and backups included at no extra charge. Clear pricing, no long-term contracts, no surprises.
Take a look →Classes & free tools
Rather learn to handle it yourself? I teach this, and I give away the tools I built for my own cleanups.
Take a look →Something else broken?
Half my work is untangling what someone else started, gave up on, or broke. Describe it in plain words and I’ll tell you honestly.
Take a look →Tell me what’s wrong. I’ll tell you what it takes.
No queue, no call centre, no sales pitch — one person who answers, quotes honestly, and does the work.