Sigurnost u C Sharp-u

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

Temu rezervirao: Bernard Curić

Članovi:

- Bernard Curić

- Filip Faletar

Link na repozitorij: https://github.com/ffaletar/securityCSharp


Sadržaj

Uvod

U ovom projektu obraditi će se tema "Sigurnost u C#". Objasniti ćemo principe, savjete i preporuke Owasp.org-a, te Microsofta na ovu temu, te ćemo na primjeru pokazati jedan od načina realizacije sigurnosti u C#.

Programski jezik C# je programski jezik koji je potpuno baziran na principima objektno orijentiranog programiranja, svi elementi unutar njega predstavljaju objekt. Prethodnici C# su C i C++, te je sličan programskom jeziku Java. Razvili su ga Anders Hejlsberg, Scott Wiltamuth i Peter Golde kao dio .Net projekta. Prvi puta ga je javnosti predstavio Microsoft 2002. godine. Najnovija verzija je C# 6.0. 2014. Godine Microsoft je promijenio kompajler za C# koji je open-source kod, čime su omogućene lakše promjene na programskom jeziku. .Net Framework je glavna Microsoft-ova platforma za razvoj aplikativnih rješenja, koja podržava API za ASP.NET, Windows desktop aplikacije, Windows Communication Foundation servise, Share Point, Visual Studio alate za Office i druge tehnologije. Microsoft održava .Net Framework up-to-date putem Winodws Update servisa, te programeri ne moraju zasebno provoditi ažuriranje Frameworka. Pojedini framework-ovi mogu se ažurirati koristeći NuGet.

-- Bernard Curić

.Net Framework smjernice Owasp.org-a

Pristup podatcima

-- Bernard Curić

Enkripcija

-- Bernard Curić

Općenito

-- Bernard Curić

Smjernice za ASP.NET Web Forme

-- Bernard Curić

Smjernice za Windows Forms aplikacije


-- Bernard Curić

.Net Framework mehanizmi za zaštitu

.Net Framework nudi nekoliko mehanizama za zaštitu resursa i koda neautoriziranog koda i korisnika:

-- Bernard Curić

SQL Injection

SQL Injection je tehnika umetanja nedopuštenog koda na mjesta gdje aplikacija traži korisnički unos. Prema Owasp.org-u, napad SQL Injection-om ocijenjen je kao najkorišteniji napad od strane hackera. Ova tehnika se prvi put pojavila 1998. godine te se od tada konstantno širila. Do danas su razvijene mnoge tehnologije i načini obrane od SQL Injection-a. Ovakav se napad najviše pojavljuje u web aplikacijama, no moguć je u svim aplikacijama koji imaju svoju SQL bazu podataka. Danas je vrlo teško napasti web aplikaciju na ovaj način, čak i ako web aplikacija nije razvijena prema smjernicama koje predlaže Owasp.org kao najbolju obranu od napada. Razlog je taj što svi moderniji web preglednici imaju ugrađene razne funkcije sprječavanja unošenja nedopuštenog koda na mjesta predviđena za korisnički unos, kao npr. prijava, registracija korisnika, pretraživanje itd.

Iako današnji web preglednici svojim metodama smanjuju ranjivosti web aplikacija, ipak je pri razvitku aplikacija potrebno poduzeti preventivne mjere svođenja aplikativnih ranjivosti na minimum. SQL Injection je vrlo poznati napad po svojoj jednostavnošću, ali poznat je i po svojoj lakoj prevenciji s jednostavnim mjerama opreza.

-- Filip Faletar

Primjeri SQL Injection-a

Primjer 1

Početni upit:

 upit = "SELECT * FROM korisnik WHERE korisnickoIme = '" + korisnickoIme + "';" 

Za prethodno navedeni upit moguće je izvšiti SQL Injection na dva načina:

Unos:
 ' OR '1'='1 
Upit s prethodnim unosa:
 SELECT * FROM korisnik WHERE korisnickoIme = '' OR '1'='1'; 

Rezultat ovog upita je uvijek true, stoga je napadač uspio dohvatiti sve podatke iz tablice korisnik.


Unos:
 ' OR '1'='1' -- 
