PortSwigger Academy - Source Code Disclosure via Backup Files
This lab leaks its source code via backup files in a hidden directory. To solve the lab, identify and submit the database password, which is hard-coded in the leaked source code.

Lab Overview
❓ This lab leaks its source code via backup files in a hidden directory. To solve the lab, identify and submit the database password, which is hard-coded in the leaked source code.
Instructions
To solve the lab:
- Identify and submit the database password
Source code disclosure vulnerabilities can have devastating consequences, especially when sensitive information, such as database credentials, are exposed. This write-up explores how such vulnerabilities occur, their implications, and how attackers exploit them.
Discovery Process
To identify the vulnerability, I used tools like Dirbuster and Gobuster to enumerate directories and files. During the scan, I discovered a /backup
directory:
This directory contains a file named ProductTemplate.java.bak
. This file, a backup of the Java source code, was publicly accessible and unprotected. Upon inspecting the file, I found sensitive hardcoded credentials within the source code:
"postgres" - Username
"xlf0wurkoxlq7zmu55auymt1g2gvgvr4" - Password
This username and password can be found by conducting code analysis on the Java backup file (see below) and is used to connect to the database. These hard-coded credentials provide attackers with direct access to the underlying data via the PostgreSQL driver.
Code Analysis
Below is an excerpt from the ProductTemplate.java.bak
file:
package data.productcatalog;
import common.db.JdbcConnectionBuilder;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ProductTemplate implements Serializable {
static final long serialVersionUID = 1L;
private final String id;
private transient Product product;
public ProductTemplate(String id) {
this.id = id;
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
ConnectionBuilder connectionBuilder = ConnectionBuilder.from(
"org.postgresql.Driver",
"postgresql",
"localhost",
5432,
"postgres",
"postgres",
"xlf0wurkoxlq7zmu55auymt1g2gvgvr4"
).withAutoCommit();
try {
Connection connect = connectionBuilder.connect(30);
String sql = String.format("SELECT * FROM products WHERE id = '%s' LIMIT 1", id);
Statement statement = connect.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if (!resultSet.next()) {
return;
}
product = Product.from(resultSet);
} catch (SQLException e) {
throw new IOException(e);
}
}
public String getId() {
return id;
}
public Product getProduct() {
return product;
}
}
Upon reviewing the code, the connectionBuilder
object is passed various parameters which appear to be database credentials.
ConnectionBuilder connectionBuilder = ConnectionBuilder.from(
"org.postgresql.Driver", // Database driver (PostgreSQL)
"postgresql", // Database type
"localhost", // Database host (running locally)
5432, // Port number (default for PostgreSQL)
"postgres", // Database name
"postgres", // Username
"xlf0wurkoxlq7zmu55auymt1g2gvgvr4" // Password (hardcoded, security risk)
).withAutoCommit();
The values from this coonnectionBuilder
object are then used to establish a connection to the database using the connect
object.
try {
Connection connect = connectionBuilder.connect(30);
Why It’s Vulnerable
1. Exposed Backup Files
The /backup
directory is publicly accessible, and directory indexing is enabled. This oversight allows attackers to enumerate and retrieve files within the directory easily. Files with extensions like .bak
, .old
, .tmp
, or .zip
often contain sensitive information and are commonly left behind during development.
2. Hardcoded Credentials in Source Code
The backup file contains the following hardcoded database username and password:
"postgres" - Username
"xlf0wurkoxlq7zmu55auymt1g2gvgvr4" - Password
This practice is inherently insecure because:
- Anyone with access to the file can extract these credentials and connect to the database.
Example using psql command-line client, which is included in PostgreSQL installations:
psql -h localhost -p 5432 -U postgres -d postgres
-h localhost: The hostname or IP address of the database server.
-p 5432: The port number (default is 5432 for PostgreSQL).
-U postgres: The username (postgres in this case).
-d postgres: The database name.
- Hardcoding secrets in source code increases the likelihood of exposure during a breach.
3. Lack of Access Controls
No authentication or authorization is required to access the /backup
directory or the files within it. This makes it easy for attackers to exploit the vulnerability.
4. Directory Indexing Enabled
The /backup
directory has directory indexing enabled, as shown by the HTML response. This enables attackers to list and retrieve files directly.
The Impact
Using the hardcoded database credentials, an attacker can:
- Gain unauthorized access to sensitive data stored in the database.
- Manipulate or delete records, leading to data integrity issues.
- Use the compromised credentials to pivot further into the system.