Categories
PHP

Escribiendo código correcto

Antes de empezar con PHP, escribía mis aplicaciones con ASP 3, utilizando como editor al Visual Interdev, cuando PHP 4 salió a la luz, muchos programadores de ASP se pasaron a PHP, y no sólo ellos sino sus prácticas de programación.

Para esto los desarrolladores de PHP dieron la comodidad a estos "nuevos usuarios" para que sigan con sus malas prácticas de programación y código desordenado, me refiero en especial a la sintaxis para embeber PHP en una página, una de estas es:

PHP:

<?
    echo "Hola Mundo!";
?>
 

¿Qué está mal? Pues la etiqueta <? está reservada para declarar documentos XML y XHTML, debemos olvidarnos de esto definitivamente.

Recordando un poco de ASP, y una de las peores formas de escribir PHP:

PHP:

<?="Hola Mundo!"; ?>
 

¿Qué está mal? Otra vez nos estamos metiendo con XML, si tratamos de mostrar esa página de hecho que tendremos un error, si no es de XML será de PHP.

Y esta que es la peor de todas,

PHP:

<% echo "Hola Mundo!"; %>
 

Este ni hablar, es el estilo de ASP, y recuerdas amigo? ¡ESTAMOS TRABAJANDO CON PHP!

La Solución

Pues es muy fácil, tenemos que escribir el código estándar; es decir:

PHP:

<?php
    echo "Hola Mundo!";
?>
 

Usar la etiqueta de apertura <?php, ¿por qué? pues porque:

  • Se garantiza que cualquier persona entenderá tu código
  • Tus documentos XML serán válidos y se notará la separación con PHP
  • Funciona en todos los documentos PHP

Supongo que alguno me dirá: "Pero Braulio, yo siempre escribo con el método <?= porque es más fácil para pequeñas líneas de código y pierdo menos tiempo" Bueno yo también decía eso... pero lo malo es que a veces lo fácil trae consecuencias catastróficas. Empezemos a ser ordenados desde ahora.

Una pequeña reflexión: "No dije que fuera fácil, dije que valdría la pena."

Referencias

Categories
PHP Quiz Seguridad

Quiz sobre validación de datos en PHP

El código mostrado a continuación, es una versión reducida de una falla de seguridad presente en una aplicación algo conocida.

Indiquen la falla, lo que se puede hacer con ésta, una forma de explotarlo y la solución que plantean al mismo:

php:

// demo.php
<?php

include './db.php';

error_reporting(0);

$tb_url    = $_POST['url'];
$title     = $_POST['title'];
$excerpt   = $_POST['excerpt'];

if (empty($title) || empty($tb_url) || empty($excerpt)) {
        die ('Invalid values');
}

$titlehtmlspecialchars( strip_tags( $title ) );
$title = (strlen($title) > 150) ? substr($title, 0, 150) . '...' : $title;
$excerpt = strip_tags($excerpt);
$excerpt = (strlen($excerpt) > 200) ? substr($excerpt, 0, 200) . '...' : $excerpt;

$contents=@file_get_contents($tb_url);
if(!$contents) {       
        die('The provided URL does not seem to work.');
}

$query = "INSERT INTO tabla (url, title, excerpt) VALUES ('%s', '%s', '%s')";

$db->query
        (
                sprintf (
                        $query,
                        $db->escape($tb_url),
                        $db->escape($title),
                        $db->escape($excerpt)
                        )
        );

?>

php:

// show.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <title>Bug</title>
        </head>
        <body>

                <ul>
                <?php

                include './db.php';
                $items = $db->get_results('SELECT url, title, excerpt FROM tabla');

                foreach ($items as $tb) :
                        echo '<li><a href="'.$tb->url.'" title="'.$tb->excerpt.'">'.$tb->title.'</a></li>';               
                endforeach;

                ?>
                </ul>

        </body>
</html>

Para el acceso a datos se usa la clase ez_sql, el método escape en mi versión, contiene lo siguiente:

php:

function escape($string) {
        if (get_magic_quotes_gpc())
                $string = stripslashes($string);
        return mysql_real_escape_string( $string, $this->dbh );
}
Categories
PHP

Escribiendo código seguro – Más sobre comparación de tipos

Tenemos la siguiente porción de código:

