(Ayuda) tips para evitar Sql Injection con PHP

padawanluke Seguir

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
24 Jun 2013
Mensajes
96
Estoy creando una web y estoy preocupado por la seguridad del sitio, lo que siempre hice fue basicamente eliminar las camillas simples de las variables que vienen por POST y GET, poner captcha en los formularios, etc.
No se mucho de seguridad , pero creo que estoy desprotegiendo mis desarrollos, estuve googleando y hay mil maneras pero no se con cual quedarme, me seria bastante engorroso aplicar todas las tecnicas existentes .

Por lo que leí hasta ahora lo que mas me interesó en usar es utilizar PDO, aunque nunca antes lo habia utilizado, ustedes me lo recomiendan?

Recurro a la experiencia de los usuarios, si me pueden contar cuales son las tecnicas que utilizan.

Muchas gracias.
 
Última edición:

Isidro

Gamma
Programador
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
18 Jun 2012
Mensajes
157
Es un error suprimir las comillas simples que se envíen por los parámetros. Yo creo que debe pasar por unos filtros que eviten la inyección, pero sin que éstos alteren directamente el contenido.

Es cierto que mysql_real_escape_string() queda obsoleta en PHP 5.5 (no es recomendable, aunque se puede seguir utilizando), pero como alternativa se puede usar otra función de una de las extensiones, mysqli_real_escape_string().

La función anterior, como bien indica su nombre, escapará todo "string" que contenga la llamada... Pero no evita una inyección con cadenas que no sean de texto, como los números. Para ello se puede usar "(int)", que forzará a que el contenido de la variable sea numérico. No obstante, no quiere decir que con eso ya estemos exentos de todos los problemas. Existen muchos métodos que pueden usarse para evitar las inyecciones (no sólo con PHP), pero tardaría bastante en escribirlos.


Enviado desde mi GT-I9300 usando Tapatalk 4 Beta
 

padawanluke

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
24 Jun 2013
Mensajes
96
OK , entonces anoto la opción de la función mysqli_real_escape_string() , ire probando a ver como se implementa y como funciona.

Esperamos mas opciones de todas maneras , gracias por la info Isidro !
 

vlad

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
26 Ago 2012
Mensajes
59
Yo uso PDO. Te pongo un código de ejemplo para que veas como va. Los parámetros que llegan desde el usuario no se insertan directamente en la sentencia sql sino que se introducen con bindParam o bindValue y así ya no se puede inyectar código poniendo las comillas.

Insertar CODE, HTML o PHP:
function pdo_queryall_page( $sql, $params, $offset, $display )
{
	try 
	{
		$sql .= ' LIMIT :offset, :display';		
		$conn = new PDO('mysql:host=localhost;dbname=nombredb', 'dbuser', 'dbpass');
		$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	  	$stmt = $conn->prepare($sql);
	  	foreach ($params as $key => &$val) {
    		   $stmt->bindParam($key, $val);
		}	  	
	  	$stmt->bindValue(':offset', (int) $offset, PDO::PARAM_INT); 
	  	$stmt->bindValue(':display', (int) $display, PDO::PARAM_INT);
	  	$stmt->execute();
	  	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
	  	
	  	return $rows; 
	} 
	catch(PDOException $e) {
	    trace( $e->getMessage() );
	}
}

$results = pdo_queryall_page('SELECT id, picture FROM pictures WHERE userid = :fbid ORDER BY id DESC', array(':fbid' => $this->uid), $page - 1, 2 );
 

Isidro

Gamma
Programador
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
18 Jun 2012
Mensajes
157
Hay que tener en cuenta que no sólo se pueden hacer inyecciones con las comillas. Hay otros caracteres (y otras codificaciones) que permitirán hacer lo mismo.

