Sunteți pe pagina 1din 17

UNIVERSITATEA DE STAT DIN REPUBLICA MOLDOVA

DEPARTAMENTUL CONTABILITATE, CIBERNETICĂ ŞI INFORMATICĂ


ECONOMICĂ

STUDIU DE CAZ

TEMA: PROTEJAREA BAZELOR DE DATE

Autor:
Colun Ion, CIE1401
Coordonator ştiinţific:
Apetrii Natalia, lector universitar

Chişinău 2017
CUPRINS
INTRODUCERE…………………………………………………………3
CAPITOLUL 1. Integritatea datelor……………………………………4
CAPITOLUL 2. Securitatea bazelor de date…………………………...6
CAPITOLUL 3. Structura BD MySQL………………………...………9
CAPITOLUL 4. Atacurile de tip SQL injection…….………………...11
4.1 Bazele SQL-injection………………………………………….......….11
4.2 Proceduri de testare a aplicaţiilor web la SQL-injection…….…....….12

4.3 Identificarea parametrilor vulnerabili………….…….………….…....13


4.4 Metode de atac……………………………………..……………..…..14
4.5 Metode de apărare………………………………………………….....14

CONCLUZIE………………………………………………………..…..16
BIBLIOGRAFIE……………………………………………………..…17

2
INTRODUCERE

Protecția bazelor de date constă dintr-un set de măsuri umane şi facilități oferite de SGBD
prin care se urmăreşte asigurarea integrităţii datelor, definită ca fiind corectitudinea datelor
introduse și manipulate, și a securității datelor, ce vizează interzicerea accesului la date pentru
persoanele ce nu au competențe în folosirea lor. Aceasta capăta o importanță deosebită în contextul
extinderii folosirii configurațiilor cu număr mare de utilizatori și cu un volum mare de date de
prelucrat.

În ceea ce privește sfera de acțiune a metodelor utilizate pentru protecția datelor, pot fi puse
în evidență doua tendințe: protecția împotriva unor defecte sau erori accidentale şi protecția
completă care realizează în plus față de prima și protecția contra unor acțiuni voite. Teoretic, toate
sistemele ar trebui să asigure protecția completă a datelor. În practică însă, costul protecției, care
crește pe măsură ce sunt reduse posibilităţile de apariție a unor erori şi de violare a confidențialității
datelor, este cel care dictează complexitatea metodelor de protecţie care vor fi utilizate. Aspectele
protecției bazelor de date ce vor fi prezentate mai jos se bazează pe presupunerea că protecția
informației la nivelul sistemului de operare este asigurată.

3
CAPITOLUL 1. Integritatea datelor
Corespunzător situațiilor care pot genera apariția unor date incorecte în baza de date, se
disting trei aspecte ale asigurării integrităţii datelor:

· Asigurarea integrităţii semantice a datelor - presupune prevenirea introducerii unor date incorecte și
a efectuării unor prelucrări greșite. Dacă acest lucru nu va fi împiedicat sau semnalat imediat, datele
vor fi utilizate în alte prelucrări, declanşându-se astfel un proces necontrolat de alterare a bazei de
date. Cu cât sesizarea unei erori are loc după o perioadă mai mare, cu atât efectele ei vor fi mai greu
de controlat;

· Controlul accesului concurent la date - presupune prevenirea obținerii unor rezultate incorecte din
execuția concurență (simultană) a unor prelucrări în regim multi-utilizator. O altă problemă care
poate apăre la prelucrarea concurentă este dată de interblocare. Aceasta înseamnă că două tranzacții
blochează anumite resurse, apoi solicită fiecare resursele blocate de cealaltă ;

· Salvarea și restaurarea bazei de date. Au ca scop readucerea datelor la o formă consistentă în urma
unor evenimente care au alterat corectitudinea lor precum:

o Funcţionarea anormală sau o cădere a SGBD sau a sistemului de operare;

o Defecţiune fizică a suportului fizic pe care este memorata baza de date.

În primul caz, prin întreruperea tranzacțiilor active în momentul respectiv, baza de date va
rămâne într-o stare de inconsistență. În cel de-al doilea caz, suportul pe care rezidă baza de date va
fi inaccesibile, deci toate datele se vor pierde.

