Stručně: Filtrovat požadavky na nahrávání na okraji znamená odmítat požadavky POST typu multipart/form-data na proxy, ve webovém serveru nebo ve WAF, pokud nesměřují na známou cestu pro nahrávání. Odborní autoři to navrhují jako dočasné, neoficiální opatření proti PHP2Shell. Může rozbít formuláře a nahrávání a aktualizaci nikdy nenahrazuje. Postupujte ve třech krocích: protokolovat, určit výjimky, teprve poté blokovat, s pevným datem konce.
Návrh z odborné diskuse
Dokud server není záplatován, hledají provozovatelé vše, co snižuje riziko. V odborné diskusi k PHP2Shell se přitom objevil návrh: požadavky POST ve formátu multipart/form-data, tedy ve formátu pro nahrávání souborů a některé formuláře, povolit jen tam, kde je aplikace skutečně očekává. Všechny ostatní se odmítnou na proxy nebo ve webovém aplikačním firewallu.
Důležité je zařazení. Návrh nepochází od php.net, ale od odborných autorů a je výslovně myšlen jako dočasné opatření. php.net uvádí vlastní přechodná opatření, souhrnně na stránce Okamžitá opatření, když zatím nemůžete záplatovat. Filtr je může doplnit, ne nahradit.
Popisujeme zde, jak jej zavést kontrolovaně. Podrobnosti o tom, proč a proti kterým útokům by mohl pomáhat, záměrně vynecháváme.
Co filtr dává a kde škodí
Myšlenka za tím je zmenšení plochy pro útok. Většina stránek webu nepotřebuje nahrávání souborů. Pokud takové požadavky přijímá už jen několik známých cest, velká část možných pokusů o útok se k PHP vůbec nedostane.
Odvrácená strana je stejně jasná. Každá funkce, která posílá požadavky multipart a chybí na seznamu výjimek, vypadne. Týká se to nejen zjevných formulářů pro nahrávání.
| Funkce | Často používá multipart/form-data | Riziko při blokování |
|---|---|---|
| Kontaktní formuláře a formuláře pro uchazeče s přílohou | ano | požadavky se ztratí |
| Správa médií v backendu CMS | ano | redakce nemůže nahrávat obrázky |
| Import produktů nebo zákazníků | ano | rozhraní se tiše rozbijí |
| Formuláře bez přílohy | někdy | podle nástroje pro tvorbu formulářů |
| Rozhraní a zpětná hlášení externích služeb | zřídka, ale možné | výpadek se pozná pozdě |
Přistupuje zásadní problém: Cloudflare, který sám nasadil ochranná pravidla proti PHP2Shell, varuje, že pravidla jen podle dat požadavku nestačí. Jak obě úrovně promyslet dohromady, popisuje WAF, nebo aktualizace: proč potřebujete obojí.
Krok 1: nejprve protokolovat, pak blokovat
Než cokoli zablokujete, zjistěte, které cesty vůbec dostávají požadavky multipart. Standardní logy typ obsahu neukazují. Pro Nginx proto přechodně založte vlastní protokol:
# v bloku http
map $uri $upload_pfad {
default 0;
~^/kontakt/upload\.php$ 1;
~^/admin/medien/ 1;
}
map "$request_method:$upload_pfad:$content_type" $multipart_fremd {
default 0;
"~*^POST:0:multipart/form-data" 1;
}
log_format multipart '$time_iso8601 $remote_addr "$request" "$content_type" $status';
# v bloku server
# Pozor: access_log v bloku server nahrazuje zděděný protokol,
# proto zde běžný log uveďte znovu.
access_log /var/log/nginx/access.log combined;
access_log /var/log/nginx/multipart-test.log multipart if=$multipart_fremd;
Záznamy v $upload_pfad jsou příklady. Začněte s prázdným seznamem výjimek, pak testovací protokol ukáže všechny požadavky POST multipart. V Apache to lze udělat stejně pomocí proměnné prostředí:
# ve VirtualHost
SetEnvIfNoCase Content-Type "^multipart/form-data" ist_multipart
CustomLog ${APACHE_LOG_DIR}/multipart-test.log combined env=ist_multipart
Nechte protokol běžet několik dní, ideálně v období, kdy jsou aktivní i redakce, uchazeči a rozhraní.
Krok 2: určit výjimky a blokovat kontrolovaně
Z testovacího protokolu odvodíte cesty, které nahrávání legitimně potřebují. Seznam sladte s odpovědnými osobami: Kdo spravuje obsah, jaké formuláře existují, které služby posílají data?
- Sestavte seznam výjimek z protokolu a dotazů a zapište jej do
$upload_pfadpopř. do řádkůRewriteCond. - Filtr nejprve aktivujte v testovacím prostředí nebo v klidném časovém okně.
- Sami vyzkoušejte všechny formuláře, nahrávání a cesty objednávek.
- Sledujte chybový protokol na odmítnuté požadavky (stav 403) a seznam podle potřeby doplňte.
- Určete datum konce: po aktualizaci PHP a restartu všech workerů se filtr opět odstraní.
V Nginx k tomu doplňte v bloku server blokování:
# v bloku server, po vyhodnocení fáze protokolování
if ($multipart_fremd) {
return 403;
}
V Apache tento úkol přebírá mod_rewrite. Několik podmínek se podle dokumentace Apache spojuje pomocí AND:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} =POST
RewriteCond %{HTTP:Content-Type} ^multipart/form-data [NC]
RewriteCond %{REQUEST_URI} !^/kontakt/upload\.php$
RewriteCond %{REQUEST_URI} !^/admin/medien/
RewriteRule ^ - [F]
Pokud používáte CDN nebo cloudovou WAF, lze stejnou logiku často vyjádřit jako vlastní pravidlo. I tam platí: nejprve v režimu protokolování, poté blokovat.
Filtr není náhradou za aktualizaci PHP ani důvodem ji odkládat. PHP2Shell je opraveno jen s PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 nebo potvrzeným backportem, následovaným restartem všech procesů PHP.
Správně opatření zařadit
Filtr uploadů patří do řady s dalšími návrhy, které právě kolují. Některé jsou užitečné, jiné škodlivé. Přehled toho, které tipy odborní autoři odmítají, například blokování všech požadavků se session cookie, podává Nebezpečné falešné tipy k PHP2Shell.
Jak PHP nahrávání interně zpracovává a proč při tom hraje formát multipart/form-data zvláštní roli, vysvětluje Jak PHP zpracovává nahrávání souborů. Pro většinu firem ale není nejdůležitějším krokem filtr, nýbrž jasný termín aktualizace.
Závěr: nástroj na dny, ne na měsíce
Filtr uploadů na okraji je typickým příkladem nouzového opatření: může v přechodné době zmenšit plochu pro útok, má však vedlejší účinky a nemá oficiální podporu php.net. Správně nasazen, s fází protokolování, odsouhlaseným seznamem výjimek, testy a pevným datem konce, je obhajitelný. Bez těchto kroků riskujete ztracené přihlášky, zablokované redakce a tiché chyby rozhraní.
Rozhodněte se proto vědomě a zaznamenejte, kdo rozhodnutí kdy učinil. A mějte na paměti pořadí: nejprve přijde aktualizace PHP s restartem všech workerů, přechodná opatření od php.net překlenou dobu do ní a filtr je nanejvýš dodatečná vrstva.
Jak konkrétně pomáhá PHP SOS?
- Posoudit situaci: Zjistíme, zda má filtr uploadů ve vaší situaci vůbec smysl, nebo zda je aktualizace rychlejší.
- Protokolovat a vyhodnotit: Zavedeme fázi protokolování a seznam výjimek odvodíme ze skutečných přístupů.
- Blokovat kontrolovaně: Filtr aktivujeme, otestujeme formuláře a cesty objednávek a sledujeme odmítnuté požadavky.
- Čistě odstranit: V rámci WAF a virtuálního záplatování filtr po aktualizaci opět odstraníme.
Časté dotazy
Je filtrování požadavků multipart oficiálním doporučením php.net?
Ne. php.net uvádí jiná přechodná opatření, například limity pro post_max_size a vypnutí session.upload_progress. Filtrování na okraji je návrh z odborných příspěvků a výslovně se myslí jen jako dočasné opatření.
Které funkce mohou kvůli filtru vypadnout?
Vše, co posílá soubory nebo formuláře ve formátu multipart a není na vašem seznamu výjimek: kontaktní formuláře s přílohou, formuláře pro uchazeče, správa médií v CMS, funkce importu, některá rozhraní a zpětná hlášení plateb. Proto před blokováním přichází fáze protokolování.
Nahrazuje filtr aktualizaci PHP?
Ne. Nejvýše zmenšuje plochu pro útok v přechodné době. Cloudflare sám upozorňuje, že pravidla jen podle dat požadavku nestačí. PHP2Shell je opraveno jen záplatovanou verzí PHP a restartem všech workerů.
Mám místo toho blokovat požadavky s PHPSESSID?
Ne. Tento kolující tip odborní autoři výslovně odmítají. Ochromí přihlášení a nákupní košíky, aniž by poskytoval spolehlivou ochranu.