2008-12-16 56 views
9

Como el tema sugiere, deseo poder pasar los nombres de tabla como parámetros usando .NET (no importa qué idioma realmente) y SQL Server.Parametrizar el nombre de la tabla en .NET/SQL?

Sé cómo hacer esto para valores, p. command.Parameters.AddWithValue("whatever", whatever) usando @whatever en la consulta para denotar el parámetro. La cuestión es que estoy en una situación en la que deseo poder hacer esto con otras partes de la consulta, como los nombres de columnas y tablas.

Esta no es una situación ideal, pero es una que tengo que usar, no es realmente propensa a la inyección de SQL ya que solo alguien que usa el código puede establecer estos nombres de tabla y no el usuario final. Sin embargo, es desordenado.

Entonces, ¿es posible lo que estoy pidiendo?

EDITAR: Para aclarar el punto acerca de la inyección SQL, los nombres de las tablas solo se transfieren por código fuente, dependiendo de la situación. Es el desarrollador quien especifica esto. El desarrollador tendrá acceso a la capa de la base de datos de todos modos, así que la razón por la que estoy preguntando no es tanto por seguridad sino simplemente para que el código sea más limpio.

Respuesta

3

No piensa He visto esta capacidad en cualquier dialecto SQL que he visto, pero no es un área de especialización.

Sugeriría restringir los caracteres a AZ, az, 0-9, '.', '_' Y '' - y luego usar el paréntesis apropiado para la base de datos (por ejemplo, [] para SQL Server, I creer) para envolver todo el asunto. Luego simplemente colóquelo directamente en el SQL.

No está del todo claro qué quiso decir con que no se trata de un riesgo de inyección SQL. ¿Quiere decir que los nombres estarán en el código fuente y solo en el código fuente? Si es así, estoy de acuerdo que hace las cosas mejor. Es posible que ni siquiera necesite hacer el horquillado automáticamente, si confía en que sus desarrolladores no sean cretinos (deliberadamente o no).

+0

Sí, código fuente y solo en el código fuente. Es para facilitar el trabajo de compilación de instrucciones de actualización/inserción mientras refactorizo ​​esto. – Damien

4

Puede pasar el nombre de la tabla como un parámetro como cualquier otro parámetro. la clave es construir una declaración SQL dinámica, que luego debería considerar si es más fácil construirla en su nivel de aplicación o en los procesos.

create procedure myProc 

@tableName nvarchar(50) 

as 

sp_executesql N'select * from ' + @tablename 

FYI este ejemplo de código de la memoria es echar un vistazo a BOL para la sintaxis correcta de sp_executesql.

También esto es altamente susceptible a la inyección de SQL, ya que indica que no es un problema para usted, pero cualquiera que lea esto debe ser muy cuidadoso de aceptar comentarios de un usuario para generar sus consultas de esta manera.

+0

Seleccionaría * de '+ nombre_table. Ser parametrizado entonces? (usando el código VB.Net, procedimientos no almacenados). – Damien

+0

Si construye la consulta en vb.net, entonces no será necesario parametrizar ninguna @table. Su código vb se vería como sqlString = "select * from" + tableName. Entonces ejecutaría sqlString como usar el objeto de comando. (establecer el tipo de comando a texto) – JoshBerke

3

Los parámetros de consulta SQL solo pueden tomar el lugar de un valor literal. No puede usar un parámetro para un nombre de tabla, nombre de columna, lista de valores u otra sintaxis SQL. Ese es el comportamiento estándar de SQL en todas las marcas de base de datos.

La única manera de hacer dinámico el nombre de la tabla es interpolar una variable en su consulta SQL antes de preparar esa cadena como una instrucción.

Por cierto, te estás engañando a ti mismo si crees que esto no es un riesgo para la inyección de SQL. Si interpola dinámicamente el nombre de la tabla en la consulta, necesita usar delimited identifiers alrededor del nombre de la tabla, del mismo modo que usaría comillas alrededor de una cadena literal que se interpola desde una variable.

5

No se puede parametrizar directamente el nombre de la tabla.Puedes hacerlo indirectamente a través de sp_ExecuteSQL, pero también puedes construir el TSQL (parametrizado) en C# (concatenando el nombre de la tabla pero no los otros valores) y enviarlo como un comando. Obtiene el mismo modelo de seguridad (es decir, necesita SELECT explícito, etc., y asumiendo que no está firmado, etc.).

Además, asegúrese de hacer una lista blanca del nombre de la tabla.

2

La idea de que no es propenso a la inyección de SQL está equivocada. Puede ser menos propenso a la inyección de SQL de los usuarios front-end, pero todavía es mucho más propenso a la inyección SQL. La mayoría de los ataques a las bases de datos provienen del interior de la compañía atacada, no de los usuarios finales.

empleados pueden tener rencores, pueden ser deshonestos, pueden ser contrariado, o simplemente puede no ser tan brillante y pensar que está bien a la seguridad de puente para hacer lo que sea que ELLOS que debería hacerse a la base de datos.

+0

Iba a decir esto, simplemente voté en su lugar. A menos que el parámetro sea una opción codificada, esta es una mala idea. –

+3

Bueno, las personas de la compañía tampoco tendrían acceso. Es solo el método de llamada que podría especificar los nombres de campo y tabla. Realmente, cualquiera que tenga acceso a la lógica de negocios también tendrá acceso al código de acceso a datos, – Damien

0

Por favor, vea este post respuesta por el usuario Vimvq1987: MySqlParameter as TableName

Esencialmente primero se comprueba el nombre de la tabla en el esquema, en el que el nombre de la tabla se utiliza de forma parametrizada. Entonces, si todo está bien, el nombre de la tabla es legítimo.

idea básica es Parafraseado:

SELECT table_name 
    FROM information_schema.tables 
    WHERE table_schema = 'databasename' 
    AND table_name = @table; 

    cmd.Parameters.AddWithValue("@table",TableName); 

Si esto devuelve bien con el nombre de tabla, seguir adelante con su consulta principal ...

0

acabo comprobaría select OBJECT_ID(@tablename) la idea es prevenir inyección sabes que tiene que ser el nombre de la tabla, esto era si esto devuelve un número y luego ejecutaría la consulta real,

Cuestiones relacionadas