2012-05-10 6 views
6

¿Hay alguna forma de garantizar que los datos $_POST que recibió mi código provinieran de mi formulario y no una influencia externa? Básicamente, no quiero que alguien pueda falsificar un $_POST en una página disponible universalmente, como la creación de cuentas. Todos los usuarios pueden acceder a la página de creación de cuentas, pero quiero asegurarme de que solo los datos enviados por mi formulario account_creation sean procesados.

Lo único que se me ocurrió fue iniciar un $_SESSION, y luego suministrar el session_id al formulario utilizando una entrada oculta. Con $ _POST, el valor de la entrada oculta se compararía con el session_id actual.

¿Hay un método mejor para lograr este resultado? Si hay ganas de escucharlo.

Respuesta

7

No puede garantizar que los datos provienen de un formulario . Una solicitud POST es solo una solicitud POST, se puede generar de muchas maneras. Un formulario HTML es solo uno de esas formas que es muy fácil de usar. Su servidor necesita validar si los datos recibidos a través de la solicitud POST son válidos o no y si debe actuar en consecuencia o no.

Habiendo dicho eso, hay cosas que pueden ayudarlo a restringir y validar los datos que se envían. En primer lugar, exija que un usuario inicie sesión utilizando cookies (de sesión). Eso elimina las solicitudes aleatorias de usuarios anónimos. En segundo lugar, puede insertar un token como un campo oculto en el formulario que también guarda en la sesión del usuario. La solicitud POST debe contener ese token para que sea válida. El token es simplemente una cadena pseudoaleatoria.
Puede mejorar esto preparando un hash de los campos de formulario que espera que el usuario envíe. Si el valor del formulario debe ser de solo lectura, también puede incluir el valor en el hash. P.ej.:

$rand = md5(mt_rand()); 
$hash = sha1('lastname:firstname:email:' . $rand); 

$_SESSION['rand'] = $rand; 
$_SESSION['hash'] = $hash; 

// on form submit: 

$keys = array_keys($_POST); 
$checkHash = sha1(join(':', $keys) . ':' . $_SESSION['rand']); 
if ($checkHash != $_SESSION['hash']) { 
    die('Form submission failed token validation'); 
} 

Eso es sólo un ejemplo rápido, es probable que desee ordenar alfabéticamente las claves para asegurarse de que obtendrá el mismo hash etc. demuestra el concepto de que el usuario necesite tener un único token para sin embargo, cada solicitud evita que se atempere con los formularios y envíe más o menos datos de los deseados.

Esto todavía no significa que un usuario realmente usó su formulario para enviar los datos.

1

Un poco mejor es agregar validación adicional como user_agent, user_ip y algunos otros $ _SERVER vars: esos son los dos que uso.

Por lo tanto, cree la ID única (o ID de sesión) tal como lo describe, pero agregue un poco de validación adicional que el agente y la IP también coincidan. No a prueba de tontos, pero agrega otra pequeña capa de seguridad.

Editar: Debo agregar que no devuelve al agente de usuario; mantener ese lado del servidor y validar en silencio contra la identificación de la sesión devuelta.

Además, si una presentación falla la validación, nunca la revele al usuario el motivo por el cual, de esa manera, un truco no sabe cómo lo hace. También puede agregar el seguimiento de "5 inválidos y está fuera", pero debe ordenar el inicio de sesión para eso.

1

El uso de la ID de sesión es sin duda una forma de hacerlo. Pero hay otras opciones más (si no todas) de las cuales implican agregar algunos datos como un campo oculto.

  1. Utilice un CAPCHA. Eso siempre será único para cada carga de página y, por lo tanto, es obligatorio usar su formulario.
  2. Genere datos aleatorios y guárdelos en la base de datos (o simplemente en la variable $_SESSION) y verifíquelos una vez que se haya enviado el formulario.

La opción uno es la que recomiendo para un formulario de creación de usuario, ya que requiere una doble función. Detiene el envío automático de su propio formulario, al tiempo que garantiza que los datos de $_POST provengan de su propio formulario.

0

Este es un patrón de patrón estándar para evitar XSRF. Esencialmente es similar a lo que mencionaste. El servidor crea un token aleatorio cuando se genera el formulario para el usuario. Está vinculado a una cookie de navegador para el usuario. Al enviar el formulario, se envía de vuelta al servidor. El servidor compara el token con lo que se emitió y la acción de forma se realiza solo después de una coincidencia exitosa.

0

Hay muchas buenas referencias de poner un valor único en la forma y coincidir con el valor almacenado en la sesión del lado del servidor. Haga eso, pero también piense en lo que sucede cuando un usuario usa el botón Atrás y posiblemente intenta enviar el formulario dos veces, o abren una segunda ventana del navegador (¡la misma sesión!), O usan múltiples formularios en su sitio.

No cree errores locos al no pensar en su sistema.

+0

Gracias por esto, no había pensado en las otras implicaciones que podría tener esta acción. Aunque creo que estos problemas podrían evitarse usando algo como esto 'if (! Isset ($ _ SESSION ['hash'])) {create hash} else {use hash existente}'. –

2
$ref = $_SERVER['HTTP_REFERER']; 
if($ref !== 'some site path/index.php') 
{ 
    die("Access Denied!"); 
} 

Esto debe evitar que la mayoría de la gente coloque los datos de su base de datos a partir de una influencia externa.

Cuestiones relacionadas