Después de que mi buen amigo/enemigo Ddaz, me pusiera unas arrastradas en cuanto a seguridad web hace meses, me vi en la tarea de aprender un poco mas en este escabroso asunto de la seguridad de formularios. Por la complejidad de la seguridad en formularios dividiré este manual en 2 o quizás 3 partes. Comenzaremos pues, con los envíos de formularios en PHP. Para enviar al servidor web un formulario, en el atributo ACTION del formulario debe ir una pagina o secuencia PHP. Cuando se envían estos datos, dependiendo del método en el que se envían, sera la manera en la que se recuperan. Los métodos son GET o POST, de igual manera PHP tiene dos matrices superglobales $_GET y $_POST respectivamente, donde se quedan guardados los datos del formularios de acuerdo al método con el que se enviaron.
Estas matrices, se asocian directamente al nombre o atributo NAME del campo del formulario, por tanto el valor de la variable $_GET['edad'] contendrá el valor del objeto HTML cuyo atributo NAME sea edad. El uso de la matriz $_GET supone que el formulario fue enviado por el método GET, en caso contrario de que fuera enviado por el método POST, estaría en la variable $_POST. Hay una tercera opción que es $_REQUEST, que guarda todos los datos enviados, sin importar el método, sin embargo por cuestiones de seguridad, no se recomienda utilizar esta variable.
Si se usa de atributo NAME un . como por ejemplo myformulario.edad, la manera de acceder a el seria $_GET['myformulario_edad'].
También requerimos el conocimiento sobre las sesiones en PHP. Para iniciar una sesión se utiliza el comando session_star(), aunque hay otros dos métodos, este es el que requerimos; debemos recordar que el comando debe estar al inicio del archivo de PHP antes de cualquier otra instrucción. Para registrar una sesión, utilizamos el comando session_register($nombre_de_vriable [, $siguiente_nombre_de_variable [, ...] ]).
Ademas de esto necesitaremos un método de encriptacion. Pueden usar el anteriormente mencionado o bien uno de su propia creación, la cuestión es que encripte, aunque recomiendo MD5 y el ejemplo lo haré sobre este tipo de encriptacion.
Integridad de los datos del Formulario
Para proteges la integridad de los datos, debemos agregar un campo oculto que contenga un valor único de sesión (para esto debemos maneras sesiones de usuarios), en este caso registraremos una sesión y la encriptaremos.
< ?php session_start(); $_SESSION['USUARIO'] = 'Nombre_de_usuario'; $_SESSION['LLAVE'] = MD5($_SESSION['USUARIO'] . 'Frase_unica');?><input name="seguro" value="<?=$_SESSION['LLAVE']?/>" type="hidden" />
Con esto ahora podremos hacer la validación para asegurarnos de que efectivamente el formulario proviene del usuario al que se envió originalmente. Se encripta para evitar que falseen la identidad y se agrega una frase unica que solo el servidor conozca, para evitar el desencriptamiento del mismo. Para la validación se haría la siguiente sentencia:
< ?php
session_start();
if(md5($_SESSION['USUARIO'] . 'Frase_unica')==$_GET['seguro']){
echo 'Formulario proveniente de usuario valido';
}else{
echo 'Datos no seguros';
}
?>
Para mayor seguridad, se puede hacer que la sesión caduque cada determinado tiempo, dándole al usuario un tiempo limitado para completar el formulario y enviarlo.
Validación básica de un Formulario
Para validar un campo, no se debe hacer en el cliente, puesto que un usuario mal intencionado, puede enviar los datos “falseados” a servidor. La validación (generalmente) javascript que se realiza en el cliente, es exclusivamente para que el usuario promedio, sepa que o como debe escribir en el formulario, jamas deben hacerse validaciones de otro tipo que no sean enfocadas a este aspecto. Por lo tanto la validación de los datos provenientes de las variables superglobales $_POST y $_GET, deben hacerse en el servidor.
Como cada campo, requiere de una validación muy especifica (cada situación es diferente), aquí solo pondré como validar u numero Telefónico, evitar la inyección de sql y validar que el usuario tenga permisos para realizar dicho movimiento.
1.- Funciónes para validar un campo de formulario
< ?php
function email($valor, $nombre) {
$valido = "/^\([1-9][0-9]{2}\)[1-9][0-9]{3}-[0-9]{4}/i;
if(preg_match($valido,$valor) != 1 ) {
return 'El valor del campo '.$nombre.' es incorrecto';
}
return true;
}
?>
La función seria llamada con el valor que se reciba en la variable $_POST, incluido con el nombre del campo. Si regresa true, se procesa, en caso contrario, se mostrara el mensaje de error. Este es solo un ejemplo de como se deben validar en el servidor los valores. Si pasa la validación, se debe pasar por un filtro para limpiarlo por código malicioso, la función para esto seria:
< ?php
function nosql($var){
$var=mysql_escape_string($var);
$sen=array("SCRIPT"," AND ", "+" ,"SELECT", "UPDATE", "INSERT", "DELETE", "<>", "*","DROP","WHERE","\'"," OR ","ALERT");
$cache=str_replace($sen,"",strtoupper($var),$num);
if($num>0){
return false;
}
return true;
}
function seg($var,$min,$max){
$var=mysql_escape_string($var);
if(is_null($var)){
return false;
}elseif(strlen($var)< $min){
return false;
}elseif(strlen($var)>$max){
return false;
}
return nosql($var);
}
?>
// La función seg, tiene tres parámetros, el valor del campo, el máximo y mínimo
// de caracteres permitidos para dicho valor.
Una vez mas, cada parámetro debe ser pasado por esta validación, en caso de que algún parámetro no pase la validación, se debe considerar la posibilidad de que un usuario malicioso esta intentando dañar los datos o la aplicación, por tal motivo puede bannearse la ip del usuario por determinado tiempo.
Para este punto, hemos logrado dos cosas: Que el dato venga en el formato que requerimos, que no contenga código malicioso. Ahora solo debemos asegurarnos, que el usuario tenga los permisos para realizar la acción que deseamos con los datos.
Este paso es un poco mas complicado, así que lo dejare para el próximo manual, incluyendo la encriptacion de paginas y las huellas digitales.
Dias inolvidables… en los que te tronaba todo en la cara jeje…, pero bueno ya mejoraste…
salu2
Ddaz Ddaz(Seleccionar comentario)
Me gusta el manual, si me pudieras mandar una copia a mi mail de este y la continuación te lo agradecería enormemente, la verdad estoy preocupado porque tengo varios sitios de clientes desarrollados de forma no tan segura por un desarrollador que contrate y son fallas bastante graves… saludos! y gracias ya con esto me doy una idea… Chava(Seleccionar comentario)
no entiendo esta linea podrías explicarla bien? me suena a jeroglífico jejeje
$valido = “/^\([1-9][0-9]{2}\)[1-9][0-9]{3}-[0-9]{4}/i; Anonimo(Seleccionar comentario)
$valido = “/^\([1-9][0-9]{2}\)[1-9][0-9]{3}-[0-9]{4}/i;
preg_match($valido,$valor);
Lo que generamos es una cadena de validación para la función preg_match. Esta función nos devuelve el numero de coincidencias que tendría $valido, de acuerdo al patrón que generamos en la cadena $valor.
En este caso en especifico le indicamos un numero de teléfono (acabo de caer en cuentas que esta mal, porque debería ser un email, pero bueno…) le indicamos que debe contener [1-9][0-9]{2} (dos caracteres {2}, el primero debe contener un valor comprendido entre el 1 y el 9 [1-9] y el segundo debe tener un valor comprendido entre el 0 y el 9 [0-9] y deben estar entre parentensis: \([1-9][0-9]{2}\)
preg_match(“([1-9][0-9]{2}\)”,”(26)”); // Devuelve uno
preg_match(“([1-9][0-9]{2}\)”,”(01)”); // Devuelve cero
preg_match(“([1-9][0-9]{2}\)”,”12″); // Devuelve cero
Para mas información sobre esto puedes consultar funcion preg_match Antioroku(Seleccionar comentario)
hola escribo por que tengo una web en la cual estan insertando span e creado un capcha y no me sirve de nada me gustaria saber que puedo hacer juan carlos(Seleccionar comentario)
hola saludos muy interesante este post pero tengo una pregunta, yo estoy haciendo un software en php con mysql y pues hize un login y utilice sesion pero resulta que cuando cierro sesion y le doy atras me muestra la pagina anterior y y eso que destruyo la sesion cuando dan el vinculo cerrar sesion y no quiero que me muestre lo anterior, alguna ayuda? Jonathan Mendoza(Seleccionar comentario)
hola saludos yo estoy haciendo un control de entradas y salidas de personal con php y mysql pero el registro debe de ser con huella digital y nesecito saber como conectarlo con php o que consejo me das agradecere demasiado tu respueta. gracias edwar ortega(Seleccionar comentario)
Muchas gracias, claro, útil y conciso. mcartur(Seleccionar comentario)