' OR '1'='1' /* 
Upit s prethodnim unosom:
 SELECT * FROM korisnik WHERE korisnickoIme = '' OR '1'='1' -- '; 

Primjer 2

Početni upit:

 upit = "SELECT * FROM korisnik WHERE korisnickoIme = '" + korisnickoIme + "';" 
Unos:
 1; DROP TABLE korisnik 
Upit s prethodnim unosom:
 upit = "SELECT * FROM korisnik WHERE korisnickoIme = 1; DROP TABLE korisnik; 

Napadač ovim upitom izvršava naredbu za brisanje tablice u bazi podataka te na taj način stvara veliku štetu žrtvi.

-- Filip Faletar

Prevencija SQL Injection-a

Parametrizirani upiti

Umjesto umetanja korisničkih unosa u SQL upit, preporučeno je da se koriste parametrizirani upiti čije su vrijednosti poznate tek prilikom izvršenja naredbe. Korištenim parametrima je određen tip parametra, što onemogućuje korisnicima upisivanje raznih znakova kao što su navodnici, zagrade, razmaci itd.

Primjer parametriziranog upita u C#:

 string upit = "UPDATE Korisnik SET korisnickoIme = @korisnickoIme " + "WHERE id = @id;";
SqlCommand naredba = new SqlCommand(upit, connection);
naredba.Parameters.AddWithValue("@korisnickoIme", "ffaletar");
naredba.Parameters.AddWithValue("@id", 5); 

Object Relational Mapping

Korištenjem ORM-a izbjegavamo pisanje SQL naredbi. ORM samostalno generira parametrizirane SQL naredbe iz objektno orijentiranog koda.

Upotreba uzoraka

Bez obzira kojeg tipa podataka je parametar, preporučuje se korištenje uzoraka (eng. pattern). Potrebno je odrediti pattern koji program prihvaća pri unosu podataka, dakle provjerava se odgovara li uneseni podatak određenom uzorku, odnosno patternu.

Primjer regexa:

 Regex rgx = new Regex(@"^[a-zA-Z0-9]\d{2}[a-zA-Z0-9](-\d{3}){2}[A-Za-z0-9]$"); 

Dozvole baze podataka

 DENY SELECT ON korisnik TO korisnik123; 

Dozvole baze podataka omogućuju kontrolu nad upitima. Korisnicima se može onemogućiti dohvaćanje podataka iz neke tablice ili dohvaćanje određenog podatka iz tablice.

-- Filip Faletar

Cross-Site Request Forgery

CSRF je vrsta napada kojom se korisnici prisiljavaju da naprave neke neželjene akcije na web aplikacijama gdje predstavljaju trenutno prijavljenog korisnika. Ovi napadi se najčešće obavljaju preko mail servisa. Na taj način napadači šalju poveznice korisnicima web aplikacije, koji zapravo izvrše neželjenu akciju. Ova vrsta napada se ne koristi za prikupljanje podataka, već za promjene raznih podataka web aplikacije.

Primjer CSRF-a

Dobar primjer CSRF napada je objašnjen na stranici Owasp.org. Postoje tri uloge na bankovnoj web aplikaciji, Alice koja želi poslati prijatelju Bob-u $100 te Maria, koja kao napadač želi da Alice upravo njoj pošalje $100000.

Ovisno o tome koristi li banka za izvršenje ove akcije POST ili GET metodu, razlikujemo sljedeća dva napada:

Napad preko GET metode

Pošto web aplikacija ove banke za prebacivanje novca s jednog na drugi račun koristi GET metodu, napadač Maria mora izvršiti napad preko GET metode, također. Reći ćemo da se zahtjev za prijenos novca obavlja na ovaj način:

 GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1 

Kao što je vidljivo, u GET metodi naveden je primatelj, odnosno račun primatelja te iznos novca kojeg Alice želi poslati. Kako je Maria odlučila napasti Alice, ona uzima originalnu GET naredbu te mijenja parametre, koji su ovom primjeru račun primatelja i iznos novca. Sada zahtjev izgleda ovako:

 GET http://bank.com/transfer.do?acct=MARIA&amount=100000 

