jueves, 18 de julio de 2013

Seguridad PHP - Autenticación HTTP vs PHP (formularios)

Aunque puedan haber ventajas con el uso de autenticación HTTP, sus desventajas hacen que en la mayoría de los caso se opte por una identificación basada en formularios. En vez de confiar en la identificación a nivel de protocolo. Aquí tenemos algunos inconvenientes:

- La nula posibilidad de 'customizar' que proporciona las ventanas emergentes de identificación HTTP. Las ventanas donde se introducen los datos en este tipo de identificación no permiten modificar su estilo. Lo que hace que tengan un estilo completamente diferente al del resto de la aplicación. Y eso quita atractivo a la aplicación/página web.

- En la autenticación HTTP la información de identificación es recordada hasta que se cierra el navegador. Si no se cierra el navegador seguirá recordando tus datos por lo que no los pedirá. Ya que no proporciona un método sencillo para que el usuario finalice la sesión. Por lo que hay que utilizar algún que otro 'truco'.
La consecuencia de esto es que si otra persona intenta entrar en el sitio web podrá entrar haciéndose pasar por ti, ya que no se le solicitaría ningún tipo de credenciales.

miércoles, 17 de julio de 2013

Seguridad PHP - Autenticación HTTP digest

Si la autenticación HTTP básica anterior no se combina con HTTPS, estamos trasmitiendo la información codificada en base-64. Pero no encriptada o usando algoritmos 'hash'. Lo que es muy fácil de decodificar y es prácticamente como si la enviásemos en texto plano.
Por eso el mecanismo que se presenta a continuación, mejora al anterior, transmitiendo la contraseña como un valor resultante de un algoritmo 'hash'. Lo que lo hace algo más seguro. O por lo menos era más seguro hace unos años. Ya que el algoritmo usado es MD5.  Y es bien sabido, que este algoritmo es vulnerable (por fuerza bruta) desde hace tiempo.
El propósito del esquema de autenticación HTTP digest es permitir que los usuarios prueben que ellos conocen una contraseña pero sin revelar dicha contraseña. Al contrarío que la identificación HTTP básica, en esta se crea un hash de diferentes datos usando la contraseña. El hash implica la creación de una cadena basada en datos que tanto el usuario (y por lo tanto el cliente) y el servidor conocen. Pero en definitiva, se envía el hash y no la contraseña. Lo que en caso que alguien consiga interceptar la conexión y suplantar al usuario, no disponga de la contraseña. Que normalmente es requerida para cambios de configuraciones en lo sitios web.

Seguridad PHP - Autenticación HTTP básica

La autenticación básica HTTP es un sencillo mecanismo con el que un servidor puede solicitar información de autenticación (un ID de usuario y contraseña) de un cliente. El cliente pasa la información de autenticación al servidor en una cabecera de autorización. Dicha información se encuentra codificada en base-64. Dada su poca seguridad, es útil para sistemas con un número muy limitado de usuarios y donde la protección no es muy importante. Por ejemplo para sistemas donde solo se quiere evitar usuarios anónimos para acceder al algún recurso.

Proceso:

