Reputation: 7680
I have the following code:
SqlDataAdapter adapter = new SqlDataAdapter("SELECT TOP 0 * FROM [tableName]", conn);
DataTable dt = new DataTable();
adapter.FillSchema(dt, SchemaType.Mapped);
I am using this to build a DataTable
of the table schema.
Normally, when people are asking about SQL injection, they are talking about query params :), my question is about the table name:
SELECT TOP 0 *
FROM [tableName]
[tableName]
is actually going to be dynamic / determined at runtime (this is for a framework btw)...
The tableName
passed into the method is not trusted, so I want to make sure there isn't any funny business going on?
Do I have to manually scrub the table name (and I'm sure I'll miss something)? Or is there a built in method for that? Or somehow to prevent the SQL injection on the table name?
Upvotes: 0
Views: 895
Reputation: 46203
The tableName passed into the method is not trusted, so I want to make sure there isn't any funny business going on?
One method is to first execute a parameterized query, passing the table name as a parameter (nvarchar max length 128) to the QUOTENAME
function:
SELECT QUOTENAME(@TableName) AS ScrubbedTableName;
The returned value can then be used in your TableAdapter query without the risk of SQL injection. However, this will not prevent disclosure of meta data if a table other than one expected is specified.
Upvotes: 1
Reputation: 46
You can keep sqlDataAdapter and use
Adapter.selectcommand.parameters.add(@"whatever", value)
Edit: Sorry! I missed the part about this being related to a table name, this code doesnt work. :( I apologize.
Upvotes: -2
Reputation: 13796
You can use the following query to get a list of all tables in the database and use that as a white list:
SELECT TABLE_NAME FROM <DATABASE_NAME>.INFORMATION_SCHEMA.Tables
WHERE TABLE_TYPE='BASE TABLE'
Replace
<DATABASE_NAME>
with your database name.
If someone attempts to input a table name which is not in that list, then don't execute the query.
Update
As for the "multiple connection strings" case, you can also use a simple query to check the current database name:
SELECT db_name()
So you should be able to easily craft a method that simply gets a list of valid table names from the current database, no matter if the connection-string/db-name is dynamic or not. And in the grand scheme of things, I doubt that these two queries are going to affect the performance of your application, like you said, you could easily cache the table list, if necessary.
Upvotes: 1
Reputation: 45096
You could just go with the rules for valid table names
128 char - letters, numbers, and limited other special characters
In those rules I don't think you could do an injection
CreateTable see table_name
ValidIdentifier
Upvotes: 1