Database audit fix

How to Secure Web-Based Database Admin Panels on VPS

phpMyAdmin has no access control of its own beyond the database login, so once it sits under a web root it is a public login form for your database and is brute-forced constantly. Put it behind HTTPS, HTTP auth and an IP allowlist, or remove it.

Hiren KalariyaLast reviewed: Sep 25, 2026Check web-db-admin-tools
Medium
severity
No
needs root or sudo
2
results it can return
7 of 7
checks in this audit

Every threshold on this page is transcribed from the database-security-network-isolation audit script that CtrlOps runs, and a build check fails if the two ever disagree. See all 7 Network Isolation checks, or how the audit runs.

Medium severityNo sudo needed

What this check reads

It assembles one list of footprints from five sources: the directories /usr/share/phpmyadmin and /usr/share/phpMyAdmin, a phpmyadmin package reported by dpkg -l or rpm -q, the directory /usr/share/adminer, a process matching pgrep -f pgadmin, and a find across /var/www, /srv/www and /usr/share/nginx at -maxdepth 4 for anything named adminer*.php or phpmyadmin. Those find results are truncated to the first three matches before being added. Nothing in the check tests whether a tool is served, reachable or protected, so the threshold is simply whether that list ends up empty: any single entry produces the WARN, and only an empty list passes.

When it applies

Always runs, needs no root. It looks for a footprint, not a working installation, in five places: the /usr/share/phpmyadmin and /usr/share/phpMyAdmin directories, a phpmyadmin dpkg/rpm package, /usr/share/adminer, a running process matching pgadmin, and files named adminer*.php or directories named phpmyadmin up to four levels under /var/www, /srv/www, /usr/share/nginx (first three matches only). It cannot tell whether the tool is actually served, reachable, or protected - a leftover directory that no vhost exposes still produces WARN, which is why the status is WARN and not FAIL. Tools installed elsewhere, renamed (/var/www/html/db.php), or run in a container are not detected.

What each result means

Result thresholds this check applies
ResultWhenWhat it means
WARNAny footprint foundSomething that looks like a web database console is present and is listed, though the check cannot tell whether it is actually reachable.
PASSNoneNone of the five footprints matched, so no phpMyAdmin, Adminer or pgAdmin was found where the check looks.

Why it matters

Web DB consoles are the single most brute-forced and most CVE-heavy component on a LAMP host (phpMyAdmin has had authentication bypass, CSRF and RCE issues; Adminer had SSRF/file-read bugs). OWASP WSTG-CONF-05 "Enumerate Infrastructure and Application Admin Interfaces"; OWASP Top 10 A05:2021. The phpMyAdmin project itself documents restricting access by IP and HTTPS.

Why it fails, and when it is wrong

  • The package being installed but the vhost alias disabled (a2disconf phpmyadmin) still WARNs; the check looks for presence, not reachability.
  • pgrep -f pgadmin can match unrelated processes whose command line contains "pgadmin" (e.g. a tail -f pgadmin.log).
  • Adminer deployed as a single renamed PHP file (db.php) is not detected.

How to fix it

  • Remove if not needed: apt purge phpmyadmin; delete adminer*.php.
  • Otherwise: serve only over HTTPS, restrict by IP (Require ip / allow), add HTTP basic auth in front, move it off the default path, keep it updated, and consider SSH-tunnelled local access instead of public exposure.
  • phpMyAdmin: set $cfg['AllowArbitraryServer']=false, $cfg['Servers'][$i]['AllowRoot']=false, and use TrustedProxies correctly.

Verify the fix

# Reproduce the footprint search:
ls -d /usr/share/phpmyadmin /usr/share/phpMyAdmin /usr/share/adminer 2>/dev/null
dpkg -l phpmyadmin 2>/dev/null | grep '^ii'; rpm -q phpmyadmin 2>/dev/null
pgrep -af pgadmin
find /var/www /srv/www /usr/share/nginx -maxdepth 4 \( -iname 'adminer*.php' -o -iname 'phpmyadmin' \) 2>/dev/null

# What matters - is it reachable, and is it protected?
curl -sS -o /dev/null -w '%{http_code}\n' https://your-host/phpmyadmin/
curl -sS -o /dev/null -w '%{http_code}\n' https://your-host/adminer.php
# expected: 404 (removed) or 401/403 (behind auth or an IP allowlist)

Debugging

Common after apt install phpmyadmin on a host whose vhost never exposed it. Confirm with the curl checks; a 404 means the immediate risk is low. Purge the package (apt purge phpmyadmin) to clear the finding properly, since a future vhost or alias change can expose it.

It is outside the searched paths, deeper than four levels, renamed to something the patterns miss, or running in a container. Search wider: find / -xdev -iname 'adminer*.php' -o -iname 'phpmyadmin' 2>/dev/null, and check docker ps for phpMyAdmin/pgAdmin images.

The file search reports head -3. Use the find command above for the full list.

The check cannot see access controls, so it will keep warning. Put it behind HTTP auth plus an IP allowlist plus HTTPS, or better, reach it over an SSH tunnel and do not expose it at all; then record the finding as accepted.

The pattern matches any command line containing pgadmin, including a text editor with the word in a filename. Confirm with pgrep -af pgadmin.

Sources

How the script reads this

Next

Re-run the Network Isolation audit after applying the fix and confirm this check moves to PASS. CtrlOps runs all 7 checks over your existing SSH connection and scores the result, so the change is visible without reading another config file.

All 7 Network Isolation fixes
Audit your fleet

Find every one of these on every server, in one click

CtrlOps runs this audit over your existing SSH connection - no agents, no scripts to manage. $7/user/month after a 1 month free trial - no credit card required.

Windows

✓ Start instantly·✓ No credit card·✓ No sneaky autorenewals