The file scanner reports a clean account, yet the site still sends visitors to a pharma
redirect. That pattern almost always means the payload is in the database: a <script>
injected into wp_posts.post_content, a rogue URL in wp_options, or a base64 blob in a
widget setting. Imunify360's file scanner cannot see any of it. The Malware Database
Scanner (MDS) can.
This guide covers how to enable MDS server-wide, read its detections, run the
imunify_dbscan CLI against a single site when you need control, and undo a cleanup that
broke something. It assumes Imunify360 is already installed. If it isn't, start with
installing Imunify360 on cPanel or the
Plesk equivalent.
What MDS scans and what it skips
MDS connects to the application's MySQL or MariaDB database and matches row content
against a dedicated signature set (mds-ai-bolit-hoster.db for detection,
mds-procu2.db for cleanup). Its main target is client-side malware: injected JavaScript,
hidden links, SEO spam, and redirects. Since the aibolit-32.1.11 package it also has
better coverage for PHP code stored in the database.
Hard limits worth knowing before you rely on it:
- Supported applications: WordPress, Joomla, and Magento 2. Drupal, PrestaShop, OpenCart, and custom apps are not scanned.
- Database engine: MySQL or MariaDB 5.5 or later; 5.6+ recommended. Every supported cPanel or Plesk install already meets this.
- Discovery is config-driven. MDS finds databases by parsing
wp-config.php,configuration.php, orapp/etc/env.php. A WordPress whose config sits one level above the docroot, or that reads credentials from environment variables, may not be found automatically.
Enable MDS server-wide
MDS has shipped enabled by default on new installs since Imunify360 6.12. Older servers that were upgraded in place often still have it off. Check and enable it:
imunify360-agent config show | grep -A2 MALWARE_DATABASE_SCAN
imunify360-agent config update '{"MALWARE_DATABASE_SCAN": {"enable": true}}'
In the UI, the same switch is under Imunify360 → Settings → Malware → Malware Database Scanner. Once it is on, every background user scan also queues a database scan for that user's supported applications. You don't have to schedule it separately; it runs on whatever cadence you set under Background Scanning.
Read database detections
DB hits appear on the same Imunify360 → Malware Scanner → Malicious tab as file hits. Filter by the Type column, which shows Malware Database Scanner instead of Malware Scanner. Each entry identifies the database and table, and current versions show a preview snippet of the matched content. That preview is the quickest way to confirm a true positive before you clean anything.
Signature IDs follow the same scheme as file detections. CMW means client malware,
which covers almost every DB hit, and INJ means injection into otherwise legitimate
content. A row flagged CMW-INJ-… in wp_posts is a classic injected-script infection.
To exclude a database from scanning, for example a staging copy that holds known-bad content for a forensic case, add it on the Ignore List tab with the DB type and the application path as the value. Use the directory that holds the config file, not the database name:
/home/acmeshop/public_html
Wildcards are not accepted.
Run MDS by hand against one site
The UI path is fine for fleet-wide coverage. During an incident you want a scan of one
database, now, with a report you can read. The CLI tool lives at
/opt/ai-bolit/imunify_dbscan.php and must run through the bundled wrapper.
Step 1 — Scan only
--scan is read-only. Chain --search-configs with --creds-from-xargs so MDS finds the
config and pulls the credentials itself. Nothing ends up in shell history.
mkdir -p /root/mds/acmeshop && cd /root/mds/acmeshop
/opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--search-configs /home/acmeshop/public_html \
| xargs -n1 /opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--creds-from-xargs \
--avdb=/var/imunify360/files/sigs/v1/aibolit/mds-ai-bolit-hoster.db \
--report-file="$(pwd)/report.json" \
--log-level=ALL --log-file="$(pwd)/log.txt" \
--scan
On Plesk, point --search-configs at /var/www/vhosts/acmeshop.com/httpdocs.
When credentials are not discoverable, pass them explicitly and pipe the password on stdin:
printf '%s' "$DB_PASS" | /opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--host=localhost --port=3306 --login=acmeshop_wp --password-from-stdin \
--database=acmeshop_wp --prefix=wp_ \
--avdb=/var/imunify360/files/sigs/v1/aibolit/mds-ai-bolit-hoster.db \
--report-file="$(pwd)/report.json" \
--scan
Set --prefix correctly. Hardened installs often use something other than wp_, and a
wrong prefix finishes "clean" without scanning anything.
Step 2 — Clean with a backup
--clean includes the scan, so you don't need to repeat Step 1. Add the cleanup signature
database and an explicit backup path:
/opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--search-configs /home/acmeshop/public_html \
| xargs -n1 /opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--creds-from-xargs \
--avdb=/var/imunify360/files/sigs/v1/aibolit/mds-ai-bolit-hoster.db \
--procudb=/var/imunify360/files/sigs/v1/aibolit/mds-procu2.db \
--report-file="$(pwd)/report.json" \
--backup-file="$(pwd)/mds_backup_acmeshop.csv" \
--clean
report.json lists each affected table, row, and signature. The CSV holds the original
row content before cleanup.
Step 3 — Roll back if the cleanup broke the site
Cleanup occasionally strips legitimate inline JavaScript, most often from page-builder
content or tracking snippets stored in wp_options. Restore exactly the rows MDS touched:
printf '%s' "$DB_PASS" | /opt/ai-bolit/wrapper /opt/ai-bolit/imunify_dbscan.php \
--port=3306 --login=acmeshop_wp --password-from-stdin --database=acmeshop_wp \
--report-file="$(pwd)/restore.json" \
--restore="$(pwd)/mds_backup_acmeshop.csv"
Then remove the malicious portion of that one row by hand, and submit the false positive so the signature is fixed at the source.
Verify detection with the test signature
MDS ships an EICAR-style test signature, SMW-INJ-16483-eicar.tst.mds. Use it on a
throwaway WordPress install to prove the pipeline works end to end before you trust it in
an incident:
UPDATE wp_posts
SET post_content = '<script>X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-MDS-ANTIVIRUS-TEST-FILE!$H+H*'
WHERE ID = 1;
Run the Step 1 scan. The report should show the row in wp_posts. Run Step 2 and the
content is cleaned. If the scan comes back empty, check discovery and the table prefix
before you suspect the signatures.
Where MDS fits in the cleanup workflow
Treat MDS as one stage of the response, not the whole of it. The sequence that holds up on shared servers:
- File scan and cleanup, as in the Imunify360 malware cleanup workflow.
- MDS scan, then
--cleanwith a backup. - Persistence hunt for admin users, cron hooks, and
mu-plugins. - Credential rotation, covering the DB password and WordPress salts.
- Turn on ProactiveDefense and the WAF virtual patching rules so the same plugin hole can't be used again.
MDS runs as part of the existing Imunify360 scanner, so it needs no separate license. If the server isn't covered yet, an Imunify360 license includes it along with the rest of the stack.
How do I scan a WordPress database for malware with Imunify360?+
Which CMS databases does Imunify360 MDS support?+
Can I undo an Imunify360 database cleanup?+
Why does Imunify360 say the site is clean when it still redirects?+
Is the Imunify360 Malware Database Scanner enabled by default?+
Next steps
- Work through the full incident runbook in Imunify360 malware cleanup and reinfection workflow.
- Keep the agent commands to hand with the imunify360-agent CLI reference.
- If you are still choosing a product, see Imunify AV vs AV+ vs Imunify360 or Imunify360 pricing.