Trumpai: žurnalų vedimas PHP atsižvelgiant į duomenų apsaugą reiškia: saugumui svarbius įvykius fiksuoti pilnai, bet slaptažodžių, žetonų, sesijos identifikatorių ir jautrių klientų duomenų į žurnalą niekada nerašyti. Klaidos priklauso žurnalui, o ne ekranui, žurnalai yra už žiniatinklio šakninio katalogo ir apsaugoti nuo pakeitimo. Kiek laiko žurnalai išlieka, sprendžiate sąmoningai kartu su duomenų apsaugos pareigūnu.
Tarp pėdsakų išsaugojimo ir duomenų nutekėjimo
Po PHP2Shell specializuota žiniasklaida patarė saugoti žiniatinklio serverio žurnalus nuo 2026-10-20. Kas tai norėjo įgyvendinti, dažnai pastebėjo du dalykus. Arba žurnalai jau seniai buvo suksuoti ir ištrinti. Arba juose buvo dalykų, kurių ten niekada neturėjo būti: pilnos formų įvestys, slaptažodžiai iš nepavykusių prisijungimų, API raktai URL.
Abu variantai yra problema. Be žurnalų incidento beveik neįmanoma rekonstruoti. Su per dideliu turiniu pats žurnalas tampa taikiniu, nes kas gauna prieigą prie serverio, mielai skaito jį kartu. Geras žurnalų vedimas yra per vidurį: pakankamai pėdsakų paieškai, kuo mažiau saugotinų duomenų.
Ką PHP programa turėtų fiksuoti
OWASP Logging Cheat Sheet nurodo įvykius, svarbius saugumui ir atsekamumui. Tipinėms PHP programoms juos galima apibendrinti taip:
| Į žurnalą | Ne į žurnalą |
|---|---|
| sėkmingi ir nepavykę prisijungimai | slaptažodžiai, taip pat neteisingai įvesti |
| nepavykusios teisių patikros | sesijos identifikatoriai atviru tekstu |
| paskyrų ir teisių pakeitimai | prieigos žetonai (access token) ir API raktai |
| įvesties patikros klaidos | duomenų bazės prisijungimo duomenys |
| įkėlimai, importai ir eksportai | mokėjimo ir banko duomenys |
| konfigūracijos pakeitimai, paleidimas ir sustabdymas | sveikatos duomenys ir kiti ypač saugotini duomenys |
| vykdymo klaidos su vieta, be naudingųjų duomenų | pilnas formų turinys |
Kiekvienas įrašas turėtų atsakyti į klausimus kada, kur, kas ir ką: laiko žymė, programa ir kompiuteris, šaltinio adresas, naudotojo identifikatorius, įvykio rūšis ir rezultatas. Vardus ar pašto adresus dažnai galima užmaskuoti arba pakeisti vidiniu identifikatoriumi nepraradus naudos.
Du nepageidaujamų duomenų žurnale šaltiniai dažnai nepastebimi. Pirmas yra URL: jei žetonas, slaptažodžio atstatymo raktas ar pašto adresas stovi užklausos eilutėje (query string), jis automatiškai patenka į žiniatinklio serverio prieigos žurnalą, tarpinių serverių žurnalus ir naršyklės istoriją. Tokioms reikšmėms vieta užklausos kūne (body) ar antraštėje, o ne adrese. Antras šaltinis yra derinimo režimas. Karkasai ir papildiniai derinimo režimu dažnai rašo pilnas užklausas, duomenų bazės užklausas ir aplinkos kintamuosius. Jei šis režimas po klaidų paieškos lieka aktyvus, nepastebimai auga failas su būtent ta informacija, kurios užpuolikas ieško. Po kiekvienos klaidų paieškos patikrinkite, ar derinimo išvestys vėl išjungtos, ir ištrinkite tuo metu atsiradusius failus.
Žurnalų vedimas PHP: pagrindiniai nustatymai
Pirmas lygmuo yra pats PHP. Gamyboje klaidos turi būti fiksuojamos, bet neišvedamos. Žurnalas yra už žiniatinklio šakninio katalogo, kad nebūtų pasiekiamas per URL.
; php.ini arba FPM baseinas gamybai
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/app-error.log
Kodėl matomos klaidos pavojingos, aprašo Klaidų išvesties gamyboje išjungimas. Kaip klaidos ir išimtys PHP susijusios, aiškina Klaidos ir išimtys PHP.
Antras lygmuo yra programa. Daugelis karkasų tam naudoja biblioteką pagal PHP-FIG standartą PSR-3, nustatantį vieningą žurnalo (logger) sąsają. Svarbi ne biblioteka, o disciplina: konteksto duomenis rinktis sąmoningai, užuot į žurnalą rašius ištisas užklausas ar objektus.
<?php
// Įvestis prieš žurnalavimą neutralizuoti ir užmaskuoti
function logSicher(string $text): string {
return mb_substr(str_replace(["\r", "\n"], ' ', $text), 0, 200);
}
function maskiereMail(string $mail): string {
[$name, $domain] = array_pad(explode('@', $mail, 2), 2, '');
return mb_substr($name, 0, 1) . '***@' . $domain;
}
$logger->warning('Anmeldung fehlgeschlagen', [
'benutzer' => maskiereMail(logSicher($_POST['email'] ?? '')),
'ip' => $_SERVER['REMOTE_ADDR'] ?? '',
// niekada: 'passwort' => $_POST['passwort']
]);
Žurnalo injekcija ir suklastoti įrašai
Jei programa įvestis nefiltruotas rašo į žurnalą, užpuolikas su eilučių pabaigomis gali sukurti suklastotus įrašus. Tai painioja vertinimą ir gali paslėpti pėdsakus. OWASP Cheat Sheet rekomenduoja struktūrinius formatus kaip JSON, eilučių pabaigų pašalinimą ar kodavimą ir žurnale esančių įvesčių ilgio ribą.
Taip pat svarbi pačių žurnalų apsauga:
- Laikymas už žiniatinklio šakninio katalogo ir su teisėmis, kurių žiniatinklio serverio naudotojui reikia rašyti, bet ne ištrinti senų failų.
- Kopija į antrą sistemą, pavyzdžiui, per syslog šifruotu ryšiu. Kas perima serverį, neturi galėti paprasčiausiai ištrinti pėdsakų.
- Apriboti skaitymo prieigą ir pačią ją žurnaluoti. Žurnaluose beveik visada yra asmens duomenų.
- Atpažinti sutrikimą: jei žurnalas staiga lieka tuščias, tai perspėjamasis ženklas.
- Suderinti laiką: visi serveriai laiką gauna iš to paties šaltinio ir į žurnalą rašo vienareikšmę laiko juostą. Kitaip po incidento žiniatinklio serverio, PHP ir duomenų bazės įrašų vargu ar galima sujungti į laiko juostą.
Žurnalas, esantis tik pažeistame serveryje, kaip įrodymo priemonė silpnas. Tęstinė kopija atskiroje sistemoje po incidento dažnai yra vienintelis patikimas šaltinis.
Saugojimą ir duomenų apsaugą spręsti sąmoningai
Kiek laiko žurnalai gali ir turi būti saugomi, yra svarstymas tarp saugumo intereso, duomenų taupymo ir įstatymų ar sutarčių reikalavimų. BDAR 32 straipsnis reikalauja riziką atitinkančių techninių ir organizacinių priemonių, be kita ko, siekiant nuolat užtikrinti sistemų konfidencialumą, vientisumą ir prieinamumą; žurnalų vedimas gali prie to prisidėti. Kartu asmens duomenys negali būti saugomi ilgiau, nei būtina.
Todėl nustatykite terminą kiekvienai žurnalo rūšiai, užrašykite pagrindimą ir abu suderinkite su savo duomenų apsaugos pareigūnu. Vykstančiam tyrimui gali prireikti išsaugoti žurnalus ilgiau nei įprastas terminas. Tai taip pat turėtų būti dokumentuota. Šis puslapis yra bendra informacija, o ne teisinė konsultacija; konkrečiais klausimais padeda duomenų apsaugos pareigūnai ir advokatas. Kaip vertinti žurnalus po atakos, rodo Žiniatinklio serverio žurnalų vertinimas po atakos.
Kaip PHP SOS padeda konkrečiai?
- Tikriname jūsų esamus žurnalus dėl slaptažodžių, žetonų ir kitų duomenų, kuriems ten ne vieta.
- PHP ir programą nustatome taip, kad klaidos būtų fiksuojamos, bet nerodomos.
- Įrengiame apsaugotą žurnalų kopiją atskiroje sistemoje.
- Per saugumo stebėseną nuolat vertiname saugumui svarbius įrašus ir apie įtartinus dalykus pranešame suprantamai.
Išvada: geri žurnalai yra taupūs turiniu ir dosnūs apsauga. Kas šiandien nustato, kas fiksuojama ir kas niekada, ištikus nelaimei turi panaudojamus pėdsakus ir jokio papildomo duomenų nutekėjimo.
Dažni klausimai
Ar IP adresai gali būti žurnalo failuose?
IP adresai gali būti asmens duomenys. Ar ir kiek laiko juos saugote, priklauso nuo tikslo ir teisinio pagrindo. Apimtį ir saugojimą išsiaiškinkite su savo duomenų apsaugos pareigūnu; šis puslapis nėra teisinė konsultacija.
Kiek laiko reikėtų saugoti žurnalus?
Tiek, kiek reikia saugumui ir klaidų paieškai ir kiek teisiškai leidžiama, ir ne ilgiau. Po PHP2Shell specializuota spauda rekomendavo saugoti žiniatinklio serverio žurnalus nuo 2026-10-20. Terminus nustatykite sąmoningai ir dokumentuokite.
Kas yra žurnalo injekcija (log injection)?
Jei įvestyje yra eilučių pabaigų ar valdymo simbolių ir ji nefiltruota įrašoma į žurnalą, ji gali sukurti suklastotus įrašus. Tai iškraipo vertinimus. Struktūriniai formatai kaip JSON ir eilučių pabaigų pašalinimas to išvengia.
Ar display_errors gamyboje turi būti išjungtas?
Taip. Klaidos turi eiti į žurnalą, o ne į išvestį lankytojams. Matomi klaidų pranešimai išduoda kelius, užklausas ir kartais prisijungimo duomenis.