ugrás a tartalomhoz

A MySQL biztonsági kérdései

Baranyai László · 2004. Május. 15. (Szo), 22.00
A MySQL biztonsági kérdései
Az SQL adatbázisok használatba vétele során a legelső lépés az adattáblák szerkezetének (mezők és relációk) megtervezése úgy, hogy az illeszkedjen a várható lekérdezésekhez. Sajnos az adatbázisok tényleges létrehozása során sokan kihagyják a jogosultságok megfelelő beállítását és ellenőrzését. A kisebbik rossz, ha kevesebb jogot kaptunk, mert azt azonnal észrevesszük, amint dolgozni szeretnénk. Komolyabb problémát okozhat, ha több jogot kaptunk, mert egy elgépelt utasítás belerondíthat mások adatbázisába is ahelyett, hogy hibaüzenetet kapnánk.

Adatbázis létrehozása

A táblák, adamezők létrehozását és kezelését szolgáló parancsokat a test nevű adatbázison gyakorolhatjuk. Ez telepítés után egy üres adatbázis, amihez minden felhasználónak minden joga megvan. Amennyiben megkaptuk a jogot, hogy belépjünk a szerverre (ssh-val), használhatjuk a mysql parancsot. Mielőtt bármit is teszünk, győződjünk meg róla, hogy senki más adatait nem töröljük, módosítjuk!

$ mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 23 to server version: 3.23.49-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test;
Database changed

mysql> show tables;
Empty set (0.00 sec)
A test nevű adatbázis üres, tehát bátran elkezdhetjük a munkát. Ha a sor végén nincsen ';' jel, az ENTER leütése után új sorban folytathatjuk a parancs begépelését és kicsit áttekinthetőbb lesz amit írunk. Nagy segítség, ha közben olvasni tudjuk a MySQL leírását is a www.mysql.com oldalon, vagy onnan letölti a kézikönyvet PDF formátumban.

mysql> create table valami (
    -> kod int,
    -> neve varchar(200),
    -> megjegyzes text );
Query OK, 0 rows affected (0.00 sec)

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| valami         |
+----------------+
1 row in set (0.00 sec)

mysql> desc valami;
+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| kod        | int(11)      | YES  |     | NULL    |       |
| neve       | varchar(200) | YES  |     | NULL    |       |
| megjegyzes | text         | YES  |     | NULL    |       |
+------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
Ha befejeztük a gyakorlást a test adatbázisban, a rendrakás kötelező! A létrehozott tábla törlését a drop parancs segítségével tehetjük meg.

mysql> drop table valami;
Query OK, 0 rows affected (0.00 sec)

mysql> show tables;
Empty set (0.00 sec)
Elegánsabb megoldás, ha előre eltervezünk mindent és a megfelelő parancsokat egy szöveges állományba gyűjtjük. Sok esetben ez elkerülhetetlen, mert a szolgáltató nem ad nekünk jogot adatbázisok és táblák létrehozásához. Ilyenkor az elkészített parancsállományt kell eljuttatni a rendszergazdához. Ha mi hozzuk létre az adatbázist, akkor az első sorba create database sajat_db kerül (értelemszerűen sajat_db tetszőleges név lehet). Az utasítások kerüljenek most valami.sql-be:
  1. use test;  
  2.   
  3. create table valami (  
  4.  kod int,  
  5.  neve varchar(200),  
  6.  megjegyzes text  
  7. );  
Használata pedig nagyon egyszerű, DOS (Windows) és Linux alatt is működik a következő példa:

$ mysql <valami.sql

Adminisztráció grafikus felületen

Természetesen léteznek grafikus kezelői felületek is, amelyek megkönnyítik a munkát. Kettőt tudok ajánlani:
  • phpMyAdmin
    Az adatbázis kezeléséhez PHP osztályokat használ, telepítése után a webszerveren keresztül kommunikálhatunk vele (tetszőleges böngésző programban behívható).
  • MySQL Control Center
    A Trolltech Qt nevű elemtárára épülő alkalmazás elérhető Linux és Windows operációs rendszerekhez (letölthető a forráskódja is).