PHP:

<?php
    function foo($respuesta) {
        if ($respuesta > 10) {
            return true;
        } else {
            return $respuesta;
        }
    }
    if (foo(11)) {
        echo "11 es mayor que 10<br />";
    }       
    if (foo(9)) {
        echo "9 es mucho mayor que 10<br />";
    }
?>
 

Lo que hace la función es comparar la variable $respuesta con 10, si es mayor que este entonces devuelve true, caso contrario devuelve el valor de $respuesta. Veamos la salida:

CODE:

11 es mayor que 10
9 es mucho mayor que 10
 

El error está en que PHP toma a cualquier número mayor que cero como un valor verdadero, por eso es que vemos esta salida incoherente.

La Solución

Igual que en la entrada anterior, es mejor usar comparación estricta de tipos, esto es:

PHP:

<?php
    function foo($respuesta) {
        if ($respuesta > 10) {
            return true;
        } else {
            return $respuesta;
        }
    }
    if (foo(11) === true) {
        echo "11 es mayor que 10<br />";
    }       
    if (foo(9) === true) {
        echo "9 es mucho mayor que 10<br />";
    }
?>
 

Ahora si la salida será correcta:

CODE:

11 es mayor que 10
 

Espero sus comentarios y duras, mañana seguiremos con más 😉

Referencias

Categories
PHP

Escribiendo código seguro – Comparación de Tipos

Cuando en PHP comparamos diferentes variables, pero que en cierto contexto son iguales, los tipos de datos se pierden. Por ejemplo un valor booleano verdadero es representado como 1 y el valor falso es representado como 0. Veamos lo que hace PHP con el siguiente ejemplo:

PHP:

<?php
$entero = 1;
$cadena = "1";
$booleano = true;

var_dump($entero == $cadena);
var_dump($cadena == $booleano);
var_dump($entero == $booleano);
?>
 

En los tres casos se espera "false", pero sin embargo:

CODE:

bool(true) bool(true) bool(true)
 

Otro ejemplo mucho peor:

PHP:

<?php
var_dump('1' == '1.');
?>
 
CODE:

bool(true)
 

En todos los ejemplos hemos usado un "comparador flexible" (==), este solo compara una igualdad. Esto puede traer consecuencias no deseadas en nuestra aplicación, como comenté en la entrada anterior.

La solución

Si queremos código seguro, debemos usar comparadores seguros. Para solucionar nuestro pequeño error, debemos usar un "comparador estricto" (===), este operador sólo dará verdadero si dos variables son idénticas.

PHP:

<?php
$entero = 1;
$cadena = "1";
$booleano = true;

var_dump($entero === $cadena);
var_dump($cadena === $booleano);
var_dump($entero === $booleano);
?>
 

Ahora si la salida será correcta:

CODE:

bool(false) bool(false) bool(false)
 

Una pequeña reflexión: "Así vemos que por medios pequeños, podemos hacer grandes cosas"

Referencias

Categories
PHP

Escribiendo código seguro – Manipulación de Tipos

PHP no soporta la definición explícita de tipos de datos, es decir que cada variable actúa de acuerdo a como es usada. Veamos un ejemplo:

Nota: Para los ejemplos vamos a usar la función var_dump, que nos muestra información acerca de una o mas variables.

PHP:

<?php
$cadena = "1";
$entero = $foo + 1;
var_dump($cadena, $entero);
?>
 

La salida será:

CODE:

string(1) "1" int(2)
 

Como vemos aunque hayamos definido la primera variable como "cadena", al sumarlo con un entero, nos dá otro entero. Para solucionar esto (aunque en realidad no es un problema tan grave), si es que queremos sumar la cadena con un entero, primero deberíamos convertir la cadena a un entero usando casting:

La solución

PHP:

<?php
$cadena = "1";
$entero = (int)$foo + 1;
var_dump((int)$cadena, $entero);
?>
 

La salida será:

CODE:

int(1) int(2)
 

Tratemos de tener siempre en cuenta los tipos de datos que estamos usando, alguien podría aprovechar uno de estos descuidos y podría enviar código malicioso concatenándolo con algún id númerico de nuestra base de datos por dar un ejemplo.

Mañana seguiremos con más 😉

Referencias