Pentru restaurarea bazei de date este necesară existența unor informații despre derularea
tranzacțiilor până în momentul întreruperii lucrului și aplicarea, după caz a uneia din următoarele
tehnici de restaurare de bază:

· Derularea înapoi a tranzacţiilor (ROLLBACK) - care presupune anularea modificărilor efectuate de


acestea asupra bazei de date și reîntoarcerea la statutul inițial;

· Derularea înainte a tranzacțiilor completate dar nereflectate în bază de date (ROLLFORWARD) -


care presupune efectuarea acelor transformări prin care baza de date restaurată să conţină rezultatele
acestora.

Se observă deci că tranzacția poate fi considerată unitatea de restaurare, în sensul că baza de


date restaurată trebuie, fie să reflecte rezultatele finale ale tranzacțiilor, fie să nu fie afectată de

4
acestea. Procesul de restaurare utilizează o serie de infromații obținute prin aplicarea unei anumite
strategii de salvare. Datele salvate pot fi diferite combinații între:

· Copii ale bazei de date și copii ale jurnalelor acesteia;

· Jurnale ale tranzacțiilor;

· Jurnale ale imaginii înregistrărilor din baza de date.

Copiile bazei de date pot fi realizate automat de către sistem la anumite intervale de timp, sau la
comanda administratorului bazei de date, ori de câte ori este nevoie, de preferat pe suporturi
magnetice diferite de cele pe care este stocată baza de date. În cazul unei deteriorări a suportului
magnetic care păstrează baza de date, acesta este singura posibilitate de recuperare a bazei de date.

Jurnalul tranzacțiilor este un fișier special, întreținut de SGBD, în care sunt memorate informații
despre tranzacțiile efectuate asupra bazei de date, cum sunt:

· Identificatorul sau codul tranzacției;

· Momentul începerii execuției tranzacției;

· Numărul terminalului sau identifacatorului utilizatorului care inițiat tranzacția;

· Datele introduse;

· Înregistrările modificate și tipul modificării.

Pe baza lui va putea fi stabilită ulterior succesiunea corectă și natura prelucrărilor efectuate în
intervalul de timp pentru care trebuie să se asigure restaurarea bazei de date. Jurnalul imaginilor se
deosebește de jurnalul tranzacțiilor prin aceea că el nu conține descrierea operațiilor efectuate
asupra bazei de date ci efectul acestora. Poate îmbarca una din următoarele forme:

· Jurnalul cu imaginea înregistrărilor după modificare (after image) - va conţine copia fiecărei
înregistrări ce este modificată, în formă rezultată după modificare;

· Jurnalul cu imaginea înregistrărilor înaintea unei modificări (before image) - va conţine copia
fiecărei înregistrări ce este modificată, în formă iniţială, anterioară efectuării modificării;

· Jurnalul care conţine atât imaginea înregistrărilor înainte cât şi după modificare;

· Restaurarea bazei de date se poate face automat sau manual.

5
CAPITOLUL 2. Securitatea bazelor de date

Asigurarea securităţii bazei de date presupune interzicerea accesului neautorizat la date.


Aceasta se realizează cu ajutorul unui set de măsuri de protecție umane, software şi hardware. O
primă astfel de măsură o poate constitui izolarea sistemului de calcul în încăperi în care accesul
persoanelor să fie permis pe bază de legitimații sau a altor forme de identificare.

Un alt nivel de protecție îl poate constitui stabilirea de parole pe baza cărora să fie permis
accesul la resursele sistemului de calcul. În timpul lucrului efectiv cu baza de date se va verifica
dacă utilizatorul are dreptul de a executa un tip de operație asupra anumitor date. SGBD poate ține
și un jurnal pentru urmărirea accesului la baza de date, pe baza căruia pot fi depistate încercările de
acces neautorizat la baza de date.

Pentru cererile de intrare/ieșire transmise sistemului de operare de către SGBD sunt posibile
verificări suplimentare referitoare la utilizarea corectă a fișierelor sau a funcțiilor sistemului de
operare. Hardware-ul poate să ofere o protecție suplimentară, ca de exemplu transferarea datelor
numai în zonă de memorie controlată de SGBD. De asemenea, datele pot fi memorate pe suportul
extern într-o formă criptată.

În continuare vor fi prezentate următoarele mecanisme de asigurare a securităţii datelor din


baza de date:

Ш Autorizarea și controlul accesului la date presupune identificarea utilizatorilor, restricționarea


accesului acestora la date precum și restricționarea operațiilor ce pot fi executate asupra datelor
accesate.

Cea mai mare parte a SGBD-urilor actuale folosesc pentru identificarea utilizatorilor parole.
Fiecare parolă va fi asociată cu anumite drepturi de acces la date, ea nefiind decât un prim obstacol
pentru cei care încearcă să violeze securitatea bazei de date.

Astfel, pentru fiecare utilizator identificat prin parolă, SGBD menține o listă a privilegiilor
acestuia. De asemenea, utilizatorii pot fi asociați unor grupuri de utilizatori, la drepturile fiecaruie
adăugindu-se drepturile stabilite pentru grupul respectiv. Privilegiile unui utilizator depind astfel de
clasa de utilizatori căreia îi aparține.

Din acest punct de vedere, utilizatorii se împart în: administratorul bazei de date care are toate
drepturile asupra acesteia, utilizatori proprietari de obiecte (tabele, viziuni, proceduri), un obiect

6
fiind întotdeauna în proprietatea celui care-l creează, și utilizatorii obișnuiți, care nu au în
proprietate obiecte și nu au alte privilegii decât cele moștenite ca membrii ai unui grup sau
menționate explicit de administratorul bazei de date.

Ш Definirea și utilizarea viziunilor. Viziunile (schemele externe) sunt partiții logice ale bazei de date.
Ele sunt definite pentru diferiți utilizatori în raport cu necesitățile acestora de a avea acces la date,
putind fi utilizate pentru a restricționa accesul la date.

Privilegiile pentru o viziune sunt specificate independent de cele pentru obiectele pe baza căreia
este definită. Securitatea datelor este asigurată prin definirea tuturor drepturilor necesare unui
utilizator pentru o viziune și revocarea drepturilor pentru obiectele inițiale. Aceasta modalitate este
suficientă în cazul în care asupra datelor viziunii este permisă doar operația de citire. Pentru
operația de modificare trebuiesc avute în vedere efectele laterale pe care acesta le poate produce
asupra obiectelor inițiale. Utilizatorului nu trebuie să i se permită să efectueze asupra viziunii acele
operații care pot afecta obiectele inițiale. În caz contrar, pot să apară erori sau inconsistențe în baza
de date.

Ш Realizarea de proceduri speciale. Unele SGBD oferă facilitatea definirii unor proceduri ce vor fi
păstrate la nivelul sistemului într-o formă precompilată.

În cadrul acestor proceduri vor fi specificate explicit operațiile ce trebuie efectuate asupra datelor.
Utilizatorului i se va acorda dreptul de execuție a acestor proceduri și i se va interzice accesul direct
la obiectele bazei de date gestionate de procedură.

Ш Criptarea datelor este operația de codifcare a datelor în timpul stocării sau al transportului, astfel
încât descifrarea lor să poată fi făcută numai de posesorii de cod. La nivelul SGBD această facilitate
poate îmbarca două forme:

o Existența unor rutine speciale care realizează criptarea datelor la cerere sau automat;

o Existența unor instrumente de criptare care permit utilizatorului să-și realizeze propriile rutine de
criptare.

Procesul efectiv de criptare presupune folosirea unui sistem de cifrare, ale cărui componente sunt:

· Algoritmul de criptare – realizează transformarea datelor din forma inițială în forma criptată;

· Cheia de criptare – valoare ce constitue o intrare a algoritmului de criptare, aleasă dintr-o mulțime
de chei posibile;

· Algoritmul de decriptare – realizează transofrmarea datelor di formă criptată în formă în formă


inițială;

7
· Cheia de decriptare – valoare ce constitue o intrare în algoritmul de decriptare, dependentă de
cheia de criptare.

8
CAPITOLUL 3. Structura BD MySQL

Când este instalat MySQL, acesta creează automat o bază de date numită mysql . Toate
informațiile utilizate pentru a proteja datele sunt stocate în această bază de date, inclusiv numele de
cont, parole, nume de gazde, și privilegii.

Privilegiile sunt stocate în coloane.Formatul fiecărui nume de coloană este privilegiu _priv ,
în care privilegiu este un privilegiu cont.De exemplu, coloană care conține privilegii ALTER este
numit alter_priv .Valoarea din fiecare coloană privilegiu este Y sau N , adică da sau nu.

