Vietoj įžangos

Šiuo pirmu įrašu norėčiau pradėti “paskaitų ciklą” apie teisingą programavimą. Informacija bus pateikiama ne tik iš mano asmeninės patirties, bet ir iš kitų šaltinių. Tikrai nesakau, kad viską aš čia surašysiu, bet tai bus puiki pradžia. Reiktų atkreipti dėmesį į tai, kad su bet kuria programavimo kalba galima programuoti tiek saugiai, tiek ne. Kadangi PHP yra populiariausia programavimo kalba bei mano duona - mano kalba bus daug labiau pritaikyta PHP.

Ši pateikta informacija skirta mokymosi tikslams, kad jaunieji kolegos programuotojai išmoktų rašyti saugų kodą. Aš atsiriboju nuo bet kokio kenksmingo informacijos panaudojimo. Esu už saugų internetą/saugias svetaines.

Kurdami bet kokią programą ir, tiesa pasakius, bet kuria programavimo kalba reikia būti iš dalies paranoiku. Visa gaunama informacija iš vartotojo yra nepatikima. Tad ji kiekvieną kartą privalo įgyti jūsų pasitikėjimą. Manyčiau, reikėtų atkreipti dėmesį į šiuos faktus:

  • Vartotojas nežino kaip veikia programa, nežino ką žinot jūs, jis gali atlikti veiksmus tokius, dėl kurių vėliau programa atliks neįtikėtinus veiksmus.
  • Vartotojas gali stengtis ieškoti klaidų ir panaudoti tai savo tikslams.
  • Internetas ne visuomet gerai veikia. Tai jis per lėtas, tai nenusiunčiami visi paketai, dėl to jūsų programinis kodas gali veikti neįtikėtinai keistai.
  • Pati programavimo kalba gali turėti klaidų apie kurias jūs net nežinote, o jei žinote ir naudojat per senas PHP versijas galite nukentėti ir dėl to.
  • Ir dar kiti neįtikėtini veiksniai, kurie nepriklauso nuo jūsų bei jūsų įpročių.

Niekas negimė mokėdamas. Blogiausia, kad turbūt visi mes mokomės iš savo klaidų. Yra tikras menas išmokti mokytis iš kitų klaidų arba atradimų. Tad tikiuosi ši informacija jums padės. Nemanau, kad pavyks viską aprašyti, bet esminius dalykus paminėsiu. Malonaus skaitymo.. prie kavutės.

Turbūt naudingiausia pradėti rašyti nuo elementariausių principų. Prie ko reikia priprasti programuojant su darbiniu kompiuteriu ir kuo tai skiriasi nuo publikuoto projekto.

Sunkiausia priprasti turbūt rašyti tokį kodą, kuris visiškai nesikeikia (programuoti be klaidų). Tai ne tik kokie warning ar fatal klaidų pranešimai, kurie yra kritiniai sistemos veikimui, bet sakyčiau ir tokie ne esminiai (na beveik) notice pranešimai. Beveik visose sistemose, kurios jau kuriamos ir tobulinamos n metų, jeigu įjungtume visišką klaidų rodymą pamatytume nemažai klaidų pranešimų apie naudojamus neapibrėžtus kintamuosius ir panašiai. Publikuotoje svetainėje, žinoma, geriausia to visiškai nerodyti, bet programuojant tai gyvybiškai svarbu.

Kuriant visuomet įsijunkite pilną klaidų rodymą, kuris leis pamatyti apie neaprašytus kintamuosius:

error_reporting(2047)

Serverio nustatymuose išjunkite register globals, kurie neleis kintamųjų inicializuoti per get/post parametrus. Jei to nepadarysite, gali būti tokia situacija:

//kažkas pradžioje
if ($_POST[‘user’] == ‘adminas’ && $_POST[‘passwd’] == ‘admino_slaptazodis’) {
    $prisijunges = 1;
}
if ($prisijunges) {
    // rodom admino interfeisą ir atliekam veiksmus
    // ….
}
// kažkas gale

Vartotojas gali perduoti kintamąjį $prisijungęs GET metodu, naršyklėje įvedęs ’skriptas.php?prisijunges=1′ ir taip matys prisijungusiojo turinį. Kitose situacijose, galima įterpti ne tuos failus, bet apie tai papasakosiu kitoje dalyje.

Programuojant būtina rašyti viską tvarkingai. Tai ne tik svarbu dėl to, kad programa turi gražiai atrodyti (pvz. PEAR Coding Standards), bet ir teisingai pavadinti kintamieji. Jei jūs kintamąjį pavadinsite kokiu $xxx, tai garantuoju po mėnesio nei jūs, nei jūsų kolegos greitai negalės prisiminti, ką jis savyje laiko. Daug teisingiau naudoti suprantamus pavadinimus, kad ir $kaina, $pavadinimas, $prekes. Bet viskas atrodys dar gražiau ir bus patogiau, jei pirmąjį kintamojo simbolį paskirsite aprašyti duomenų tipui. Tad, kai reikės jį panaudoti iškart žinosite, kas turi jame būti. Pavyzdžiui:

$iMetai = 2007; // integer
$sPavadinimas = “AJAX”; // string
$aPrekes = array(1,2,3); // array
$oMail = new MailClass; // objektas
$fKaina = 555.95 // float

Kaip minėjau šiek tiek anksčiau, duomenimis iš vartotojo reikia kuo mažiau pasitikėti. Visų pirma reiktų išjungti galvos skausmą magic_quotes, kuri uždeda stebuklingus simbolius ant kabučių ir pan. Jei negalite keisti serverio nustatymų - pasinaudokite šiuo kodo gabaliuku, kurį reiktų įdiegti pačioje pradžioje.

