5

I have to fix a project that is vulnerable to SQL injection.

All the forms in every page on the project do not use parametrized query but simply string query.

For example I have the search page, and looking at the code behind I see that there is a method CreateQuery() that creates the query basing on the text fields as example:

string sQuery = "";
sQuery += "b.name like '%" + txtName.Text + "%'";

Then in the btnSearch_Click() I have the method that does the query:

query = CreateQuery();
var totalList = GetAllBlaBla(query);

My question is:

Since I have hundreds of forms and thousands of formText and values to FIX, is there a "quick" solution to implement like

  1. A global function that parametrizes the query or handle the situation in some way?
  2. Since in every class the query is executed in the SubmitButton_Click() code behind method, can I handle the situation here, of course in every class?
  3. Should I modify every form and every entry in the form codebehind to parametrize the SQL string, that is gonna take one million of years?
  4. (Edit) What about Encode/Decode input values? SO that the example above will be:

    string sQuery = "";
    var txt = var txt = HttpUtility.HtmlEncode(txtName.Text);
    sQuery += "b.name like '%" + txt + "%'";
    

    Is this a possible temporary patch?

5- (Edit) Is this a possible solution, or it simply does not change anything?

        cmd.Parameters.Add("@txtNameParameter", SqlDbType.VarChar);
        cmd.Parameters["@txtNameParameter"].Value = txtName.Text;
        sQuery += "b.name like '%" + (string)cmd.Parameters["@txtNameParameter"].Value + "%'";

The problem is that I have to return a string because the logic that handles the query is defined in another business class that takes a string as a query, I cannot give it a CommandType or SqlDataAdapter...

Suggestion?

Thanks in advance.

Attila
  • 702
  • 1
  • 12
  • 34
  • If you are limited to just a string (no parameters), that is going to be very hard to fix. Can you not propose a change to accept even a single `object` as a query-parameters object? If ou can do *that* you can do it safely (dapper is an example of this - it only needs one `object` to express *all* your parameters). Without that separation, I don't think it can be done *reliably*. note: if you need to "sell" this change, this will also give better performance as it allows query-plan re-use. Better security **and** performance? seems a no-brainer to me. – Marc Gravell Jul 04 '11 at 14:48
  • The logic that handles the query is in another class, so in this class I just get the where clauses from the textFields, I put them in a string and i give this string to the class that is gonna handle the query. Of course I need to make these where clauses sql-injection-proof. So my question is: Is the point 5 a possible solution or it does not change anything? If it does not change anything is there a way to parameterizing the textFields inputs and return a string without exectuing the query? – Attila Jul 04 '11 at 15:06
  • if you ***only*** have a string, then it isn't parameterised and no: IMO cannot be made robustly safe. To be parameterised you need the string *plus* the parameter values. Which needn't be hard - a single object can express them all. – Marc Gravell Jul 04 '11 at 15:51

6 Answers6

4

You already know there is a problem; IMO, any "quick" fix here is likely to reduce the attack surface, but is not likely to prevent determined abuse; simply, blacklisting is truly hard and there are some really bizarre inputs readily available on black-hat (and, as samples, on white-hat) sites. These are not always easily recognizable as abusive. It isn't all ' drop table Customers -- ;p

WHATEVER you do, I would advise doing it properly; parameters. Tools like dapper might reduce the code you need, though:

sQuery += "b.name like '%'+@text+'%'"
...
conn.Execute(sQuery, new {text=txtName.Text});

