Dabartinė padėtis: PHP2Shell. Du kritiniai PHP pažeidžiamumai (CVSS 9,2) leidžia vykdyti kenkėjišką kodą be prisijungimo. Pataisos nuo 2026-10-21.Ką dabar daryti →

expose_php ir Server antraštė: versijų duomenų slėpimas

PHP, Nginx ir Apache numatytai nurodo savo versijos numerį kiekviename atsakyme. Tai neapsaugo nuo atakų, bet skeneriams suteikia patogų taikinių sąrašą. Sužinokite, kaip tai išjungti ir vis tiek išlaikyti apžvalgą.

Būsena 5 min. skaitymoSutvirtinimas ir konfigūracija

Trumpai: su expose_php = Off php.ini išnyksta antraštė X-Powered-By: PHP/…. Prie to priklauso server_tokens off; Nginx bei ServerTokens Prod ir ServerSignature Off Apache. Tai nepadaro serverio saugesnio, bet atima iš automatizuotų skenavimų paruoštą versijų sąrašą. Savo pataisų būseną po to tikrinkite per paketų valdymą ir procesus, o ne per antraštes.

Vizitinė kortelė kiekviename atsakyme

Kas po 2026 m. spalio 21 d. norėjo sužinoti, kiek serverių dar rodo seną PHP versiją, ilgai ieškoti neturėjo. Daugelis žiniatinklio serverių savo PHP versiją nurodo kiekviename atsakyme, pavyzdžiui, kaip X-Powered-By: PHP/8.2.20. Viso interneto paieškos paslaugos šiuos duomenis nuskaito, o Palo Alto Networks komanda Unit 42 PHP2Shell atveju suskaičiavo daugiau nei 22,6 mln. viešai pasiekiamų, potencialiai pažeidžiamų instancijų.

Užpuolikams toks nurodymas yra trumpesnis kelias. Jie gali iš anksto rūšiuoti taikinius užuot bandę aklai. Operatoriams, priešingai, jis nenaudingas, nes neįrodo net savo pataisų būsenos: distribucijos pataisas dažnai pateikia kaip atgalinį perkėlimą (backport) be naujo versijos numerio.

Šis straipsnis parodo, kur PHP ir žiniatinklio serveris išduoda versijų informaciją ir kaip šiuos duomenis išjungti. Jis taip pat atvirai sako, ką tai duoda ir ko ne.

Kur visur pasirodo versijų duomenys

PHP versija yra tik viena iš kelių vietų. Verta pažvelgti į viską, nes viena užmiršta vieta nuvertina kitas priemones.

Radimo vieta Pavyzdys Išjungimas per
PHP HTTP antraštė X-Powered-By: PHP/8.3.x expose_php = Off php.ini
Žiniatinklio serverio HTTP antraštė Server: nginx/1.x arba Server: Apache/2.4.x (Debian) server_tokens off; arba ServerTokens Prod
Žiniatinklio serverio klaidų puslapiai versijos eilutė po 404 ar 500 puslapiais tie patys nustatymai, Apache papildomai ServerSignature Off
Programos antraštė karkasų savi X-Powered-By nurodymai fastcgi_hide_header arba Header unset
Failai žiniatinklio šakniniame kataloge phpinfo() testiniai failai, readme ir changelog failai ištrinti arba užblokuoti
PHP klaidų pranešimai keliai ir versijos detalės naršyklėje display_errors = Off

Testiniai failai su phpinfo() yra vaisingiausias šaltinis užpuolikams. Jie išduoda ne tik versiją, bet visą konfigūraciją; daugiau apie tai straipsnyje phpinfo() failai: kodėl jie turi išnykti.

expose_php išjungimas php.ini

Pasak PHP vadovo, expose_php numatytai įjungtas ir keičiamas tik php.ini, ne baseine, ne per .htaccess ir ne vykdymo metu. Todėl reikšmę nustatykite php.ini kiekvieno svetaines teikiančio veikimo režimo, pavyzdžiui, Debian ir Ubuntu sistemose po /etc/php/<version>/fpm/ ir prireikus /etc/php/<version>/apache2/.

; žiniatinklio SAPI php.ini, po to iš naujo paleisti PHP-FPM arba Apache
expose_php = Off

Jei lygiagrečiai veikia kelios PHP versijos, kiekvienai reikia įrašo. Atitinkamos paslaugos paleidimas iš naujo privalomas, nes PHP skaito php.ini tik paleidimo metu.

Server antraštės trumpinimas Nginx ir Apache

Nginx numatytai savo versiją nurodo Server antraštėje ir klaidų puslapiuose. Su server_tokens off; lieka tik produkto pavadinimas. Papildomai X-Powered-By antraštę, kurią nustato pati programa, galima išfiltruoti su fastcgi_hide_header. Pasak Nginx dokumentacijos, Nginx pats paslepia tik Status ir X-Accel-…, o ne X-Powered-By.

# http bloke, galioja visoms svetainėms
server_tokens off;
fastcgi_hide_header X-Powered-By;

Apache ServerTokens valdo Server antraštę ir kartu versijos eilutę po klaidų puslapiais. Pasak Apache dokumentacijos, nustatymas galioja tik visame serveryje, ne kiekvienam VirtualHost. Kadangi PHP-FPM atsakymai per mod_proxy_fcgi patenka į kitą antraščių lentelę nei paties serverio atsakymai, šalinimą nustatykite abiem variantais.

# visos serverio konfigūracija, pvz., /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off

# reikalingas mod_headers
<IfModule mod_headers.c>
    Header unset X-Powered-By
    Header always unset X-Powered-By
</IfModule>

