You are on page 1of 9

1. Uso de variables sin definir.

Esta es la práctica mas usual que se encuentra en los desarrollos en php. La mayoría
de programadores no tienen en cuenta si la variable fue definida o no y la utilizan
directamente sin percatarse en el problema que eso puede acarrear.
?
1<?php
2 if($variable) echo "ejecute sentencia";
3?>

Este sería un código común entonces, el programador considera que si la variable


contiene un valor entonces arroja verdadero y si no, arroja falso. Pero esto no es
realmente así!!!!!.

Recordemos lo que se enseña cuando aprendemos el magnánimo lenguaje C que profesa en uno de sus
apartados:

Si una variable esta contenida con un valor vacío, su equivalencia


booleana será false, pero si contiene un valor, sea del tipo que sea, se
considera true, pero si el contenido es integer, si el valor diferente de
cero, se tomará como true y si es cero, será false.

Ahora que ya sabemos eso, me pregunto: ¿y como demonios va a saber que contiene una variable si ni siquiera
existe a nivel de memoria, es decir, si no se ha definido?

Cierto es que con PHP, la definición de variables no es necesaria, pero y si no existe, ¿dónde la va a buscar?

?
1
2
3
4<?
5// Acá se asume la conversión de null a false
6$variable = NULL;
7if($variable) echo "se ejecutaría si fuera cierto";
8
9// Acá se hace correctamente, definiendo de antemano como false
1$variable = false;
0
1if($variable) echo "se ejecutaría si fuera cierto";
1
1// Si es una variable que supuestamente existe pero no hay
2// seguridad que exista como un $_GET
1
3if(isset($_GET['indice_variable'])) echo "se ejecutaría si fuera cierto";
1?>
4
1
5

Lo mejor por hacer siempre es validar primero si la variable está definida o definirla antes, si es el efecto.

Ahora que ya sabemos que lo mejor es definir las variables antes de validarlas, otra buena costumbre o muy
buena costumbre mejor, es el tratamiento de las variables de tipo string.

2. tratamiento de variables de tipo string o de cadenas de texto.

La mayoría de programadores están acostumbrados a hacer esto:

?
1<?
2 if($variable == 'texto') echo "ejecute sentencia";
3?>

NOOOO, no esta bien, para eso existen unas funciones para tratamniento de cadenas que se
deben utilizar.

?
1<?
2 if(strcmp($variable,'texto') == 0) echo "Esto si valida y devuelve un
3
booleano";
?>

Ahora otra práctica que se suele implementar:

?
1<?
2 $variable = '1' // Nótese que es un string.
3
4
if($variable) echo "Validar si es cierto.";
5
6
if($variable == 1) echo "Validar si es cierto.";
7
8
if($variable == '1') "Validar si es cierto.";
9
1
0?>

Esta práctica hace referencia al uso de los strings como variables de cualquier otro tipo, es decir, se tiene una
variable de valor 1 como string es decir, '1' y con esta variable, se pretende validar 3 momentos:

1. que si la variable como viene con valor = 1, entonces, se asume que por validación booleana, de un
resultado de true y si puede ser true, pero no por el 1, porque es un string, solo devuelve true porque contiene
un valor.

2. se trata de validar 2 tipos de valores diferentes, un string con un integer, entonces el compilador debe hacer
conversión de tipos, entonces puede ocurrir problemas porque o ambos se establecen como strings o como
enteros.

3. comparación de strings con operador "==", práctica no adecuada, como describí antes, para eso están las
funciones de strings.

Por último, no me resta mas que recomendarles, que como desarrolladores, consideren que su aplicación debe
ser óptima, tanto en la interfaz que debe ser amigable como en la parte sustancial del aplicativo: el código. Si
el código es óptimo, van a tener una aplicación mas escalable y que funcione como debe ser y se evitarán
problemas indeseables y ahorraran tiempo de reprocesos, verificando problemas que se pudieron evitar con tan
solo seguir buenas conductas.

Asegurarse del tipo de datos


● Usar “tags” cortas es malo
● Ser “E_STRICTo” es bueno
● Emplear excepciones
● Usar un depurador (debugger)
● Evitar reinventar la rueda
● Los estándares de código son buenos
● Documentar, documentar, documentar

“Tags” cortas son dañinas (1)


La situación: PHP permite varias formas de
marcar el comienzo del código:
➔ Forma estándar: <?php echo “Hola!”; ?>
➔ Forma corta: <? echo “Hola!”; ?>
o aún peor: <?= “Hola!”; ?>
➔ ... y para los masoquistas:
<% echo “Hola!”; %>
Pero:
➔ <? esta reservado para declarar XML
➔ <?= no es XML válido (<?php si lo es)
➔ <% es para los que sueñan/sufren con ASP

