Sigurnost Django frameworka

Izvor: SIS Wiki
Skoči na: orijentacija, traži

Članovi:
Igor Čoklo
--Igor Čoklo 20:41, 9. studenog 2015. (CET)

Sadržaj

Uvod

Django je jedan od mnogih web programskih okvira za Python programski jezik. Django je besplatan i open source programski okvir koji olakšava izradu web aplikaciju i on se brine oko raznih gnjavaža vezanih uz web razvoj tako da se programer može fokusirati samo na izradu aplikacije, a Django će se pobrinuti za ostale low level detalje kao što su protokoli, soketi ili upravljanje procesima/dretvama. Django podržava mnoge baze podataka kao što su PostgreSQL, MySQL, Sqlite, Oracle, IBM DB2, Microsoft SQL Server, Firebird i mnoge druge. Django dolazi s bazom SQLite koja je ujedno i najjednostavnija za rad i oni koji se baš ne razumiju u baze i samo žele isprobati Django se nebi trebali zamarati drugim bazama jer im je ova sasvim dovoljna za testiranje Djanga. Django je web programski okvir koji slijedi Model-View-Controller (MVC) dizajn koji se kod njega zove Model-View-Templates i označava sljedeće: model je zapravo entitet o kojem aplikacija prikuplja podatke, pogled (eng. view) je funkcija koja dohvaća te podatke iz baze i prikazuje ih na predlošku (eng. template).
[1]


Hello World program

S obzirom da se Django okvir koristi za razvoj velikih web aplikacija, kad se stvori Django aplikacija tada nam se automatski kreiraju i određeni direktoriji:
Direktoriji.PNG

Unutar mape projektSis se zapravo nalazi moja aplikacija u kojoj ću pisati svoj kod, sad se možda zapravo pitate ćemu to kad se to sve moglo napraviti i u mapi app, to je zapravo zato jer je Django namijenjen izradi velikih projekata koji će se sastojati od više aplikacija. Ovdje ću reći razliku između projekta i aplikacije, naime aplikacija je web aplikacija koja radi određenu akciju, a projekt se sastoji od više aplikacija. Ostale stavke neću pojašnjavati zato jer zasad to nije potrebno.
Da bi se moglo kreirati jednostavnu Hello World aplikaciju potrebno je napraviti sljedeće stvari:

  1. trebamo reci serveru da kad se u adresnoj traci preglednika pojavi rijec pocetna da nas on preusmjeri na pogled 'projektSis.views.pocetna', a to ćemo napraviti sljedećom linijom koda u datoteci urls.py:
     url(r'pocetna/', 'projektSis.views.pocetna',name='pocetna'), 
  2. nakon toga trebamo definirati svoj pogled u datoteci views.py:
     
    def pocetna(request):
        return HttpResponse("Hello World!")
    
  3. pokrenuti aplikaciju

Nakon što to napravimo uspjeli smo napraviti Django Hello World program koji se prema zadanim postavkama može vidjeti na adresi http://localhost:8000/pocetna/.
[1]

Injection

SQL injection je vrsta napada u kojem zlonamjerni korisnik može izvršavati proizvoljni SQL kod nad bazom podataka, ovo bi značilo da ako u aplikaciji postoji ranjivost na SQL injection tada zlonamjerni korisnik može raditi neke nedopuštene stvari nad bazom podataka: može saznati podatke o korisnicima aplikacije, može brisati te podatke, može ih objaviti negdje tako da su svima dostupni, itd.
Korištenjem Django querysets, rezultirajući SQL će biti siguran od napada kao što je SQL injection, ali Django također pruža programerima pisanje neobrađenih (eng. raw) upita. Kod korištenja takvih neobrađenih upita treba biti jako oprezan i izbjegavati korištenje parametara koje korisnik može kontrolirati jer ako programeri nisu oprezni mogli bi korištenjem neobrađenih upita napraviti aplikaciju koja je ranjiva na SQL injection.
Pošto Django koristi ORM (eng. Object-relational mapping) što je programska tehnika koja omogućuje programerima da koriste podatke iz baze kao objekte, tj. da im pristupaju kao objektima. Django Queryset predstavlja kolekciju objekata iz baze podataka koji se mogu filtrirati po raznim filterima. U SQL terminima QuerySet odgovara SELECT naredbi, a filtar je zapravo naredba WHERE ili LIMIT.
Primjer Django Queryset-a:
Ako u našoj bazi podataka postoji tablica korisnika(kod Djanga se korisnici dohvaćaju preko klase User) onda je veoma lagano dohvatiti sve korisnike iz baze podataka preko jednostavnog Queryset-a (bez da se koristi ikakav SQL upit):

 korisnici=User.objects.all() 

Isto tako se može veoma jednostavno dohvatiti bilo kojeg korisnika po njegovom IDu:

 korisnik=User.objects.get(id=korisnikovID) 

