// Security · Admin Logins
Suspicious Admin Login Detection
Admin panel logins are high-value targets. Successful logins from unexpected IPs, countries, or times — and failed login floods — are detectable from access logs. This page covers WordPress, generic CMS panels, cPanel/WHM, and phpMyAdmin login analysis.
Admin Login Patterns in Logs
WordPress wp-admin
# Normal wp-admin access (own IP, reasonable rate) 203.0.113.1 - - [10/Apr/2025:09:00:01 +0000] "GET /wp-admin/ HTTP/1.1" 302 0 203.0.113.1 - - [10/Apr/2025:09:00:02 +0000] "GET /wp-login.php HTTP/1.1" 200 4830 203.0.113.1 - - [10/Apr/2025:09:00:10 +0000] "POST /wp-login.php HTTP/1.1" 302 0 # 302 after POST = successful login redirect to /wp-admin/ # Suspicious: successful login from an IP that has never accessed before 91.108.4.77 - - [10/Apr/2025:03:22:44 +0000] "POST /wp-login.php HTTP/1.1" 302 0 91.108.4.77 - - [10/Apr/2025:03:22:44 +0000] "GET /wp-admin/ HTTP/1.1" 200 15200 91.108.4.77 - - [10/Apr/2025:03:22:46 +0000] "GET /wp-admin/plugin-install.php HTTP/1.1" 200 12100 # Red flags: 03:22 local time, Russian IP range, immediately goes to plugin install # Brute force: many POST /wp-login.php with 200 (failed) responses 198.51.100.23 - - [10/Apr/2025:01:00:01 +0000] "POST /wp-login.php HTTP/1.1" 200 4830 198.51.100.23 - - [10/Apr/2025:01:00:02 +0000] "POST /wp-login.php HTTP/1.1" 200 4830 # 200 on POST wp-login = failed login (302 = success). A flood of 200s = brute force
phpMyAdmin
# phpMyAdmin should NEVER be publicly accessible. Any external access is suspicious. 185.220.101.8 - - [10/Apr/2025:04:00:00 +0000] "GET /phpmyadmin/ HTTP/1.1" 200 9821 185.220.101.8 - - [10/Apr/2025:04:00:05 +0000] "POST /phpmyadmin/index.php HTTP/1.1" 302 0 # 302 on phpMyAdmin POST = successful DB login. Immediate data exfiltration risk.
cPanel / WHM
# cPanel login attempts (port 2083 in cPanel logs / /cpanel in proxy setups) 91.108.4.12 - - [10/Apr/2025:02:15:00 +0000] "POST /login/ HTTP/1.1" 200 2100 "-" "Mozilla/5.0" # Check /usr/local/cpanel/logs/login_log for cPanel-specific auth events
Red Flag Indicators
| Indicator | What It Suggests | How to Check |
|---|---|---|
| POST /wp-login.php → 302, new IP never seen before | Successful login with stolen credentials | grep "POST /wp-login.php" log | grep " 302 " |
| Admin login at 2am–5am (off-hours for site timezone) | Attacker in different timezone or automated | Filter log by hour: grep ":0[2-5]:" log | grep wp-admin |
| Login from new country/ASN never seen in 30 days of logs | Compromised credentials from phishing or leak | Run source IPs through whois / ipinfo.io |
| Successful login immediately followed by plugin-install.php | Attacker installing backdoor via plugin | grep "plugin-install\|plugin-editor\|theme-editor" log |
| Successful login then immediate /wp-admin/export.php | Data exfiltration — downloading DB content | grep "export.php\|admin-ajax.*export" log |
| phpMyAdmin 302 from external IP | DB admin interface compromised | Block at firewall; allow only 127.0.0.1 |
| 500+ POST /wp-login.php from single IP in one hour | Brute force attack in progress | grep "POST /wp-login.php" log | awk '{print $1}' | sort | uniq -c | sort -rn |
Detection Commands
bash
LOG=/var/log/nginx/access.log # All IPs that successfully logged into wp-admin (POST → 302) grep "POST /wp-login.php" $LOG | awk '$9=="302" {print $1}' | sort -u # Brute force: IPs with > 20 POST attempts to wp-login grep "POST /wp-login.php" $LOG | awk '{print $1}' | sort | uniq -c | sort -rn | awk '$1 > 20' # Admin activity after successful login (plugin installs, theme edits, exports) grep -E "wp-admin/(plugin-install|plugin-editor|theme-editor|export|options-general)\.php" $LOG # Off-hours wp-admin access (midnight to 5am UTC) grep "wp-admin\|wp-login" $LOG | awk -F':' '$2+0 >= 0 && $2+0 <= 5' # Any access to phpMyAdmin (should be zero from external IPs) grep -iE "/(phpmyadmin|pma|myadmin|mysql|phpmyadmin2)" $LOG | grep -v "^127\.\|^10\.\|^192\.168\." # Lock out admin panel by IP (Nginx config snippet) echo "# Add to nginx server block: location /wp-admin/ { allow 203.0.113.1; # your IP deny all; }"