La solución: Usemos E_STRICT, y


revisemos nuestro código: (en php.ini)
error_reporting=E_ALL | E_STRICT
Error típico encontrado usando E_STRICT:
uso de is_a() en lugar de instanceof:
<?php
if (is_a($object, 'ClassName')) {
$object>
algunMetodo();
}
?>
<?php
if ($object instanceof ClassName) {
$object>
algunMetodo();
}
?>

Abusando de las excepciones:


Cuando podríamos haber hecho algo mas sensato:
<?php
function check_input($input) {
if ($input !== "Hello!") {
throw new Exception("User input wrong");
}
}
?>
<?php
function check_input($input) {
if ($input !== "Hello!") {
return false;
} else {
return true;
}
}
?>

<?php
try {
$person>
setName('John Doe');
$person>
setAddress('Something St. 12');
$person>
setbirthDate('10101900');
$person>
store();
} catch (Exception e) {
throw new DataPopulationException(
'Unable to fill data for person ' . $person>
getId(), e
);
}
?>

Usa un depurador (4)


La solución: ¡Usen un buen depurador!
● Recomendación: Xdebug
(http://xdebug.org)
➔ Es Código Libre
➔ Usado por muchos desarrolladores
➔ Se integra con PHP como una extensión
➔ Se integra con IDEs (ej. Komodo)
➔ Tiene opciones para obtener perfiles de uso y cobertura de código
● Otros depuradores:DBG(http://dd.cron.ru), APD (http://pecl.php.net/package/apd), Zend
IDE (propietario)

Inicializa todas tus variables y


nunca (si, ¡nunca!) confíes en datos que vienen del usuario (del exterior):
$_POST, $_GET, $_REQUEST, $_COOKIE, $_SERVER,
$_ENV
Ejemplo simple de XSS. Al código:
... le inyectamos el URL siguiente:
generando una ventana en JavaScript que
imprime el texto “XSS”

Valida los archivos a incluir


usando una lista fija implementada con arreglos o con 'switch', etc.
<?php
$valid_files = array(
'show' => 'show.php',
'list' => 'list.php',
);
if (isset($valid_files[$_GET['action']])) {
require_once $valid_files[$_GET['action']];
} else {
echo 'Not a valid action.';
}
?>

La situación: El necesitar usar datos de los


usuarios, puede permitir a estos el manipular la forma como se accede a la
base de datos.
Dado el código:
Se puede manipular usando:
<?php
$sql = 'SELECT password FROM user WHERE login = '
. $_GET['login'];
?>
http://example.com/form4.php?login=username+OR+1

La solución: Usa funciones para escapar


datos de tu base de datos:
O aún mejor, usa comando preparados:
<?php
$sql = 'SELECT password FROM user WHERE login = ' .
mysql_real_escape_string( $_GET['login'] );
?>
<?php
$db = new PDO( ... );
$stmt = $db>
prepare( 'SELECT password FROM user WHERE login = ?' );
$stmt>
execute( array( $_GET['login'] ) );
?>

Validación de datos de entrada (1)


La situación: Validar los datos que entra el usuario es difícil y poco interesante.
La solución: Usar ext/filter o ext/ctype
<?php
var_dump( ctype_alnum( 'foobar_42' ) );
var_dump( ctype_alnum( 'Bad Characters $%&/' ) );
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('example.com',
FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
?>

Validación de datos de entrada (2)


Sugerencia:
Para datos numéricos, es más fácil el forzar al dato a tener un tipo un entero (integer)
<?php
var_dump( (int) '42' );
var_dump( (int) '42; DELETE * FROM users;' );
var_dump( (int) 'Evil string' );
?>

Seguridad por obscuridad


La situación: Información acerca de las rutas, extensiones, y configuración, hace fácil el
trabajo de quien quiere atacar tu sistema.
La solución: Oculta bien esta información.
➔ No tengas un script con phpinfo() en tu directorio
de web por defecto
➔ En producción, desactiva display_errors y usa
error_log en su lugar
➔ El cambiar los tipos de archivos por defecto (ej. usar
.abc en lugar de .php), y desactivar expose_php
también puede ayudar

Usa ' en lugar de " para no tener que interpretar


valores
➔ Usa valores múltiples de echo en lugar de usar concatenación de valores
➔ Donde sea posible usa ++$i en lugar
de $i++
echo "Hola\nTodos"; echo 'Hola Todos';
Preferido
echo 'Hola '.$nombre; echo 'Hola ', $nombre;
Preferido
for ($i=0; $i<100; $i++)
for ($i=0; $i<100; ++$i)

You might also like