Ellenőrzés PHP programmal

Érdemes egy kisebb PHP programot írni, amely feltérképezi, hogy mely adatbázisok milyen tábláihoz férhetünk hozzá egy adott felhasználói névvel és jelszóval. Az alábbi függvény kapcsolatot teremt a MySQL szerverrel, majd a mysql_list_dbs segítségével lekérdezi az összes adatbázis nevét, majd a mysql_list_tables segítségével megpróbálja kilistázni a benne levő táblákat. A hozzáférhető táblák összes mező elemét névvel, típussal és mérettel kiírja.
  1. <?php  
  2.   
  3. function MySQL_Test($server_name,$user_name,$password)  
  4. {  
  5.   
  6.  if (!($DBLink=mysql_connect($server_name,$user_name,$password))) {  
  7.   echo "Error: Cannot connect to database!";  
  8.   exit;  
  9.  }  
  10.  echo "<code>\n";  
  11.  echo "Accepted connection. ID = " . $DBLink . "\n";  
  12.  if ($DBRes = mysql_list_dbs($DBLink)) {  
  13.   while ($db_row = mysql_fetch_row($DBRes)) {  
  14.    echo "&amp;lt;Database '<b>" . $db_row[0] . "</b>'&amp;gt;\n";  
  15.    if ($TBRes = mysql_list_tables($db_row[0],$DBLink)) {  
  16.     while ($tb_row = mysql_fetch_row($TBRes)) {  
  17.      echo "  &amp;lt;Table '<i>$tb_row[0]</i>'&amp;gt;\n";  
  18.      if ($FDRes = mysql_list_fields($db_row[0],$tb_row[0],$DBLink)) {  
  19.       for ($i=0;$i<mysql_num_fields($FDRes);$i++) {  
  20.        echo "   ";  
  21.        echo mysql_field_name($FDRes$i) . " ";  
  22.        echo mysql_field_type($FDRes$i) . "(";  
  23.        echo mysql_field_len($FDRes$i) . ")";  
  24.        echo " " . mysql_field_flags($FDRes$i) . "\n";  
  25.       }  
  26.      }  
  27.      echo "  &amp;lt;/Table&amp;gt;\n";  
  28.     }  
  29.    }  
  30.    echo "&amp;lt;/Database&amp;gt;\n";  
  31.   }  
  32.  }  
  33.  echo "</code>\n";  
  34.  mysql_close($DBLink);  
  35.   
  36. }  
  37.   
  38. ?>  
A függvény alkalmazására másik PHP programot javaslok, amely akár egy form adatait is használhatja. Most a legegyszerűbb esetet mutatnám be:
  1. <?php  
  2.   
  3.  include "mysql_test.php";  
  4.  MySQL_Test("localhost","root","");  
  5.   
  6. ?>  
Ha a fenti listázás eredményes, sürgősen nézzünk utána a jogok beállításának a MySQL kézikönyv vonatkozó részeiben. A "root" névvel és jelszó nélkül üzemeltetett adatbázisokhoz bárki hozzáférhet korlátozások nélkül (nem kell sok fantázia hozzá, hogy egy cracker ezt a párosítást kipróbálja).

Megfelelő jogosultság esetén a böngésző ablakában látható lista csak test adatbázis részleteit ismerteti.
  1. Accepted connection. ID = Resource id #1  
  2.   
  3. <Database 'mysql'>  
  4. </Database>  
  5. <Database 'test'>  
  6.  <Table 'valami'>  
  7.   kod int(11)  
  8.   neve string(200)  
  9.   megjegyzes blob(65535) blob  
  10.  </Table>  
  11. </Database>  
