Introduction
A brute force attack against administrative accounts can trigger account lockout policies, effectively locking out legitimate administrators from the systems they manage. This is a double-impact attack: the attacker attempts to guess credentials while simultaneously denying legitimate access through lockout mechanisms. Recovery requires out-of-band access, careful investigation of the attack source, and strengthening authentication controls.
This attack pattern is particularly effective against organizations that have implemented strict account lockout policies without considering the denial-of-service potential. An attacker can intentionally trigger lockouts by sending a handful of failed login attempts, effectively holding the organization hostage. The recovery process must balance security concerns with the urgent need to restore administrative access.
Symptoms
- Admin accounts locked with
Account locked due to too many failed login attempts /var/log/auth.logshows hundreds of failed login attempts from a single IP- fail2ban or similar tool has blocked IPs but legitimate admin is also affected
- PAM tally shows maximum failed attempts reached
- Application admin panel shows
Account temporarily locked - Users report being unable to log in despite correct credentials
- Security alerts about brute force activity from monitoring tools
- Unusual login patterns in authentication logs from multiple IPs
Additional symptoms to check:
```bash # Check failed login attempts by user sudo lastb | head -20
# Check PAM faillock status sudo faillock
# Check for distributed attacks from multiple IPs sudo grep "Failed password" /var/log/auth.log | \ awk '{print $11}' | sort | uniq -c | sort -rn | head -20
# Check application-level lockouts # For Django: python manage.py shell -c "from django.contrib.auth.models import User; [print(u.username, u.is_active) for u in User.objects.filter(is_superuser=True)]" ```
Common Causes
- SSH or web login exposed to the internet without rate limiting
- Weak or default admin passwords easily guessed by automated tools
- No IP-based access restrictions on admin login endpoints
- Account lockout threshold too low (3-5 attempts) without automatic unlock
- Botnet-based distributed brute force from many source IPs
Step-by-Step Fix
- 1.Unlock the admin account:
- 2.```bash
- 3.# For PAM-based lockout (faillock)
- 4.sudo faillock --user admin --reset
# For PAM tally2 sudo pam_tally2 --user=admin --reset
# For application-level lockout (check the specific application) # Django: python manage.py shell -c "from django.contrib.auth.models import User; u=User.objects.get(username='admin'); u.is_active=True; u.save()" ```
- 1.Identify the attack source and scope:
- 2.```bash
- 3.# Find the top attacking IPs
- 4.sudo grep "Failed password" /var/log/auth.log | \
- 5.awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
# Check the time range of the attack sudo grep "Failed password" /var/log/auth.log | head -1 sudo grep "Failed password" /var/log/auth.log | tail -1 ```
- 1.Block the attacking IPs:
- 2.```bash
- 3.# Block individual IPs
- 4.for ip in $(grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort -u); do
- 5.sudo iptables -A INPUT -s $ip -j DROP
- 6.done
# Or block entire subnets if the attack is from a specific region sudo iptables -A INPUT -s 185.220.101.0/24 -j DROP ```
- 1.Install and configure fail2ban for automated protection:
- 2.```bash
- 3.sudo apt install fail2ban
- 4.sudo nano /etc/fail2ban/jail.local
- 5.
` - 6.Add:
- 7.```ini
- 8.[sshd]
- 9.enabled = true
- 10.maxretry = 3
- 11.bantime = 3600
- 12.findtime = 600
[nginx-http-auth]
enabled = true
maxretry = 3
bantime = 3600
``
bash
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
- 1.Strengthen admin authentication:
- 2.```bash
- 3.# Disable password authentication for SSH
- 4.sudo nano /etc/ssh/sshd_config
- 5.PasswordAuthentication no
- 6.PubkeyAuthentication yes
- 7.PermitRootLogin no
- 8.sudo systemctl restart sshd
# Enable MFA for web admin panels # Implement IP whitelisting for admin access ```
- 1.Implement account lockout policies that do not enable denial-of-service:
- 2.```bash
- 3.# Use progressive delays instead of hard lockouts
- 4.# Configure PAM with pam_faillock:
- 5.sudo nano /etc/security/faillock.conf
- 6.# deny = 5
- 7.# unlock_time = 900 (15 minutes, not permanent)
- 8.# even_deny_root (protect root too)
- 9.
`
Prevention
- Use SSH key-only authentication for all admin accounts
- Implement MFA for all administrative access
- Restrict admin login endpoints to specific IP ranges (VPN, bastion hosts)
- Use fail2ban or cloud-based WAF rate limiting for automated brute force protection
- Implement progressive lockout delays (exponential backoff) instead of permanent lockouts
- Monitor authentication logs for brute force patterns and alert on threshold exceedance
- Use non-obvious admin usernames that don't indicate elevated privileges
- Implement CAPTCHA on web login forms after a few failed attempts
- Set up an out-of-band admin access method for emergency recovery
- Regularly audit user accounts and remove unused admin accounts
Verification
After implementing the fix, verify the security improvements:
```bash # Verify fail2ban is running and configured sudo fail2ban-client status sudo fail2ban-client status sshd
# Check SSH configuration sudo sshd -T | grep -E "passwordauthentication|pubkeyauthentication|permitrootlogin"
# Test account unlock works sudo faillock --user admin --reset sudo faillock --user admin # Should show no failed attempts
# Verify MFA is enabled (if configured) google-authenticator --time-based --force
# Check firewall rules are in place sudo iptables -L INPUT -n -v | head -20
# Verify fail2ban bans are working # (From a test machine, try a few failed logins and check) sudo fail2ban-client status sshd # Should show banned IPs after failed attempts ```
Test the lockout policy:
```bash # From a test machine, verify lockout triggers correctly # After 5 failed attempts, the IP should be banned sudo tail -f /var/log/fail2ban.log
# Verify automatic unlock works # Wait for bantime to expire, then try a correct login ```
Verify monitoring is working:
```bash # Check if log monitoring tools are receiving events grep "Failed password" /var/log/auth.log | tail -5
# Verify alerts would trigger (test with a monitoring check) # Example for a simple script: #!/bin/bash FAILED=$(grep "Failed password" /var/log/auth.log | wc -l) if [ $FAILED -gt 100 ]; then echo "WARNING: High number of failed login attempts: $FAILED" fi ```
Related Articles
- [Fix Fix Admin Panel Blocked After Malware Cleanup Issue in Security Recovery](fix-admin-panel-blocked-after-malware-cleanup)
- [Fix Fix Admin Password Reset Email Sent To Attacker Issue in Security Recovery](fix-admin-password-reset-email-sent-to-attacker)
- [Fix Fix Adminer Or Phpmyadmin Exposed Publicly Issue in Security Recovery](fix-adminer-or-phpmyadmin-exposed-publicly)
- [Fix Fix Apache Mod Security False Positive Admin Issue in Security Recovery](fix-apache-mod-security-false-positive-admin)
- [Fix Apache mod_security False Positive Blocking Admin (security recovery variant 2)](fix-apache-mod-security-false-positive-blocking-admin)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Security Brute Force Attack Locking Out Admin Accounts", "description": "Recover from brute force attacks locking out admin accounts. Learn to unlock accounts, block attackers, and implement stronger authentication controls.", "url": "https://www.fixwikihub.com/security-brute-force-attack-locking-out-admin-accounts", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-01-07T21:13:43.417Z", "dateModified": "2026-01-07T21:13:43.417Z" } </script>