whiteweb.security / guides / .htpasswd exposed
.htpasswd High severity ~6 min read

My .htpasswd password file got exposed. What should I do?

The .htpasswd file stores the usernames and password hashes for HTTP Basic Authentication. Although the passwords are hashed rather than stored in plaintext, MD5-APR hashes (the most common format) can be cracked rapidly with modern tools. Everyone with an account in that file needs a new password — now.

The hashes are crackable — treat every password in the file as exposed.

Apache's default MD5-APR hash format ($apr1$...) can be tested at millions of candidates per second on consumer hardware. A common password will be cracked in minutes. Even bcrypt hashes buy time rather than true safety. Reset every account.

// the 60-second version

  • Move the .htpasswd file outside the web root and update your Apache config to point to the new path.
  • Reset every password in the file — assume all hashes will be cracked.
  • Check access logs for who downloaded the file and whether they subsequently authenticated.
  • Consider replacing HTTP Basic Auth with a more robust authentication mechanism.

01Understand what .htpasswd contains and how crackable it is

An .htpasswd file looks like this — one line per user, in the format username:hash:

example .htpasswd contents.htpasswd
admin:$apr1$xyz12345$abc...  ← MD5-APR (default htpasswd format)
editor:$2y$10$...             ← bcrypt (much stronger)
deploy:{SHA}W6ph5...          ← SHA-1 (very weak, avoid)
legacy:GHxbUz...              ← DES crypt (extremely weak)

The format matters enormously for how quickly hashes can be cracked:

  • MD5-APR ($apr1$) — the default format created by htpasswd -m. Fast to compute, therefore fast to crack. Millions of candidates per second on a GPU.
  • bcrypt ($2y$) — the recommended format (htpasswd -B). Computationally expensive by design. Much harder to crack at scale, but still offline-crackable with sufficient time and a weak password.
  • SHA-1 ({SHA}) and DES crypt — considered broken. Treat any password with these hashes as already cracked.

Usernames are also exposed. Even if the passwords resist cracking, an attacker now knows valid usernames for the protected area. They can use these for targeted credential stuffing against other services if your users reuse usernames.

02Move the file outside the web root

The immediate fix is to place .htpasswd in a directory that the web server cannot serve. Then update your Apache config to point to the new path:

move .htpasswd and update Apache configbash + apache config
# move the file to a safe location
mv /var/www/html/.htpasswd /etc/apache2/.htpasswd
chmod 640 /etc/apache2/.htpasswd
chown root:www-data /etc/apache2/.htpasswd
update the AuthUserFile path in your vhost/etc/apache2/sites-enabled/…
<Directory "/var/www/html/protected">
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

Reload Apache after making the change: systemctl reload apache2. Verify from an external network that /.htpasswd now returns a 404.

03Reset all passwords in the file

For every user in the .htpasswd file, generate a new password and update the hash. Use bcrypt (-B flag) regardless of what algorithm was used before:

update passwords with bcrypt hashingbash
# update an existing user's password using bcrypt htpasswd -B /etc/apache2/.htpasswd admin # add a new user with bcrypt htpasswd -B /etc/apache2/.htpasswd newuser # verify the file now contains only $2y$ (bcrypt) hashes cat /etc/apache2/.htpasswd

Communicate new credentials to each user via a secure channel — not the same email thread that might be monitored.

04Check access logs for exploitation

Look for two things: who downloaded the file, and whether any successful authentications followed from unfamiliar IP addresses after the download:

find downloads and subsequent auth attemptsbash
# who got a 200 for the .htpasswd file? grep "\.htpasswd" /var/log/apache2/access.log | grep " 200 " # successful auths to the protected area from suspicious IPs grep "/protected/" /var/log/apache2/access.log | grep " 200 " | \ awk '{print $1}' | sort | uniq -c | sort -rn

If you find successful authentications from IPs you don't recognise, investigate what those sessions accessed: look for reads, downloads, or any actions taken in the protected area.

05Consider upgrading to a stronger authentication mechanism

HTTP Basic Authentication protected only by .htpasswd has significant limitations: credentials are sent in every request (though protected by HTTPS), there's no account lockout against brute force, no multi-factor authentication, and no session management. If this protects anything important, consider alternatives:

  • OAuth2 / SSO — integrate with Google, GitHub, or your organisation's identity provider. No local passwords to manage.
  • VPN-only access — for internal tools, restrict access at the network level rather than relying on application authentication.
  • IP allowlisting — for truly restricted areas, combine with Basic Auth as an additional layer.
  • Application-level authentication — move to a full auth system with session management, rate limiting, and MFA support.

Always add .htpasswd to your .gitignore. Password files committed to a repository are an extremely common — and completely avoidable — source of credential exposure.

Was this guide useful?

These playbooks are free to read and share. If a heads-up ever saved you a bad week, you can say thanks — or jump into the other guides.