chessh Posted July 11, 2008 Report Posted July 11, 2008 Cum sa te protejezi de CSRFDefinitia CSRF-uluiUn atac CSRF (Cross-Site Request Forgeries) reprezinta o vulnerabilitate a aplicatiilor web neprotejate. El consta intr-un link, pe care hackerul il poate folosi pentru a modifica continut. De obicei codul este scris in (X)HTML sau JavaScript.Scopul CSRF-uluiScopul acestui tip de atac este de a modifica continut, in numele unui utilizator sau chiar administrator, cu acest drept de acces (fara ca cei din urma sa afle). In general, aceste atacuri ii vizeaza pe toti utilizatorii. Despre CSRFAtacurile de acest tip falsifica anteturile cererilor HTTP, trimise in mod normal de catre browser la server (prin comunicarea intre cei doi). Ele folosesc de obicei elementul img (XHTML) si atributul sau, src, ce are ca valoare URL-ul unui script (nu al unei imagini, cum ar trebui sa fie in mod normal).Pentru a intelege mai bine, va voi face o schema, dupa care actioneaza majoritatea hackerilor.Hackerul intra pe siteHackerul scrie un mesaj (care provoaca vulnerabilitatea)Un utilizator intra pe pagina unde hackerul a scris mesajulCererea HTTP este trimisa serveruluiExemplu CSRFVa voi arata prin acest exemplu, cum un hacker poate sterge un anumit user, cunoscand scriptul atacat sau avand putin noroc.Vom crea o noua baza de date (folosind phpMyAdmin) numita csrf si tabelul users, cu doua campuri: user si pass.CREATE DATABASE csrf;USE csrf;CREATE TABLE users (id INT NOT NULL AUTO_INCREMENT, user VARCHAR(20) NOT NULL, pass VARCHAR(32) NOT NULL, PRIMARY KEY(id));INSERT INTO users (user, pass) VALUES ('csrf', '123456');Avem urmatorul script pentru stergerea unui utilizator de pe site:<html><head><title>Sterge utilizator</title></head><body><?phpif(isset($_GET['user']) && $_GET['user'] != '') { @mysql_connect('localhost', 'root', '') or die('MySQL error.'); @mysql_select_db('csrf') or die('MySQL error.'); $sql = "DELETE FROM users WHERE user='{$_GET['user']}'"; $result = @mysql_query($sql) or die('MySQL error.'); echo 'Utilizatorul '.$_GET['user'].' a fost sters.';} else { ?><form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">Sterge utilizatorul: <input type="text" name="user" /><input type="submit" name="submit" value="Delete" /></form><?php } ?></body></html>Acum sa vedem ce se intampla. Daca de exemplu, hackerul scrie un mesaj care contine urmatorul cod XHTML:[img=http://site.com/delete.php?user=csrf]Cererea HTTP va arata in felul urmator:GET /delete.php?user=csrf HTTP/1.1HOST: [url]www.site.com[/url]Cookie: PHPSESSID=4c50d3f5e75cfd3b9df18da4f568cf07Cand administratorul va intra pe pagina in care hackerul a postat mesajul ce contine codul de mai sus utilizatorul 'csrf' va fi sters.Pentru a preveni acest lucru, scriptul de stergere al utilizatorilor va trebui sa arate asa:<html><head><title>Sterge utilizator</title></head><body><?phpif(isset($_GET['user']) && $_GET['user'] != '') { if(isset($_POST['confirm']) && $_POST['value'] == 'yes') { @mysql_connect('localhost', 'root', '') or die('MySQL error.'); @mysql_select_db('csrf') or die('MySQL error.'); $sql = "DELETE FROM users WHERE user='{$_GET['user']}'"; $result = @mysql_query($sql) or die('MySQL error.'); echo 'Utilizatorul '.$_GET['user'].' a fost sters.'; } else { ?><form action="<?php echo $_SERVER['PHP_SELF']; ?>?user=<?php echo $_GET['user']; ?>&<?php echo $_GET['submit']; ?>" method="post">Sterge utilizatorul? Nu<input type="radio" name="value" value="no" checked />Da<input type="radio" name="value" value="yes" /><input type="submit" name="confirm" value="Confirm" /></form><?php }} else { ?><form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">Sterge utilizatorul: <input type="text" name="user" /><input type="submit" name="submit" value="Delete" /></form><?php } ?></body></html>O confirmare ce foloseste un formular cu metoda post este o modalitate buna de a preveni CSRF-ul in cazul nostruPrevenirea CSRF-uluiAsadar, cum putem preveni atacurile CSRF? Cateva sfaturi bune ar fi:Folosirea metodei POST in formularele care produc modificari importanteFolosirea unui formular de confirmare, ce foloseste metoda POSTFolosirea variabilei de sesiune in linkuri ($_GET['session'])Sper sa va fie de folos. Daca am vreo greseala, va rog postati un reply. Quote
moubik Posted July 11, 2008 Report Posted July 11, 2008 1,2: formularele POST nu te salveaza de csrf, nici formular de confirmare.3: e valid atata timp cat nu ti-a aflat sesiuneaeu prefer metoda 4: se creaza cheie random la fiecare refresh al paginii, si o cheie numita salting pentru a fi folosita la morpharea saltingului se salveaza in sesiune rezultatul criptarii pentru a putea fi comparat cu ce primim de la user.exemplu: de genul cheie random: Ajf84Odka03 --> $_GET['sid']si salting: unixtime() --> $_GET['time']$_SESSION['result'] <-- aici se salveaza hash-ul pe care speram sa-l obtinem la verificare pentru a face actiunea userului. (mai jos se da un exemplu de criptare)se salveaza in sesiune pentru fiecare cheie un hash prin metoda privata sau sau criptari bazate pe salting.salting care poate fi schimbat des si stiut numai de server (pentru a te proteja de reply attack)exemplu:$saltingMorph = $_GET['time'];$resultedFromUser = hash_hmac("md5", $_GET['sid'], "text stiut numai de server".$saltingMorph);if ($resultedFromUser === $_SESSION['result']){ //s-a validat}PS chiar iti place modul de scriere GNU al codului ?mie mi se pare foarte putin lizibil ... Quote
chessh Posted July 12, 2008 Author Report Posted July 12, 2008 1,2: formularele POST nu te salveaza de csrf, nici formular de confirmare.Da-mi un exemplu prin care poti sa treci de formularele post. Inca invat securitatea web, asa ca doresc sa aud sfaturi.3: e valid atata timp cat nu ti-a aflat sesiuneaCorect.PS chiar iti place modul de scriere GNU al codului ?mie mi se pare foarte putin lizibil ...Da, asa m-am obisnuit.PS: Foarte bine gandita metoda ta. Intr-adevar, nu prea ai cum sa treci de ea. Quote
moubik Posted July 14, 2008 Report Posted July 14, 2008 un formular cu post e la fel de vulnerabil ca un formular cu getcu get rezulta ceva de genulhttp://site.com/index.php?var1=valoare&var2=valoare - deci ar fi usor sa pacalesti userul sa intre pe acest urlcu post e explicat aici:http://websecurity.ro/blog/2007/11/17/csrf-cross-site-request-forgery-tutorial/ Quote
chessh Posted July 14, 2008 Author Report Posted July 14, 2008 Ah mersi de link. Nu m-am gandit la metoda asta cu post. So...util ar fi sa-ti protejezi sesiunea, si sa introduci variabila de sesiune in link. Quote