1. El navegador (cliente) iniciará la comunicación realizando la petición al servidor. Y enviará las siguientes cabeceras (similar) al servidor:

 GET /download/report.doc HTTP/1.1   
 Accept: application/msword, */*   
 Accept-Language: en-ES  
 Accept-Encoding: gzip, deflate   
 User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)   
 Host: ejemplo.com  
 Connection: Keep-Alive  

martes, 16 de julio de 2013

PDO - Parte 2

Otras funciones útiles de PDO 

Existen tres funciones importantes para obtener información de la consulta ejecutada sin tener que recorrer los resultados:

A) Obtener el id de la última fila o secuencia insertada en la base de datos.

 public string PDO::lastInsertId ([ string $name = NULL ] )  

El parámetro $name opcional, sirve para indicar el nombre de columna. Como PDO depende de los drivers para cada gestor de base de datos soportado, en alguno de estos quizás sea necesario especificar el nombre de columna que almacena los identificadores. Como ocurre en PostgreSQL.

 $conn = new PDO('mysql:dbname=test;host=127.0.0.1', 'user', 'password');  
 $stmt = $conn->prepare('INSERT INTO test (name) VALUES (:name)');  
 $stmt->execute([':name' => 'foo']);  
 var_dump($conn->lastInsertId());  

Recuerda que la función es de la clase PDO y no de PDOStatement.

PDO - Parte 1

La extensión PDO nos facilitará mucho la vida a la hora de trabajar con bases de datos, ya que nos permite abstraernos del tipo de gestor de base de datos que estemos utilizando. Esto quiere decir que sin el uso de PDP, si por ejemplo decides migrar tu aplicación de MySQL a PostgreSQL tendrías que cambiar todos los métodos del conector de MySQL por los métodos de PostgreSQL. Con PDO bastaría con que se cambie únicamente la creación del objeto PDO, donde se especifica el tipo de base de datos a conectar, y el resto de la aplicación seguiría funcionando igual. Por lo esta abstracción del acceso de datos convierte a esta extensión en un elemento muy importante para la portabilidad de la aplicación/web.
PDO además te permitirá usar consultas preparadas. Y como vimos en el caso de la extensión MySQLi nos proporciona una herramienta muy importante en seguridad y rendimiento.
- Se encargan de 'desinfectar' los datos automáticamente.
- La separación de lógica y datos hace que la consulta sea analizada/preparada una única vez y se pueda ejecutar múltiples veces con los mismos datos o similares. Evitando cada vez el ciclo de análisis, compilación y optimización que ocurriría en cada consulta no preparada.
- Al igual que Mysqli, proporciona el uso de transacciones.

miércoles, 10 de julio de 2013

Cookies en PHP

Básicamente una cookie es un fichero de texto almacenado en el navegador de un cliente por orden de un sitio web. En estos ficheros, de tamaño máx. 4 KB se almacena información útil para el servidor como podría ser información del último acceso o información para la personalización de la web de un usuario concreto. Una cookie solo puede ser leída por el sitio web (dominio) que la creó.
Hay un limite de cookies que el navegador puede almacenar:
- 20 cookies para un servidor o dominio
- 300 cookies en total.
Ya que estas se almacenan en el disco duro del usuario, hay que tener cuidado con la posibilidad de que dicho usuario desactive su uso. En dicho caso no se almacenarán. Por lo que hay que tener previsto otro tipo de almacenamiento si la persistencia de información en cookies es indispensable para el sitio web.

Una cookie se envía junto a las demás cabeceras HTTP. Por lo tanto se exige lo mismo que exigíamos cuando queríamos enviar dichas cabeceras. Que no haya ninguna salida (elemento html, espacio en blanco o salida del script) anterior al envío. http://programandolo.blogspot.com.es/2013/07/redireccionamiento-php.html

domingo, 7 de julio de 2013

Sesiones en PHP

PHP en cada petición ejecuta el script correspondiente de principio a final. Y hay ocasiones en que sin necesitar la persistencia de datos que ofrece una base de datos, necesitamos almacenar de alguna forma ciertos datos mientras el usuario este utilizando la aplicación/web.
Y al igual que los arrays superglobales asociativos $_GET  y  $_POST existe otro  de especial importancia para dicho almacenamiento de datos: $_SESSION.  Cada vez que un usuario entre en el sitio web, podremos iniciar una sesión con un identificador exclusivo para dicho usuario y se podrán almacenar datos por medio del array $_SESSION hasta que decidamos finalizar una sesión. Dicho ciclo de inicio y fin suele coincidir con login y desconexión del sistema por parte de un usuario.
Internamente, el servidor, almacena los datos del array superglobal de la sesión en un archivo temporal cuyo nombre está formado por 'sess' + dicho ID de sesión (depende de la configuración de php.ini).

Uso de sesiones

1. Inicializando

 session_start();  

Con esta función no solo iniciaremos una nueva sesión particular en el servidor, sino que reanudaremos una posible sesión existente. Ya que al haber iniciado una sesión nueva, el identificador único que se crea es pasado por medio de una cookie al cliente. De esta manera el servidor sabrá si existe una sesión que tiene que recuperar o no. Dicha cookie por defecto se llamará PHPSESSID aunque podremos modificar el nombre en el el archivo php.ini (etc/php5/apach2/php.ini).

miércoles, 3 de julio de 2013

Redireccionamiento en PHP

En PHP existe una función llamada header() que se encarga de especificar una cabecera HTTP.
Dicha función debe de ser llamada antes de mostrar nada por pantalla. De otra manera se producirá un error.
Cada vez que enviamos una salida desde el servidor al cliente (o viceversa) dicha información será enviada junto a un conjunto de cabeceras HTTP. PHP enviará cabeceras aunque no las especifiquemos. Estas cabeceras serán por defecto si no se han sobreecrito con header(). Por lo tanto si existe alguna salida anterior a la llamada de header(), ya se habrá procesado el envió de cabeceras. Y se producirá el error: "headers already sent".

 void header ( string $string [, bool $replace = true [, int $http_response_code ]] )  

- El primer parámetro es la cabecera que indicará la acción a realizar. Las tres cabeceras más habituales, en header() son:
  • "Location ...". Es el uso más típico de header(). Con  este encabezado redirigimos a la dirección especificada y enviará un código 302 (redirect) de estado. Por lo tanto enviará las cabeceras especificas hasta el momento y procederá a realizar una redirección. Podemos introducir una ruta relativa al servidor o una absoluta. 
 header("Content-Type: application/json;charset=utf-8");    
 header("Location: info.php");  
  • "HTTP/...". Especificaremos una cabecera que especificará un código de respuesta HTTP de la respuesta al navegador. 
 header("HTTP/1.1 200 OK");   
  • "Content-Type ..." Con esta cabecera especificaremos el formato de la salida que mostrará el navegador del cliente.
  header("Content-Type: application/json;charset=utf-8");   

martes, 2 de julio de 2013

Formularios y PHP

Cuando un usuario rellena un formulario HTML y presiona el botón (input) de tipo 'submit' toda la información que este haya introducido en los distintos controles será enviado a la dirección (script) y mediante el método indicado.
Ciclo de envío de formulario a un servidor PHP

El método utilizado para el envío de los datos al servidor, indicará como viajan los datos hacia él.

A) GET

- Todos los nombres de los campos y valores viajan por la URL (query strings).
- Como son mostrados por la URL el navegador los almacena en su historial. Lo que no es muy conveniente para el caso de información sensible y más si ese ordenador puede ser usado por más personas. Además que el usuario despistado puede compartir datos al compartir la URL.
- Debido a esta hay una restricción de longitud de los datos. La longitud máxima de la URL es de 2048 caracteres.
- Los datos enviados al servidor, al viajar por la URL, pueden quedar almacenados en los ficheros de 'logs' del mismo.
- Solo se permite enviar datos ASCII.
- Resultados de operaciones GET pueden ser cacheadas. Lo que quiere decir que múltiples llamadas a un servicio pueden resultar una única petición.
- Tipo de codificación (enctype): application/x-www-form-urlencoded. Es el tipo por defecto, además del único, por lo que no es necesario indicarlo.

lunes, 1 de julio de 2013

Extensión MySQLi - Parte 4: Transacciones

Las transacciones con la extensión MySqli son un mecanismo que nos asegura que todas y cada de las consultas que las forman van a ser ejecutadas. En el caso de que falle alguna declaración, la transacción no se llevará a cabo.

Pero tenemos que tener cuidado con el tipo de tabla o tablas sobre las que vamos a realizar la transacción. Como sabemos los tipos más comunes de motores de almacenamiento de tablas en MySQL son MyISAM y InnoDB. Siendo el primero el que se utiliza por defecto si no se dice nada y que excluye la seguridad proporcionada por la integridad referencial. Sin embargo con este tipo no se permiten transacciones. Así que transacciones solo se pueden llevar a cabo sobre tablas InnoDB.

Fases de las transacciones

1. Iniciar transacción - Autocommit

Por defecto, MySQL se ejecuta en modo autocommit. Tener activo el modo de ejecución automática (autocommit) significa que cada consulta se tratará como una transacción individual.  Lo que  conlleva a  que tan pronto como se ejecuta una sentencia se modifica una tabla de MySQL. Haciendo imposible la vuelta atrás (modificación permanente). Pero gracias a InnoDB y a las transacción, las consultas se puede revertir (roll back). Y para ello tenemos que desactivar el citado modo de ejecución automática. Lo que iniciará la transacción.