Overcoming rudimentary SQL injection protection

I'm in the process of documenting the many ways in which an application is terrible. One of those ways is that it's vulnerable to SQL injection. It's not completely open, but you can manipulate a few fields together to make a SQL statement that can drop objects, update fields, etc. Selecting additional data may be possible, but it's not likely (and not really a concern at the moment).

The application doubles single quotes (mystr.Replace("'", "''");). It also replaces "+" with a space, and '*', and '%' with an empty string, and it inserts single quotes around commas. I've managed to get around the "*" replacement by using a Unicode character (I don't remember which one offhand) that's not actually "*" but which MSSQL still treats as one. This allows me to do multi-line comments (/* ... */), which lets me break up my statement into several fields, commenting out the additional SQL the application adds. This is important because each of the several fields I'm injecting data into is limited to approximately 40 characters (the length of each specific field varies). I haven't been able to find a similar character to replace + or , though.

What I'm trying to do is append a script tag to a field in every row of the database, and to do that, I need the + operator, which is replaced by a space.

I've looked through all of the vaguely +-like characters I can find, and MSSQL doesn't treat any of them like an actual +. Because of the length limit on each segment, I can't just exec(cast(0x012345... as varchar(8000))) with a really long string.

The application is .NET 1.1, and the SQL server is SQL 2000 with the latest SP.

Maybe I'm missing something here. If this is your app, you should access to the SQL server to update your tables properly, or design a proper admin utility to allow you to do it through the web interface. If this isn't your app, are you really going to ask on the net in a searchable forum for instructions on breaking in? Is there a third option?

The application doubles single quotes (mystr.Replace("'", "''");). It also replaces "+" with a space, and '*', and '%' with an empty string, and it inserts single quotes around commas.

What idiots hire these devs and then let them write unreviewed framework code? I could understand a junior dev doing this if given access, and then I can understand a more senior dev smacking the crap out of him/her and making sure it never happens again.

It's my app in that it's licensed and used by my company, and I'm trying to document for the vendor, the many ways in which it fails.

Find the proper code for SQL injection protection, paste in a document and label it "Correct SQL Injection Protection".

Take their code, paste it in the same document and label it "Incorrect SQL Injection Protection."

Include a snippet from your favorite site listing SQL injection attacks and the cost they have had on the companies infected. Below that, put the amount you pay the vendor in bright red lettering. Something like, "Vendor software (in jeopardy): $50,000".

Half of the failure is in the technical details, the other half is in the sale it's about to cost them.

Unless you have a competitor for whatever they do, you're likely screwed, but good luck!

It's my app in that it's licensed and used by my company, and I'm trying to document for the vendor, the many ways in which it fails.

Find the proper code for SQL injection protection, paste in a document and label it "Correct SQL Injection Protection".

Take their code, paste it in the same document and label it "Incorrect SQL Injection Protection."

Include a snippet from your favorite site listing SQL injection attacks and the cost they have had on the companies infected. Below that, put the amount you pay the vendor in bright red lettering. Something like, "Vendor software (in jeopardy): $50,000".

Half of the failure is in the technical details, the other half is in the sale it's about to cost them.

Unless you have a competitor for whatever they do, you're likely screwed, but good luck!

That's already been done - my management is fully on-board. What I'm trying to do is a severe injection attack as a proof of concept, to demonstrate to the vendor that they really, really need to fix this, and not just hand-wave it as an unlikely scenario. I can already get information that I shouldn't be able to, but I want to move beyond information disclosure, and into exploiting end-users.

Unfortunately, the vendor doesn't really have any competition, so our options are to a) get them to fix the product, or b) roll our own. Option b would be cost prohibitive.

Interestingly, they (unintentionally) make semicolons unavailable. Fortunately (?) MSSQL doesn't require semicolons between statements. You can just string them together with no delimiters at all. I can drop tables, update one column with the value of another, but I can't actually append anything to a column, because the only concatenation operator available to me is +, which I can't use.

No - all of my testing has been with a db_owner account, but the production system does actually run with a pretty limited account. It can still select from all tables, and can insert/update/delete from several others.

I think I've proven the vulnerability sufficiently at this point that the vendor is taking it seriously. I'm curious to see how they fix it. I'm guessing they'll just do some additional character replacements.

No - all of my testing has been with a db_owner account, but the production system does actually run with a pretty limited account. It can still select from all tables, and can insert/update/delete from several others.

I think I've proven the vulnerability sufficiently at this point that the vendor is taking it seriously. I'm curious to see how they fix it. I'm guessing they'll just do some additional character replacements.

They'll do some keyword search/replacement. It'll work for the known and obvious exploits.

It's fundamentally shit however, and if they don't agree to a proper fix they should get their asses kicked.

They'll do some keyword search/replacement. It'll work for the known and obvious exploits.

And this is why you should exploit the minimum, or at least only document the minimum. So when they come back with a patch that "fixes all known vulnerabilities", you can pull an ace out of your sleeve and say, "You categorically did NOT fix SQL injection issues." But like I said - no competition means no real fix.

