Jump to content
chessh

Cum sa te protejezi de CSRF

Recommended Posts

Cum sa te protejezi de CSRF

Definitia CSRF-ului

Un 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-ului

Scopul 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 CSRF

Atacurile 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.

  1. Hackerul intra pe site
  2. Hackerul scrie un mesaj (care provoaca vulnerabilitatea)
  3. Un utilizator intra pe pagina unde hackerul a scris mesajul
  4. Cererea HTTP este trimisa serverului

Exemplu CSRF

Va 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>
<?php
if(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.1
HOST: [url]www.site.com[/url]
Cookie: PHPSESSID=4c50d3f5e75cfd3b9df18da4f568cf07

Cand 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>
<?php
if(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 nostru

Prevenirea CSRF-ului

Asadar, cum putem preveni atacurile CSRF? Cateva sfaturi bune ar fi:

  1. Folosirea metodei POST in formularele care produc modificari importante
  2. Folosirea unui formular de confirmare, ce foloseste metoda POST
  3. Folosirea variabilei de sesiune in linkuri ($_GET['session'])

Sper sa va fie de folos. Daca am vreo greseala, va rog postati un reply.

Link to comment
Share on other sites

1,2: formularele POST nu te salveaza de csrf, nici formular de confirmare.

3: e valid atata timp cat nu ti-a aflat sesiunea

eu 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 ...

Link to comment
Share on other sites

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 sesiunea

Corect.

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. :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...