2010-08-27 18 views
6

Soy un desarrollador de escritorio a escribir para los usuarios internos, así que no estoy preocupado por los hackers, pero me gustaría saber si hay algo que pudieran entrar al actualizar un valor que pudiera ejecutar SQL en el servidor.¿Pueden mis usuarios inyectar mi sql dinámico?

El negocio define su esquema de contenido y tengo una aplicación CRUD para ellos que no tiene que cambiarse cuando cambia su esquema porque los detalles de validación son basados ​​en tablas y las actualizaciones son con SQL dinámico. Tengo que admitir comillas simples en su entrada de datos, así que cuando las ingresan, las doblo antes de que se ejecute SQL en el servidor. Por lo que he leído, sin embargo, esto no debería ser suficiente para detener una inyección.

Así que mi pregunta es, ¿qué texto podrían entran en un campo de texto de forma libre que podría cambiar algo en el servidor en lugar de ser almacenados como un valor literal?

Básicamente, estoy construyendo una instrucción SQL en tiempo de ejecución que sigue el patrón:

actualización de campo de tabla del set = valor donde pkField = pkVal

con este código VB.NET:

Friend Function updateVal(ByVal newVal As String) As Integer 
    Dim params As Collection 
    Dim SQL As String 
    Dim ret As Integer 

    SQL = _updateSQL(newVal) 
    params = New Collection 
    params.Add(SQLClientAccess.instance.sqlParam("@SQL", DbType.String, 0, SQL)) 
    Try 
     ret = SQLClientAccess.instance.execSP("usp_execSQL", params) 
    Catch ex As Exception 
     Throw New Exception(ex.Message) 
    End Try 
    Return ret 
End Function 

Private Function _updateSQL(ByVal newVal As String) As String 
    Dim SQL As String 
    Dim useDelimiter As Boolean = (_formatType = DisplaySet.formatTypes.text) 
    Dim position As Integer = InStr(newVal, "'") 
    Do Until position = 0 
     newVal = Left(newVal, position) + Mid(newVal, position)  ' double embedded single quotes ' 
     position = InStr(position + 2, newVal, "'") 
    Loop 
    If _formatType = DisplaySet.formatTypes.memo Then 
     SQL = "declare @ptrval binary(16)" 
     SQL = SQL & " select @ptrval = textptr(" & _fieldName & ")" 
     SQL = SQL & " from " & _updateTableName & _PKWhereClauses 
     SQL = SQL & " updatetext " & _updateTableName & "." & _fieldName & " @ptrval 0 null '" & newVal & "'" 
    Else 
     SQL = "Update " & _updateTableName & " set " & _fieldName & " = " 
     If useDelimiter Then 
      SQL = SQL & "'" 
     End If 
     SQL = SQL & newVal 
     If useDelimiter Then 
      SQL = SQL & "'" 
     End If 
     SQL = SQL & _PKWhereClauses 
    End If 
    Return SQL 
End Function 

cuando actualice un campo de texto con el valor

Redmond '; drop table OrdersTable--

que genera:

Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3' 

y actualiza el valor al valor literal que entraron.

Qué otra cosa podían entrar en ese inyectaría SQL?

Una vez más, no estoy preocupado de que alguien quiere piratear el servidor en su trabajo, pero me gustaría saber cómo si accidentalmente podrían pegar texto desde otro lugar y romper algo.

Gracias.

+4

"No estoy preocupado de que alguien quiere piratear el servidor en su trabajo" - que es mejor que seas, empleados descontentos hacer atacantes bastante desagradables. –

+4

Si fueras uno, ¿qué sql usarías? – Beth

+1

+1 Para una buena pregunta. Esto es algo que me he preguntado acerca de mí mismo. He visto muchas afirmaciones vagas en los libros de texto acerca de que esto es insuficiente, pero nunca hay ninguna explicación de por qué. Estaría encantado si alguien pudiera responder esto correctamente con un ejemplo definitivo de la entrada del usuario que podría causar un problema. Estoy dispuesto a apostar ahora que esto no va a suceder y completar las respuestas no ** que no abordan la pregunta muy específica ** recomendando SQL parametrizado se votará a la parte superior. –

Respuesta

1

Asumiendo que escapar de las cadenas literales (que a partir de lo que ha dicho que está haciendo), usted debe ser seguro. La única otra cosa en la que puedo pensar es si usa un juego de caracteres basado en Unicode para comunicarse con la base de datos, asegúrese de que las cadenas que envía son válidas en esa codificación.

+0

¿me puede dar un ejemplo de una cadena inválida que puedo intentar pegar en mi cuadro de texto? – Beth

+0

Si intento publicar aquí una cadena no válida, es probable que el sitio la corrija, de modo que UTF-8 no válido no se almacene en la base de datos de StackOverflow.Así que puedo proporcionarle una receta para una cadena no válida, pero en realidad no puedo publicar una. Hay varias formas en que una secuencia de bytes puede no ser válida como UTF-8; ver the wikipedia page. Por ejemplo, un valor de byte de 254 o 255 no puede aparecer en UTF-8 válido. – Hammerite

+0

Los errores de codificación que probablemente le preocupen más son las codificaciones demasiado largas de caracteres ASCII, como la secuencia de bytes (192, 166) (que es una codificación demasiado larga de una comilla simple). – Hammerite