Maria sada želi ovaj zahtjev nekako podmetnuti Alice, kako bi ona umjesto originalne akcije, upravo izvršila ovu. To može obaviti na sljedeće dva načina:

Ovo je dobar primjer HTML koda koji prikazuje vrlo jednostavan način da Alice pozove GET metodu:

 <a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a> 

Dakle, u mailu koji je Alice primila od napadača (iako ona misli da je mail poslan od strane banke) nalazi se slika koju će vrlo vjerojatno otvoriti ne znajući da upravo, ni kriva ni dužna, radi veliku grešku. Pritiskom na sliku, Alice poziva GET metodu koja joj oduzima novac.

Napad preko POST metode

Napad preko POST i GET metode vrlo su slični, jedina je razlika u tome kako se zahtjev izvršava. Neka POST zahtjev za prijenos novca izgleda ovako:

 POST http://bank.com/transfer.do HTTP/1.1

acct=BOB&amount=100 

POST metode može biti izvršena samo preko forma za unos korisničkih podataka. Stoga, da bi napadač Maria prisilio korisnika Alice da izvrši POST metodu, koristi sljedeću formu koju Alice ne vidi. Ovakva forma može biti izvršena i jednostavnim Javascript pozivom metode za submit forme.

 <form action="http://bank.com/transfer.do" method="POST">
<input type="hidden" name="acct" value="MARIA"/>
<input type="hidden" name="amount" value="100000"/>
<input type="submit" value="View my pictures"/>
</form> 

Kod preuzet s: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

-- Filip Faletar

Cross-Site Scripting (XSS)

Još jedan vrlo poznati napad je Cross-Size Scripting. Ovaj napad izvršava se na klijentskoj strani gdje napadač ubacuje zlonamjerne skripte u web aplikacije. Moguće ga je izvršiti preko raznih skriptnih jezika, npr. ActiveX, VBScript i Flash, ali ipak se najčešće pojavljuje umetanje JavaScript koda u određenu web aplikaciju. Na taj način napadač potiče žrtvu na izvršenje neželjenih akcija. Može se reći da je XSS jedna od najpoznatijih ranjivosti web aplikacije, a pojavljuje se na web aplikacijama koje nemaju podešenu validaciju korisničkih unosa. Bitno je napomenuti da napadač ne napada žrtvu direktno, već koristi web aplikaciju koju bi žrtva mogla posjetiti te na taj način žrtvi prenosi svoj maliciozni kod.

Primjer XSS napada

Za početak, napadač treba "upoznati" žrtvu, odnosno poznavati navike žrtve, točnije web aplikacije koja žrtva posjećuje. Zatim među tim web aplikacijama pronalazi onu koja je ranjiva, odnosno koja nema podešenu validaciju korisničkog unosa. Nakon što napadač izvrši ove početne korake, spreman je za napad. Recimo da web aplikacija koristeći sljedeći kod, korisnicima omogućuje prikaz zadnjih komentara.

 print "<html>"
print "<h1>Most recent comment</h1>"
print database.latestComment
print "</html>" 

Napadač koristi tih par linija koda kako bi izvršio svoj napad, na način da piše komentar na web aplikaciju koja nema podešenu validaciju za pisanje komentara. Maliciozni komentar izgleda ovako:

 <script>doSomethingEvil();</script> 

Tada se komentar već nalazi u bazi podataka od web aplikacije. Sada obični korisnik web aplikacije posjećuje sekciju s prikazom komentara te na taj način izvršava maliciozni kod.

 <html>
<h1>Most recent comment</h1>
<script>doSomethingEvil();</script>
</html> 

CrossSiteScripting.png

Kod i slika preuzeta s: https://www.acunetix.com/websitesecurity/cross-site-scripting/

-- Filip Faletar

Denial Of Service

Denial of Service je napad koji se najviše izvodi nad web aplikacijama. Cilj ovog napada je učiniti neku uslugu nedostupnom za krajnjeg korisnika. Napadač izvodi napad na način da u kratkom vremenskom roku pošalje veliki broj zahtjeva, koji je toliko velik da ih server jednostavno ne može sve obraditi. Na taj način postiže nedostupnost web aplikacije. DOS napadi mogu ciljati serversku infrastrukturu, aplikacijske ranjivosti, ranjivosti u komunikacijskim protokolima i propuste u operacijskim sustavima. Postoje razni programski proizvodi i alati za prevenciju DOS napada.

