Contactar con soporte

Respondemos por correo, normalmente en dos días.

Google reCAPTCHA revisa este envío frente a abusos; se transmiten datos a Google. El script se carga solo al abrir el formulario.

← Todas las entradas

Una copia en el directorio web es una fuga de código

Antes de editar un archivo grande, el gesto natural es copiarlo primero. cp index.php index.php.antes-del-cambio, y a trabajar. Si ese archivo está en el directorio que publica el servidor web, acabas de dejar todo tu código fuente descargable como texto plano — credenciales de base de datos, secretos, todo lo que el archivo contenga.

Apache pasa index.php por PHP porque termina en .php. index.php.antes-del-cambio no termina en .php. Termina en .antes-del-cambio, que Apache no ha visto nunca, así que hace lo predeterminado y envía los bytes.

La regla que casi todos escriben, y por qué no basta

La protección habitual es una lista de extensiones prohibidas: .bak, .orig, .save, .sql, .old. Atrapa el archivo en el que pensaste. Probada aquí, esa lista dio la respuesta correcta para probe.bak y la equivocada para todos estos:

  • index.php.vor-xyz — así ocurrió de verdad
  • index.php.2026-08-19
  • index.php.kopie
  • style.css.alt
  • index.php.1

Todos servidos con 200. El patrón de nombre en el que no pensaste es justo el que vas a usar, porque las copias se nombran según lo que estabas haciendo en ese momento.

Invertir el corte

La regla que funciona no pregunta qué extensiones están prohibidas. Hace una pregunta estructural: ¿contiene este nombre de archivo una extensión de código que no esté al final?

Si la contiene, es una copia de algo que debía ejecutarse, diga lo que diga el sufijo posterior. index.php.loquesea coincide. style.css.loquesea coincide. El patrón cubre los nombres que nadie ha inventado todavía, que es justo de lo que se trata.

Comprobado hoy contra el servidor en marcha: los cinco nombres de arriba devuelven ahora 403, incluidos los que no existen — la regla le niega el paso a la forma, no al archivo.

La excepción, y qué enseña

Un nombre de archivo legítimo aquí tiene exactamente esa forma: los recursos precomprimidos se escriben como style.css.1787777226.gz, con una extensión en medio por diseño. Así que la regla lleva una única excepción estrecha para un segmento numérico seguido de .gz, y ese archivo devuelve 200 como debe.

En una excepción así es donde estas reglas suelen fallar, conviene por tanto decir qué hace segura a esta: es lo bastante estrecha como para que no puedas construir index.php.algo.gz y recuperar tu código, porque el segmento del medio debe ser solo dígitos. Una excepción más amplia — «cualquier cosa terminada en .gz» — habría devuelto la regla entera.

Y el consejo más simple sigue siendo el que hace innecesario todo esto: guarda las copias fuera del directorio publicado. La regla es una red para el día en que se te olvide, no un permiso para dejar de preocuparte por dónde cae la copia.

Publicidad