1

I have taken some search but ether the examples only use one parameter / columnname or they just add Strings together.

I have a table describing projets. There are unchangable columns like an id, projectnumber and such, and several 'dynamic' columns, which a user / admin can add through an interface in the application.

After that a user should see a List of all 'dynamic' Colums, and can decide to display them through checkboxes.

So what I need now, is a query as this

SELECT id, projectname, <LIST_OF_COLUM_NAMES> FROM project

I would like this to be safe from malicious Queries, like someone very clever naming a column

; DELETE TABLE projets --

and then displaying it.

I found several solutions where the querystring is just concatenated ether on the programm side or inside a stored procedure.

I found several examples for stored procedures which get one colum name and create a query statement from it.

I found this article How to pass an array into a SQL Server stored procedure on which I must admit I am not sure if it applies to my problem.

Is there a way to achive this without creating a security risk throug SQL-Injection?

Community
  • 1
  • 1
Lorgarn
  • 136
  • 1
  • 15

2 Answers2

1

There are several easy way to resolve this without risk of sql injection.

  • Write SELECT * FROM query and limit number of columns that are seen on application, this way all columns are returned and it is up to application to decide which ones to display.
  • Instead of passing string of columns to stored procedure, have user pass list of column indexes and based on integer value, you can have dynamic sql that generates SELECT statement only with columns that user wants back.
  • If you just want to display list of columns that exists in a table to the user you should select list of columns from Information Schema Views, this way you are sure which column exists in database.
  • In SQL-Server you can assign parameter datatype of sysname which has is how all system objects names are stored as, this could give you extra data validation.

No matter what you decide to do, you should never concatenate strings in application or stored procedures.

  • Never say never :). Some application needs require it. – Jeremy Jan 13 '15 at 20:03
  • Thanks for you comment. I am posting my approach as an own answer, I would like your comments on if this is a safe way to tackle this problem. – Lorgarn Jan 14 '15 at 10:47
0

I tried to work with the Information Schema Views but I was not able to avoid conatenating Strings alltogether. This is what I came up with:

When the user wants to add a Column he can enter a display name, and select from a range of Datatypes. Then I create an internal unique internal column name (like DATETIME_67).

Then I create my query like this:

String querystring = "ALTER TABLE projects ADD " + internalname + " " + typestring;

Note that the String internalname and typestring are both generated inside my code, with no input from the user (so this should be safe against injection, I guess).

Then I write the internal name and the display name to a lookup table:

String querystring = "INSERT INTO lookup (tablename, displayname) " +
"VALUES (@tablename, @displayname)";
using (SQLCommand command = new SQLCommand(querystring, con)) { //con is a SQLConnection object
  command.Parameters.AddWithValue("@tablename", internalname);
  command.Parameters.AddWithValue("@displayname", displayname);
}

Here the actual Input from the user is inserted, but it is parameterized, so it should also be safe.

When I retrieve the columns I want to display I do also use the (hopefully) safe internal names:

 List<String> selectedColumns; //the list of internal col names   
 String query = "SELECT id, projectnumber, projectname {0} FROM projects"; //projectnumer and name a mandatory fields 
                if (selectedColumns.Count > 0)
                {
                    fieldstring  = String.Join(",", selectedColumns);
                    fieldstring = ", " + fieldstring;
                }
                query = String.Format(query, fieldstring);

Please comment on this. Is is working exactly as I need it. The user can add (and remove) custom field to the datatabe and provide display names for them. He can also define, which of the present custom field are to be displayed, and he can enter data for the created fields. I am just not sure, if this save against malicious injections.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Lorgarn
  • 136
  • 1
  • 15