Foros del Web » Programando para Internet » PHP »

¿Es sql inyection? ¿Cómo lo han hecho?

Estas en el tema de ¿Es sql inyection? ¿Cómo lo han hecho? en el foro de PHP en Foros del Web. Hola a todos: El problema es que en una tabla SQL (con pocos registros) han desaparecido todos y en su lugar han aparecido registros duplicados: ...
  #1 (permalink)  
Antiguo 26/10/2005, 15:08
 
Fecha de Ingreso: mayo-2004
Mensajes: 393
Antigüedad: 13 años, 7 meses
Puntos: 0
¿Es sql inyection? ¿Cómo lo han hecho?

Hola a todos:

El problema es que en una tabla SQL (con pocos registros) han desaparecido todos y en su lugar han aparecido registros duplicados: mismo nombre, email, etc. Sin embargo, la fecha de alta (se genera en la página php) no parece que se haya modificado.

Lo que sí queda registrado es que en la misma fecha (ayer) los registros se han modificado.

He oido hablar Sql inyection y he puesto alguna seguridad en varias partes de la web.

¿Os parece que pueda tratarse lo que comento de un ataque Sql inyection?

Yo no sabía que un ataque de este tipo pudiera no solo borrar, sino modificar algunos campos y mantener otros.

Por eso tengo la duda de lo que pueda ser. Porque si no es un ataque, lo único que se me ocurre es un fallo en el servidor.

La configuración en el servidor dice:

magic_quotes_gpc On On
magic_quotes_runtime Off Off
magic_quotes_sybase Off Off


Por favor, decidme algo. Gracias
  #2 (permalink)  
Antiguo 26/10/2005, 17:18
 
Fecha de Ingreso: junio-2005
Mensajes: 981
Antigüedad: 12 años, 6 meses
Puntos: 2
Decirte que es un ataque, puede ser, un error, puede ser no se te puede decir si fue o no con el simple echo de preguntarlo. Para obtener este tipo de informacion son buenas costumbres guardar ip's y ya que te dice cuando fueron modificados a tal hora fijar y comparar y ver si tenes visitas en esa hora o demas, tambien una fuente para saber esto es el hackear tu mismo tu pagina revisar por donde pudieron ingresar ese tipo de cosas y demas y ver si tenes alguna falla de seguridad grande. Otra cosa tambien es el echo en que parte de tu pagina se ingresan o modifican valores sobre esa tabla, si es en una seccion sola, enfocar tu investigacion en esa seccion. Tambien verificar que nunca has agregado directamente a una consulta variables como $_GET[''] o que no has ingresado una variable sin ningun y tipo de chequeo. Tambien tienes que considerar de sacar todos los datos posible y despues arreglar el problema y dejarlo como antes de que ocurriese, y si pasan unos dias y vuelve a pasar exactamente lo mismo, considera en empezar a rediseñar la pagina.

Saludos y espero que te sirva de algo.
  #3 (permalink)  
Antiguo 26/10/2005, 17:35
Avatar de Master Solution  
Fecha de Ingreso: octubre-2005
Mensajes: 51
Antigüedad: 12 años, 2 meses
Puntos: 1
Habria que ver mas como es que quedo la tabla al principio, y al final.

Pero, traquilamente podria haber sido, mediante SQL Injection se pueden hacer monton de cosas en las bases de datos, casi las misma que podes hacer vos al escribir el codigo, siempre dependiendo de varios factores, pero es muy amplio el abanico de posibilidades de cosas que podes hacer.

Ahora, segun la configuracion del servidor, te esta protegiendo de este tipo de ataques, pero igualmente habria que revisar el codigo, si es que por mas proteccion que tengas del servidor, la estes haciendo obsoleta en tu aplicacion.
__________________
-=[ 3KLabs ]=-
-=[ Diseño - Programación - Desarrollo ]=-
-=[ Posicionamiento en Buscadores ]=-
-=[ Hosting de Calidad ]=-
  #4 (permalink)  
Antiguo 27/10/2005, 03:01
 
Fecha de Ingreso: mayo-2004
Mensajes: 393
Antigüedad: 13 años, 7 meses
Puntos: 0
Muchas gracias por responder.

Descarto que sea un error por lo que dice Master Solution. Además, los técnicos del hosting me han dicho que no es posible entrar a no ser que algún script permita acceder a la tabla o que alguien conozca las contraseñas de la BD.

Así que el problema debe estar en la página. Os explico la estructura y la forma en que he pensado investigar los fallos de seguridad para ver qué os parece.