DOS.jpg

-- Filip Faletar

Sensitive data exposure

Do Sensitive data exposure dolazi kada aplikacija neadekvatno zaštiti svoje osjetiljive podatke. Ti podatci mogu biti bilo što, kao što su lozinke, tokeni sesije, podatci o kreditnim karticama, te različiti privatni podatci koji se mogu izložiti. Savjeti za moguću prevenciju:

-- Bernard Curić

Projektni primjeri

Izradili smo Windows Form aplikaciju u alatu Visual Studio kako bismo prikazali neke ranjivosti i preventivne mjere. Dobra zaštita od raznih računalnih napada je enkripcija, stoga smo je prikazali u prvom primjeru u ovom projektu. Zatim smo praktično obradili i SQL Injection u Windows Form aplikacijama. Iako se SQL Injection najviše izvršava na web aplikacijama, ovdje ćemo pokazati da je on moguć i na desktop aplikacijama. Također smo isprobali tehnologiju pod nazivom ClickOnce Security and Deployment.

-- Filip Faletar

Enkripcija lozinke

SQL Injection

SQL Injection jedan je od najpoznatijih sigurnosnih prijetnji na web aplikacijama, no i desktop aplikacije vrlo lako mogu biti oštećene ovom vrstom napada. Mi ćemo u ovom primjeru prikazati SQL Injection u Windows Form aplikaciji. Za početak smo kreirali formu koja je prikazana na sljedećoj slici:

PocetnaForma.png

Na lijevoj strani smo napravili pretraživanje korisnika preko Entity Framework-a, koji je ujedno dobra prevencija za izvšenje SQL Injection napada. Kako bismo prikazali način na koji SQL Injection funkcionira, s desne strane smo napravili formu za pretraživanje koja podatke dohvaća direktno iz baze podataka bez parametriziranih upita koji također dobro služe kao zaštita od SQL Injection-a.

 using (connection = new SqlConnection(connectionString))
                {
                    connection.Open();
                    SqlCommand command = new SqlCommand("SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE '" + textBox1.Text + "%'", connection);
                    SqlDataReader reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        string korisnickoIme = reader["korisnickoIme"].ToString();
                        string ime = reader["ime"].ToString();
                        string prezime = reader["prezime"].ToString();
                        string mail = reader["mail"].ToString();

                        Korisnik1 korisnik = new Korisnik1(ime, prezime, korisnickoIme, mail);

                        listaKorisnika.Add(korisnik);
                    }
                    dataGridView2.DataSource = dt;

                } 

Kao što je vidljivo u kodu, ne postoje parametrizirani upiti, niti ORM alata, stoga je ovaj način pisanja koda otvoren za SQL Injection. Da ponovimo, SQL Injection je napad kojim se ubacuje SQL kod na mjesta koja nisu predviđena za to, a to su uglavnom razni inputi podataka. Gornji primjer pisanja koda je vjerojatno najgora moguća obrana protiv SQL Injection. Toplo se preporuča upotrebo nekog ORM alata, korištenje parametriziranih upita, pisanje dozvola baze podataka i korištenje uzoraka.

Ranjivi upit koji dohvaća korisnike iz baze podataka.

 SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE 'Korisnik%' 

Umjesto paramatra "Korisničko ime", napadač će unijeti sljedeći kod, kako bi izbrisao korisnik s korisničkim imenom "Korisnik1"

 Filipo'; DELETE FROM Korisnik WHERE korisnickoIme = 'Korisnik1' --%' 

Tada cijeli upit izgleda ovako:

 SELECT korisnickoIme, ime, prezime, mail FROM Korisnik WHERE korisnickoIme LIKE 'Filipo'; DELETE FROM Korisnik WHERE korisnickoIme = 'Korisnik1' --%' 

Mogući su razni unosi koji mogu oštetiti i korisnika i aplikaciju, odnosno vlasnika aplikacije.

 Filipo'; DROP TABLE Korisnik;
Filipo'; UPDATE Korisnik SET lozinka='hack' WHERE korisnickoIme='Korisnik1' -- 

