Ukratko: Filtrirati zahtjeve za prijenos na rubu znači odbijati POST zahtjeve tipa multipart/form-data na proxyju, web-poslužitelju ili u WAF-u ako ne idu na poznati put za prijenos. Stručni autori to predlažu kao privremenu, neslužbenu mjeru protiv PHP2Shella. Može pokvariti obrasce i prijenose i nikada ne zamjenjuje ažuriranje. Postupajte u tri koraka: zapisivati, odrediti iznimke, tek tada blokirati, s čvrstim datumom završetka.
Prijedlog iz stručne rasprave
Dok poslužitelj nije zakrpan, operateri traže sve što smanjuje rizik. U stručnoj raspravi o PHP2Shellu pojavio se pritom jedan prijedlog: POST zahtjeve u formatu multipart/form-data, dakle formatu za prijenose datoteka i neke obrasce, dopuštati samo tamo gdje ih aplikacija doista očekuje. Svi ostali odbijaju se na proxyju ili u Web Application Firewallu.
Važno je svrstavanje. Prijedlog ne potječe od php.net-a, nego od stručnih autora i izričito je zamišljen kao privremena mjera. php.net navodi vlastite prijelazne mjere, skupljene na stranici Hitne mjere ako još ne možete zakrpati. Filtar ih može dopuniti, ne zamijeniti.
Ovdje opisujemo kako ga kontrolirano uvesti. Pojedinosti o tome zašto bi i protiv kojih napada mogao pomoći namjerno izostavljamo.
Što filtar postiže i gdje šteti
Ideja iza toga je smanjenje napadne površine. Većini stranica web-mjesta prijenosi datoteka nisu potrebni. Ako takve zahtjeve prihvaća samo nekoliko poznatih putova, velik dio mogućih pokušaja napada uopće ne dolazi do PHP-a.
Naličje je jednako jasno. Svaka funkcija koja šalje multipart zahtjeve, a nedostaje na popisu iznimaka, ispada. To se ne tiče samo očitih obrazaca za prijenos.
| Funkcija | Često koristi multipart/form-data | Rizik pri blokiranju |
|---|---|---|
| Kontaktni obrasci i obrasci za prijave s privitkom | da | zahtjevi se gube |
| Upravljanje medijima u CMS backendu | da | redakcija ne može učitavati slike |
| Uvoz proizvoda ili kupaca | da | sučelja se tiho kvare |
| Obrasci bez privitka | ponekad | ovisno o alatu za obrasce |
| Sučelja i povratne obavijesti vanjskih usluga | rijetko, ali moguće | ispad se kasno primijeti |
Tome se pridodaje načelan problem: Cloudflare, koji je i sam uveo zaštitna pravila protiv PHP2Shella, upozorava da pravila samo na temelju podataka zahtjeva nisu dovoljna. Kako te dvije razine promišljati zajedno, opisuje članak WAF ili ažuriranje: zašto trebate oboje.
Korak 1: najprije zapisivati, zatim blokirati
Prije nego išta blokirate, saznajte koji putovi uopće primaju multipart zahtjeve. Standardni zapisnici ne pokazuju tip sadržaja. Za Nginx zato privremeno izradite vlastiti zapisnik:
# u http bloku
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';
# u server bloku
# Pažnja: access_log u server bloku zamjenjuje naslijeđeni zapisnik,
# zato ovdje ponovno navedite uobičajeni zapisnik.
access_log /var/log/nginx/access.log combined;
access_log /var/log/nginx/multipart-test.log multipart if=$multipart_fremd;
Unosi u $upload_pfad su primjeri. Počnite s praznim popisom iznimaka, tada testni zapisnik pokazuje sve multipart POST-ove. U Apacheu isto uspijeva s varijablom okruženja:
# u VirtualHostu
SetEnvIfNoCase Content-Type "^multipart/form-data" ist_multipart
CustomLog ${APACHE_LOG_DIR}/multipart-test.log combined env=ist_multipart
Pustite zapisnik da radi nekoliko dana, idealno kroz razdoblje u kojem su aktivni i redakcija, kandidati za posao i sučelja.
Korak 2: odrediti iznimke i kontrolirano blokirati
Iz testnog zapisnika izvodite putove kojima prijenosi legitimno trebaju. Popis uskladite s odgovornim osobama: tko održava sadržaje, koji obrasci postoje, koje usluge šalju podatke?
- Izraditi popis iznimaka iz zapisnika i upita te ga upisati u
$upload_pfadodnosno u retkeRewriteCond. - Filtar najprije aktivirati na testnom okruženju ili u mirnom vremenskom prozoru.
- Sami proći sve obrasce, prijenose i putove narudžbe.
- Pratiti zapisnik pogrešaka za odbijene zahtjeve (status 403) i po potrebi dopuniti popis.
- Odrediti datum završetka: nakon PHP ažuriranja i ponovnog pokretanja svih workera filtar se ponovno uklanja.
U Nginxu za to u server blok dodajte blokadu:
# u server bloku, nakon evaluacije faze zapisivanja
if ($multipart_fremd) {
return 403;
}
U Apacheu zadatak preuzima mod_rewrite. Više uvjeta prema dokumentaciji Apachea povezuje se s I:
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]
Ako koristite CDN ili cloud WAF, ista se logika često može preslikati kao vlastito pravilo. I tamo vrijedi: najprije u načinu zapisivanja, zatim blokirati.
Filtar nije zamjena za PHP ažuriranje niti razlog da ga odgodite. PHP2Shell je otklonjen tek s PHP-om 8.5.12, 8.4.27, 8.3.36, 8.2.35 ili potvrđenim backportom, nakon čega slijedi ponovno pokretanje svih PHP procesa.
Ispravno svrstati mjeru
Filtar za prijenose pripada u niz s drugim prijedlozima koji trenutačno kruže. Neki su smisleni, drugi štetni. Pregled koje savjete stručni autori odbacuju, primjerice blokiranje svih zahtjeva s kolačićem sesije, daje članak Opasni pogrešni savjeti o PHP2Shellu.
Kako PHP interno obrađuje prijenose i zašto format multipart/form-data pritom ima posebnu ulogu, objašnjava članak Kako PHP obrađuje prijenose datoteka. Za većinu tvrtki najvažniji korak ipak nije filtar, nego jasan termin za ažuriranje.
Zaključak: alat za dane, a ne za mjesece
Filtar za prijenose na rubu tipičan je primjer hitne mjere: može smanjiti napadnu površinu u prijelaznom razdoblju, ali ima nuspojave i nema službenu potporu php.net-a. Ispravno primijenjen, s fazom zapisivanja, usklađenim popisom iznimaka, testovima i čvrstim datumom završetka, opravdan je. Bez tih koraka riskirate izgubljene prijave za posao, blokirane redakcije i tihe pogreške sučelja.
Zato odluku donesite svjesno i zabilježite tko ju je kada donio. I imajte na umu redoslijed: najprije dolazi PHP ažuriranje s ponovnim pokretanjem svih workera, prijelazne mjere php.net-a premošćuju vrijeme do toga, a filtar je u najboljem slučaju dodatni sloj.
Kako PHP SOS konkretno pomaže?
- Procijeniti situaciju: razjašnjavamo ima li filtar za prijenose u Vašoj situaciji uopće smisla ili je ažuriranje moguće brže.
- Zapisivati i analizirati: postavljamo fazu zapisivanja i popis iznimaka izvodimo iz stvarnih pristupa.
- Kontrolirano blokirati: aktiviramo filtar, testiramo obrasce i putove narudžbe te nadziremo odbijene zahtjeve.
- Uredno ukloniti: u sklopu WAF-a i virtualnog zakrpanja filtar nakon ažuriranja ponovno uklanjamo.
Česta pitanja
Je li filtriranje multipart zahtjeva službena preporuka php.net-a?
Nije. php.net navodi druge prijelazne mjere, primjerice granice za post_max_size i isključivanje session.upload_progress. Filtriranje na rubu prijedlog je iz stručnih članaka i izričito je zamišljeno samo kao privremena mjera.
Koje funkcije zbog filtra mogu ispasti?
Sve što šalje datoteke ili obrasce u multipart formatu, a nije na Vašem popisu iznimaka: kontaktni obrasci s privitkom, obrasci za prijave, upravljanje medijima u CMS-u, funkcije uvoza, neka sučelja i povratne obavijesti o plaćanju. Zato prije blokiranja dolazi faza zapisivanja.
Zamjenjuje li filtar PHP ažuriranje?
Ne. Najviše smanjuje napadnu površinu u prijelaznom razdoblju. Cloudflare sam upozorava da pravila samo na temelju podataka zahtjeva nisu dovoljna. PHP2Shell je otklonjen tek zakrpanom verzijom PHP-a i ponovnim pokretanjem svih workera.
Trebam li umjesto toga blokirati zahtjeve s PHPSESSID?
Ne. Taj savjet koji kruži stručni autori izričito odbacuju. Paralizira prijave i košarice, a ne nudi pouzdanu zaštitu.