El uso de PDO u otra extensión MySQL no aumentará notoriamente la seguridad, y los valores de los parámetros siempre deben pasar por unos filtros, para comprobar que sea lo que queremos que sea. Por ejemplo, si es una fecha se puede comprobar que sea una fecha y no otra cosa. Si es una serie de números, se puede usar otra función, como ctype_digit(), para evitar incluso tener que hacer la consulta.

Enviado desde mi GT-I9300 usando Tapatalk 4 Beta
 

IgnacioViglo

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
31 Dic 2012
Mensajes
55
usa mysqli_real_escape_string (como te dijeron anteriormente) y no tendrás problema. Para campos numéricos podes usar (int) o intval. Además recuerda que para mostrar textos directamente desde la bd (si no lo filtras en el insert) usá htmlspecialchars para evitar XSS.
Con eso y las suficientes comprobaciones creo que ya será seguro.
 

padawanluke

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
24 Jun 2013
Mensajes
96
Miren esto, me ha pasado que al final de un GET me ponen esto :

))%20or%201=@@version--

Onda la cadena llega asi :

Ficha.asp
htp://blabla.com/index.php?tipo=1&Id=1)%20or%201=@@version--

Que es lo que pretenden hacer en ese caso?

IgnacioVigio comentaste de evitar XSS que es eso?? no lo habia escuchado.

Saludos.
 

Isidro

Gamma
Programador
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
18 Jun 2012
Mensajes
157
Miren esto, me ha pasado que al final de un GET me ponen esto :

Insertar CODE, HTML o PHP:
))%20or%201=@@version--

Onda la cadena llega asi :

Insertar CODE, HTML o PHP:
Ficha.asp
htp://blabla.com/index.php?tipo=1&Id=1)%20or%201=@@version--

Que es lo que pretenden hacer en ese caso?
Es algo típico. Como dije en anteriores respuestas, puedes usar "(int)".

Ejemplo sin (int):
Insertar CODE, HTML o PHP:
htp://blabla.com/index.php?tipo=1&Id=123$'%6/)"3Ñ´ÇZº

Ejemplo con (int):
Insertar CODE, HTML o PHP:
htp://blabla.com/index.php?tipo=1&Id=123

Ejemplo con intval():
Insertar CODE, HTML o PHP:
htp://blabla.com/index.php?tipo=1&Id=123

Debido a que obligará a que todo el valor del parámetro sea numérico entero. Si no quieres bajo ninguna circunstancia registrar un valor negativo, puedes cambiar el tipo de valores en la misma columna de la tabla donde se registrarán. También -como mencioné antes- se puede comprobar que sean números naturales usando la función ctype_digit(). Así te ahorrarás hacer la consulta y por tanto las posibles inyecciones.

Si por el contrario quieres saltarte las comprobaciones, pero quieres estar seguro de que sea un número natural, puedes usar la función abs() unida a (int) o intval(). Así tampoco habrán decimales.


IgnacioVigio comentaste de evitar XSS que es eso?? no lo habia escuchado.

Saludos.
Puede considerarse un tipo de "exploit" peligroso, ya que permite inyectar código HTML, JavaScript u otro tipo de código ejecutable en alguna parte del sitio. Si ese código se registra en alguna base de datos o por cualquier otra razón puede ser leído por un usuario, entonces tendrás un problema. Con XSS puedes robar cookies (y con ello podrías identificarte como el administrador del sitio), por ejemplo.

Al igual que para evitar inyecciones, hay muchos métodos para evitar XSS. Es bastante usual el uso de htmlspecialchars() o htmlentities() para evitar que sea ejecutado como código. Permitirá su lectura en texto.
 

WWWW

Pi
Verificación en dos pasos activada
Desde
4 Mar 2013
Mensajes
5.258
[MENTION=45047]padawanluke[/MENTION]

Por lo que se buscan la version del Sql, después a base de esto buscan o hacen bugs.

Lo ideal seria que tu proveedor tenga actualizado todo, incluyendo SQL en sus ultimas versiones, y que implementes filtros como te mencionaron, no importando que lenguaje utilices.
 
Arriba