if (get_magic_quotes_gpc()) {
    function stripslashes_deep($value)
    {
        $value = is_array($value) ?
                    array_map(’stripslashes_deep’, $value) :
                    stripslashes($value);
 
        return $value;
    }
 
    $_POST = array_map(’stripslashes_deep’, $_POST);
    $_GET = array_map(’stripslashes_deep’, $_GET);
    $_COOKIE = array_map(’stripslashes_deep’, $_COOKIE);
    $_REQUEST = array_map(’stripslashes_deep’, $_REQUEST);
}

Prieš dirbant su kintamaisiais nepamirškite apdoroti jų, nes juk vartotojas gali juos pakeisti savo nuožiūra, o ne vaikščioti per nuorodas. Tad būtina patikrinti duomenis taip, kad galimos reikšmės būtų tik tos, kurios yra galimos. Sutikite, perkant e-shop’e prekių kiekis negali būti neigiamas, tiesa?

if (isset($_GET[‘news_id’]) && is_numeric($_GET[‘news_id’])) {
    //.. bandom ieškoti naujienos id
    $aNewsData = $db->getRow(“SELECT * from naujienos where id=’”. $_GET[‘news_id’] .“‘”);
    if ($aNewsData) {
        // atvaizduojam naujieną
    }
    else {
        // naujiena nesurasta
    }
}

Patarčiau nenaudoti tokio tipo apsisaugojimo, kurį padarė valstybinio puslapio programuotojai po jų svetainės patikrinimo per saugumo konferenciją. Su (int) jie pavertė kintamąjį į integer tipą, bet ši svetainė vis vien liko pažeidžiama XSS tipo atakomis. Žinoma, apie tai dar ir daugiau parašysiu.

$aNewsData = $db->getRow(“SELECT * from naujienos where id=’”. (int)$_GET[‘news_id’] .“‘”);
if ($aNewsData) {
    // atvaizduojam naujieną
    echo “<input type=’hidden’ name=’news_id’ value=’”. $_GET[‘news_id’].“‘/>”;
    // .. ir t.t
}
else {
     // naujiena nesurasta
}

PHP validacijai/apdorojimui turi ne vieną: is_array, is_numeric, is_bool, is_object, is_string, is_float…

Vartotojui reikia svetainėje pavaizduoti tik tiek duomenų, kiek jų reikia. Nes gali atsitikti gan įdomių situacijų. Turbūt girdėjot apie Horde framework’ą. Jis vartotojo prisijungimui gali naudoti įvairius scenarijus: POP3, IMAP, LDAP, SQL.. Buvo serveris sukonfigūruotas su IMAP autorizacija. Jei vartotojas įveda teisingą el. pašto adresą bei slaptažodį, tai serveris gražina, kad vartotojas prisijungęs. Pačiame horde frameworke buvo patikrinimas ar šis el. pašto adresas gali prisijungti ir kokias teises turi. Prisijungimo informacija buvo, žinoma, įvedama per input elementą, o autorizacijos serverio nustatymai (imap serveris, jo naudojama direktorija ir pan.) per hidden elementus/standartiškai. Kaip manote galima lengvai įeiti į “privačią zoną”?

Pasirodo galima. Jei jūs pakeistumėte autorizacijos serverio vardą į savo (reiktų sukonfigūruoti, kad imap serveris pas jus būtų reikiamo domeno), jums užtektų žinoti tik reikiamą vartotoją. Ir štai - jūs prisijungę. Žinoma, svetimo pašto skaityti jums nepavyks, bet jei įdiegti dar kiti moduliai, jų duomenis matysite.

Tad savaime suprantama, kad nereikia leisti, kad serverio nustatymus vartotojas galėtų keisti - jie turi būti nematomi. Toks būdas leidžiamas tik tuomet, jei tai yra nemokamo pašto tikrinimo programa - įvesk pop3 nustatymus, prisijungimus - mes tau parodysim tavo laiškus.

Kituose įrašuose aprašysiu kritines funkcijas, kurias neteisingai naudojant gali įsilaužti į jūsų svetaines, SQL, XSS atakas ir pan.

Jeigu jus kas nors konkrečiau domina, parašykite apie tai komentaruose. Ačiū.

Originalus straipsnis “PHP saugumas: Saugus programinis kodas. 1 dalis.

Panašūs straipsniai


“PHP saugumas: Saugus programinis kodas. 1 dalis.” komentarų: 2

  1. » Savaitgalio skaitiniai #26 Archyvas » Pixel.lt

    […] Sveiki, su greitai artėjančia vasara, su prasidedančiomis sesijomis, egzaminais ir t.t. ir pan. Šią savaitę ačiū Vaidui Žilioniui už straipsnį PHP saugumas: Saugus programinis kodas. 1 dalis.. Galime pasidžiaugti jog šio savaitgalio skaitiniai yra visi lietuviški! “Elgsena paremtas” programavimas(angl. Behaviour Driven Development). I dalis. “Elgsena paremtas” programavimas(angl. Behaviour Driven Development). II dalis. Ajax klaida […]

  2. Vaidas

    Notice: Use of undefined constant id - assumed ‘id’ in C:\AppServ\www\chatas\chat.php on line 15 Ką reikškia ši klaida?

Rašyti komentarą

Jūs privalote prisijungti jeigu norite rašyti komentarą.