Rosszul beállított jogok esetén (pl. "root" felhasználó jelszó nélkül) mindenhez korlátlan hozzáférésünk van, így láthatóvá válik a mysql adatbázis is. Ebben tárolja a MySQL szerver az adatbázisok és felhasználóik jogait, korlátozásait.
  1. <Database 'mysql'>  
  2.  <Table 'columns_priv'>  
  3.   Host string(60) not_null primary_key binary  
  4.   Db string(64) not_null primary_key binary  
  5.   User string(16) not_null primary_key binary  
  6.   Table_name string(64) not_null primary_key binary  
  7.   Column_name string(64) not_null primary_key binary  
  8.   Timestamp timestamp(14) not_null unsigned zerofill timestamp  
  9.   Column_priv string(31) not_null set  
  10.  </Table>  
  11.  <Table 'db'>  
  12.   Host string(60) not_null primary_key binary  
  13.   Db string(64) not_null primary_key binary  
  14.   User string(16) not_null primary_key multiple_key binary  
  15.   Select_priv string(1) not_null enum  
  16.   Insert_priv string(1) not_null enum  
  17.   Update_priv string(1) not_null enum  
  18.   Delete_priv string(1) not_null enum  
  19.   Create_priv string(1) not_null enum  
  20.   Drop_priv string(1) not_null enum  
  21.   Grant_priv string(1) not_null enum  
  22.   References_priv string(1) not_null enum  
  23.   Index_priv string(1) not_null enum  
  24.   Alter_priv string(1) not_null enum  
  25.  </Table>  
  26.  <Table 'func'>  
  27.   name string(64) not_null primary_key binary  
  28.   ret int(1) not_null  
  29.   dl string(128) not_null  
  30.   type string(9) not_null enum  
  31.  </Table>  
  32.  <Table 'host'>  
  33.   Host string(60) not_null primary_key binary  
  34.   Db string(64) not_null primary_key binary  
  35.   Select_priv string(1) not_null enum  
  36.   Insert_priv string(1) not_null enum  
  37.   Update_priv string(1) not_null enum  
  38.   Delete_priv string(1) not_null enum  
  39.   Create_priv string(1) not_null enum  
  40.   Drop_priv string(1) not_null enum  
  41.   Grant_priv string(1) not_null enum  
  42.   References_priv string(1) not_null enum  
  43.   Index_priv string(1) not_null enum  
  44.   Alter_priv string(1) not_null enum  
  45.  </Table>  
  46.  <Table 'tables_priv'>  
  47.   Host string(60) not_null primary_key binary  
  48.   Db string(64) not_null primary_key binary  
  49.   User string(16) not_null primary_key binary  
  50.   Table_name string(60) not_null primary_key binary  
  51.   Grantor string(77) not_null multiple_key  
  52.   Timestamp timestamp(14) not_null unsigned zerofill timestamp  
  53.   Table_priv string(68) not_null set  
  54.   Column_priv string(31) not_null set  
  55.  </Table>  
  56.  <Table 'user'>  
  57.   Host string(60) not_null primary_key binary  
  58.   User string(16) not_null primary_key binary  
  59.   Password string(16) not_null binary  
  60.   Select_priv string(1) not_null enum  
  61.   Insert_priv string(1) not_null enum  
  62.   Update_priv string(1) not_null enum  
  63.   Delete_priv string(1) not_null enum  
  64.   Create_priv string(1) not_null enum  
  65.   Drop_priv string(1) not_null enum  
  66.   Reload_priv string(1) not_null enum  
  67.   Shutdown_priv string(1) not_null enum  
  68.   Process_priv string(1) not_null enum  
  69.   File_priv string(1) not_null enum  
  70.   Grant_priv string(1) not_null enum  
  71.   References_priv string(1) not_null enum  
  72.   Index_priv string(1) not_null enum  
  73.   Alter_priv string(1) not_null enum  
  74.  </Table>  
  75. </Database>  

Összefoglalás

A programozók a hagyományos szemlélet alapján (és az adatbázis szerver felhasználóinak ellenőrzése érdekében) általában előnyben részesítik a kész SQL szkriptek almalkazását az adatbázisok létrehozása során, hiszen ez a munka komolyabb átgondolását kényszeríti ki. A grafikus kezelői felületek sok kényelmi funkcióval rendelkeznek, nagyobb méretű fejlesztéseknél nagyságrendekkel gyorsíthatják a munkát.

