No sé solucionar grave error de seguridad en mi programa con MySQL [Soy novato]

Estoy creando un juego en unity, conectado a un servidor local de MySQL.

Vamos a analizar lo que pasa si alguien se registra con este nombre:
a'); INSERT INTO `users` (`id`, `Nombre`) VALUES (NULL, 'jajaja

(A ver, eso por ejemplo no se podría poner ya que tiene un limite de carácteres, pero es de ejemplo.)

El código es este(es el comando que se manda a la base de datos):
Comando = "INSERT INTO `usuarios` (`id`, `Nombre`) VALUES (NULL, '" + NOMBRE+ "'");


Entonces, al final si tenemos en cuenta que el usuario se pone el código anterior, el resultado sería este:

Comando = "INSERT INTO `users` (`id`, `Nombre`) VALUES (NULL, 'a'); INSERT INTO `users` (`id`, `Nombre`) VALUES (NULL, 'jajaja');


A ver, si, el que intente hacer eso, tendrá que saber muchas cosas, como el nombre de la tabla por ejemplo, pero si descubre todo, podría ejecutar algo, o romper el comando en sí.
(Las tablas tienen obviamente más datos, pero dejé solo el ID y el Nombre para que se entendiese más fácilmente)


¿Cómo podría solucionar esto?
¿Prohibiendo carácteres en los nombres? No me gusta mucho prohibir carácteres pero si no queda otra...
No tengo ni idea de como se podría hacer. No se si hay más comandos, ya que no se casi nada de los comandos de MySQL.


Espero haberme expresado bien, y que me puedan ayudar, gracias por leer!
A bote pronto se me ocurre que añadas dos restricciones a la tabla:

- Prohibir valores nulos.
- Expresión regular para los caracteres que dejas introducir o los que quieres prohibir.
Alonso707 escribió:A bote pronto se me ocurre que añadas dos restricciones a la tabla:

- Prohibir valores nulos.
- Expresión regular para los caracteres que dejas introducir o los que quieres prohibir.


Lo que te dicen aqui arriba y luego me miraría como defenderme de "inyección sql"

Saludos.
La idea es no construir una sentencia SQL concatenando cadenas que te lleguen del usuario. Como hablas de Unity, supongo que estás usando C#. En C# (y otros lenguajes), creas el objeto tipo Command con la sentencia base marcando donde irán los valores y entonces añades lo parámetros:
Aquí lo verás bien explicado y con ejemplos: https://docs.microsoft.com/es-es/dotnet ... data-types
Muchas gracias a todos, tendré en cuenta todo lo que me dijeron :)

(Si, uso C#)

@Khin He leído el enlace que me mandaste, aunque lo leeré más atentamente cuando me ponga a programar(ahora no tengo mucho tiempo).
Según lo que he leído, las variables que va a usar MySQL, como el nombre, no se almacenan en Unity, sino en el servidor MySQL. Entonces sería así: ¿No?
Comando = "INSERT INTO `usuarios` (`id`, `Nombre`) VALUES (NULL, @Nombre);

Ese es el comando que se enviará a la base de datos, y entiendo que esta, interpretará el "@Nombre" como la variable ya guardada ( antes de ejecutar esta línea de código).

Entonces, se envía lo que viene a ser la variable "@Nombre", y luego se manda el comando en sí(lo de arriba).
Y de esa manera ya no se podrían inyectar instrucciones, ¿no?

Muchas gracias por todo, cuando tenga tiempo lo confirmaré :)
G44Gonzalo escribió:Según lo que he leído, las variables que va a usar MySQL, como el nombre, no se almacenan en Unity, sino en el servidor MySQL. Entonces sería así: ¿No?
Comando = "INSERT INTO `usuarios` (`id`, `Nombre`) VALUES (NULL, @Nombre);

Ese es el comando que se enviará a la base de datos, y entiendo que esta, interpretará el "@Nombre" como la variable ya guardada ( antes de ejecutar esta línea de código).

Entonces, se envía lo que viene a ser la variable "@Nombre", y luego se manda el comando en sí(lo de arriba).
Y de esa manera ya no se podrían inyectar instrucciones, ¿no?


Más o menos va por ahí, aunque lo de la variable "@Nombre" me confunde un poco, no sé si te refieres a que antes necesitas tener una variable con ese nombre pero no sería el caso, @Nombre es el nombre que le das al parámetro para poder referirte a él después (esto depende del lenguaje o SGBD, en algunos casos la posición de un parámetro se marca con un ?).

Una vez has inicializado el objeto de tipo Command con esa cadena, usas el método Add() o AddWithValue() de su propiedad Parameters para darle valor a ese parámetro, refiriéndote a él por su nombre o por su posición. Creo que también podías especificar el tipo de dato.

Y luego ejecutas el comando. Si el usuario te ha intentado meter código SQL de esta manera lo que pasará es que se guardará en su campo nombre mientras no exceda la longitud límite :p

Si el campo ID lo tienes definido como auto_increment en MySql, puedes escribir el insert obviándolo:
INSERT INTO `usuarios` (`Nombre`) VALUES (@Nombre);
(mensaje borrado)
@Khin Muchisimas gracias por todo, funciona perfecto :)
8 respuestas