Deci, de exemplu, în tabelul de utilizator, nu ar fi un rând pentru un cont și o coloană pentru


alter_priv .În cazul în care câmpul de cont pentru alter_priv conține Y , contul poate fi utilizat
pentru a executa o instrucțiune ALTER .În cazul în care alter_priv conține N , contul nu are
privilegiul de a executa o instrucțiune ALTER .

Baza de date MySQL conține următoarele tabele care stochează privilegii:

· Utilizator;

· Tabel: Aceasta stochează tabel privilegii care se aplică tuturor bazelor de date și tabele.Acesta
conține un rând pentru fiecare cont valid, care include coloanele numele de utilizator , numele
gazdei , și parola .MySQL server respinge o conexiune pentru un cont care nu există în acest tabel;

· Db_tabel: Aceasta stochează tabel privilegii care se aplică o anumită bază de date.Acesta conține
un rând pentru baza de date, ceea ce conferă privilegii unui nume de cont și un nume de
gazdă.Contul trebuie să existe în tabelul de utilizator pentru privilegiile care urmează să fie
acordate. Privilegii care sunt date în tabelul de utilizator treacă peste privilegii în acest tabel;

De exemplu, în cazul în care masa utilizator are un rând pentru designer de cont , care oferă
privilegii INSERT , proiectantul poate însera în toate bazele de date.În cazul în care un rând în
tabelul de db prezintă N pentru INSERT pentru contul proiectantul în baza de date PetCatalog ,
masa utilizator -l respinge, iar designerul poate însera în baza de date PetCatalog.

· Gazdă tabel : Acest tabel controlează accesul la o bază de date, în funcție de gazdă. Tabelul gazdă
funcționează cu tabelul de db;

În cazul în care un rând în tabelul de db are un câmp gol pentru gazdă, MySQL verifică
tabelul de gazdă pentru a vedea dacă db are un rând acolo.În acest fel, puteți permite accesul la o db
de la unele gazde, dar nu de la alții.

9
De exemplu, să presupunem că aveți două baze de date: db1 și db2 .Baza de date db1 are
informații sensibile, așa că doriți doar anumite persoane să-l vadă.Baza de date db2 dispune de
informații pe care doriți ca toată lumea să vadă.

Dacă aveți un rând în db tabelul pentru db1 cu un câmp gol gazdă, puteți avea două rânduri
pentru db1 în tabelul gazdă. Un rând poate da toate privilegiile utilizatorilor conectarea de la o
gazdă specifică, în timp ce un alt rând se poate nega privilegii pentru utilizatorii conectați la orice
altă gazdă.

· tables_priv tabel: Aceasta stochează tabel privilegii care se aplică tabelelor specifice.

· columns_priv tabel: Acest tabel stochează privilegii care se aplică anumite coloane.

Puteți vedea și modifica tabelele din mysql direct, dacă utilizați un cont care are privilegiile
necesare.Aveți posibilitatea să utilizați interogări SQL, cum ar fi SELECT , INSERT și UPDATE
.Dacă accesați MySQL prin intermediul angajatorului, un client sau o companie de găzduire web,
probabil că nu au un cont cu privilegiile necesare.

10
CAPITOLUL 4. Atacurile de tip SQL injection

4.1. Bazele SQL-injection

SQL Injection este o vulnerabilitate ce apare în cazurile când datele primite de la utilizatori
nu se prelucrează corect. Ca consecinţa – răufăcătorul potenţial poate schimba cererea la baza de
date, asfel fiind posibil furtul datelor private.

Această lucrare reflecta tehnicile simple şi avansate ce sunt folosite de răufăcători în


procesul de exploatare a vulnerabilităţii SQL Injection. Aceste tehnici demonstrează cum pot fi cu
uşurinţă obţinut conţinutul bazelor de date, datele private, realizarea atacului DoS, obţinerea
privilegiilor maxime etc.

Să presupunem că avem o bază de date ce conţine relaţia (tabelul) users de următoarea


structura:

O interogare ce extrage datele din baza de date poate avea formă:


