Autor Tema: Evitar Inyección SQL  (Leído 8740 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Evitar Inyección SQL
« : agosto 29, 2009, 04:40:10 am »
Para poder evitar una inyección SQL desde MySQL necesitas tener un par de cosas en claro, no es nada del otro mundo.

Podemos encontrar buenas referencias de seguridad acá: http://cl.php.net/manual/es/security.database.sql-injection.php

Para comenzar en una query donde ingresamos valores de tipo string siempre se deben ingresar encerradas en comillas simples y los valores numéricos con (int) de la siguiente forma:

Valores Integers
Código: php [Seleccionar]
<?php
if(!$_GET['id'])
 $_GET['id'] = '1'; // Da el valor por defecto

$resultado = mysql_query('
 SELECT *
 FROM noticias
 WHERE ID = \''.(int)$_GET['id'].'\'
', $handle);
.........
?>

Fijense que antepuse (int), de esta forma si la variable es numérica la dejará pasar, en caso contrario el valor cerá cero.

Valores String
Código: php [Seleccionar]
if($_GET['buscar']){
 mysql_query('
  SELECT *
  FROM datos
  WHERE palabra LIKE \'%'.mysql_real_escape_string($_GET['buscar'].'%\'
  LIMIT 0, 30
 ', $handle);
....
}


De todas formas hay que recordar que si queremos procesar una variable con magic quotes activado es recomendable filtrarlas con stripslashses como en este ejemplo:
http://www.webcomparte.com/foro/programacion-en-php/eliminar-magic-quotes-de-forma-rapida/
Código: php [Seleccionar]
<?php
$_GET = stripslashses_gpc($_GET);
$_POST = stripslashses_gpc($_POST);
$_COOKIE = stripslashses_gpc($_COOKIE);
$_SERVER = stripslashses_gpc($_SERVER);
 
function stripslashses_gpc($buffer){
 if(!function_exists('get_magic_quotes_gpc'))
  return $buffer;
 if(get_magic_quotes_gpc()){
  if(is_array($buffer)){
   foreach($buffer as $variable => $valor){
    $temp[$variable] = stripslashses_gpc($valor);
   }
   return $temp;
  }else{
   return stripslashes($buffer);
  }
 }else{
  return $buffer;
 }
}
?>


Eso es todo, no necesitan filtros especiales que borren comillas (es inutil), IDS, expresiones regulares, etc etc etc, es tan simple como utilizar comillas simples para encerrar strings mas mysql_real_escape_string() y si es numérico utilizar (int), eso es todo y cuidarse de los errores que muchos cometen al no darle un limit a sus busquedas de datos dentro de la base de datos ya que si la query contiene %dato% como comodín cualquier atacante podría solicitar un "%" quedando en "%%%" forzando a MySQL que devuelva todos los datos que se encuentren en la base de datos y cuando no tiene limite puede causar que tu servidor colapse o que el script en php almacene demasiada información en sus variables y no pueda ser ejecutado correctamente devido al límite de memoria establecido por script en el archivo de configuraciones de php (php.ini).

Dudas, consultas?
« Última Modificación: marzo 08, 2012, 05:40:29 pm por WHK »
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -
Si has encontrado útil este articulo recuerda que puedes ayudarnos con tu donación voluntaria la cual ayudará al staff y a la mantención del foro.

Desconectado JanW

  • Recién llegado
  • *
  • Mensajes: 7
  • Karma: +0/-0
    • Ver Perfil
Re: Evitar Inyección SQL
« Respuesta #1 : septiembre 13, 2009, 03:11:14 pm »
Buen artículo.
También existen otro función la cual es addslashes, pero varios problemas, uno de estos es que escapa menos carácteres.

Algunos artículos con respeco a lo que dije
> http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
> http://blog.preinheimer.com/index.php?/archives/247-addslashes-vs-mysql_escape_string.html

En el segundo link, hay una tabla donde se muestra las diferencias que hay.

lucas-ruroken

  • Visitante
Re: Evitar Inyección SQL
« Respuesta #2 : octubre 15, 2009, 10:53:23 pm »
sos un capo man, excelente tuto

Gracias me sirve mucho para las cosas qe desarrollo ;D

Desconectado ZharkD

  • Recién llegado
  • *
  • Mensajes: 2
  • Karma: +0/-0
  • CEO, Web Developer & Graphic Designer
    • Ver Perfil
    • CristalByte
Re: Evitar Inyección SQL
« Respuesta #3 : mayo 13, 2010, 06:42:47 pm »
Yo tengo una consulta,

Resulta que estoy interesado en prevenir inyecciones en mi sitio sin embargo, no me queda del todo claro si lo que llevo hasta ahora es suficiente.

Bueno comienzo con mis dudas:
* En tu ejemplo de arriba:
1- Segun revise el magic quotes ya esta obsoleto (segun lei) por lo que el ultimo codigo que proporcionas "se pasaria por alto" cierto?
2- En el caso de las consultas de arriba, que vendria siendo "$handle"?
3- El mysql_real_escape_string($_GET['buscar']), podria ser remplazable por "%s" (no en caso de usar LIKE, sino una comaracion mysql_query(".... WHERE nombre='%s'", mysql_real_escape_string($_GET['nombre']));
4- Recomiendas usar "*" despues de un SELECT? Ya que hace tiempo lei en una pagina que me tope que era conveniente usar algun campo aunque no fuera necesario despues de un SELECT ya que es otro factor para ayudar a prevenir inyecciones.

* En mi caso, tengo un script donde valido las variables que regresan los campos de texto de un formulario despues de "enviarlo" esto es $_POST. Las variables efectivamente son bien aseguradas, sin embargo me entro por la mente que si estas son enviadas "ANTES" de que sean revisadas es posible que entre la inyeccion.
Es decir:
Cita de: ESQUEMA
- Se carga la web
- Se llena el formulario
- Se envia
- Se procesan las instrucciones del formulario (instrucciones para "inyectar" base de datos)
- Entran las instrucciones para validar el formulario (aunque esten incluidas antes de <html>), o al menos eso creo.
- Se carga la web.
Estoy en lo cierto, o me equivoco?

Muchas gracias por tu atencion a este tema.
ZharkD | CristalByte.com
CEO, Web Developer & Graphic Designer
http://CristalByte.com - Web Development & Graphic Design

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Re: Evitar Inyección SQL
« Respuesta #4 : mayo 14, 2010, 02:15:55 am »
Hola

Citar
1- Segun revise el magic quotes ya esta obsoleto (segun lei) por lo que el ultimo codigo que proporcionas "se pasaria por alto" cierto?
así es, lo pasa por alto.

Citar
2- En el caso de las consultas de arriba, que vendria siendo "$handle"?
handle, manejador, manipulador, link, resource, recurso, etc
$handle = mysql_connect('localhost', 'mysql_user', 'mysql_password');

Citar
3- El mysql_real_escape_string($_GET['buscar']), podria ser remplazable por "%s" (no en caso de usar LIKE, sino una comaracion mysql_query(".... WHERE nombre='%s'", mysql_real_escape_string($_GET['nombre']));
da igual.

Citar
4- Recomiendas usar "*" despues de un SELECT? Ya que hace tiempo lei en una pagina que me tope que era conveniente usar algun campo aunque no fuera necesario despues de un SELECT ya que es otro factor para ayudar a prevenir inyecciones.

para nada, todo depende de la query, es simple lenguaje mysql. Si vas a usar * dale LIMIT para limitar la cantidad de resultados. Digamos que te debuelve 10000 resultados, los mostrarás todos o esperarás a que te debuelva los 10000 resultados? eso va a colapsar la conección al servidor mysql asi que es mejor ponerle un limit despues de un * a menos que tenga una cantidad de filas predefinidas y no dinámicas.

saludos.
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -

Desconectado ZharkD

  • Recién llegado
  • *
  • Mensajes: 2
  • Karma: +0/-0
  • CEO, Web Developer & Graphic Designer
    • Ver Perfil
    • CristalByte
Re: Evitar Inyección SQL
« Respuesta #5 : mayo 14, 2010, 10:43:55 am »
Hola

Citar
1- Segun revise el magic quotes ya esta obsoleto (segun lei) por lo que el ultimo codigo que proporcionas "se pasaria por alto" cierto?
así es, lo pasa por alto.

Citar
2- En el caso de las consultas de arriba, que vendria siendo "$handle"?
handle, manejador, manipulador, link, resource, recurso, etc
$handle = mysql_connect('localhost', 'mysql_user', 'mysql_password');

Citar
3- El mysql_real_escape_string($_GET['buscar']), podria ser remplazable por "%s" (no en caso de usar LIKE, sino una comaracion mysql_query(".... WHERE nombre='%s'", mysql_real_escape_string($_GET['nombre']));
da igual.

Citar
4- Recomiendas usar "*" despues de un SELECT? Ya que hace tiempo lei en una pagina que me tope que era conveniente usar algun campo aunque no fuera necesario despues de un SELECT ya que es otro factor para ayudar a prevenir inyecciones.

para nada, todo depende de la query, es simple lenguaje mysql. Si vas a usar * dale LIMIT para limitar la cantidad de resultados. Digamos que te debuelve 10000 resultados, los mostrarás todos o esperarás a que te debuelva los 10000 resultados? eso va a colapsar la conección al servidor mysql asi que es mejor ponerle un limit despues de un * a menos que tenga una cantidad de filas predefinidas y no dinámicas.

saludos.

Ohh,

Muchas gracias por tus respuestas, me han sido muy utiles =D
Podria pasarles la web (una vez que la termine) para que me revisen brevemente si tiene vulnerabilidades de inyeccion?
ZharkD | CristalByte.com
CEO, Web Developer & Graphic Designer
http://CristalByte.com - Web Development & Graphic Design

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Re: Evitar Inyección SQL
« Respuesta #6 : junio 22, 2010, 03:54:24 am »
no hay problema.
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -

Desconectado Awes0mn

  • Recién llegado
  • *
  • Mensajes: 8
  • Karma: +1/-0
    • Ver Perfil
    • Email
Re: Evitar Inyección SQL
« Respuesta #7 : julio 31, 2010, 06:38:27 am »
Esto es muy muy útil,puesto que para un script que ando haciendo,creo que no le añadí seguridad,luego lo miro,lo e ido modificando tanto xD  :mi: :shsh: :md:

colegio

  • Visitante
Re: Evitar Inyección SQL
« Respuesta #8 : agosto 12, 2010, 06:34:01 pm »
Estoy intentando meter en el código la instrucción mysql_real_escape_string para evitar inyeccion sql.
Teniendo en cuenta que no se nada de código, intento hacerlo copiandolo de ejemplos que busco en internet pero siempre me da algún error.
El código de acceso a la base de datos que tengo es este
<?php
mysql_connect("localhost","user","pass");
mysql_select_db('db_datos');
$resultado = mysql_query('select distinct `ID`,`columna1` from `columna2` order by `columna1` limit 0,20');

while($fila = mysql_fetch_array($resultado)){
$i=$fila['ID'];
echo '<a href="http://www.misitio.com/alava/pueblo.php?'.$fila['columna1'].'&amp;id='.$i.'">'.$fila['columna1'].'</a><br>';
}

?>

¿donde tendría que incluir el           mysql_real_escape_string
para evitar la inyección sql y que no me de errores?
Con este código y como están las comillas estaría seguro?
Gracias por vuestra ayuda

Desconectado janito24

  • Usuario constante
  • ***
  • Mensajes: 222
  • Karma: +7/-0
  • Booooooo!
    • Ver Perfil
    • SkyDrive.cl
Re: Evitar Inyección SQL
« Respuesta #9 : agosto 14, 2010, 11:02:51 am »
En las variables de ingreso y consulta a la base de datos que pueda modificar el usuario,  por ejemplo en tu código, en ninguna parte.

colegio

  • Visitante
Re: Evitar Inyección SQL
« Respuesta #10 : agosto 15, 2010, 05:29:15 am »
Gracias janito24
Entonces quieres decir que no es necesario dicha función en mi código?
En mi caso no tengo acceso de usuarios ni para entrar ni para modificar
Solo tenía un fomulario de contacto, donde me entró un código que creo era un intento de inyección y al verlo he retirado el formulario de contacto.
¿Pueden hacer inyección sql si no tengo accesos de usuarios?
Perdona mi ignorancia pero estoy preocupado por la seguridad de la base de datos y la web

Desconectado WHK

  • 吴阿卡
  • Administrador
  • Aportador
  • *****
  • Mensajes: 555
  • Karma: +15/-3
  • Coder
    • Yahoo Instant Messenger - yan_uniko_102
    • Ver Perfil
    • WHK
    • Email
Re:Evitar Inyección SQL
« Respuesta #11 : marzo 08, 2012, 05:39:23 pm »
Agrego al tema un enlace fundamental para su lectura proveniente directamente de php.net:

http://cl.php.net/manual/es/security.database.sql-injection.php
Mi WEB - The Hacktivism is not a crime - Si no lo hago yo, que lo hagan otros -

Desconectado alexander1712

  • Recién llegado
  • *
  • Mensajes: 3
  • Karma: +0/-0
  • [H]arkonnen
    • Ver Perfil
Re:Evitar Inyección SQL
« Respuesta #12 : enero 30, 2013, 09:17:55 pm »
hola! teniendo en cuenta que el post ya tiene unos años, y para agregar unas cosas para cualquier lector que se pase por aquí, decir que en principio la rama de funciones Mysql_ está obsoleta, y en cambio se agregó una rama de funciones Mysqli, que teóricamente y segun php.net es más segura y rápida, además de que otorga una forma más manipulable siendo una funcion que trabaja con objetos.

Tambien quiero decir, que cuando se trata de enteros, forzar el tipo de dato a (int) es la solución ideal a las inyecciones, pero no obstante, cuando se trata de strings, mysql_real_escap_string como ya se sabe desde hace tiempo, es bypasseable, todo esto lo digo porque en estos días ubo un debate muy interesante en un foro afiliado a esta web (underc0de.org) en el cual cada uno exponía sus distintas formas de trabajar.

y tratandose de cadenas de texto, una buena forma es forzando a tipos alfanuméricos, ctype_alnum, pero esto evita guiones, y otro tipo de caracteres por lo que podría ser bastante molestos.

otros an asegurado que pdo es mucho más seguro, la verdad no puedo decir mucho de ello porque nunca usé pdo aunque es algo en lo que estoy trabajando ahora (investigar el funcionamiento y características de pdo).

me gustaría saber tu opinión.

un saludo para todos! y era una simple aclaración para los lectores ya que, creo que el autor de éste post tiene más conocimientos que yo en el área y debe saber más al respecto.
« Última Modificación: enero 30, 2013, 09:31:58 pm por alexander1712 »


. . . . . . . .