En resumen: con los permisos de archivos en el servidor web rige un principio: el usuario con el que se ejecuta PHP puede leer su propio código, pero no modificarlo. Solo las carpetas de subidas, caché y temporales reciben permisos de escritura, y en ellas no se ejecuta PHP. Permisos como 777 no tienen cabida en un servidor de producción.
Por qué los permisos de archivos marcan la diferencia tras una intrusión
Cuando los atacantes ejecutan código en un servidor a través de una vulnerabilidad, ese código se ejecuta con los permisos del proceso de PHP. Lo que puede hacer ese usuario, puede hacerlo también el atacante. Justo aquí se decide si una intrusión se convierte en una puerta trasera persistente.
Con PHP2Shell, este escenario se ha vuelto muy concreto en octubre de 2026. Las vulnerabilidades CVE-2026-109618 y CVE-2026-109619 permiten ejecutar código malicioso sin autenticación. Están corregidas desde el 21/10/2026 en PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35. Unos buenos permisos de archivos no impiden un ataque, pero evitan que el código introducido a escondidas reescriba su aplicación de forma permanente.
En muchas instalaciones, todo el código pertenece al usuario del servidor web para que las actualizaciones funcionen con solo pulsar un botón. Es cómodo, pero es justo la situación que buscan los atacantes.
El principio básico: separar el propietario y el usuario de ejecución
Lo razonable es repartir dos roles. Un propietario, por ejemplo un usuario de despliegue, posee los archivos e instala las actualizaciones. El proceso de PHP se ejecuta con otro usuario y solo tiene permiso de lectura a través del grupo.
| Ámbito | Propietario : grupo | Permisos de archivos | Permisos de carpetas |
|---|---|---|---|
| Código del programa | deploy : seite1 | 640 | 750 |
| Configuración con contraseñas | deploy : seite1 | 640 | – |
| Subidas, caché, temporales | seite1 : seite1 | 640 | 750 |
| Registros | root o seite1 | 640 | 750 |
El propio servidor web, por ejemplo Nginx, con PHP-FPM solo necesita acceso de lectura a archivos estáticos como imágenes y CSS. Ese acceso lo obtiene mediante el grupo o una regla de acceso específica. Quien gestiona varios sitios web asigna a cada uno su propio usuario de ejecución; cómo se combina esto con los pools se explica en la guía open_basedir y aislamiento por sitio web.
Comprobar los permisos de archivos en el servidor web
Antes de cambiar nada, obtenga una visión general. Los comandos siguientes no modifican nada.
# ¿Con qué usuario se ejecutan los procesos de PHP?
ps -eo user,cmd | grep -E "[p]hp-fpm|[a]pache2|[h]ttpd" | sort | uniq -c
# Archivos y carpetas con permiso de escritura para todos
find /var/www -perm -o+w -ls
# Archivos que pertenecen al usuario del servidor web (ejemplo www-data)
find /var/www -user www-data -type f -name "*.php" | head -50
# Permisos de los archivos de configuración
ls -la /var/www/*/wp-config.php /var/www/*/.env 2>/dev/null
Las entradas con permiso de escritura para todos son casi siempre un error. Los archivos PHP que pertenecen al usuario de ejecución muestran que este puede modificar su código. Llaman la atención, además, los archivos sueltos cuyo propietario o permisos difieren de los de los archivos vecinos. Puede ser un indicio de archivos introducidos a escondidas, como se describe en la guía Detectar y eliminar webshells.
Corregir los permisos paso a paso
Cambie los permisos solo después de una copia de seguridad y, a ser posible, primero en un entorno de pruebas. Si sospecha una intrusión, conserve antes las pruebas, porque el propietario y las marcas de tiempo son entonces medios de prueba.
SITE=/var/www/seite1
# Propietario: usuario de despliegue, grupo: usuario de ejecución
sudo chown -R deploy:seite1 "$SITE"
# Carpetas 750, archivos 640
sudo find "$SITE" -type d -exec chmod 750 {} +
sudo find "$SITE" -type f -exec chmod 640 {} +
# Solo en estas carpetas puede escribir PHP (adapte las rutas a la aplicación)
sudo chown -R seite1:seite1 "$SITE/public/uploads" "$SITE/var/cache"
Después, revise el sitio web por completo: página de inicio, inicio de sesión, formularios, subida de imágenes, cachés. Qué carpetas debe poder escribir una aplicación figura en los requisitos del sistema del fabricante, en su página oficial.
Un chmod -R 777 para resolver rápido un problema abre el servidor a cualquier usuario local y a cualquier proceso introducido a escondidas. Corrija en su lugar el propietario y el grupo.
Impedir la ejecución de PHP en carpetas con permiso de escritura
Los permisos de escritura son la mitad de peligrosos si ahí no se puede ejecutar código. Bloquee la ejecución de PHP en las carpetas de subidas y de caché a nivel del servidor web. Para Apache, en la configuración del VirtualHost:
<Directory "/var/www/seite1/public/uploads">
<FilesMatch "\.(php|phtml|phar)$">
Require all denied
</FilesMatch>
</Directory>
Para Nginx basta un bloque location que rechace las peticiones a archivos PHP en esas carpetas. La regla debe ir en la configuración del servidor, no en un .htaccess en la carpeta de subidas, que un atacante con permisos de escritura podría volver a modificar.
Como complemento, merece la pena revisar la umask del usuario de despliegue, para que los archivos nuevos no se creen automáticamente con permisos demasiado abiertos. Un valor de 027 da 640 para archivos y 750 para carpetas. En servidores propios, esta responsabilidad recae por completo en usted; lo que más forma parte de ello lo describe Proteger por su cuenta servidores root y vServers.
Casos especiales: paneles de hosting, hosting compartido y despliegues
No todos los servidores se pueden configurar según el manual. Los paneles de hosting como Plesk o cPanel crean usuarios y permisos propios y los restablecen con algunas acciones. Cambie allí los permisos, a ser posible, mediante las funciones del panel o compruebe tras las actualizaciones del panel si sus ajustes siguen vigentes.
En el hosting compartido, normalmente solo tiene un usuario para todo. Entonces no es posible separar el propietario y el usuario de ejecución. Tanto más importantes son los permisos mínimos en los archivos de configuración, no usar permisos 777 y desactivar la ejecución de PHP en las carpetas de subidas, en la medida en que el proveedor lo permita.
Quien trabaja con despliegues automáticos debería establecer los permisos en el propio script de despliegue. De lo contrario, cada versión nueva restablece el estado antiguo, demasiado abierto. Una breve comprobación al final del despliegue, por ejemplo con el comando para archivos con permiso de escritura visto arriba, detecta de forma fiable estos retrocesos y se puede integrar sin mucho esfuerzo en cualquier pipeline.
¿Cómo ayuda PHP SOS en concreto?
- Registramos el propietario, los permisos y el usuario de ejecución de todos los sitios web del servidor.
- Definimos un esquema de permisos que encaje con su aplicación y su forma de actualizar.
- Aplicamos los permisos y los bloqueos de ejecución y probamos después el sitio web por completo.
- Documentamos el esquema para que los despliegues y las actualizaciones no lo vuelvan a debilitar.
Cómo se integra esto en una protección duradera lo describe el servicio Refuerzo de servidores PHP.
Preguntas frecuentes
¿Son alguna vez aceptables los permisos 777?
En un servidor de producción, prácticamente nunca. Con 777, cualquier usuario del sistema puede crear y modificar archivos. Si una aplicación no funciona sin 777, lo normal es que el propietario esté mal definido, no que los permisos sean demasiado escasos.
¿Por qué no debe poder el servidor web modificar sus propios archivos?
Porque el código introducido a escondidas se ejecuta con los permisos del servidor web. Si el servidor web puede escribir archivos PHP, un atacante puede manipular scripts existentes o crear nuevas puertas traseras. Si se separan el propietario y el usuario de ejecución, el código queda protegido contra escritura.
¿Cómo actualizo un CMS si el servidor web no puede escribir?
Entonces las actualizaciones se hacen mediante el propietario, por ejemplo con WP-CLI, Composer o un despliegue, no con el botón de actualización del backend. Es algo más laborioso, pero el código introducido a escondidas no puede modificar archivos del programa.
¿Qué permisos necesita el archivo de configuración con la contraseña de la base de datos?
Los mínimos posibles: legible para el usuario de PHP y para nadie más. Lo habitual es 640 con el grupo adecuado o 400 si el propio usuario de PHP es el propietario.