SELECT *
FROM users
WHERE name = '$name'
În acest caz valorile din câmpul “name” sunt comparate cu valoarea variabilei “$name”. Dacă
valoarea aceastei variabile a fost obţinută din parametrii URL sau cookie şi nu se prelucrează la
simboluri speciale atunci interogarea la baza de date este vulnerabilă. Voi aduce un exemplu simplu
cum răufăcătorul poate modifica interogarea.
Dacă variabilă $name primeşte valoarea şu, atunci cerea la baza de date va fi următoarea:
SELECT *
FROM users
WHERE name = 'su'

11
Interogarea este corectă. Însa dacă valoarea variabilei va primi valoarea aaa' interogarea va
deveni incorecta din punct de vedere sintactic, deoarece este prezent un simbol ' în plus:
SELECT *
FROM users
WHERE name = 'aaa''
Simbolul ' permite de a modifica cererea la baza de date, şi nu este unicul simbol ce permite
acest lucru (după cum veţi vedea mai jos). Să presupunem că cerea de mai sus o foloseşte o
aplicaţie web pentru a afişa datele private a utilizatorului curent logat. Utilizând simbolul '
răufăcătorul cu uşurinţă poate vedea datele private a tuturor utilizatorilor înregistraţi, transmiţând
una din următoarele valori pentru parametrul $name (presupunem că în sistem sunt înregistraţi
utilizatorii admin, şu şi lma0):
random_data' OR name='admin
random_data' OR name='su
random_data' OR name='lma0
Cererile SQL la baza de date vor fi:
SELECT * FROM users WHERE name='random_data' OR name='admin'
SELECT * FROM users WHERE name='random_data' OR name='su'
SELECT * FROM users WHERE name='random_data' OR name='lma0'
Înjectarea permite de a extrage datele private a unui utilizator. Răufăcătorul la dorinţă poate să
obţină datele despre toţi utilizatorii transmiţând parametrului $name valoarea:
random_data' OR '1'='1
Cererea cu codul injectat:
SELECT * FROM users WHERE name='random_data' OR '1'='1'
va întoarce toate tuplurile (înregistrările) din tabelul users.

4.2. Proceduri de testare a aplicaţiilor web la SQL-injection

Procedurile de testare a aplicaţiilor web la SQL-injection se reduc la formarea unei liste de


parametri cu care lucrează aplicaţia (atât parametrii GET cât şi POST), incluzând şi parametrii
cookie. Apoi aceşti parametri se testează individual la prelucrarea simbolurilor speciale sau a
cuvintelor cheie (de genul WHERE) care ar ajuta la exploatarea vulnerabilităţii.

12
4.3 Identificarea parametrilor vulnerabili

Să presupunem că aplicatia-web este configurata astfel, încât în cazul apariţiei unei erori
SQL, în browser va apare textul erorii şi posibil o porţiune din interogare. Dacă răufăcătorului i se
afişează chiar şi o porţiune de interogare, injectarea codului SQL malicios nu va fi o problemă.
Presupunem că aplicatiei-web i s-a transmis un parametru GET id=aaa':
http://127.0.0.1/inj.asp?id=aaa'
Pentru a determina dacă parametrul este vulnerabil este nevoie de a căuta în pagina
returnata de server a frazelor de genul “ODBC”, “have an error”, “SQL syntax”, “SQL Server”,
“MySQL”, “Oracle” etc. Exista cazuri când erorile returnate de server se plasează în parametrii
ascunşi (hidden input, headers) sau comentarii. În acest caz răufăcătorului îi este foarte uşor de a
injecta un cod SQL malicios:
http://127.0.0.1/inj.asp?id=aaa';+drop+table+users;--
Ar trebui de menţionat că nu toate SGBD permit concatenarea interogărilor la baza de date.
Este foarte răspândită situaţia, când din textul erorii returnate de server poate fi aflat tipul bazei de
date pe care o foloseşte aplicatia-web:
Warning: mysql_fetch_object(): supplied argument îs not a valid MySQL result
resource în ...
Textul erorii de mai sus este foarte util răufăcătorului la formarea codului SQL malicios
specific unui tip de SGBD.

13
4.4 Metode de atac

Să presupunem că răufăcătorul a găsit un parametru vulnerabil. Pentru a exploata


