Lab 01 Report — SQL Injection (Java
Desktop)
Course: CIS416 — Data and Information Management
Prepared by:
Name ID
Institution:
Imam Abdulrahman bin Faisal University — College of Computer
Science & IT
Date: 30-09-2025
1. Project Summary
The objective of this lab is to build a simple Java desktop application
(Swing) with a login form connected to an SQLite database,
demonstrate at least two SQL Injection attacks against a vulnerable
implementation, and secure the application using effective mitigation
techniques (PreparedStatement and input validation). All steps,
evidence, and explanations are documented in this report.
2. Environment
Operating System: (Windows 11)
JDK: 11+
SQLite JDBC driver: [Link]
Database file: [Link] (MYSQL)
3. Database Setup
SQL script ([Link]):
Create Database UserLogin
CREATE TABLE IF NOT EXISTS users (
username VARCHAR(50) NOT NULL PRIMARY KEY,
userpassword VARCHAR(50)NOT NULL
);
INSERT INTO users (username, password) VALUES ('admin',
'admin123');
INSERT INTO users (username, password) VALUES ('user1',
'password1');
4. Code Overview
4.1 [Link]
Manages MYSQL connection (jdbc:mysql:[Link]).
Initializes the connection.
4.2 [Link]
A simple Swing UI with username and password fields and a login
button.
Builds SQL queries using string concatenation and executes them
with Statement — making it vulnerable to SQL Injection.
4.3 [Link]
Similar UI but uses PreparedStatement and a simple whitelist
input validation for the username, preventing SQL Injection.
5. Vulnerable Application — Attack Execution
(Detailed)
Run the vulnerable application (VulnerableLogin) after
ensuring [Link] is present or allow DBHelper to create it.
5.1 SQL Injection 1 — Authentication Bypass
- Username: ' OR '1'='1' --
- Password: (leave empty)
Why it works:
The constructed query becomes:
SELECT username FROM users WHERE username = '' OR '1'='1' -- '
AND password = '';
The -- turns the remainder into a comment, and the condition '1'='1'
is always true, returning the first user row.
Expected Result: “Login success!” with the first username (e.g.,
admin).
Evidence:
5.2 SQL Injection 2 — Data Extraction using UNION
- Username: ' UNION SELECT password FROM users --
- Password: (leave empty)
Why it works:
The injection appends a UNION clause to include the password column
values in the query result. If column counts/types align, the application
will display stored passwords.
SELECT * FROM users WHERE username = '' UNION SELECT * FROM users
-- AND password = '';
Expected Result:
The application returns passwords (admin) in the output.
Evidence:
6. Secure Application — Mitigations and Testing
6.1 Applied Mitigations
1. PreparedStatement :
Separates SQL structure from user data so inputs cannot change
the query structure.
2. OR Input Validation (Whitelist):
Restrict username characters to a safe pattern [A-Za-z0-9_\-]
{1,30} to block special characters commonly used in injections.
6.2 Testing Steps
Run Secure_Login_UI and retry the same SQL Injections used
against the vulnerable app.
Results: The SQL Injections either fail the input validation or do
not alter the query logic; login attempts do not succeed with
injected payloads.
Evidence:
7. Code Listings (Appendix)
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
public class DBConnection {
/** The URL to connect to the MySQL database */
private static final String URL =
"jdbc:mysql://localhost:3306/userLogin";
/** MySQL database username */
private static final String USER = "root";
/** MySQL database password */
private static final String PASSWORD = "12345";
/**
* Establishes and returns a connection to the MySQL
database.
*
* @return A valid {@link Connection} object to the
database.
* @throws SQLException if a database access error occurs
or the connection URL is invalid.
*/
public static Connection getConnection() throws
SQLException {
return [Link](URL, USER,
PASSWORD);
}
Vulnerable_Login_UI.java
private void login_btnActionPerformed([Link] evt)
{
// 1. Read input directly from the text boxes
String username = user_name_box.getText();
String password = [Link](password_box.getText());
try (Connection conn = [Link]()) {
// 2. VULNERABILITY: Unsafe string concatenation for the SQL
query
String sql = "SELECT * FROM users WHERE user_name = '"+
username + "' AND user_password = '"+ password+"';";
// 3. Statement is used, which does not protect against
injection
Statement stmt = [Link]();
ResultSet rs = [Link](sql);
// 4. Login check
if ([Link]()) {
[Link](this, "welcome
Successfull login " + [Link](1) + "\n\n");
dispose();
} else {
[Link](this, "Invalid
username or password.");
}
} catch (SQLException e) {
[Link](this, "Database
error." + [Link]());
}
Secure_Login_UI.java
private void login_btnActionPerformed([Link] evt)
{
// 1. Read input directly from the text boxes
String username = user_name_box.getText();
String password = [Link](password_box.getText());
try (Connection conn = [Link]()) {
// 2. VULNERABILITY: Unsafe string concatenation for the SQL
query
String sql = "SELECT * FROM users WHERE user_name = '"+
username + "' AND user_password = '"+ password+"';";
// 3. Statement is used, which does not protect against
injection
Statement stmt = [Link]();
ResultSet rs = [Link](sql);
// 4. Login check
if ([Link]()) {
[Link](this, "welcome
Successfull login " + [Link](1) + "\n\n");
dispose();
} else {
[Link](this, "Invalid
username or password.");
}
} catch (SQLException e) {
[Link](this, "Database
8. Conclusion & Security Recommendations
Never store passwords in plain text. Use strong hashing
(bcrypt, argon2) with salt.
Always use parameterized queries (PreparedStatement)
or reputable ORMs that handle sanitization.
Apply least privilege for DB accounts: application user should
have only necessary permissions.
Avoid verbose error messages that reveal SQL structure or
stack traces to end users.
Log and monitor failed login attempts and suspicious patterns.