El sistema de modulación de naveda, tiene (quizás) una pequeña vulnerabilidad que encontré mientras hacía mi propio sistema...
Este es el código de naveda:
<?PHP
if (isset($_GET['id'])) {
if (!empty($_GET['id']) && $_GET['id'] != "index") {
if (file_exists($_GET['id'].".php")) {
include ("./".$_GET['id'].".php");
} else {
echo "No existe esta seccion";
}
} else {
include ("principal.php");
}
} else {
include ("principal.php");
}
?>
Si os fijáis, comprueba si está el
?id=, luego comprueba que no esté vacío y que no sea
index (porque sino se crearía un bucle infinito, el index llama al index, ese hace lo mismo que el anterior, y por eso se crea un bucle infinito) y finalmente comprueba que el archivo existe en el servidor... aquí es donde falla... ¿por qué? porque si en vez de
?id=archivo pongo
../archivo sube un directorio y ¡CHAN! ya puede acceder a aquellos archivos a los que hemos prohibido que se acceda directamente (y justo por eso usamos sistema de modulación). Para solucionar ese detalle, simplemente debemos añadir a esta línea:
<?
if (file_exists($_GET['id'].".php")) {
?>
un preg match, así:
<?
if (file_exists($_GET['id'].".php") && preg_match('/^[a-zA-Z0-9\-_]+$/i', $_GET['id'])) {
?>
Te preguntarás, ¿qué hace el preg match? se llama expresión regular, y se usa así:
<?
preg_match('/aqui tu expresion regular/modificadores', $dondebuscar);
?>
El mío hace esto:
- Donde dice [] significa que se admiten solamente los caracteres que están dentro de los corchetes
- En el primer parámetro, siempre hay que poner esto: '/^$/'... entre el ^ y el $ está la expresión
- a-zA-Z significa que se admiten solamente letras, sin importar si son mayúsculas o minúsculas
- 0-9 admite números, hasta ahora tenemos letras y números
- \- y _ hace que también se admitan guiones y guiones bajos (- y _)
- Y el + del final, significa que puede ser más de una letra (se puede repetir una o más veces)
- El segundo parámetro es la variable o string en el que buscar, en este caso, en el GET
En resumen, compruebo que no hay caracteres raros (como por ejemplo una barra
/ o puntos
.., porque poniendo
../ sube un directorio, y ya está fuera de control...)
Así nos aseguramos que solamente se incluirán archivos del directorio actual

PD: Si queréis poner barras, para ingresar así:
?do=categoria/info, simplemente reemplazad el preg match de antes por este:
<?
preg_match('/^[a-zA-Z0-9\-_\/]+$/i', $_GET['id']);
?>
Le puse
\/ al preg match, así admito barras (
/ ), pero ¿por qué 2 barras en vez de una?
Porque hay que escapar la barra con otra barra (invertida), para más información, visita
wikipediaSaludos, y espero que os ayude