Django ima jako puno mogućnosti za dohvaćanje i filtriranje podataka iz baze. Ako programer želi napraviti aplikaciju koja je zaštićena od SQL injectiona tada treba koristiti već spremljene funkcije kod Djanga kojih zbilja ima mnogo, kao na primjer kod autentifikacije korisnika:

def prijava(request):
    rijecnik={}
    rijecnik.update(csrf(request))
    return render(request,'prijava.html',rijecnik)

def provjera_korisnika(request):
    korisnicko_ime=request.POST['kime']
    lozinka=request.POST['lozinka']
    korisnik=auth.authenticate(username=korisnicko_ime,password=lozinka)

    if korisnik is not None:
        auth.login(request, korisnik)
        return HttpResponse('Uspjesno ste se prijavili u aplikaciju')
    else:
        return HttpResponse('Neuspjesna prijava, provjerite jeste li unijeli dobre podatke!')

Kod pogleda prijava se samo prikazuje predložak prijava koji služi za prijavu u aplikaciju, a pogled provjera_korisnika koristi funkciju auth.authenticate za autentifikaciju korisnika, ako ova funkcija vrati None znači da korisnik ne postoji u bazi ili da su uneseni krivi podaci i tada će ovaj pogled ispisati u pregledniku tekst 'Neuspjesna prijava, provjerite jeste li unijeli dobre podatke!', a ako ne vrati None znači da korisnik postoji u bazi i sa funkcijom auth.login se korisnik prijavljuje u aplikaciju i ispisuje se tekst 'Uspjesno ste se prijavili u aplikaciju' .
Korištenjem neobrađenih upita riskira se da aplikacija bude ranjiva na SQL injection, ali ipak možda je u nekim situacijama potrebno koristiti taj način. Primjer korištenja neobrađenih upita nad tablicom korisnika:

 
korisnici=User.objects.raw('SELECT * FROM auth_user')
for k in korisnici:
        print(k)

Ovo je primjer jednostavnog upita koji će nam vratiti sve korisnike iz tablice auth_user (tablica koju nam Django stvara i u nju se spremaju svi korisnici)

[2],[3],[4]

Broken Authentication and Session Management

Broken Authentication and Session Management iliti problemi sa autentifikacijom i upravljanje sesijama je problem koji je povezan s krađom korisničkih podataka kao što su username ili password prilikom logina na neku stranicu.
Načini na koje web aplikacija može zakazati pri zaštiti korisničkog imena, lozinke i sessionIDa:

  1. nekriptirana konekcija (bez https) – svatko može vidjeti podatke koji se šalju preko nekriptirane veze, rješenje je omogućavanje enkripcije na zahtjevima koji sadrže osjetljive podatke
  2. predvidljivi podaci za prijavu u web aplikaciju: primjer korisničkog imena: 123456, qwerty, lozinka: 12345678, abc123 (jako loše kombinacije) , rješenje je tjeranje korisnika da koriste bolje lozinke pomoću regularnih izraza
  3. nema isteka sesije/sesija nije poništena kod logouta (problem je krađa sesije), rješenje je postavljanje isteka sesije nakon određenog vremena neaktivnosti i poništavanje sesije kod logouta
  4. sesion id se koristi u url-u, problem je krađa sesije, ako se nekom pošalje link sa id-om sesije u sebi tada se neki drugi korisnik može koristiti aplikacijom kao da je prijavljen kao neki drugi korisnik (ja se prijavim u app, pošaljem link kolegi koji u sebi ima sesion id i on koristi app i prijavljen je kao ja u toj aplikaciji), rješenje je: ne slati sesion id u url-u, nego ga slati u tijelu POST zahtjeva, to bi trebalo vrijediti za sve, ne slati osjetljive podatke u url-u nego u tijelu POST zahtjeva.

Kod Djanga može nastati sljedeći problem: Na primjer napadač se može prijaviti na stranicu good.example.com i dobiti valjanu sesiju za svoj račun. Ako napadač ima kontrolu nad stranicom bad.example.com, on može iskoristiti tu stranicu kako bi poslao svoj ključ sesije nekom običnom korisniku zato jer poddomena dopušta postavljanje kolačića na sve stranice *.example.com. Dok obični korisnik posjeti stranicu good.example.com on će biti prijavljen kao napadač i mogao bi nehotice unijeti svoje osjetljive podatke (broj kreditne kartice) u napadačev račun.
Drugi napad koji bi se mogao desiti kod Djanga je ako bi stranica good.example.com postavila varijablu SESSION_COOKIE_DOMAIN (domena za spremanje sesijskih kolačića) na ".example.com" što bi prouzročilo da se sesijski kolačići od stranice good.example.com šalju stranici bad.example.com.
[5],[6]

Cross-Site Scripting (XSS)

Cross-Site Scripting je tehnika napada kod koje napadač može ubaciti (injectati) nesigurne isječke javascript koda u našu aplikaciju bez validacije. Taj Javascript kod će se onda izvršiti kad neka žrtva posjeti zaraženu aplikaciju/stranicu. Postoji više vrsta XSS napada:

Rizici koji se mogu desiti prilikom XSS napada:

Zaštita od XSS napada:

Naputci vezani uz Django: korištenje Django predložaka nas štiti od većine XSS napada. Django predlošci ispuštaju (eng. escape) posebne znakove koji su posebno opasni kod HTML-a. Iako ovaj način štiti korisnike od većine malicioznih unosa, taj način nije potpuno siguran. Na primjer, ovaj način nas neće zaštiti od sljedećeg:

<style class={{ var }}>...</style>

Ako je varijabla var postavljena na sljedeću vrijednost 'class1 onmouseover=javascript:func()' to može rezultirati neovlaštenim izvršavanjem Javascript-a, ovisno o tome kako preglednik prikazuje nesavršen HTML. (citiranjem vrijednosti atributa class bi se riješio ovaj problem)
Također programeri Django aplikacija trebaju biti veoma oprezni kod spremanja HTML-a u bazu, osobito kad se taj HTML treba dohvatiti i prikazati.
[2] i [5]

Cross Site Request Forgery (CSRF)

Ovo je tip ranjivosti koji omogućuje napadačima da natjeraju obične korisnike da izvode neke aktivnosti nesvjesno, kod csrf-a korisnici su obično nesvjesni da se maliciozne akcije izvode u pozadini. Na primjer: korisnik Igor se logira u aplikaciju svoje banke i on želi poslati Hrvoju 200kn za instrukcije iz programiranja, a u isto vrijeme dok je logiran na stranicu svoje banke ujedno je i na nekoj drugoj stranici koju kontrolira Ivan (zločesti haker) i sad Igor klikne da uplati novac s svojeg računa na Hrvojev, a Ivan u isto vrijeme presretne taj POST zahtjev i napravi sljedeću modifikaciju u formi i pošalje sebi novac:

<form action="http://bank.com/transfer.do" method="POST">
<input type="hidden" name="account" value="Ivan"/>
<input type="hidden" name="amount" value="10000"/>
<input type="submit" value="Izvrši uplatu"/>
</form>

Nakon toga na Ivanov račun dođe 10000 kuna, a Igor ostane bez svojih novaca bez da to prvotno nije znao, ali kad Igor pogleda sva svoja plačanja vidit će da je poslao novac Ivanu, a da Hrvoju nije poslao ni lipe.
Django i CSRF: Django ima ugrađenu zaštitu protiv većine vrsta csrf napada, pod uvjetom da su programeri omogućili tu zaštitu i koristili je tamo gdje je potrebno. Međutim ovdje se može desiti problem tako da na primjer programeri isključe csrf modul globalno ili ga samo isključe na određenim pogledima ==> programeri bi to trebali raditi samo ako razumiju što rade.
CSRF zaštita radi tako da se provjeri postoji li nonce (number used only once) u svakom POST zahtjevu. Time je osigurano da zlonamjerni korisnik ne može ponoviti POST zahtjev na određenu stranicu kako bi na primjer prenio novac na svoj račun, da bi to napravio zlonamjerni korisnik bi trebao znati nonce, koji je specifičan za svakog korisnika.
Programeri trebaju biti veoma oprezni kada obilježavaju poglede sa csrf_exempt anotacijom (ona isključuje csrf modul) i tu anotaciju ne treba koristiti osim ako je apsolutno neophodno.
[2], [5]

Zaštita podataka korištenjem HTTPS protokola

Uvijek je bolje za sigurnost implementirati web aplikaciju korištenjem HTTPS protokola. Bez ovog protokola, zlonamjerni korisnici mogu vidjeti sve podatke koji se šalju između klijentskog računala i servera te mogu te podatke iskoristiti kako bi se prijavili kao neki drugi korisnik i napravili neku štetu ili mogu čak mijenjati te podatke. Kad se koristi HTTPS protokol veza je kriptirana i zlonamjerni korisnik tada ne može raditi štetu korisnicima.
Ako Django programeri žele koristiti zaštitu koju HTTPS pruža u svojim web aplikacijama i ako server podržava HTTPS postoje neki dodatni koraci koji bi im mogli zatrebati:

[2]

Literatura

  1. Igor Čoklo (2015), Razvoj web aplikacija u Python-u, dostupno 10.01.2016 na http://services.foi.hr/thesis/web/tema/2437/file
  2. Security in Django, https://docs.djangoproject.com/en/1.9/topics/security/
  3. Making queries, https://docs.djangoproject.com/en/1.9/topics/db/queries/
  4. Performing raw SQL queries, https://docs.djangoproject.com/en/1.9/topics/db/sql/
  5. Owasp top 10, https://www.youtube.com/watch?v=02mLrFVzIYU&list=PLoyY7ZjHtUUVLs2fy-ctzZDSPpawuQ28d
  6. Session Security, https://docs.djangoproject.com/en/1.9/topics/http/sessions/#topics-session-security
Osobni alati
Imenski prostori
Inačice
Radnje
Orijentacija
Traka s alatima