Sunteți pe pagina 1din 40

TEMA: VALIDAREA

INTRĂRILOR DE DATE ÎNTR-


O APLICAȚIE WEB

Autor: N.Pleșca, lector univ.


CONȚINUT
■ Modul de lucru al aplicațiilor web, inclusiv în HTML și HTTP
■ Aplicații vulnerabile la atacuri parvenite prin intrările de date
■ Strategii de validare ale datelor de intrare
■ Găsirea vulnerabilităților aplicației web și analiza tehnicilor de
apărare împotriva SQL Injection
Modul de lucru al aplicațiilor web în HTML
și HTTP. 1
Modul de lucru al aplicațiilor web în
HTML și HTTP. 2
■ Datele de intrare pot fi transmise pe server prin intermediul serviciului web prin
mai multe metode. Două, cele mai uzuale metode:
– Ca și componente ale interogărilor GET

– Ca și componente ale interogărilor POST. La transmiterea formularului,


care are specificat la atributul method="POST". Conținutul formularului,
în cazul interogării POST, se va transmite ca și parametri în corpul
interogării POST (încapsulate), iar valorile variabilelor nu se vor adăuga la
sfârșitul URL-ului (ca în cazul metodei GET)

Necesitatea validării datelor
■ Este necesar să se obțină de la utilizator datele necesare în formatul
solicitat — aplicațiile web nu vor ”lucra” corespunzător, dacă datele
utilizatorului vor fi salvate într-un format nepermis sau dacă utilizatorii
introduc date nepermise, incorecte sau în genere nu introduc date în câmpuri
■ Toate datele referitoare la conturile create ale utilizatorilor trebuie
protejate — prin obligarea utilizatorului ca acesta să introducă parole
protejate, se va asigura ca informațiile corespunzătoare conturilor lor să fie
protejate
■ Este necesar să ne protejăm aplicația și organizația căreia îi aparține
aplicația web — există multe metode de atac pe care le pot utiliza
persoanele rău-intenționate asupra formularelor neprotejate cu scopul
deteriorării aplicației folosite
Diferite tipuri de verificare a formularelor
(a datelor de intrare)
■ Verificarea pe partea ”client” - această validare se face în browser, înainte ca datele să fie expediate spre server.
Este cu mult mai comod ca validarea să se facă pe partea client, decât validarea pe partea server, deoarece răspunsul
se generează momentan tot de browser. Acest tip de validare poate fi de două tipuri:
– Validarea cu limbajul JavaScript. Această validare poate fi adaptată la datele verificate
– Validarea încorporată în formular. Sunt folosite atributele de validare ale formularului din HTML5. În acest caz nu mai este
necesar JavaScript. Această metodă de validare are productivitate mai ridicată dar nu este atât de adaptivă la toate controalele
formularului ca și metoda cu utilizarea JavaScript
■ Verificarea pe partea server - acest tip de validare are loc pe server, doar după ce datele sunt expediate. Scriptul
server-side este folosit pentru validarea datelor înainte de a salva datele în BD. Atunci când datele nu satisfac
cerințele de validare, se generează un răspuns clientului, printr-un mesaj destinat utilizatorului ca acesta să știe ce nu
a introdus corect și să corecteze intrarea de date. Validarea server-side nu este atat de comodă ca și validarea client-
side, deoarece mesajul de eroare nu se va genera până ce datele nu vor fi transmise pe server prin intermediul
formularului. Însă trebuie să se țină cont că validarea server-side reprezintă ultimul nivel de protecție împotriva
datelor incorecte sau ale celor cu impact de distrugere în cadrul aplicațieie web
■ Toate framework-urile server-side au încorporate funcții de validare și curățare ale datelor primite de pe partea
client, ceea ce le face mult mai sigure în utilizare în procesul creării de aplicații web
■ La dezvoltarea aplicațiilor web reale dezvoltatorii, ca regulă, combină validarea client-side cu
validarea server-side!!!
Unul dintre motivele apariției vulnerabilităților în
aplicațiile web...
■ Validarea incorectă a datelor de intrare
– Din motiv că există o încredere oarbă în utilizatorii aplicației sau
– Datele se verifică doar pe partea client a aplicației
■ Este necesară verificarea corectitudinii datelor introduse în formular. Nu se recomandă să se aibă
încredere în utilizatori, că aceștia vor introduce doar date permise. Siguranța trebuie să apară doar
după validarea datelor. Altfel apare riscul introducerii în script și/sau în BD a valorilor incorecte sau
riscul accesului la date nepermise
– Interogarea în aplicație se face în baza datelor introduse de utilizator. De obicei aceste date
servesc drept parametri pentru adăugarea datelor în BD, extragerii datelor și prezentării
acestora clientului, modificării datelor sau ștergerii datelor
– În oricare din cazurile expuse, datele introduse de utilizator sunt folosite pentru a genera
interogări ale BD și a le transmite spre BD. Aceste interogări trebuie formate foarte atent,
utilizând doar date permise și simboluri speciale ecranate, cu scopul evitării creării de
interogări SQL incorecte din punct de vedere sintactic sau chiar periculoase
SQL-injection. I
Validarea incorectă a datelor poate conduce la atacuri de tip SQL-injection
(atunci când aplicația are la bază o BD ce poate fi interogată prin limbajul SQL)
■ Se cunoaște deja că SQL — este un limbaj folosit pentru a interacționa cu BD
relaționale, iar cuvântul Injection s-ar traduce ca și „introducere, inserare”
■ Cu SQL Injection este posibilă inserarea unui cod SQL aliator, pe care serverul BD îl
va prelucra și va genera un răspuns
■ SQL Injection – este o vulnerabilitate periculoasă, care apare din cauza nevalidării și
filtrării insuficiente a datelor introduse de utilizatori, ceea ce va permite influiențarea
instrucțiunilor predefinite din script și modificării interogărilor BD
■ Rezultatul exploatării cu succes a SQL Injection poate conduce la accesul
nesancționat la datele, la care în condițiile normale utilizatorul nu trebuie să aibă
acces
SQL-injection. II
■ SQL-injection – este acel atac prin care utilizatorul poate schimba structura interogării
SQL adresată BD
■ Impactul acestui tip de atac: utilizatorul poate insera operatorii proprii SQL sau poate
modifica un anumit operator SQL din script, care este folosit pentru interogarea BD
■ Urmările posibile în cazul producerii cu succes a unui atac de tip SQL-injection:
– Accesarea datelor confidențiale din BD, deturnarea confidențialității sau a integrității
datelor
– Modificarea datelor din BD (insert/update/delete),
– Ridicarea nivelului de privilegii pe server (realizarea operațiilor de administrare a BD, ca
de exemplu inserarea noilor date în BD, includerea de noi fișiere în sistemul de fișiere sau
chiar să fie generate comenzi pentru sistemul de operare
– Deteriorarea accesului la date a aplicației web (se distrug tabelele BD sau chiar întreaga
BD – DROP…)
– Deteriorarea integrității aplicației (inclusiv accesul la anumite funcții ale aplicației)
Interacțiunea utilizatorului cu aplicația web în
cadrul funcției de introducere/modificare date (așa
cum ar trebui să fie)

<<include>>

Validare date
Introduce/modifica date <<include>>
user

Autentificare utilizator
Pașii (scenariul de acces) care ar trebui realizați în
procesul interacțiunii cu BD atunci când așteaptă
răspund la o anumită interogare (cum ar trebui să fie)
1. Introducerea datelor în formular
2. Validarea datelor introduse și apoi transferul acestora spre server
3. Recepționarea datelor pe server și validarea corectitudinii acestora
4. Crearea interogării BD
5. Primirea răspunsului de la BD (vor fi returnate una sau mai multe înregistrări)
6. Crearea răspunsului în format HTTP (depinde de rezultatul interogării)
1. În acest răspuns poate nimeri un set de înregistrări extrase din BD
2. Sau răspunsul poate să depindă de rezultatele interogării (ca de exemplu în procesul
autentificării sunt generate diferite pagini – în funcție de răspunsul returnat de BD)
Pașii (scenariul de acces) care ar trebui realizați în
procesul interacțiunii cu BD atunci când așteaptă răspund
la o anumită interogare (cum ar trebui să fie - grafic)
...cum se întâmplă de fapt atunci când se acordă
atenție realizării funcționalităților, fără să se
țină cont de securizarea accesării aplicației

<<include>>

Validare date
Introduce/modifica date <<include>>
user

Autentificare utilizator
Cum se realizează un atac de tip SQL
injection
■ Un atac de succes de tip SQL Injection, necesită ca atacatorul să prelucreze și să corecteze, așa cum are
el nevoie, o interogare SQL (preventiv înțelegând și ce tehnologii au fost utilizate pentru a elabora
partea server a aplicației)
■ Dacă aplicația returnează un mesaj de eroare, generat de aplicație la accesarea interogării incorecte,
atunci atacatorului îi poate fi chiar mai simplu să înțeleagă logica pe care ar trebui să o aplice și cum ar
trebui să realizeze injectarea
■ Sunt cunoscute câteva metode ce pot fi aplicate pentru a realiza SQL-injection. Ele pot fi utilizate în
combinație sau chiar și separat:
– Operatorul SQL Union: poate fi utilizat în operatorul SELECT, ceea ce va permite reuniunea a
două interogări într-un singur rezultat
– Boolean: sunt folosite condițiile logice pentru a verifica dacă anumite condiții adevărate sau false
– Metoda bazată pe erori: această metodă obligă BD să genereze o eroare, ceea ce poate oferi
atacatorului informații suplimentare pentru ca acesta să perfecteze interogarea pentru atac
– Reținerea timpului: sunt folosite comenzi ale BD (de exemplu, sleep – în MySql) pentru a reține
răspunsurile în interogările condiționale
Metode de depistare a vulnerabilităților
pentru atacuri de tip SQL injection
Primul pas care trebuie realizat ar fi înțelegerea în ce moment aplicația interacționează cu BD
pentru a solicita anumite date. Exemple tipice de interacțiune a aplicației cu BD ar fi:
■ Formularele de autentificare: atunci când autentificarea se face cu utilizarea unui formular
HTML, datele de cont ale utilizatorului sunt verificate cu cele stocate într-o BD și care
conține toale loghinurile și parolele
■ (Sub)sistemele de căutare: șirul introdus de utilizator în câmpul de căutare se folosește într-
o interogare SQL, care va extrage toate înregistrările cerute din BD
■ Site-urile care realizează comerț electronic: denumirile produselor și alte caracteristici ale
acestora (preț, descriere, accesibilitate etc.), mai mult ca sigur se vor păstra într-o BD
■ Înregistrare utilizator, abonare la noutăți etc.
Suplimentar mai trebuie analizate toate antetele HTTP și fișierele cookie
Exemplu pentru testare online

■ https://demo.owasp-juice.shop/#/
Problemă
■ Fie o mini-aplicație care acceseaza detalii referitoare la niște produse. Pentru a avea acces la
funcționalitățile acestei aplicații este solicitată autentificarea utilizatorului
■ Formularul de autentificare are 2 câmpuri: loghin și parolă
■ Pentru a avea posibilitatea ieșirii din spațiul privat al paginii de administrare acesta accesează opțiunea
corespunzătoare și este direcționat înapoi la formularul de autentificare
■ În BD a aplicației există câteva conturi de utilizator, pentru a fi posibilă intrarea în spațiul privat. Voi
folosi pentru acces contul cu datele: admin1 (loghin), admin1 (parola)
■ Atunci când datele sunt introduse corect (acestea coincid cu un set din cele existente în BD) – este posibil
accesul la spațiul privat
Introducerea incorectă a delor – nu va
permite accesul la spațiul privat
... Utilizatorul va fi direcționat înapoi la formularul de autentificare
• În script se verifică doar ca datele introduse în formular să coincidă cu un set
existent în BD
• Alte validări nu se fac – nici pe partea client și nici pe partea server
La introducerea intenționată a unor date eronate,
dar care conțin condiții logice suplimentare –
aplicația va oferi acces în spațiul privat
■ Din cauză că utilizatorul a introdus în câmpuri datele (loghin = 1' or '1' = '1 parolă = 1'
or '1' = '1), care se vor concatena în interogare și rezultatul interogării mereu va returna
«true»
■ Astfel de date în BD nu există – dar intrarea a fost realizată. De ce?
Analizăm scriptul de comparare a datelor...
$login = $parola = "";
if ($_POST['ok']) {
$login = $_POST["login"];
$parola = $_POST['password'];
$query = "SELECT * FROM users WHERE login='$login' AND password='$parola'";
$res = mysqli_query($conn, $query);
if($row=mysqli_fetch_array($res)) {
header('Location: http://'.$_SERVER['SERVER_NAME'].$cale.'meniu.php');
} else { header('Location: http://'.$_SERVER['SERVER_NAME'].$cale); }
mysqli_close($conn);
}
$login = $parola = "";
Ce se întâmplă la introducerea datelor
corecte și incorecte?
Este necesar să se implementeze reguli de diferențiere a unei interogări reușite și a uneia
nereușite
■ La introducerea datelor corecte:
$query = "SELECT * FROM users WHERE login = 'admin1' AND password = 'admin1' ";
– Se va găsi o potrivire a datelor (true) – ele sunt în BD
■ La introducerea datelor incorecte – și schimbării textului interogării:
$query = "SELECT * FROM users WHERE login='1' or '1' = '1' AND password='1' or '1' = '1' ";
– Nu se vor găsi potriviri cu datele existente în BD – astfel de date acolo nu sunt, dar rezultatul
returnat de condiția din «where», mereu va fi «true» indiferent câte înregistrări sunt în tabelul
BD – se vor găsi tot atâtea potriviri și aplicația va direcționa utilizatorul la pagina privată:
header('Location: http://'.$_SERVER['SERVER_NAME'].$cale.'meniu.php');
Ce se recomandă a fi verificat?
■ Primele simboluri care trebuie verificate dacă pot fi introduse în câmp sunt adăugarea de
ghilimea unară (') sau simbolului punct-virgulă (;) la testarea câmpului
– Primul simbol numit se folosește în SQL ca și delimitator al sirurilor de simboluri
textuale - și dacă nu se filtrează va genera o interogare incorectă
– Cel de-al doilea simbol se folosește în SQL pentru a specifică sfârșitul interogării, și
dacă nu este filtrat nici acesta – tot se generează o eroare
■ De asemenea se testează câmpul la acceptarea simbolurilor care indică comentarii în script (--
sau / * * /) și alte cuvinte cheie din SQL, precum 'AND’ și 'OR’, folosite în modificarea
interogării. O metodă simplă și recomandată este de a încerca introducerea unui șir de
caractere atunci când se așteaptă un număr
■ Se recomadă să fie controlate toare răspunsurile serverului web și să fie parcurse codurile
HTML / javascript. Uneori în ele pot fi depistate erori
■ Este foarte importat ca fiecare câmp să fie testat separat. O singură variabilă trebuie să fie
modificată, iar celelalte să rămână constante, pentru a înțelege care ca pametri sunt
vulnerabili și care nu
Uneori pot fi injectate și următoarele
succesiuni de simboluri....
1. Se comentează restul textului
interogării
-- se folosește la comentare în SQL

2. Se inserează un comentariu în
PHP

Obs.: la mine aceste șiruri nu au trecut


– interpretatorul și SGBD au facut
validările 
Scriptul client-side pentru validarea
intrărilor
<form action="<?php $_SERVER['SCRIPT_NAME']?>" method="post" onsubmit="return
validare();">
<label>Loghin<input type="text" class="linie" name="login" id="log" title="Introdu cel putin 4
litere sau cifre si cel mult 20!" maxlength="20" /> </label><br />
<label>Parola&nbsp;<input type="password" class="linie" name="password" id="pass"
title="Introdu cel putin 4 litere sau cifre si cel mult 15!" maxlength="15</label><br />
<input type="submit" name='ok' class="w3-container w3-border w3-round-xlarge w3-card-16 w3-
green w3-padding-16 w3-hover-border-green" value="Intra" />
</form>
<span id="err" style="color: red;"></span>
JavaScript-ul pentru validare

function validare() {
var log = document.getElementById("log").value;
var pass = document.getElementById("pass").value;
var mess="";
var er=0;
if(!/^[A-z0-9]{4,20}$/.test(log)) {mess += "Loghinul contine doar litere sau cifre - minim 4 si maxim
20!"; er=er+1; }
if(!/^[A-z0-9]{6,15}$/.test(pass)) {mess += "<br />Parola contine doar litere sau cifre - minim 6 si
maxim 15!"; er++;};
document.getElementById("err").innerHTML = mess;
return (er==0);
}
Rezultatul îndeplinirii acestui script –
datele nevalide nu sunt expediate pe server
Aceste date vor fi validate pe partea client pănă când utilizatorul nu va introduce litere și
cifre în numărul solicitat
Aceste intrări de date de asemenea nu
vor fi acceptate
Avantajele validării datelor pe partea client
■ Browserul va valida datele introduse pentru a se convinge că utilizatorul a introdus
datele solicitate înainte de expedierea formularului pe server. Atunci când datele nu
satisfac cerințele înaintate utilizatorului, acestuia i se propune să înlăture neajunsurile,
iar acesta nu va putea transmite datele spre server până nu va rezolva problema
■ Avantajul validării datelor pe partea client mai constă și în faptul că utilizatorul
primește momentan informația referitoare la problemele apărute. Dacă nu ar fi funcția
de validare în browser utilizatorul va expedia datele pe server, acolo se vor valida,
apoi i se vor genera erorile. Pentru rețelele de calculatoare cu o viteză mică de transfer
al datelor și a serverelor care sunt supraîncărcate acest proces poate fi foarte
îndelungat și chiar neplăcut
■ !!! Validarea pe partea client trebuie să suplimenteze validările pe partea server și nici într-
un caz să nu le înlocuiască. Nu trebuie să avem încredere în utilizatori și să folosim doar
validarea în browser. Pentru un atacator a scrie un script care să atace aplicația, atunci
când nu se fac validările pe partea server, este o nimica toată
Este recomandat să se facă validările și pe
partea server
■ În cazul în care este deconectată opțiunea executării JavaScripturilor
■ Pentru asigurarea unui nivel mai înalt al securizării
■ Dacă se adaugă doar o condiție suplimentară în scriptul server-side (1-l nivel de
protecție)
■ A fost: $query = "SELECT * FROM users WHERE login='$login' AND password='$parola' "; $res =
mysqli_query($conn, $query); $row=mysqli_fetch_array($res); if($row) {...}

■ Transformăm în: $query = "SELECT * FROM users WHERE login='$login' AND password='$parola' ";
$res = mysqli_query($conn, $query); $row = mysqli_fetch_array($res); if(mysqli_num_rows($res)==1) {...} – se
va minimiza numărul coincidențelor până la 1. Dar noi deja știm că avem 3
conturi și numărul coincidenților la adăugarea secvenței 1' or '1' = '1 va fi tot 3 și
această validare suplimentară va exclude posibilitatea accesării panoului de
administrare
Completăm scripurile server side...

■ Scriem funcția de ”curățare” de simboluri nepermise, a datelor introduse:


function curat($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Scriptul de validare server-side bazat pe
expresii regulate
■ Verificăm câmpurile dacă au fost completate, le ”curățăm” și le verificăm în baza expresiilor regulate:
$login = $parola = "";
$login_err = $parola_err = 0;
if ($_POST['ok']) {
$login = $_POST["login"]; $parola = $_POST['password'];
if (empty($_POST["login"])) { $login_err++; } else {
$login = curat($_POST["login"]);
if (!preg_match("/^[A-z0-9]{4,20}$/",$login)) { $login_err++; }
}
if (empty($_POST["password"])) { $parola_err++; } else {
$parola = curat($_POST["password"]);
if (!preg_match("/^[A-z0-9]{6,15}$/",$parola)) {$parola_err++; }
}
Scriptul de validare server-side. Continuare
if (($login_err + $parola_err) == 0) {
$query = "SELECT * FROM users WHERE login='$login' AND password='$parola'";
$res = mysqli_query($conn, $query);
if($row=mysqli_fetch_array($res)) {
header('Location: http://'.$_SERVER['SERVER_NAME'].$cale.'meniu.php');
} else {
header('Location: http://'.$_SERVER['SERVER_NAME'].$cale);
}
mysqli_close($conn);
}
}
$login = $parola = "";
Acum după completarea câmpurilor cu date,
acestea vor fi validate și pe partea server
Alte exemple ale acestui atac –
formularul de căutare
■ Rezultatul căutării înregistrărilor referitoare la produse după câmpul ”denumire_produs”
Alte exemple ale acestui atac – formularul de
căutare. Injectez simboluri speciale

A fost afișat conținutul întregului tabel ”produse”


Scriptul de căutare – fără validare
$sir_cautat = strtoupper("".$_GET['cauta']);
require('connection.php');
$sqlQwer=mysqli_query($conn, "SELECT denumire, descriere, pret_unitar, imagine FROM produse WHERE UPPER(denumire)
LIKE '%$sir_cautat%'");
if ($sqlQwer) {
echo '<div class="date_form w3-container w3-border w3-round-xlarge w3-card-8 w3-hover-border-green"><table>';
while($rows=mysqli_fetch_array($sqlQwer)){
echo '<tr>';
echo '<td class="w3-border w3-padding-16"><img width="55" height="47" border="1" src="'.$rows['imagine'].'"</td>';
echo '<td class="w3-border w3-padding-16">'.$rows['denumire']." - ".$rows['pret_unitar']." lei</td>";
echo '<td class="w3-border w3-padding-16">'.$rows['descriere']."</td>";
echo '</tr>';
}
mysqli_close($conn);
echo '</table></div>';
}
Adaug validările pe partea client și pe
partea server
Client:
<form method="get" onsubmit="return validare();" ...
... function validare() {
var text = document.getElementById("cauta").value;
var mess="";
var er=0;
if(!/^[A-Za-z]{1,20}$/.test(text)) {mess += "Denumirea contine doar litere - maxim 20!"; er++; }
document.getElementById("err").innerHTML = mess;
return (er==0); }
Server:
$sir_cautat = strtoupper("".$_GET['cauta']);
$sir_cautat = curat($sir_cautat);
if (preg_match("/^[A-Za-z]{1,20}$/",$sir_cautat)) {
echo '<div class="date_form w3-container w3-border w3-round-xlarge w3-card-8 w3-hover-border-green"><table>';
require('connection.php');
$sqlQwer=mysqli_query($conn, "SELECT denumire, descriere, pret_unitar, imagine FROM produse WHERE UPPER(denumire) LIKE
'%$sir_cautat%’»);...
Încerc sa atac iar...
■ Nu reușesc inserarea codurilor suplimentare – acestea sunt respinse
Concluzii
■ Înainte de a folosi datele în aplicație, acestea trebuie validate, pentru a ne
asigura că aplicația este protejată de date vulneravile
■ Validați datele de intrare utilizând expresiile regulate pe partea client și pe
cea server. Dacă vor fi transmise în aplicație date nevalidate, aceasta va fi
supusă atacurilor de inserare de coduri
■ Pentru variabilele care primesc date de tip primitiv (când nu sunt folosite
șabloane de introducere în calitate de argumente), se recomandă folosirea
expresiilor regulate pentru validare. Atunci când datele nu satisfac cerințele
înaintate acestora, aplicația își oprește execuția afisând mesaje
corespunzătoare de eroare referitoare la prelucrările de date

S-ar putea să vă placă și