PHP saugumo nustatymai - 2 dalis
PHP nustatymų yra daug, kurie ne tik leidžia sistemai būti lanksčiai, bet ir dažnai priverčia pasimesti programuotojus ar adminus, juolab, kad nebūtinai default reikšmė yra geriausia ar saugiausia, taigi tęsiame kelionę po PHP nustatymus
Apribokime sistemos resursus
max_execution_time, standartiškai yra nustatytas 30 (sekundžių). Tai reiškia, kad skriptui bus leista naudotis procesoriumi iki 30 sekundžių vieno paleidimo metu. Šis nustatymas yra naudingas hostingo paslaugų teikėjams, kadangi apsaugo nuo piktai nusiteikusių vartotojų, norinčių pakenkti, taip pat ir dedicated serveriams - apsisaugoti nuo kreivai parašytų savų ar trečios šalies skriptų. Dažnai šis nustatymas yra interpretuojamas klaidingai - “skriptas negali suktis ilgiau nei 30 sekundžių“. Iš tiesų, gali. Laikas skaičiuojamas tik tada, kai skriptas naudoja CPU, nors veikti skriptas gali valandų valandas. Pavyzdžiui:
while (true)
{
sleep(100);
}
Toks skriptas naudoja itin mažai CPU, todėl miegodamas gali veikti net ir ištisą mėnesį. Jeigu serveryje naudojate tik web puslapius, protinga apriboti šį nustatymą į kur kas mažesnę reikšmę, pvz. 5. Jei puslapis serveryje generuojamas ilgiau nei 1 sekundę, tai jau laikoma ilgai. Kuo mažesniu laiku jį apribosim, tuo daugiau laiko liks kitoms užduotims. Šį nustatymą galima keisti ir skripto išorėje, ir viduje, su set_time_limit() funkcija.
max_input_time yra skirtas nustatyti, kiek laiko skirti vartotojo įvedimui. Jis defaultu būna 60 sekundžių. Taip pat, kaip ir vykdymo nustatymas, jis įskaičiuoja tik tą laiką, kurį naudoja CPU savo skaičiavimams. Didelio failo uploado laukimas nepaveiks šio limito. Šis nustatymas skirtas apsisaugoti nuo daugiamačių masyvų perdavimo, kurie gali itin paveikti sistemos resursus. Nepaisant to, 60 sekundžių yra ryškiai per daug, joks skriptas neturėtų švaistyti tiek daug savo laiko vartotojo įvedimui apdirbti. Nustatymą siūloma apriboti iki 2-5 sek. Šis nustatymas gali būti keičiamas tik skripto išorėje, kadangi vartotojo įvedimas apdirbamas dar prieš skripto pradžią.
memory_limit - dar vienas nustatymas, apribojantis sistemos skiriamą atmintį. Šis nustatymas yra prieinamas tik tuo atveju, jei php sukompiliuotas su atminties ribojimo palaikymu. Lengvai tai patikrinsite, kadangi memory_get_usage funkcija prieinama tik jei atminties ribojimas yra :
if (function_exists(’memory_get_usage’)) echo ‘Ok!’;
else ‘Ne Ok!’
Atminties limitas yra defaultu nustatytas iki 8MB. Šis nustatymas dauguma atvejų yra tinkamas ir paprastai nereikia jo keisti. Sistemai pakenkti gali būti naudojami skriptai, pasiimantys didelę dalį atminties ir nueinantys miegoti. Pavyzdžiui:
$a = str_repeat(’a', 100000000);
ignore_user_abort(true);
sleep(1000000);
Šis skriptas bando nugriebti ~100MB atminties ir nueiti miegoti, ignoruodamas vartotojo veiksmus, ty. net jei uždaroma naršyklė, jis ir toliau būna vykdomas. memory_limit neišsprendžia problemos iki galo, kadangi su tokiu skriptu galima paleisti kelias jo instancijas, kurių kiekviena pasiims maksimalų atminties kiekį. Be abejo, tokie įvykiai negali praeiti nepastebėti sistemos administratorių, taigi problemą anksčiau ar vėliau reikia išspręsti. Kitiems atvejams, kai kenkia ne žmogus, o kreivai parašytas skriptas, arba pvz. siunčiamas didelis duomenų kiekis iš išorinio šaltinio, tai be abejo yra naudingas nustatymas.
default_socket_timeout - leidžia apriboti laiką, skirtą inicijuoti sujungimui. Defaultu ši reikšmė yra 60 sekundžių. Dažnai sistema, atidarydama socketą praleidžia daug laiko prisijungdama prie lėtų serverių, todėl kenkėjas gali efektyviai išnaudoti sistemos resursus, atidaręs keletą tokių prisijungimų. Kol sistema eikvos laiką beprasmiams sujungimams, neliks resursų tikrų vartotojų užklausoms. Reikia atminti, kad šis nustatymas galioja tik prisijungimo inicializavimo procesui ir neturi efekto skaitymui ir rašymui jau atidarytame sockete, taigi verta naudoti ir stream_set_timeout() jei reikia apsisaugoti nuo gaišimo laukiant skaitymo ar rašymo veiksmų. default_socket_timeout gali būti pakeistas bet kurioje vietoje, protinga jį būtų sumažinti iki 5-10 sekundžių.
URL includinimas
Viena iš php streams galimybių yra elgtis su išoriniais URL lygiai taip pat, kaip ir su vietiniais failais. Pavyzdžiui, fopen() gali būti taip pat sėkmingai panaudota nuskaityti “http://www.php.net”, kaip ir “/etc/passwd”. Tai sukelia nemažai saugumo spragų, kaip pvz. kodo injekcija per išorinį šaltinį, naudojant tokias funkcijas, kaip fopen(), file_get_contents(), readfile(), taip pat didelių duomenų arba lėtai veikiančių URL įkėlimas. Taipogi, gali būti sukuriamas amžinas ciklas, skriptui nuskaitant patį save. Kartais net web serverio perkrovimas neišgelbsti, kadangi keletas užklausų lieka buferyje ir jie vėl toliau sėkmingai ryja sistemos resursus. Serveris turi būti sustabdomas keletui sekundžių ir tada paleidžiamas iš naujo.
Į pagalbą ateina allow_url_fopen nustatymas, kurį nustačius į false, skriptas galės pasiekti išorinius šaltinius tik su curl arba socketais. Blogiausia, kad streamai suteikia priėjimą prie išorinių šaltinių ir tokioms funkcijoms, kaip require ar include. Jei tokių funkcijų parametruose pasitaiko vartotojo įvedamų duomenų, kenkėjas gali nesunkiai paleisti savo rašytus skriptus. Tai dar viena rimta priežastis išjungti defaultu įjungtą allow_url_fopen. Nepaisant visko, su fopen() atidarinėti išorinius URL yra pakankamai saugu (arba/ir reikalinga), ir dabartinėje versijoje (5.2) jau galima pasinaudoti nauju nustatymu allow_url_include, kuris išjungtas defaultu. Jis atskiria URL apdirbimo funkcionalumą, kadangi leidžia kontroliuoti ar leisti tik nuskaitymus, ar ir include/require. Abu šie nustatymai gali būti keičiami tik skripto išorėje, dėl saugumo sumetimų.
Funkcijų ir klasių draudimas
Jei galvojate, kad php turi daug nustatymų, pasidomėkite, kiek yra funkcijų
Be abejo, visos funkcijos yra naudingos vienais ar kitais atvejais, tačiau kai kuriomis iš jų paslaugų teikėjai nenori leisti naudotis vartotojams. Tokios funkcijos, kaip exec() leidžia apeiti safe_mode ir open_basedir nustatymus, arba mail() - gali būti panaudota išsiųsti dideliems kiekiams spamo. Tam yra skirti nustatymai disable_functions ir disable_classes, kurioms galima pateikti kableliais atskirtą sąrašą draudžiamų funkcijų ar klasių. Skriptui, bandant naudoti uždraustą funkciją ar klasę bus grąžintas fatal error. Šis nustatymas, nors ir labai naudingas, deja, turi vieną apribojimą. Jis gali būti keičiamas tik php.ini faile, o tai reiškia, kad negalima vieniems vartotojams leisti, o kitiems apriboti tam tikrų funkcijų. Visiems bus vienodi draudimai. Po šio nustatymo keitimo taip pat būtina perkrauti web serverį.
Modulių dinaminis įkrovimas
enable_dl - leidžia pasirinkti ar leisti skriptui įkrauti modulį dinamiškai. Defaultu šis nustatymas įjungtas, todėl suteikia gan patogų dalyką - skripto metu galima įkrauti extensioną, tačiau tai yra didelė saugumo spraga. Nėra būdo žinoti, ką daro įkraunamas modulis, jis gali suteikti priėjimą vartotojui prie to, kas šiaip yra uždrausta ar atlikti bet kokias sistemos operacijas. Net ir be vartotojo piktų kėslų, modulis gali būti parašytas prastai, nekokybiškai, o tai taipogi gali paveikti visą sistemą. Rekomenduojama šį nustatymą išjungti php.ini arba virtual hosto lygmenyje.
Pabaiga
Sėkmės, būkite saugūs! Greitai pasirodys dar viena viso šio romano dalis ![]()
February 9th, 2007 at 1:48 pm
[...] Straipsnio originalas čia. Susiję straipsniai:PHP saugumo nustatymai - 1 dalisAsmens kodo saugumasEl. pašto injekcijos [...]
February 9th, 2007 at 2:26 pm
jeigu rašysi knygą, noriu būti recenzentu .)
February 11th, 2007 at 12:26 pm
Labai šaunūs paaiškinimai, tikrai pravertė
Lauksim dar…
February 11th, 2007 at 10:04 pm
gražu
Daug naudingos info
June 13th, 2007 at 4:42 pm
Klausimas:
When should the $_POST[variable] be in quotes?
PHP5 chapter 3 examples - POST and GET:
Pages 80, 84, 86, 95, 104 have single quotes ['value'].
Pages 89, 92, 98, 104 have no quotes [value].
W3schools.com uses double quotes ["value"]
Thanks