I am performing a code audit of an older VB6 application which uses dynamically constructed SQL to execute against the database. While I see this as a SQL injection point, the developer contends that since all the values are in drop-down boxes pulled from the database & there is no user input for these items, there is no risk.

Of course this is trivial for a web app; this question is specifically for applications built using windows forms (VB6/VB.NET/C# client>server type applications). I also realize that if the client can send a SQL string, so can the user (not so SQL injection as poor access control in this case).

I'm looking for a proof-of-concept type of answer (or toolkit) that would allow me to change the windows form values of the running application. Are there any readily available tools, or would this require direct memory manipulation?

2 Answers 2


First of all, direct answer to your specific question: take a look at DDE, this can cause the VB form to change almost anything at runtime.

However, I have a better answer for you:
Odds are the VB client app is not using an encrypted protocol (such as SSL) - you can just intercept the network communications, and alter it on the wire. Or, just craft your own messages and send them to the server yourself. It's a bit fiddly, but not too difficult. Or just use something like OllyDbg to grab the data before it goes down to the wires. (Btw, either way, even if they do encrypt the channel you should be able to get around that, since its encrypted on your client. It is a bit trickier, but still not too difficult. And if you go for OllyDbg the channel encryption is irrelevant.)
In this way it will be possible to perform your SQL Injection, and not even too difficult.

Now, I have an even better answer for you - don't even bother with SQL Injection.
It is very likely, given the simplistic architecture that was common back in VB6 apps, that your client app talks directly to the database. (On the off chance that there is an intermediate server app, this part won't help you).
If that's the case, that means that somewhere in the client app (possibly hardcoded), there are credentials to access the database directly. (If you can't find them, grab them using the previous techniques).
Once you have these credentials - just go directly to the database, using the database vendor's management tool, and have your way with it. The app does not need to be in your way at all.
Not only can you do anything you want with the data and tables, there will be no way to trace this back to you. In fact, it's highly unlikely that it will be possible to prove that anyone did anything wrong... (well, except for the missing data...)

  • 1
    Thanks for DDE - it was the perfect attack channel proof. Though we were using Oracle Advanced Security and user entered credentials, so I couldn't tamper with anything once on the wire, the ability to demonstrate that attack and why the client itself was vulnerable was useful. We couldn't get rid of the VB6 application, but we did change the architecture so that communications take place to a WCF service that validates credentials, user accesses, values passed, etc.
    – iivel
    Oct 19, 2012 at 17:38

The concerns for a compiled Windows application that talks directly to the database are a bit different than for a web app. As you point out in your second paragraph, access control is the real issue here. Why go to the trouble of manipulating the client program or memory if you can talk to the database directly? In reviewing/auditing this kind of application, I would make certain the following items are on whatever checklist you're using -- all of these are also concerns for web apps, but these items would be of particular concern for an app communicating directly with the DB:

  1. Is there an audit trail of who logged in (and out) and when, and from where, and what changes they made? This is crucial especially where there are potential issues with access control (which, again, as you point out is the real issue). This kind of auditing hasn't historically been a strength for most non-enterprisey database servers, but most RDBMS's have included triggers as a feature for some time, which can be leveraged to create audit trails without requiring any extra code in the application. Triggers and stored procedures can even be used to retrofit auditing to legacy apps that weren't crated with it in mind, but this needs to be done carefully, as some older apps -- like ones using DAO for data access, since you mention VB6 -- can be screwed up by triggers in various ways, like returning the insertID of the trigger-generated audit record rather than the created row that fired the trigger off.

  2. Is communication with the DB encrypted? For an internal app a self-signed cert or one from a local CA would often be fine, obviously for public-facing or high-risk apps a certificate from a trusted authority would be preferred, and client certificates as well as server could be considered too. It's easy enough to tell if there's some kind of encryption using Wireshark, which among other things is going to allow you to see not only the actual data returned, but each and every SELECT, INSERT, UPDATE, and DELETE statement used by the app if the connection is not encrypted.

  3. Are users' passwords stored in the DB? If so, are they in plain text, or hashed and salted? IMHO, ideally the application isn't storing or managing passwords at all, and is instead authenticating against LDAP, Active Directory, or some other authentication/user management system that doesn't involve storing passwords in the same DB users use and abuse. However, if they are stored in the DB, blah blah blah really just use bcrypt. :) You may also see some devs attempt to hard-code passwords or keys into the client program to get around this (i.e., hiding some or all of the authentication details from the user to try to hinder them from connecting to the DB outside the app), but this is generally understood to be a Very Bad Idea.

  4. Lastly, one good approach to the access control problem in this instance (without resorting to a proxy or middleware solution) is denying users permission to the tables entirely, and only enabling permission to stored procedures that accept parameters and return, create, or modify the appropriate rows. This admittedly makes for more complicated development, and can still be abused (you would absolutely still want to make sure anything the user inputs directly in the app is parameterized/sanitized), but if the user has full permission on the tables directly, this is the least of your worries -- they don't need to leverage your app to gain access or permission to wreak havoc (as they would need to leverage a web app in a SQL injection vulnerability) because they can do it directly.

As to whether a drop-down needs to be sanitized in the same way as a text box (which was the gist of the original question, after all), I'd say if you're not employing other measures like the ones above, it's like asking if you should lock the upstairs window when the front door is wide open and every user has a key to the gate.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .