Ótimo texto. Concordo que "atualizei o PHP, então estou seguro" é a ilusão mais perigosa. Pra quem ficou com a pergunta "ok, mas o que eu faço na prática num servidor PHP comum?", deixo algumas camadas baratas que já reduzem bastante o estrago depois que o RCE acontece:
- Usuário dedicado e sem privilégio por aplicação. Cada pool do PHP-FPM rodando com um usuário próprio, que não é dono dos arquivos do código. Se o atacante executa código, ele não consegue reescrever a aplicação nem mexer nas outras.
- Diretório de upload sem execução. Upload em pasta separada, com o servidor web configurado pra nunca interpretar PHP ali. Isso mata a clássica "subi um .php disfarçado de imagem".
- Bloquear saída de rede do servidor web. Quase todo exploit precisa falar com fora (reverse shell, baixar payload, exfiltrar dados). Uma regra de firewall de saída permitindo só o que a aplicação realmente usa (banco, API X, SMTP) quebra muita cadeia de ataque, e é a camada que eu menos vejo em projeto pequeno.
- Banco com usuário de menor privilégio. A aplicação não precisa de
DROP,GRANTnem acesso a outros schemas. Se a credencial vazar, o estrago fica limitado. disable_functionseopen_basedir. Não são fronteira de segurança (a própria documentação do PHP avisa queopen_basedirnão deve ser tratado assim, e já existiram bypasses), mas aumentam o custo de um exploit genérico. Encare como lombada, não como muro.- Detecção. Um processo
php-fpmcriandosh/bashé praticamente sempre sinal de comprometimento. Uma regra de auditoria (auditd ou similar) alertando isso te avisa em minutos, não em meses.
Nenhuma dessas impede o RCE, e esse é justamente o ponto do seu texto: elas assumem que ele vai acontecer e limitam o que o atacante consegue fazer depois.