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 | When | What it means |
|---|---|---|
| WARN | Any footprint found | Something that looks like a web database console is present and is listed, though the check cannot tell whether it is actually reachable. |
| PASS | None | None 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 pgadmincan match unrelated processes whose command line contains "pgadmin" (e.g. atail -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; deleteadminer*.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 useTrustedProxiescorrectly.
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
- phpMyAdmin docs: Securing your phpMyAdmin installation
- phpMyAdmin security announcements
- Adminer security notes
- pgAdmin 4 server deployment (reverse proxy, auth)
- OWASP WSTG-CONF-05 Enumerate Infrastructure and Application Admin Interfaces
- Apache: Require ip / local (mod_authz_core)
- nginx: ngx_http_access_module (allow/deny)
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