Prvi unos napadača izravno oštećuje bazu podataka na način da briše tablicu Korisnik. Drugi upit pak mijenja lozinku određenog korisnika, te na taj način napadač ima pristup njegovom profilu. Ipak, zadnja linija koda pokazuje koliko enkripcija pomaže pri zaštiti korisničkih podataka. Naime, zadnja linija koda ne bi izravno mogla naštetiti našoj aplikaciji s obzirom da je podešena enkripcija korisnika, odnosno korisničke lozinke. Stoga napadač izmjenjenu lozinku ne bi mogao iskoristiti kao lozinku za zlonamjernu prijavu na tuđi korisnički račun.

Sljedeća slika prikazuje istu Windows Formu nakon SQL Injection napada. Na lijevoj strani ispisa korisnika više ne postoji "Korisnik6", dakle, napadač je uspio izbrisati sve podatke za tog korisnika samo jednim unosom.

SQLInjectionNapad.png

-- Filip Faletar

ClickOnce Security and Deployment

Prema savijetima i smjernicama Owasp.org-a za razvoj sigurnosti u Windows Forms aplikacijama, napravili smo ClickOnce Deplooyment, koji objavljuje gotovu aplikaciju, koja kod svakog pokretanja aplikacije provjerava postoje li promjene, odnosno update verzije naše aplikacije. Navedeni Deployment smo koristili kako bi naknadno mogli dodati mogućnosti u aplikaciju, te ostavili prostor, kako bi mogli ispraviti prije svega sigurnosne, tako i ostale propuste u našoj aplikaciji. Kroz ovakav način Deploymenta možemo dizati različite razine sigurnosti aplikacije.

-- Bernard Curić


Provjera i pohrana lozinke

Nakon pokretanja aplikacije korisnik mora unijeti svoje korisničko ime, te lozinku, u slučaju da korisnik nema potrebne podatke, odabire mogućnost registracije, te u njoj unosi svoje podatke, koji se dalje spremaju u našu bazu podataka. Budući da je lozinka osjetljiv podatak, pokušali smo korisnika natjerati da koristi složenu lozinku, te smo pomoću metode ValidatePasword, provjerili da li upisana lozinka sadrži barem jedan broj, te po jedno veliko i malo slovo.

 
            var hasNumber = new Regex(@"[0-9]+");
            var hasUpperChar = new Regex(@"[A-Z]+");
            var hasLowerChar = new Regex(@"[a-z]+");


Nakon provjere unosa lozinke, ako je lozinka ispravna, spremamo ju kao hash, koristeći PBKDF2 funkciju, uz random salt, koju smo implementirali u CreateHash metodi, koja za argument uzima string, odnosno lozinku koju je korisnik uneo kod registracije.

 
public static string CreateHash(string password)
        {
            
            RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SaltByteSize];
            csprng.GetBytes(salt);

            
            byte[] hash = PBKDF2(password, salt, PBKDF2Iterations, HashByteSize);
            return PBKDF2Iterations + ":" +  Convert.ToBase64String(salt) + ":" + Convert.ToBase64String(hash);
        }
 


Nakon uspješne registracije korisnik se može prijaviti u aplikaciju. Unosi svoje korisničko ime, te lozinku, koja se provjerava s hashom koji je spremljen u bazi, kroz metodu ValidatePassword, koja prima dva argumenta, jedan od njih je unesena lozinka, dok je drugi hash lozinke unesenog korisničkog imena. Metoda uspoređuje hash vrijednosti unesene lozinke sa hashom lozinke pohranjene u bazi.

       
public static bool ValidatePassword(string password, string correctHash)
        {
            char[] delimiter = { ':' };
            string[] split = correctHash.Split(delimiter);
            int iterations = Int32.Parse(split[IterationIndex]);
            byte[] salt = Convert.FromBase64String(split[SaltIndex]);
            byte[] hash = Convert.FromBase64String(split[PBKDF2Index]);

            byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
            return SlowEquals(hash, testHash);
        }            


-- Bernard Curić

Literatura

Osobni alati
Imenski prostori
Inačice
Radnje
Orijentacija
Traka s alatima