Finding a Hardcoded Database Password in a Web App Config File
O desafio
Voce abriu um shell num servidor web como www-data. A aplicacao le a senha do banco de um arquivo na raiz web. Explore o shell, leia o arquivo certo e envie a senha.
O que você vai aprender
- Recognise where PHP and other web apps store database connection settings
- Use basic shell recon to list the web root and read a config file
- Search source and config for credential keys like db_pass and password
- Explain how a readable config turns web access into database access
- Apply the standard fix: environment variables and a secret manager
Habilidades testadas
Pré-requisitos
- Comfortable with basic shell commands (ls, cat, grep)
- Can read a simple PHP configuration file
Como funciona
Every web application that talks to a database needs a username and password to open that connection. In PHP projects those settings almost always live in a small configuration file - typically config.php - that sits right next to index.php in the web root and is pulled in with require or include. The same pattern shows up everywhere else under different names: settings.py for Django, application.properties for Spring, .env for Node and Laravel, and docker-compose.yml for containerised stacks.
Storing the credential in a file that ships with the app is convenient, but it is also the weakness this challenge exercises. Once you have any read access to that file - a low-privilege shell as the web server user, a path traversal bug, an exposed .git directory, or simply a teammate cloning the repository - the database password is in plain sight. Unlike a stolen session that expires, a leaked database credential often grants direct, persistent access to every row the app can see.
Finding the secret is mostly about knowing where to look. From a shell, the fast path is to list the web directory, spot the config file, and read it; a recursive grep for keywords such as password, passwd, or db_pass surfaces the same value if the filename is not obvious. The credential is stored so the app can send it to the database, so it is kept in plain text, not hashed - which is exactly why reading the file is enough.
Erros comuns
- Hunting for the password in the wrong place. The credential is not in
/etc/passwd(that file holds user accounts, not app secrets) - it lives in the application's own config next to the front controller. - Only checking the obvious file. Credentials are often duplicated in an example config, a backup such as
config.php.bak, or a commented-out line left over from testing. - Ignoring version control history. A password removed from the current file may still sit in an earlier commit, recoverable with the git log.
- Assuming a random-looking value is hashed. A database connection string keeps the password in clear text so the app can authenticate - it is not a one-way hash.
Como se proteger
The durable fix is to keep secrets out of files that ship with the code, so reading the web root never reveals them:
- Load the database credential from an environment variable at runtime instead of hardcoding it in
config.php. - Store and rotate it in a secret manager - a vault service or your cloud provider's secrets store - rather than on disk in the web root.
- Add any secret-bearing file to
.gitignoreand commit only a.env.examplewith placeholder values. - Run a secret-scanning tool in CI so a credential is caught before it ever reaches the remote.
If a credential has already been committed or exposed, treat it as burned and rotate it immediately. Deleting the line is not enough, because the old value remains in the git history and in any backups - change the database password and update the running app to use the new secret.