Es una página de Usuarios. Pueden: 1.- Darse de alta. 2.- Pedir que se les envíe su contraseña olvidada. 3.- Ingresar en en su zona y modificar sus datos y preferencias.

Como en la tabla han dejado dos campos sin modificar (la fecha de registro y un número de usuario que se genera con rand), pienso que pueden haber accedido mediante un usuario y contraseña válido o haber obtenido todas las claves y luego haber modificado los datos de los (pocos) usuarios que había.

Porque si no fuese así, ¿por qué no atacar directamente borrando toda la tabla?. Esto es sólo una suposición para fijarme un punto de partida. ¿Os parece adecuado que empiece por ahi?.

Si no me decís lo contrario, empezaré investigando el acceso de Usuarios.

1.- Cuando piden la contraseña olvidada desde la página recuperapas.php:

Código PHP:
<form action="enviarpas.php\" method=\"post\">
<input size=\"25\" type=\"text\" name=\"email\"> 
Se accede a enviarpas.php

En enviarpas.php:
Código PHP:
include("conexion.php");
// Verifica si $email está en la tabla 
$result = @mysql_query("SELECT *FROM tablausuarios WHERE email='$email'");  
if (!
$result) { 
echo(
"<p>Error al seleccionar tabla: " mysql_error() . "</p>"); 
exit(); 

//Se comprueba si existe el email
$sql_check_num mysql_num_rows($result); 
if(
$sql_check_num == 0){ 
echo 
"El email introducido no es correcto";
exit();
}
// Si el email existe saca los datos de la fila de la tabla
while ( $row mysql_fetch_array($result) ) { 
$email $row["email"]; 
$password $row ["password"]; 
$nombre $row ["nombre"];
$apellidos $row ["apellidos"];

// Se crea un correo y se envía 
En este script acabo de ver dos cosas:

1.- No verifico que $email, que llega por URL, sea la posteada.
Quizá faltaría:
Código PHP:
$email$_POST['email']; 
¿Aumentaría así la seguridad?

2.- También veo que hago dos comprobaciones del email. Una de ellas podría suprimirse.

Como véis, aquí no utilizo sesiones. Lo único que se me ocurre es asegurarme de que la variable llegue vía POST.

1.- Cuando acceden con su email y contraseña:
Código PHP:
<input type="text\" size=\"15\" name=\"email\">
<input type=\"text\" size=\"15\" name=\"password\"> 
Esto les lleva a la página control.php:
Código PHP:
include("conexion.php");
//Busca email y contraseña
$ssql "SELECT * FROM tablausuarios  WHERE email='$email' and password='$password'";
$rs mysql_query($ssql,$conn);
//vemos si el usuario y contraseña es válido 
if (mysql_num_rows($rs)!=0)
{
 
//usuario y contraseña válidos 
    //Se define una sesion y se guardan datos 
    
session_start();
    
$_SESSION['validado']= "SI";
    
$_SESSION['email']= "$email"
    
header("Location: paginausuario.php"); 
}
else
{
echo 
"Claves de acceso incorrectas";

Como se ve es un script muy usado. No se si tiene problemas de seguridad.
A mí se me ocurre que podría verificar el origen de las variables que llegan haciendo al principio:
Código PHP:
$email$_POST['email'];
$password$_POST['password']; 
¿Aumentaría esto la seguridad?

paginausuario.php incluye este archivo (seguridad.php):
Código PHP:
<?php
session_start
();
$var1 $_SESSION["validado"]; 
if (
$var1 != "SI") {       
echo 
"No tiene autorización para entrar directamente a esta página
  o se ha producido un error en la autentificación"
;
//Y se destruye la sesion
 
session_destroy();
exit();  
}     
?>
Y paginausuario.php permite modificar los datos a los usuarios y es así:
Código PHP:
<?php 
session_start
();
//pasa por el archivo que he comentado antes
include ("seguridad.php");
include(
"conexion.php"); 
$sqlmysql_query("SELECT * FROM tablausuarios WHERE email='$email'");
while (
$row mysql_fetch_array($sql) )
{
//recoge las variable obtenidas
$variable1 $row[variable1];
$variable2 $row[variable2];
//Las presenta en una tabla con formulario
<input type="text\" size=\"25\" name=\"nombre\" value=\"$nombre\">
etc....
//y las envía a procesa.php 
}
procesa.php es así:

Código PHP:
<?php
session_start
();
include (
"seguridad.php");
//Comprueba que los campos los haya escrito bien (email, teléfono, etc)
//Si pasa estos filtros, actualiza la tabla
include("conexion.php"); 
$sSQL="UPDATE tablausuarios SET  nombre='$nombre',..............fechaactual='$fecha' WHERE usuario ='$usuario'";
mysql_db_query("basedatos",$sSQL);
?>
No sé si podría aumentar la seguridad en esta parte controlando la sesión.

¿Qué pensais?

Perdonad lo extenso del post. He tratado de reducir el código al máximo dejando lo esencial.

Os agradeceré mucho vuestros consejos.

Gracias.
  #5 (permalink)  
Antiguo 27/10/2005, 04:49
Avatar de jpinedo
Colaborador
 
Fecha de Ingreso: septiembre-2003
Ubicación: Lima, Perú
Mensajes: 3.120
Antigüedad: 14 años, 2 meses
Puntos: 41
Hola:

Un par de cosas "al vuelo":
- Definitivamente tienes que verificar el origen de las variables. Pero no es suficiente. Nunca está de más hacer una "limpieza" a las variables que llegan, por ejemplo con settype() o revisando que no contengan caracteres o cadenas indeseadas (como UNION, por ejemplo).

- Tampoco es buena idea andar "despilfarrando" el mysql_error(). Esto, ante cualquier error, muestra información sobre tu base de datos (nombres de bases de datos, tablas, campos, etc.) a cualquiera que esté enfrente. En etapa de desarrollo, es buena idea porque te ayuda a descubrir errores y depurar fácilmente, pero luego quítalo. Una buena idea puede ser manejar una variable en tu archivo de configuración como ésta:
Código PHP:
$mostrar_errores_sql false// o true. 
y en tus comprobaciones de error puedes hacer algo como:
Código PHP:
$result = @mysql_query("SELECT *FROM tablausuarios WHERE email='$email'");  
if (!
$result && $mostrar_errores_sql) {
echo(
"<p>Error al seleccionar tabla: " mysql_error() . "</p>"); 
De esa manera, sólo se mostrarán los errores, cuando tengas esa variable en "true".

Por cierto, no lo he comprobado, pero "SELECT *FROM" ¿no da error al faltar el espacio entre el * y el FROM?

Saludos
  #6 (permalink)  
Antiguo 27/10/2005, 06:48
 
Fecha de Ingreso: mayo-2004
Mensajes: 393
Antigüedad: 13 años, 7 meses
Puntos: 0
Gracias por mirarte el código y responder.

Tomo nota de que:

1.- Hay que asegurar siempre que las variables llegan por post con $variable= $_POST['variable'];

2.- Es siempre preferible no mostrar los errores para no "dar pistas".

3.- Conviene establecer filtros o comprobaciones adicionales como settype() - no la conocía- y alguna verificación de los string.

No,
Código PHP:
SELECT FROM 
no me da error, aunque haya el espacio en blanco delante de FROM

Seguiré tus consejos manteniendo la estructura de los scripts.

Gracias por tu ayuda.
  #7 (permalink)  
Antiguo 27/10/2005, 07:16
 
Fecha de Ingreso: febrero-2004
Ubicación: España. Madrid
Mensajes: 454
Antigüedad: 13 años, 9 meses
Puntos: 0
vaya..voy a tener que revisar mucho todos los formularios...
alguna forma de controlar fácil que están metiendo codigo sql?
  #8 (permalink)  
Antiguo 27/10/2005, 08:47
 
Fecha de Ingreso: junio-2005
Mensajes: 981
Antigüedad: 12 años, 6 meses
Puntos: 2
Cita:
Iniciado por cyborg
vaya..voy a tener que revisar mucho todos los formularios...
alguna forma de controlar fácil que están metiendo codigo sql?
No entiendo la pregunta.
Cita:
Iniciado por javifo
1.- Hay que asegurar siempre que las variables llegan por post con $variable= $_POST['variable'];

2.- Es siempre preferible no mostrar los errores para no "dar pistas".

3.- Conviene establecer filtros o comprobaciones adicionales como settype() - no la conocía- y alguna verificación de los string.
En el tercer punto, no solo tendrias que aplicar un settype(), también otro tipo de validaciones, como puede ser validar que el mail tenga un formato de mail con expresiones regulares (busca en el foro, lo encontras rapido) y tambien como dijo jpinedo una validacion para que no tenga palabras como puede ser UNION.

Saludos.
  #9 (permalink)  
Antiguo 27/10/2005, 09:31
 
Fecha de Ingreso: mayo-2004
Mensajes: 393
Antigüedad: 13 años, 7 meses
Puntos: 0
Hola DarioDario:

Ya entendí el sentido de lo que dice jpinedo. Mi frase se refiere a que cuanto más se pueda controlar (sin llegar al exceso), mejor. De hecho, en mis scripts ya controlo la estructura del email, que el teléfono tenga solo números, etc.

Ahora estoy probando con settype() e iré poniendo más validaciones.

Gracias por tu interés.
  #10 (permalink)  
Antiguo 27/10/2005, 14:07
 
Fecha de Ingreso: febrero-2004
Ubicación: España. Madrid
Mensajes: 454
Antigüedad: 13 años, 9 meses
Puntos: 0
Cita:
Iniciado por DarioDario
No entiendo la pregunta.

Saludos.
normal.. me ha costado mirarme todo 3 veces para saber que narices estaba preguntando :p

A ver.. si no he entendido mal, el problema del post, es que cree que le han inyectado codigo sql, en alguna caja de texto de algun formulario no?

Mi pregunta, era, si hay alguna forma fácil de evitarlo o detectarlo
para que cuando pongas p.ej el usuario o la contraseña no te pongan. que se yo un "or 1=1"
y entre siempre

(no se si ahora me explico)
saludos
  #11 (permalink)  
Antiguo 27/10/2005, 17:17
Avatar de Master Solution  
Fecha de Ingreso: octubre-2005
Mensajes: 51
Antigüedad: 12 años, 2 meses
Puntos: 1
Usar addslashes(), si el servidor tiene Off magic_quotes_gpc()
__________________
-=[ 3KLabs ]=-
-=[ Diseño - Programación - Desarrollo ]=-
-=[ Posicionamiento en Buscadores ]=-
-=[ Hosting de Calidad ]=-
  #12 (permalink)  
Antiguo 28/10/2005, 01:16
 
Fecha de Ingreso: febrero-2004
Ubicación: España. Madrid
Mensajes: 454
Antigüedad: 13 años, 9 meses
Puntos: 0
cierto se me habia pasado que varias veces se habia hablado del
addslashes, aunque esa ni stripslashes(), las llego a entender bien.

Donde tiene que estar el Off magic_quotes_gpc() en el php.ini?

edito: efectivamente está ahi y yo lo tengo a ON, si lo pongo OFF... que pierdo?



; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = On

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off
  #13 (permalink)  
Antiguo 28/10/2005, 01:38
Avatar de FuLaNo_  
Fecha de Ingreso: mayo-2003
Ubicación: Don Torcuato, Buenos Aires, Argentina
Mensajes: 1.250
Antigüedad: 14 años, 6 meses
Puntos: 2
mira, el otro día por aqui habian dado un "tip" para saber si un form estaba protegido ante sql inyection o no, este era simplemente escribir, por ejemplo en un campo de busqueda, <script>alert()</script>, si la ventana del alert se ejecutaba, pues el script que procesa el form no tiene restricciones... (ojo porque puede que tengas javascript deshabilitado y crees que tu sitio es seguro).

Para evitarlo ya te han dado varias funciones, aunque tambien puedes hacerlas "a mano" si es que no te gustan, por ejemplo y para empezar, puedes cambiar los <, >, ", ', por su codigo HTML de esa manera te evitas codigos html, javascript y, en menor medida, sql...

El tema de mostrar los errores es bastante tipico, como te han dicho, es bueno mostrarlos solo en la etapa de desarrollo, para no volvernos locos, pero luego, en mi caso, los anulo todos con la @ y un mensaje personalizado (via include) que simplemente dice "intenta nuevamente" (o similar), para que nadie sepa que es lo que ocurre...
__________________
I Love Programming...
  #14 (permalink)  
Antiguo 28/10/2005, 07:05
O_O
 
Fecha de Ingreso: enero-2002
Ubicación: Santiago - Chile
Mensajes: 34.417
Antigüedad: 15 años, 11 meses
Puntos: 126
Cita:
Para evitarlo ya te han dado varias funciones, aunque tambien puedes hacerlas "a mano" si es que no te gustan, por ejemplo y para empezar, puedes cambiar los <, >, ", ', por su codigo HTML de esa manera te evitas codigos html, javascript y, en menor medida, sql...
Eso lo resuelve la función htmlentities() o strip_tags(), pero eso no resuelve problemas de "SQL injection" sino de "Cross-Site Scripting" .. que no es un error menor tambien, pero no es lo mismo.

Pueden ver este documento alusivo a todos esos problemas de seguridad:
http://phpsec.org/projects/guide/

Un saludo,
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 08:59.