Comentarios en: Ejercicio de fin de Semana: Evitar SQL Injection con PHP http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/ Diseño y Programación Sun, 15 Aug 2010 22:48:23 -0400 http://wordpress.org/?v=3-bc-1.0 hourly 1 Por: postnip http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10926 postnip Sat, 05 May 2007 23:30:07 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10926 y se puede hacer sql injection en un buscador?? me gustaria saber que vulnerabilidad es comun, y seria bueno mostrarlo para que todos arreglen sus buscadores :D y se puede hacer sql injection en un buscador?? me gustaria saber que vulnerabilidad es comun, y seria bueno mostrarlo para que todos arreglen sus buscadores :D

]]>
Por: Pablo http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10540 Pablo Wed, 04 Apr 2007 01:04:15 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10540 Yo normalmente tengo algunas funciones como: [php] function &getPostVar($sVar, $sType, $mDefaultValue = NULL) { if (isset($_POST[$sVar]) { switch($sType) { case 'int': $_POST[$sVar] = (int) $_POST[$sVar]; break; /** y así por cada tipo **/ } return $_POST[$sVar]; } else { /* No vino nada vía HTTP-POST llamado $sVar */ /* Devuelvo el valor por defecto */ return $mDefaultValue; } } [/php] Esta función devuelve una referencia al valor de la variable que le estoy indicando en el primer parámetro que ha llegado vía POST. (se puede implementar para GET, COOKIES, etc.) El uso es bien fácil: [php] $iNotId =& getPostVar('not_id', 'int', NULL); [/php] De esta forma, el valor de $iNotId ya se de entrada que es entero y lo puede utilizar en cualquier lugar estando 100% seguro, sin necesidad de estar aplicando filtros en medio del armado de las instrucciones SQL que entorpecen el código para mi gusto. Hago que devuelva una referencia al elemento del array $_POST simplemente para ahorrar memoria y no repetir datos inútilmente en el script. Yo normalmente tengo algunas funciones como:

php:
 
function &getPostVar($sVar, $sType, $mDefaultValue = NULL)
{
   if (isset($_POST[$sVar])
   {
      switch($sType)
      {
          case 'int':
             $_POST[$sVar] = (int) $_POST[$sVar];
             break;
 
          /** y así por cada tipo **/
      }
      return $_POST[$sVar];
   }
   else
   {
      /* No vino nada vía HTTP-POST llamado $sVar */
      /* Devuelvo el valor por defecto */
      return $mDefaultValue;
   }
}
 

Esta función devuelve una referencia al valor de la variable que le estoy indicando en el primer parámetro que ha llegado vía POST. (se puede implementar para GET, COOKIES, etc.)

El uso es bien fácil:

php:
 
$iNotId =& getPostVar('not_id', 'int', NULL);
 

De esta forma, el valor de $iNotId ya se de entrada que es entero y lo puede utilizar en cualquier lugar estando 100% seguro, sin necesidad de estar aplicando filtros en medio del armado de las instrucciones SQL que entorpecen el código para mi gusto.

Hago que devuelva una referencia al elemento del array $_POST simplemente para ahorrar memoria y no repetir datos inútilmente en el script.

]]>
Por: MaXaC http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10515 MaXaC Mon, 02 Apr 2007 18:36:20 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10515 Wow, excelente Alex, tu respuesta fue muy explicativa y rapida, gracias! Wow, excelente Alex, tu respuesta fue muy explicativa y rapida, gracias!

]]>
Por: alex http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10514 alex Mon, 02 Apr 2007 17:57:55 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10514 MaXac, el uso de is_numeric o is_integer depende del tipo de datos que se haya definido para ese campo. El primer ejemplo, sin hacer ningún tipo de validación, se podría reducir en algo como: [php]$SQL = "SELECT * FROM posts WHERE postID = ".(int)$_GET['id']; // o float, dependiendo el tipo de dato[/php] Sobre lo que mencionaba g3org3_x para el segundo ejemplo, me parece que se refería a un <a href="http://secunia.com/advisories/20365/" rel="nofollow">bug de MySQL</a> que dependiendo de la codificación de la conexión que se realizaba con la BD, era posible <em>sobrepasar</em> la acción de <code>mysql_real_escape_string</code>, algo como esto debería funcionar en una versión vulnerable de MySQL: [php]<?php $c = mysql_connect("localhost", "user", "pass"); mysql_select_db("database", $c); // change our character set mysql_query("SET CHARACTER SET 'gbk'", $c); // create demo table mysql_query("CREATE TABLE users ( username VARCHAR(32) PRIMARY KEY, password VARCHAR(32) ) CHARACTER SET 'GBK'", $c); mysql_query("INSERT INTO users VALUES('foo','bar'), ('baz','test')", $c); // now the exploit code $_POST['username'] = chr(0xbf) . chr(0x27) . ' OR username = username /*'; $_POST['password'] = 'anything'; // Proper escaping, we should be safe, right? $user = mysql_real_escape_string($_POST['username'], $c); $passwd = mysql_real_escape_string($_POST['password'], $c); $sql = "SELECT * FROM users WHERE username = '{$user}' AND password = '{$passwd}'"; $res = mysql_query($sql, $c); echo mysql_num_rows($res); // will print 2, indicating that we were able to fetch all records ?>[/php] MaXac, el uso de is_numeric o is_integer depende del tipo de datos que se haya definido para ese campo. El primer ejemplo, sin hacer ningún tipo de validación, se podría reducir en algo como:

php:
$SQL = "SELECT * FROM posts WHERE postID = ".(int)$_GET['id']; // o float, dependiendo el tipo de dato