vulnerablitatea răufăcătorul ar trebui aproximativ să cunoască tipul cererii SQL în care va fi injectat
codul malicios. Cel mai des în aplicatiile-web sunt utilizate 4 tipuri de cereri SQL:
1. SELECT
2. INSERT
3. UPDATE
4. DELETE
Care dintre acestea este folosit într-un caz concret, poate fi determinat analizând logica şi
semantica scriptului vulnerabil.
Dacă scriptul afişează date ce corespund unui identificator anumit, atunci cu o mare
probabilitate cererea este de tipul SELECT.
Dacă scriptul adauga unele date în baza de date, spre exemplu adăugarea unui comentariu, sau un
post în forum – cererea este de tipul INSERT.
Dacă scriptul modifica informaţia, spre exemplu schimbarea parolei, redactarea postului în
forum – cererea este de tipul UPDATE.
Dacă are loc ştergerea informaţiei, spre exemplu anularea accountului, posibil ca cererea este sau de
tipul DELETE sau de tipul UPDATE.
Cel mai des sunt întâlnite vulnerabilităţi în cereri SELECT.

4.5 Metode de apărare

Pentru a evita o posibilă exploatare a vulnerabilităţii SQL Injection în aplicaţia web, este necesarde
a prelucra toate datele ce parvin de la utilizatori la următoarele simboluri:

· Ghilimelele atât simple cât şi duble (‘, “, `). Cu ajutorul acestora în majoritatea cazurilor se
efectuiaza injectarea codului SQL.

· Simbolurile de comentarii specifice SGBD anumit (/*,--). Cu ajutorul acestora poate fi omisa o
parte din interogare.

· Simbolurile ce împart instrucţiunile SQL (;). Prezenta acestui simbol permite de a formă mai multe
cereri la baza de date.

· Deasemenea datele ar trebui să fie verificate la prezenţa şi la alte simboluri (_,%,*).

14
· În cazul când în cererea SQL se utilizează date numerice primite de la utilizatori, înainte de a le
plasa în cererea SQL acestea ar trebui aduse la tipul numeric:
$id=(int)$id;

· În cazul când în cererea SQL se utilizează date de tip şir de caractere primite de la utilizatori,
înainte de a le plasa în cererea SQL acestea ar trebui prelucrate la simboluri speciale. Cea mai bună
practica – este formarea expresiilor regulate.

15
CONCLUZIE
Pentru a evita pierderea și/sau furtul a datelor personale este necesar de a avea anumite
protocoale de securitate precum și practici de a verifica integritatea acestuia prin metode manuale
sau automate, referitor la SQL-Injection trebuie de menţionat ca vulnerabilităţile de tipul SQL
Injection sunt foarte răspândite.

În lucrare am demonstrat că prezenţa vulnerabilităţii date în aplicatia-web îi permite


răufăcătorului să afle/extragă informaţii despre server, să obţină un interpretator de comenzi sau
chiar să realizeze un atac DoS. Pentru a evita prezenţa acestei vulnerabilităţi este nevoie de a
prelucra la simboluri speciale absolut toate datele ce parvin de la utilizatori.

În această categorie intră parametrii GET, POST şi chiar cookie. Pentru a evita prezenţa
acestei vulnerabilităţi este nevoie de a prelucra la simboluri speciale absolut toate datele ce parvin
de la utilizatori. În această categorie intră parametrii GET, POST şi chiar cookie.
Aspectele reflectate în această lucrare desigur nu acoperă în întregime tema atacurilor SQL
injection. Fiecare SGBD are nuanţele sale pe care răufăcătorul potenţial poate să le folosească spre
binele sau. Tema lucrării date este derivata din tema proiectului de masterat întitulata „Metode şi
soluţii de detectare a web-atacurilor”.

16
BIBLIOGRAFIE

1) Database Language SQL { Part 2: Foundation (SQL/Foundation). ISO Internaţional Standard,


ISO/IEC 9075:1999, 1999.

2) Marshall D. Abrams, Sushil Jajodia, and Harold J. Podell, eds. Information Security: An Integrated
Collection of Essays. IEEE Computer Society Press, Los Alamitos, CĂ, 1995.

3) S. Castano, M.G. Fugini, G. Martella, and P. Samarati. Database Security. Addison Wesley
Publishing Company, 1995.

4) E.F. Codd. A Relaţional Model for Large Shared Data Banks. Communications of the ACM,
13(6):377{387, June 1970.

5) Dorothy E. Denning. Cryptography and Data Security. Addison-Wesley, Reading, MA

17

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