Prieš perkraudami patikrinkite konfigūraciją su nginx -t arba apachectl configtest. Kaip per antraštes aktyviai įjungti apsaugą lankytojams, pavyzdžiui, su HSTS ar Content-Security-Policy, aprašo gidas Saugumo antraštės svetainėms.

Kaip patikrinti rezultatą iš išorės

Po perėjimo patikrinkite kiekvieną domeną atskirai, pageidautina ir klaidų puslapį. Šios komandos siunčia tik įprastas užklausas į jūsų pačių svetaines:

# Pradžios puslapio antraštės
curl -sI https://www.example.de/ | grep -iE '^(server|x-powered-by):'
# Neegzistuojančio puslapio antraštės
curl -sI https://www.example.de/gibt-es-nicht-4711 | grep -iE '^(server|x-powered-by):'

Tikimasi Server antraštės be versijos numerio ir jokio X-Powered-By. Jei ten vis dar PHP versija, dažniausiai aktyvus kitas php.ini arba paslauga dar nepaleista iš naujo. Jei prieš serverį yra CDN, papildomai tiesiogiai patikrinkite kilmės serverį, jei jis pasiekiamas.

Patarimas

PHP versiją vis tiek užfiksuokite viduje: savo serverių inventoriuje, su paketo būsena ir paskutinės patikros data. Pataisų būseną įrodote per serverį, kaip aprašyta skyriuje PHP versijos ir pataisų būsenos teisinga patikra.

Ką slėpimas duoda ir ko ne

Sąžiningai vertinant, versijų duomenų išjungimas yra maža priemonė su nedideliu darbo kiekiu. Ji sumažina tikimybę pasirodyti tikslinėse tam tikrų versijų paieškose ir sumažina informaciją, kurią užpuolikas gauna be vargo.

Tačiau ji neapsaugo nuo automatizuotų atakų, kurios savo užklausas tiesiog siunčia kiekvienam pasiekiamam serveriui. Kaip vyksta tokie masiniai skenavimai, aprašo straipsnis Masiniai skenavimai dėl nepataisyto PHP. Nuo PHP2Shell padeda tik atnaujinimas į PHP 8.5.12, 8.4.27, 8.3.36 ar 8.2.35 arba patvirtintą atgalinį pataisų perkėlimą (backport), po to iš naujo paleidžiant visus PHP procesus.

Šalutinis poveikis, priešingai, labai naudingas: kas išorėje išjungia versijų duomenis, privalo savo versijas viduje tvarkingai fiksuoti. Tokioje padėtyje kaip PHP2Shell būtent ši apžvalga lemia, kaip greitai sužinosite, kurie serveriai paveikti.

Todėl slėpimas prasmingas kaip bazinio sutvirtinimo dalis, o ne kaip pavienė priemonė. Jis priklauso tam pačiam kontroliniam sąrašui kaip išjungtas klaidų išvedimas, ištrinti testiniai failai ir užrakintos konfigūracijos reikšmės.

Kaip PHP SOS padeda konkrečiai?

  • Surinkti radimo vietas: visų domenų antraštes, klaidų puslapius ir žiniatinklio šakninį katalogą tikriname dėl versijų duomenų ir pamirštų testinių failų.
  • Pritaikyti konfigūraciją: expose_php, Server antraštes ir antraščių filtrus nustatome kiekvienoje PHP versijoje ir kiekviename žiniatinklio serveryje ir kontroliuojamai iš naujo paleidžiame paslaugas.
  • Pataisų būseną įrodyti viduje: versijas ir paketų būsenas dokumentuojame ten, kur jos priklauso: inventoriuje, o ne HTTP antraštėje.
  • Įtraukti į sutvirtinimą: priemonė yra mūsų PHP žiniatinklio serverių sutvirtinimo dalis.

Dažni klausimai

Ar expose_php = Off padaro mano serverį saugų?

Ne. Nustatymas pašalina tik versijos nurodymą iš HTTP antraštės. Pažeidžiama PHP versija lieka pažeidžiama, o automatizuotos atakos savo užklausas dažnai vis tiek išbando kiekviename pasiekiamame serveryje. Tačiau jūs atimate iš užpuolikų paprastą išankstinę atranką ir sumažinate matomumą serverių paieškos sistemose.

Ar expose_php galiu nustatyti FPM baseine arba per .htaccess?

Pasak PHP vadovo, expose_php keičiamas tik php.ini. Todėl nustatykite reikšmę kiekvienos žiniatinklio SAPI php.ini ir po to iš naujo paleiskite PHP-FPM arba Apache.

Kodėl matau X-Powered-By, nors expose_php = Off?

Tada antraštę dažniausiai nustato pati programa ar karkasas arba aktyvus kitas php.ini. Antraštę papildomai pašalinkite žiniatinklio serveryje: su fastcgi_hide_header Nginx arba Header unset Apache.

Kaip patikrinti pataisų būseną, jei versija nebematoma?

Per patį serverį: paketų valdymas, paketo pakeitimų žurnalas su CVE numeriais ir PHP procesų paleidimo laikas. Nurodymas HTTP antraštėje vis tiek nebuvo įrodymas, nes distribucijos atgalinius pataisų perkėlimus (backport) dažnai įdiegia be naujo versijos numerio.

Šaltiniai

Skubus kontaktas

Kiekviena valanda svarbi. Parašykite mums dabar.

Trumpai aprašykite sistemą, PHP versiją ir pastebėjimus. Mes atsakysime, išsiaiškinsime padėtį ir dirbsime nuotoliu, kol incidentas bus užbaigtas ir dokumentuotas.

Skubi pagalba