Sobre lo que mencionaba g3org3_x para el segundo ejemplo, me parece que se refería a un bug de MySQL que dependiendo de la codificación de la conexión que se realizaba con la BD, era posible sobrepasar la acción de mysql_real_escape_string, algo como esto debería funcionar en una versión vulnerable de MySQL:

php:
<?php
 
$c = mysql_connect("localhost", "user", "pass");
mysql_select_db("database", $c);
 
// change our character set
mysql_query("SET CHARACTER SET 'gbk'", $c);
 
// create demo table
mysql_query("CREATE TABLE users (
    username VARCHAR(32) PRIMARY KEY,
    password VARCHAR(32)
) CHARACTER SET 'GBK'", $c);
mysql_query("INSERT INTO users VALUES('foo','bar'), ('baz','test')", $c);
 
// now the exploit code
$_POST['username'] = chr(0xbf) . chr(0x27) . ' OR username = username /*';
$_POST['password'] = 'anything';
 
// Proper escaping, we should be safe, right?
$user = mysql_real_escape_string($_POST['username'], $c);
$passwd = mysql_real_escape_string($_POST['password'], $c);
 
$sql = "SELECT * FROM  users WHERE  username = '{$user}' AND password = '{$passwd}'";
$res = mysql_query($sql, $c);
echo mysql_num_rows($res); // will print 2, indicating that we were able to fetch all records
 
?>
]]>
Por: MaXaC http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10513 MaXaC Mon, 02 Apr 2007 17:27:48 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10513 Alex una consulta, seria mejor colocar !is_numeric en vez de !is_integer ya que puede ser un valor real y no solamente entero, o bastaria con la primera opcion, y eso de hacerlo en 3 lineas, suena interesante aunque solamente veo que se pueden ahorrar if's. Y sobre el segundo ejemplo, es acaso la versiones anteriores a la 5x mas vulnerables que las actuales? Alex una consulta, seria mejor colocar !is_numeric en vez de !is_integer ya que puede ser un valor real y no solamente entero, o bastaria con la primera opcion, y eso de hacerlo en 3 lineas, suena interesante aunque solamente veo que se pueden ahorrar if's.

Y sobre el segundo ejemplo, es acaso la versiones anteriores a la 5x mas vulnerables que las actuales?

]]>
Por: alex http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10501 alex Sun, 01 Apr 2007 16:30:21 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10501 Para el primer ejemplo hay un error en la condición donde se comprueba que el parámetro <code>id</code> sea numérico, debería ser: <code>if (!is_integer(...))</code> Por esa pequeña equivocación es posible alterar la consulta -y si, estoy de acuerdo en que hay demasiado código innecesario :) Para el segundo ejemplo, en condiciones <em>normales</em> no debería ser posible modificar la consulta, aunque como dices depende si la versión de MySQL es vulnerable o no (¿te refieres a los problemas con la codificación no?). Lo de hacer XSS lo dije en plan de <em>fastidioso</em>, porque en la última línea se escribe el nombre del usuario :P Para el primer ejemplo hay un error en la condición donde se comprueba que el parámetro id sea numérico, debería ser: if (!is_integer(...)) Por esa pequeña equivocación es posible alterar la consulta -y si, estoy de acuerdo en que hay demasiado código innecesario :)

Para el segundo ejemplo, en condiciones normales no debería ser posible modificar la consulta, aunque como dices depende si la versión de MySQL es vulnerable o no (¿te refieres a los problemas con la codificación no?). Lo de hacer XSS lo dije en plan de fastidioso, porque en la última línea se escribe el nombre del usuario :P

]]>
Por: g30rg3_x http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10493 g30rg3_x Sun, 01 Apr 2007 04:08:37 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10493 Para el primero no vi errores mas que de que se deperdicia mucho codigo para hacer tan poca cosa, bien se puede hacer en 3 o 4 lineas de codigo eso... (talvez hasta dos). Para el segundo solo encontre que basarse en mysql_real_escape_string() como sabemos no estan seguro usarla ya que podemos(aunque depende de la version de MySQL ) aun asi podemos pasar el filtro, el problema seria el maximo de 20 largo pero yo creo que si se podra hacer algo con 20 caracteres. Aunque aun no veo como hacer el XSS que dices en el comentario que dejaste en el articulo original, seria bueno saber tu opinion... Saludos Para el primero no vi errores mas que de que se deperdicia mucho codigo para hacer tan poca cosa, bien se puede hacer en 3 o 4 lineas de codigo eso... (talvez hasta dos).

Para el segundo solo encontre que basarse en mysql_real_escape_string() como sabemos no estan seguro usarla ya que podemos(aunque depende de la version de MySQL ) aun asi podemos pasar el filtro, el problema seria el maximo de 20 largo pero yo creo que si se podra hacer algo con 20 caracteres.

Aunque aun no veo como hacer el XSS que dices en el comentario que dejaste en el articulo original, seria bueno saber tu opinion...

Saludos

]]>
Por: alex http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10483 alex Sat, 31 Mar 2007 15:37:51 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10483 A partir de PHP 5 si, pero con esta entrada sólo intentaba mostrar que muchas veces existe código mal hecho :) Saludos A partir de PHP 5 si, pero con esta entrada sólo intentaba mostrar que muchas veces existe código mal hecho :)

Saludos

]]>
Por: Eber Irigoyen http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/comment-page-1/#comment-10482 Eber Irigoyen Sat, 31 Mar 2007 15:33:06 +0000 http://www.buayacorp.com/archivos/ejercicio-de-fin-de-semana-evitar-sql-injection-con-php/#comment-10482 yo no puedo decir que tengo experiencia con PHP, pero que no se puede usar simplemente un query con parametros? yo no puedo decir que tengo experiencia con PHP, pero que no se puede usar simplemente un query con parametros?

]]>