Bárhogy hozzuk is létre az adatbázisainkat és azok tábláit, utólag érdemes ellenőrizni a beállításokat. Ilyenkor nem elegendő végigfutni a kezelő felület menürendszerén, mert sok esetben nem is vesszük észre a saját hibánkat, vagy a kapott listákból az nem is látható. Mindig más módszert válasszunk az ellenőrzésre és az adminisztrációra! Ez a redundancia nagyobb biztonságot nyújt.

A helytelen beállítások veszélye nem csupán abban rejlik, hogy bárki elolvashatja a rögzített adatokat, de korlátlanul módosíthat és törölhet is az illetéktelen felhasználó (pl.: "root" jelszó nélkül). Ha szervert üzemeltet, a "root" nevű felhasználó jelszavát mindenképp állítsa be (ez a leggyakoribb hiba, amivel én találkoztam)!
 
Baranyai László arcképe
Baranyai László
A Budapesti Corvinus Egyetem docense, munkája egyben a hobbija is (szeret oktatni és programozni). Több tudományos honlap tervezője, készítője. Szeret nassolni és saját bevallása szerint jó palacsintát süt.
1

Jogosultságok

Anonymous · 2004. Jún. 3. (Cs), 19.06
A select,insert,update,delete jogok általában (mindig) kellenek, többre azonban eddig (3 év alatt) nem volt szükség. Nem tudom, nekem úgy tűnik, ha egy adatbázis ezekkel a jogokkal bír, akkor az a MySQL oldaláról elégséges is a munkához, és másokra nézve sem jelent veszélyt. (A PHP-oldali hanyagság, a formokban kapott értékek ellenőrzés nélküli feldolgozása más kérdés, azt hiszem.)
Én a grafikus front-endeket szeretem (Win alatt fejlesztek), és a kedvencem a MySQlFront2.5. Múltkor komoly bajba is kerültem emiatt, mert fejből már egy vacak táblát sem tudok azonnal létrehozni, szégyenszemre a manualt kellett használnom. :) Más kérdés, hogy bizonyos lekérdezéseket meg épp a programból tanultam meg kezdetben, mert okosan kiírja az épp végrehajtott, kattintgatással előidézett kérés SQL-nyelvű megfelelőjét.
2

manual

kmm · 2004. Jún. 4. (P), 07.45
manual hasznalata nem szegyen!

--
üdv: kmm...
3

Jogok

Anonymous · 2004. Jún. 7. (H), 15.08
Azért szerintem egy ALTER nem rossz dolog, hátha kell valamit módosítani a tábla szerkezeten.. A többi mondjuk tényleg nem feltétlenül kell.
4

alter mint adatbazishasznalat

kmm · 2004. Jún. 8. (K), 17.00
nehezen tudok elkepzelni olyan adatbazis alkalmazast, ami jol van megirva aes alterelgetni kell a tablakat... adatbazis igazabol szerintem egy fix szerkezetet takar, ami igazodik az adatok milyensegehez is, azaz ha az adatok flexibilisek, akkor az adatbazis struktura is az

--
üdv: kmm...
6

ALTER

tgergely · 2011. Júl. 13. (Sze), 09.46
Találkoztam olyan alkalmazással, ahol az egyedi felhasználói mezők kezelése úgy volt megoldva, hogy amit összekattingattál az admin felületen azt a rendszer ALTER TABLE ADD COLUMN-al hozzáadogatta a táblához. Szerintem ez nem feltétlen rossz, lenézendő megoldás.
7

7 éves topic

solkprog · 2011. Júl. 13. (Sze), 13.02
(7 éves hozászolásra válaszoltál.)

De szerintem nincs igazad, egy alkalmazás ne (nagyon) adogasson oszlopokat a táblához. Ráadásul az oszlopok száma sok DBMS-ben (erősen) korlátozott.
5

re: Jogok

Anonymous · 2004. Jún. 14. (H), 15.48
Az alter tényleg nem rossz, de arra a fejlesztőnek van szüksége, nem a kész programnak. A kettő nem ugyanaz.

/sunz