Seguridad en ajax

Iniciado por Gorky, 4 Enero 2012, 13:32 PM

0 Miembros y 1 Visitante están viendo este tema.

Gorky

Hola foreros:

Quisiera saber como solucionar el siguiente problema de seguridad.
Estoy realizando una aplicación que va haciendo llamadas desde ajax y me gustaría saber como evitar que los archivos php se puedan ejecutar directamente sin pasar por el flujo normal de la aplicación.
En el caso de que fuesen llamadas normales a archivos php se que se puede hacer declarando una variable en el archivo padre y comprobando si esta definida en el hijo pero si hago eso me encuentro con que nunca esta declarada ( y es lógico que no lo esté ).
¿Se os ocurre alguna solución para mi problema? Muchas gracias.

#!drvy

2 soluciones.

1. Con un .htaccess para restringir la ejecución de archivos .PHP o ciertos archivos.

Para restringir los archivos PHP (que no puedan ser ejecutados), debes crear un .htaccess en la carpeta donde están alojados y introducir lo siguiente:
Código (apache) [Seleccionar]
<FilesMatch "\.(php)$">
Order Allow,Deny
Deny from all
</FilesMatch>


Si lo que quieres es restringir un determinado archivo, haz el mismo procedimiento de antes, solo que introduciendo lo siguiente:
Código (apache) [Seleccionar]
<files nombre.php>
order allow,deny
deny from all
</files>


2. Usar un token.
Me explico, un token es un numero (normalmente cifrado en md5) aleatorio, que se suele guardar en una cookie o en sessiones.

Este "token" permite comprobar si se ha pasado antes por un procedimiento, o la función/archivo ha sido solicitado directamente.

El código que generaría el token puede ser este:

Código (php) [Seleccionar]

<?php
function generar_token(){
   @
session_start();
   
$token md5(mt_rand(11,99999));
   
$_SESSION['token']=$token;
   return 
$token
}


Puedes incluirlo o solicitarlo al principio de la pagina y luego llamarlo cada vez que necesites ejecutar una función para que lo compruebe.

El código para que lo compruebe seria este:

Código (php) [Seleccionar]

<?php
function comprobar_token($token){
    @
session_start();
    if(
$_SESSION['token']===$token){return true;}else{return false;}
}
?>



Si necesitas mas ayuda o explicación solo comenta   :)

Saludos

Gorky

Muchas gracias por responder drvy | BSM
Me parece mejor opción la segunda pero tengo alguna laguna.
De la forma que lo he entendido, seguiría teniendo el mismo problema ya que al pasar por la función que escribe la variable de sesión (que suponemos que estaría en el archivo padre) ya tenemos la puerta abierta a ejecutar el resto de archivos php.
O dicho de otra forma. Si ejecutamos los archivos hijo al principio nos reconocería que no hemos pasado por el padre pero si ejecutamos el padre y acto seguido el hijo lo ejecutaría sin problema.
Corrígeme si me equivoco por favor.

#!drvy

#3
Pues no te entendí pero creo que te entendí  :rolleyes:

Según lo que he entendido, crees que seria lo mismo porque las 2 se llamarían desde el mismo archivo.

No. La función para comprobarlo estará en el archivo padre, pero la de generarlo estará en el que solicita la acción. Y cada vez que necesites hacer una acción tendras que mandar el token también. Asi te evitas el mal uso.

Te explico.

Tenemos 2 archivos.

Digamos que jbb.php es el que procesa la informacion que envias mediante ajax desde ajax.php por ejemplo.

en jbb.php al principio tendrias algo asi:

Código (php) [Seleccionar]
if(!comprobar_token($_POST['token'])){
die('El token no es valido, utilice nuestra web y no acceda diractamente.');
}


Esto me imagino, que sabes, que lo que hace seria llamar la función comprobar_token con el POST 'token',

Bueno y imaginemos que el  ajax.php tendra algo asi al principio.

Código (php) [Seleccionar]

<?php
$token 
generar_token();
?>



Entonces, tu cada vez que envíes algo por ajax hacia jbb.php, tendrás que incluir la variable $token como parámetro(post).

Ejemplo total:

Archivo jbb.php (el que procesa)
Código (php) [Seleccionar]

<?php
function comprobar_token($token){
@session_start();
// Comprobar si la session esta inicida.
if(!isset($_SESSION['token'])){
return false;
}
// Comprobar si es el mismo que tenemos
// nosotros guardado.
if($token==$_SESSION['token']){
// si es valido devolver true;
return true;
} else {
// si no es valido, devolver false
return false;
}
}

// Si comprobar_token(..) devuelve false, morir.
if(!comprobar_token(@$_POST['token'])){
die('El token no es valido, utilice nuestra web y no acceda diractamente.');
}

// Tu codigo
// ejemplo:
echo 'Holaaaa usuario: '.$_POST['nombre'];
?>



Archivo ajax.php (el que pide)
Código (html4strict) [Seleccionar]

<?php
function generar_token(){
@session_start();
$token md5(mt_rand(11,99999));
$_SESSION['token'] = $token;
return $token;
}
$token generar_token();
?>


<html>
<head>
<title>alalal</title>
<!-- Yo utilizare jquery porque es mas facil xD -->
<script src="http://code.jquery.com/jquery-1.7.1.min.js" ></script>

<!-- Llamar jbb.php con parametros -->
<script>
$(document).ready(function() {
$("#formulario").submit(function(e){
e.preventDefault();
$.post("jbb.php", $("#formulario").serialize(),function(data) {
  alert(data)});
});
});
</script>
</head>
<body>
<div>
<form id="formulario" action="jbb.php" method="POST">
<label>Nombre:</label>
<input type="text" name="nombre"/>
<!-- Importante, meter el token como campo oculto -->
<input type="hidden" name="token" value="<?php echo $token?>" />
<input type="submit" nombre="enviar" value="Comprobar" />
</form>
</div>
</body>
</html>


Asi, si llamamos directamente al archivo jbb.php te devolverá esto:
El token no es valido, utilice nuestra web y no acceda directamente.

Y si lo llamas sin el campo token también xD



Saludos