seguridad en paginas con selects dependientes

Raul
05 de Junio del 2004
Hola, actualmente estoy trabajando con una página Web que trabaja con selects dependientes(ej. Países, ciudades) tomando los datos desde una base de datos. Así por ejemplo, cuando el usuario escoge un país de la lista, automáticamente se lanza un llamado a otra página, la cual se redirige nuevamente a la página inicial pero agregando al campo de ciudades, todos los valores asociados a las ciudades pertenecientes al país escogido inicialmente por el usuario. La página que ejecuta la acción de redirigir(pagina.php) utiliza la función php header, ej. header("location:information.php?var1=$var1&var2=$var2&...varn=$varn"). Desgraciadamente al abrir la página information.php, el usuario puede ver los nombres de las variables y los valores asignados a cada una. Mi pregunta es cómo hago para que el usuario no pueda ver estas variables y su contenido? Cómo podría usar el método POST o algo similar para solucionar esto? Qué problemas de seguridad podría tener?


Por otro lado, cuando el usuario llena todo el formulario information.php y lo envía, la forma que lo recibe(pagina.php) ejecuta la acción de guardar en la base de datos. Sin embargo si el usuario hace clic sobre el botón actualizar en el navegador, un nuevo registro es guardado, dado que la llave primaria de la tabla es una secuencia que se genera automáticamente. Mi otra pregunta es cómo hago para que un usuario no me llene la base de datos de registros repetidos por el simple uso de un botón del navegador?

Covi
05 de Junio del 2004
Ummm, no estoy seguro del todo de lo que preguntas, pero entiendo que más o menos es controlar un poco la inserción y envio de datos por parte del usuario a través del formulario ( Algo muy importante!... y peligroso: SQL Injection).

Bueno, al lio, esto sería bastante largo, yo llevo unos días filtrando mis forms.

Lo primero que te aconsejaría sería no llamar a las páginas directamente, por el nombre de archivo, sino utilizando "alias" o cualquier otra forma ( ejemplo de webs modulares de ZonaPHP, y todos los sistemas de plantillas o CMS, etc )
Al usar DB será más fácil para tí, puedes tener un listado de modulos o páginas en la db y realizar una consulta para buscar el archivo a cargar con determinado "alias", enlace o nombre: index.php?pagina=2 ...., si se introduce un url no válido cargar pagina_defecto...

Bien, los formularios:

Lo primero que se me ocurre y como seguridad, es la filtración de los datos introducidos, pese a ser selects un usuario malintencionado puede enviar los valores que desee para confundir la consulta MySQL, desbordar la DB, obtener datos de conexion y privilegios ( SQL Injection ).
En tu caso al ser SELECTS, es más fácil aún restringir los envios que en INPUTS o TEXTAREAS:

function limpia_datos($variable)
{
$dato = trim($variable);
$dato = strip_tags($dato);
$dato = str_replace("\", "",$dato);
$dato = str_replace("'", "",$dato);
$dato = str_replace("&", "",$dato);
$dato = str_replace("|", "",$dato);
return $dato;
}
?>
Lo que veas, así como la restriccion final:
function validar_dato($dato)
{
if (eregi('españa',$dato))
// cualquier caracter:
// if (eregi('^[a-zA-Z0-9_]+$',$dato))
return true;
else
return false;
}
etc.
De la redirección, no entiendo porqué el usuario puede ver las variables, ¿te refieres a verlas en el url???... en ese caso se me ocurre hacer un array con todas las variables para pasarlo por URL y luego sacarlas tú en tu script de proceso.

También creo que sería lógico procesar el formulario a través de funciones en vez de páginas únicamente:
por ejemplo
<form method=post" action="$procesa_form">

luego puedes mandar o mostrar los inputs necesarios según las opciones:
si no rellena el formulario indicar el error y mostrarlo de nuevo, lo mismo para recargarlo.
Si todo ok!, lo mandamos a la función de inserción, actualización, borrado... lo que necesites.

Si form no ok
Vista Previa:
<input type="hidden" name="insertar_mensaje" value="no">

Si form ok:
Enviar:
<input type="hidden" name="insertar_mensaje" value="si">

luego la funcion de insercion o lo que sea:

if ((isset($_POST["insertar_mensaje"])) && ($_POST["insertar_mensaje"] == "si"))
{
// Consulta SQL
}

Para las repeticiones, depende del tipo de tabla o datos, etc...
Puedes usar IP ;( para restringir x numero de envios, muy cutre.

Usar el id único de la tabla DB si no pones autoincrement, eso sí tendrás que incrementar tú y si tienes muchos envios controlar la última inserción.

Y por último, creo que lo mejor y lo que yo uso, crear un id único para cada envio, por ejemplo, sumando caracteres de campos, o lo que sea, algo que haga único ese envio dependiendo de lo que se envie.

Luego buscas en la db, si encuentra ese id es una repetición y no procesas.

En fin, espero no haberte liado o no haber parecido pretencioso, seguro que sabes todo lo que te comento pero, solo es por ayudar un poco.

Un saludo.