Have you used google to see who else has the problems? "SQL injection <software name>" probably brings up a few results, you're not the only one with the problem. Though you may be the only one to have cared. Last year I put in an RFE with a vendor to update their gtar. A quick google saw that people were reporting the issue as far back as 2003, and the vendor never fixed it. The bug? In 2012, they were still shipping products with a version of gtar that only supported a maximum filesize of 2GB. Of course, that was at the beginning of 2012 and I'm still waiting for it to make it into production... Anyway, maybe get in touch with a few other complaintants and ask them to submit tickets referencing the same bug ID/trouble ticket/whatever, to help put some pressure on them.

I'm aware of a few dozen other clients of this vendor, and my management sent a message to them to let them know about the vulnerability, and see if any of them have reported similar issues. No responses yet, but I'm sure we'll hear something back by the end of the week.

I did google around for information about the product, but pretty much the only place I found any information was on the vendor's own website.

The nature of the software (and my company's business) is such that most people don't ever look at how secure the software is - they just take it from the vendor, install it, and say "yup, it works." My involvement and subsequent testing was completely accidental; I was asked to change a config file, in which I saw some questionable things, and started digging. Unfortunately, the SQL injection stuff is only about 20% of the overall problems I found.

Edit: And the saddest part is, I only looked at it for about 2 days, and in that short time, found several critical vulnerabilities that the vendor was supposedly unaware of. Without access to the source. And that included about 3/4 of a day coming up with a working proof-of-concept to do SQL injection, beyond just saying "yup, it's injectable." Who knows what a more thorough audit would come up with.

And the saddest part is, I only looked at it for about 2 days, and in that short time, found several critical vulnerabilities that the vendor was supposedly unaware of. Without access to the source. And that included about 3/4 of a day coming up with a working proof-of-concept to do SQL injection, beyond just saying "yup, it's injectable." Who knows what a more thorough audit would come up with.

While sad, this is far from unusual. I would venture that at least 80%* of "vertical market" application/platforms/services exhibit similar faults. Actually, I am somewhat surprised that you didn't find larger, easier to exploit issues.

So much of the "product" in this space is the result of domain experts in other fields deciding that they can "do software" and shatting out a barely-working, un-maintainable excretion that sells a few installations because it actually does one or two things that are helpful.

So much of the "product" in this space is the result of domain experts in other fields deciding that they can "do software" and shatting out a barely-working, un-maintainable excretion that sells a few installations because it actually does one or two things that are helpfulthere are no competitors to compare to.

Which is probably what led to the attempt to "do software" to begin with. It's a vicious circle of suck.

So, I revisited this today after a day off from it, and I managed to concatenate. Turns out there are ~22 characters that are equivalent to "+" when cast from nvarchar to varchar. I realized that I could get that list easily by simply creating a table with every possible nvarchar character in it, and then selecting c, cast(c as varchar), and checking if the cast version was equal to '+'. The same thing works for any other character. Turns out there are more equivalents for asterisks, semicolons, single quotes, etc. So now I can inject pretty much anything I want, with no real limitations except length, and length is a pretty easy one to overcome when you can concatenate.

What is the threat model for the app? The fact that it has abysmal SQL Injection handling may not really matter.

I can't discuss specifics, but it definitely matters. The SQL injection attack opens up the possibility of information disclosure, as well as injecting <script>s into data fields that are displayed in the application, which are not HTML-encoded. Both attacks are being mitigated until the vendor provides a fix, but I'd still rather have more protection than necessary, rather than less.

I can't discuss specifics, but it definitely matters. The SQL injection attack opens up the possibility of information disclosure, as well as injecting <script>s into data fields that are displayed in the application, which are not HTML-encoded. Both attacks are being mitigated until the vendor provides a fix, but I'd still rather have more protection than necessary, rather than less.

Regardless of the possibility of SQL injections, the app should be HTML-escaping data from the database unless you are sure that the data for display doesn't contain HTML entities, in which case you should probably pass that data through a function that blows up when it sees a HTML entity. (Of course you should be validating the data on entry into the system as well.) At that point it's probably just as easy to HTML-escape. Even if your users are honest, you should protect against "honest-but-stupid" adversaries.

100% agree, and the vendor has promised to fix it. Unfortunately for them, I don't think it's going to be as straightforward as one would expect.

It's perfectly straight forward how to fix it. Parameterized Queries. It's just a lot of work.As for output; all output should be filtered for html entities by default, with overrides only on special cases. Completely filtered.Approved entities.All. (Special case; never using user input)

Parameterized queries protect against straight-up SQL injection pretty easily, aside from crazy stored procedures that go on to generate SQL queries as text for whatever stupid reason. They don't at all protect against attacks using the content of the database itself, such as script injection, cross-site scripting (XSS), and cross-site request formatting (CSRF). These are a separate matter, that need to be addressed in their own systematic way. Fixing them and fixing SQL injection aren't lashed together, though.