(which is easier than handling all the parameters etc manually)

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • +1 for dapper. Perfect in this situation. Just don't read the source code, it'll make your head hurt! I'm still taking the tablets :) – Darren Lewis Jul 04 '11 at 12:37
  • I tried to parametize the query but it is quite difficult, the query is built in a class that handles the textfield.values and then call a buildingclass(query) that handles the logic of retrieving the data, so that I cannot use the Parameters.Add in the CreateQuery() function (I guess?) Can you tell me something more about this dapper tool? I haven't find such documentation online. – Attila Jul 04 '11 at 13:26
  • @Attila there are some samples on the project page, here on SO under the "dapper" tag (maybe dapper-dot-net), and the test project. We wrote it to support most scenarios, including parameters you can't predict in advance, etc. Let me know a full example and I can help more – Marc Gravell Jul 04 '11 at 14:39
  • @Daz I may have a somewhat different perspective there :) – Marc Gravell Jul 04 '11 at 14:39
  • I just added the point #5 The problem is that I have to return a string because the logic that handles the query is defined in another business class that takes a string as a query, I cannot give it a CommandType or SqlDataAdapter... – Attila Jul 04 '11 at 14:41
  • @Marc I know, that's why I wrote it :) I recently took a good look at dapper and Massive and liked what I saw in both. – Darren Lewis Jul 04 '11 at 14:45
  • @Daz I like to think of it that "we go to the brink of insanity *so that you don't have to*" :) – Marc Gravell Jul 04 '11 at 14:50
1
  1. Reduce the permissions of the database account that your application uses to access data. Hopefully it doesn't have sysadmin. Remove permissions to drop tables. If the account is used only for data retrieval, remove all permissions to update data. You might even consider setting up views, locking them down, and using them instead of direct table access.

  2. Turn on ASP.NET Request Validation, described here. This automatically checks all traffic for malicious character sequences.

  3. If possible, consider adding an event handler to Global for OnBeginRequest that inspects the incoming data and performs white list checks on all inputs. Not sure how well this maps to your problem but the nice thing is you only have to do it in once place and it will affect the whole site.

  4. Ensure that all of your pages call Page.Validate to ensure that the client-side validation is also enforced on the server side.

  5. Begin the long hard work of adding field-specific white list validation to every control, and figure out a long term plan to move onto parameterized database calls.

John Wu
  • 50,556
  • 8
  • 44
  • 80
1

Modify every query + validate every input.

Takes time but think about the guy who will maintain and add features to that "big web application" (it may be you).

Guillaume
  • 12,824
  • 3
  • 40
  • 48
1
<customErrors mode="On"/> 

This will prevent users to see the errors so a potential hacker would have very few clues how to exploit this security door, based on the error messages he/shes sees
Add Elmah to log errors.
Rewrite every query to use Parameters or use an ORM.
Any javascript based solution is useless, since a "hacker" for sure knows how to disable it.

Adrian Iftode
  • 15,465
  • 4
  • 48
  • 73
1

The Plain Way

Estimate the number of replacements by searching the project for string sQuery = ". Multiply it by the time you plan spending on fixing a single query (e.g. one fix in 5 minutes, plus a coffee break each 10 fixes).

Add time for testing the whole website.

Then tell management the fix is going to be huge, give them the estimate and just do it.
Surely you'll have headaches for a couple of days but at least you'll have the thing working.

The Creative Way

If you literally mean hundreds and thousands of such forms with nearly identical code (e.g. query always created in CreateQuery, executed in SubmitButton_Click), I would consider learning to use Visual Studio regular expression syntax and crafting a couple of very accurate search & replace patterns.

This saved me hours of work in one project, but you'll need to be really precise with regexps and make sure you understand what you're doing.

Another option, again, when you're sure it is worth it, is to write a tool that will rewrite C# sources.
If all you need is a simple transform like the one Marc mentioned, it could take a couple hours of work.
But you can fail miserably here so it's a risky route.

Community
  • 1
  • 1
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • Interesting solution, but I feel it's a bit complicated, since the forms are of all kinds like search, edit, add, retrieve etc the regular expression will be out of my comprehension :/ – Attila Jul 04 '11 at 14:26
-1

find all textbox controls on each page during pageload and disable special keys press handling

Vikky
  • 752
  • 3
  • 15
  • 35