1

Tan feo como su código de duplicación es (: p - Pruebe String.Replace en su lugar.) Estoy bastante seguro de que hará el trabajo.

+1

sí, funciona bien. Sigo escuchando cómo nunca, nunca, nunca utilizará sql dinámico y me gustaría entender mejor por qué, si me ocupo del caso obvio. He leído que el manejo de este caso no es suficiente, pero no se ve el ejemplo que muestra por qué. – Beth

1

La única segura supuesto es que si usted no está utilizando consultas con parámetros (y no estás, exclusivamente, aquí, ya que está concatenando la cadena de entrada en su SQL), entonces usted no está seguro .

+4

Esto no responde la pregunta. ¿Por qué no es seguro? ¿Puedes demostrar esto? –

+0

bien, entonces, ¿qué texto podrían ingresar que afectaría al servidor? – Beth

+2

Consulte http://stackoverflow.com/questions/139199/can-i-protect-against-sql-injection-by-escaping-single-quote-and-surrounding-user para casos teóricos. No dije que no estabas protegido, solo dije que la única suposición * SAFE * es que solo estás seguro si estás usando consultas parametrizadas para TODOS los datos que provienen de los usuarios. – Mark

2

Independientemente de cómo limpiar la entrada del usuario aumentando la superficie de ataque es el problema real con lo que está haciendo. Si mira hacia atrás en el historial de la inyección de SQL, notará que nuevas y aún más creativas formas de causar estragos a través de ellas han surgido con el tiempo. Si bien es posible que haya evitado lo conocido, siempre es lo que está al acecho a la vuelta de la esquina lo que hace que este tipo de código sea difícil de producir. Sería mejor simplemente usar un enfoque diferente.

+0

Entiendo que para una aplicación web donde las actualizaciones están abiertas al mundo, esto tiene sentido, pero lo primero que quieren mis usuarios es tener la aplicación personalizada que necesitan para ver y modificar sus datos, lo que SQL dinámico me permite hacer sin cambiar código cuando su esquema db cambia. – Beth

+0

Entiendo. Otro problema con SQL dinámico es la inyección de caracteres que causan efectos secundarios. Las consultas parametrizadas o el aprovechamiento de LINQ to SQL/Entity Framework solo hacen que su acceso a datos sea a prueba de fallas. –

1

Nunca jamás querrá construir una declaración de SQL usando la entrada del usuario que luego se ejecutará directamente. Esto lleva a ataques de inyección SQL, como has encontrado. Sería trivial para alguien dejar caer una tabla en su base de datos, como usted ha descrito.

Desea utilizar las consultas parametrizadas, donde crea una cadena SQL usando marcadores de posición para los valores, luego pasa los valores para esos parámetros.

utiliza VB que haría algo como:

'Define our sql query' 
Dim sSQL As String = "SELECT FirstName, LastName, Title " & _ 
        "FROM Employees " & _ 
        "WHERE ((EmployeeID > ? AND HireDate > ?) AND Country = ?)" 

'Populate Command Object' 
Dim oCmd As New OledbCommand(sSQL, oCnn) 

'Add up the parameter, associated it with its value' 
oCmd.Parameters.Add("EmployeeID", sEmpId) 
oCmd.Parameters.Add("HireDate", sHireDate) 
oCmd.Parameters.Add("Country", sCountry) 

(ejemplo tomado de here) (tampoco no soy un programador de VB por lo que esto podría no ser la sintaxis correcta, pero se vuelve el punto a través)

+2

@canspice - No creo que hayas leído la pregunta correctamente. No es trivial porque al escapar de la comilla simple, lo que se envía debe tratarse como datos. –

+2

En realidad, estoy tratando de encontrar el ataque. El SQL en la pregunta no causa uno. ¿Puedes producir sql que lo haga? – Beth

+0

Como dije, no soy un programador de VB. ¿Qué hace '_formatType = DisplaySet.formatTypes.text'? ¿Solo establece 'useDelimiter' si la entrada es texto? Supongo que lo que estoy preguntando es "¿cómo' useDelimiter' se establece en falso? " – CanSpice

2

También puede evaluar una solución alternativa. Generación dinámica de SQL con parámetros. Algo como esto:

// snippet just for get the idea 
var parameters = new Dictionary<string, object>(); 
GetParametersFromUI(parameters); 


if (parameters.ContainsKey("@id")) { 
    whereBuilder.Append(" AND id = @id"); 
    cmd.Parameters.AddWithValue("@id", parameters["@id"]); 
} 
... 
+0

Conozco el valor PK porque seleccionaron la fila y la columna para editar, por lo que solo el valor que desean actualizar se transfiere directamente al servidor. – Beth

+0

La razón por la que no estoy haciendo esto es porque quiero un enfoque genérico para las actualizaciones en todo el contenido comercial. Puedo usar este mismo código para cualquier actualización en cualquier campo en cualquier proyecto. La introducción de elementos estáticos significa cambiar/compilar/probar/implementar el código actualizado, lo que quiero evitar si todo lo que hacen es cambiar su esquema de contenido o reglas de validación. – Beth

Cuestiones relacionadas