viernes, 19 de septiembre de 2014

[Parte 8] PHP

En este apartado vamos a hablar un poco sobre metodos de seguridad para nuestros scripts php, aunque no hablaremos mucho sobre el tema por que en este mismo blog puedes encontrar una recopilacion donde nos adentramos mas profundamente en el:

Seguridad en PHP:

http://arthusu.blogspot.mx/2014/02/parte-1-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/03/parte-2-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/03/parte-3-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/03/parte-4-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-5-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-6-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-7-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-8-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-9-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-10-seguridad-en-php.html
http://arthusu.blogspot.mx/2014/04/parte-11-seguridad-en-php.html


Validando los datos por tipo

Para la mayor parte, toda la validacion de los scripts php que hemos hecho hasta ahora debe estar al minimo, incluso nisiquiera verificamos si la variable tiene algun valor o esta vacia, en varias situaciones esto es lo mejor que puedes hacer. Por ejemplo, no hay una regla perfecta para validar la direccion o un comentario de un usuario, se puede lograr algo un poco mas sofisticando utilizando expresiones regulares (http://arthusu.blogspot.mx/2013/07/phpexpresiones-regulares-pcre.html), en este caso seria mejor validar el dato por tipo. 

PHP soporta varios tipos de datos: cadenas, numeros (enteros o decimales), arrays y mas. Para cada uno de estos existe una funcion especifica para ver si una variable es de ese tipo de dato. 

is_array() - checa si es un array
is_bool() - checa si es booleano (TRUE o FALSE)
is_float() - checa si es decimal
is_int() - checa si es entero
is_null() - checa si es valor nulo (NULL)
is_numeric() - checa si es numerico
is_resource() - checa si es un recurso (por ejemplo: la coneccion a la base de datos)
is_string() - checa si es una cadena

Hay una gran parte basada en la validacion: ya sea validar por URL, cookies, formularios, datos que van fuera del servidor, a la base de datos, hay dos tipos de validaciones: lista blanca y lista negra, un ejemplo podria ser para prevenir el spam o para prevenir groserias, podriamos usar una lista negra y reemplazar esa palabra por otro o simplemente taparla (****).

Un ejemplo, podriamos hacer una calculadora que solo sume:


<form method="post">
 numero 1: <input type="text" name="n1" /><br>
 numero 2 <input type="text" name="n2" /><br>
 <input type="submit" name="enviar" />
</form>

<?php
 if (isset($_POST['enviar']) && is_numeric($_POST['n1']) && is_numeric($_POST['n2'])) {
  $n1 = $_POST['n1'];
  $n2 = $_POST['n2'];

  $result = $n1 + $n2;

  echo $result;
 }
?>


Usando la extension Filter

Introducido en PHP 5.2 Filter Extension es una importante herramienta, esta puede ser utilizada para dos propositos: validar o desinfectar. Un proceso de validacion confirma que los datos coincidan con lo esperado. Y la desinfeccion en comparacion altera los datos eliminando los caracteres inapropiados.

La funcion mas importante en la exntesion filter es  filter_var():

filter_var(variable,filter,[options]);
El primer argumento es la variable a ser filtrada, el segundo es el filtro a aplicar, el tercero es para agregar criterios adicionales.

Filtros de validacion

Constante:
FILTER_VALIDATE_BOOLEAN
FILTER_VALIDATE_EMAIL
FILTER_VALIDATE_FLOAT
FILTER_VALIDATE_INT
FILTER_VALIDATE_IP
FILTER_VALIDATE_REGEXP
FILTER_VALIDATE_URL


Filtros de desinfeccion

Constante:
FILTER_SANITIZE_EMAIL
FILTER_SANITIZE_ENCODED
FILTER_SANITIZE_MAGIC_QUOTES
FILTER_SANITIZE_NUMBER_FLOAT
FILTER_SANITIZE_NUMBER_INT
FILTER_SANITIZE_SPECIAL_CHARS
FILTER_SANITIZE_STRING
FILTER_SANITIZE_STRIPPED
FILTER_SANITIZE_URL
FILTER_UNSAFE_RAW

Por ejemplo, para confirmar que la variable sea un valor decimal:

if(filter_var($var,FILTER_VALIDATE_FLOAT)){
Un ejemplo que contenga valores opcionales podria ser el uso de FILTER_VALIDATE_INT la cual contiene min_range y max_range para controlar el minimo y maximo de valores permitidos. Viendolo en un ejemplo podria ser el siguiente:

if(filter_var($var,FILTER_VALIDATE_INT,array('min_range'=>1,'max_range'=>120))){

Hay varios filtros duplicados a funciones php. Por ejemplo: 
 

FILTER_SANITIZE_MAGIC_QUOTES es lo mismo que addslashes()
FILTER_SANITIZE_SPECIAL_CHARS es lo mismo que htmlspecialchars()
FILTER_SANITIZE_STRING es lo mismo que strip_tags()


Bueno otro tema que voy a tocar asi rapido de pasadita por que en las partes de seguridad en php se hablo mucho de ello es la proteccion contra sql injection tambien hay un tutorial de la libreria pdo en este mismo sitio.

Prevenir ataques de inyeccion SQL


En este caso utilizaremos declaraciones preparadas o preparated statements... esto lo que tiene de bueno es que son mas rapidas y mas seguras.

Las declaraciones preparadas pueden ser creadas en cualquier peticion SELECT, INSERT, UPDATE, DELETE. Comenzamos definiendo nuestra consulta marcando los placeholders:

$q = "SELECT first_name,last_name,email FROM users WHERE id=?";

Asignamos los resultados en una variable de PHP:

$stmt = mysqli_prepare($dbc,$q);
En este punto mysqli parsea la consulta pero no la ejecuta. El siguiente punto es enlazar las variables de la consulta con los placeholders:

mysqli_stmt_bind_param($stmt, 'i', $id);

La parte de i indica el valor a ser esperado.
 
Tipos de valores:

d - decimal
i - entero
b - blob (datos binarios)
s - todos los otros tipos
Un ejemplo utilizando el script de las sesiones donde iniciabamos una sesion, podria ser como la siguiente consulta:

$q = "SELECT user_id,first_name FROM users WHERE email=? AND pass=SHA1(?)";

$stmt = mysqli_prepare($dbc,$q);
mysqli_stmtm_bind_param($stmt, 'ss',$e,$p);
$e = 'correo@ejemplo.com';
$p = 'miclave';
mysqli_stmt_execute($stmt);

Para cerrar la declaracion utilizamos:

mysqli_stmt_close($stmt);

Evitar ataques de fuerza bruta


Este tambien se comenta en las partes de seguridad de php, pero solo vamos a comentar que este tipo de ataques se puede detener ya que la mayoria de las personas la realizan desde la misma IP, con lo cual despues de varios intentos le hacemos un delay (esperar) tantos segundos cada peticion esto lo hacemos con el uso de la funcion sleep() en PHP.

Si te parece interesante esto de los filtros o validacion de tipo de datos pueden adentrarte a algo mas complejo como son las expresiones regulares, de manera que encuentres lo que deseas:

http://arthusu.blogspot.mx/2013/07/phpexpresiones-regulares-pcre.html


Hasta aqui llega esta parte que parece ser la mas corta pero en realidad no lo es ya que tambien se encuentran las partes de seguridad en php al inicio del post.

No hay comentarios:

Publicar un comentario