gerzson Mon Feb 4 06:52:41 2002 EDT Modified files: /phpdoc/hu/chapters security.xml Log: Database security section translated
Index: phpdoc/hu/chapters/security.xml diff -u phpdoc/hu/chapters/security.xml:1.20 phpdoc/hu/chapters/security.xml:1.21 --- phpdoc/hu/chapters/security.xml:1.20 Tue Jan 29 13:03:06 2002 +++ phpdoc/hu/chapters/security.xml Mon Feb 4 06:52:41 2002 @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="iso-8859-2"?> -<!-- EN-Revision: 1.39 Maintainer: gerzson Status: ready --> +<!-- EN-Revision: 1.43 Maintainer: gerzson Status: ready --> <!-- CREDITS: goba --> <chapter id="security"> @@ -495,6 +495,447 @@ olyan rendszert készíteni, ahol mindent megtiltasz azon kívül, amit kifejezetten megengedsz. </para> + </sect1> + + <sect1 id="security.database"> + <title>Adatbázis biztonság</title> + + <simpara> + Mostanában, bármely dinamikus tartalmat szolgáltató web alapú alkalmazás + sarokkövének számítanak az adatbázisok. Mivel nagyon kényes, titkos adatok + tárolására szolgálnak ezek az adatbázisok, erősen megfontolandó, hogyan + védjük meg az ezeket. + </simpara> + <simpara> + Információk tárolásához vagy visszakereséséhez csatlakozni kell az + adatbázishoz, egy érvényes lekérdezést kell küldeni, az eredményt ki kell + olvasni, és le kell zárni a kapcsolatot. + Manapság ebben a párbeszédben a Structured Query Language (SQL) a + leggyakrabban használt lekérdezőnyelv. Figyeld meg, miként lehet <link + linkend="security.database.sql-injection">SQL lekérdezéseket megbabrálni</link>! + </simpara> + <simpara> + Mint látható, a PHP egymagában magától nem képes megvédeni az adatbázist. + A következő bekezdések élja, hogy betekintést adjanak az alapokba, hogyan kell + adatbázisokat elérni és módosítani egy PHP programon belül. + </simpara> + <simpara> + Tartsd észben a következő egyszerű szabályt: védekezz tagoltan. Minél több + helyen minél többet teszel a biztonság növeléséért, annál kisebb a valószínűsége, + hogy a támadók sikerrel járjanak, és kiteregessék titkos adataidat, vagy + visszaéljenek velük. A jó adatbázis- és alkalmazástervezés mindig a legnagyobb + félelmek figyelembevételéről ismerszik meg. + </simpara> + + <sect2 id="security.database.design"> + <title>Adatbázis-tervezés</title> + <simpara> + Az első lépés mindig az adatbázis létrehozása, hacsak nem egy kívülállóét + kell használni. Az adatbázis létrehozásakor az a tulajdonosáé lesz, aki + lefuttatta az utasításokat. Általában csak a tulajdonos - esetleg az ún. + superuser - jogosult bármiféle az adatbázis elemeit érintő műveletre. + Annak érdekében, hogy más felhasználók is hozzáférjenek, jogokat kell + nekik biztosítani. + </simpara> + <simpara> + Az alkalmazásoknak soha nem szabad a tulajdonosaként vagy superuserként + csatlakozni az adatbázishoz, mert ezek bármilyen utasítást és lekérdezést + tetszés szerint futtathatnak, pl. a szerkezeti módosítást (táblák + megszüntetése) vagy teljes törlésük. + </simpara> + <simpara> + Létre lehet hozni különböző szigorúan korlátozott jogosultásgú adatbázis- + felhasználókat, melyek mindegyike az adatbázis manipulációnak egy-egy + különböző nézőpontjáért felelősek. Mindig csak a legszükségesebb jogokat + szabad engedélyezni, és el kell kerülni, hogy ugyanazt a felhasználót + használjuk szerepeiben egymástól különböző esetekben. Ez azt jelenti, hogy + ha a behatoló meg is szerzi valamelyik ilyen minősítést (hitelesítési + információt = felhasználó + jelszó), akkor is csak akkora változást tud + okozni, mint az alkalmazás maga. + </simpara> + <simpara> + Nem kell minden feladatfüggő szabályozást a webalkalmazásban (PHP + szkriptben) kódolni, ehelyett inkább használd az adatbázis lehetőségeit: + view-k (nézetek), trigger-ek, rule-ok (szabályok). Ha a rendszer + fejlődik, és más alkalmazásokat is csatlakoztatni kell az adatbázishoz, + akkor mindegyiknél újra kellene programozni ezeket a szabályokat. + Mindezen felül a triggerek arra is jók, hogy átlátszó módon és + automatikusan kezeljenek egyes mezőket az adatbázisban, amelyek gyakran + bepillantást adnak abba, hogy mi is történik/történt egy tranzakció közben, + vagy nagyon hasznosnak bizonyulnak hibakeresés közben. + </simpara> + </sect2> + + <sect2 id="security.database.connection"> + <title>Kapcsolódás az adatbázishoz</title> + <simpara> + Elképzelhető, hogy SSL-n keresztül szeretnél kapcsolódni az adatbázishoz, + hogy a kiszolgáló és ügyfél közti teljes kommunikáció titkosításával + növeld a védelmet. Használhatsz ssh-t is erre a célra. Akármelyik is + áll, nagyon nehéz lesz a forgalom lehallgatásából információkat kinyerni. + </simpara> + <!--simpara> + If your database server native SSL support, consider to use <link + linkend="ref.openssl">OpenSSL functions</link> in communication between + PHP and database via SSL. + </simpara--> + </sect2> + + <sect2 id="security.database.storage"> + <title>Titkosított tárolás</title> + <simpara> + SSL/SSH az ügyfél és kiszolgáló közt mozgó adatokat védi, és nem védi + az adatbázisban tárolt megmaradó adatokat. Az SSL - kapcsolati protokoll. + </simpara> + <simpara> + Mihelyst a támadó közvetlen hozzáférést szerzett az adatbázishoz - + megkerülve a webszervert -, a tárolt adatok védtelenné váltak, és + visszaélhet velük, ha csak maga az adatbázis nem védi valahogy azokat. + Az adatok titkosítása kellőképp csillapítja ezt a veszélyt, de jelenleg + nagyon kevés adatbázis kezelő támogatja a titkosítást. + </simpara> + <simpara> + Ez a legkönnyebben saját titkosító csomag írásával oldható meg, amelyet + utána a PHP szkriptből el lehet érni. Ebben az esetben a PHP a segítséget + nyújthat néhány kiterjesztésével, mint például az <link + linkend="ref.mcrypt">Mcrypt</link> vagy az <link + linkend="ref.mhash">Mhash</link>, amelyek nagyon sokféle titkosító + algoritmust fednek le. Az szkript először titkosítja a tárolni kívánt + adatot, majd a későbbiekben visszakereséskor visszafejti azokat. Nézd + meg a hivatkozott fejezeteket további példákért, hogyan kell a titkosítást + végrehajtani. + </simpara> + <simpara> + Olyan teljsen rejtett adatok esetén, amelyeknek nyílt ábrázolásukra nincs + szükség, mert nem lesznek kiíratva, a hashelést alkalmazása is + meggondolandó. A hashelés jól ismert példája az, hogy a jelszavak helyett, + azoknak csak MD5 hash értékét tárolják az adatbzisban. Lásd még: + <function>crypt</function> és <function>md5</function>! + </simpara> + <example> + <title>Hashelt jelszó mező használata</title> + <programlisting role="php"> +<![CDATA[ +// jelszó hash értékének tárolása +$query = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');", + addslashes($username), md5($password)); +$result = pg_exec($connection, $query); + +// lekérdezés, vajon a felhasználó a helyes jelszót adta-e meg +$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';", + addslashes($username), md5($password)); +$result = pg_exec($connection, $query); + +if (pg_numrows($result) > 0) { + echo "Üdvözöllek, $username!"; +} +else { + echo "$username hitelesítése nem sikerült."; +} +]]> + </programlisting> + </example> + </sect2> + + <sect2 id="security.database.sql-injection"> + <title>SQL "beoltás"</title> + <simpara> + Sok web fejlesztő nincs tudatában annak, hogy hogyan lehet megbabrálni + az SQL utasításokat, és feltételezik, hogy az SQL uatsítás az egy megbízható + parancs. Ez azt jelenti, hogy az SQL lekérdezésekkel ki lehet játszani a + hozzáférés-szabályozásokat, ennélfogva a szabályos engedélyezési folyamatokat + megkerülni, és néha az SQL lekérdezésekkel a gazdagépen operációs rendszer + szintű hozzáférést lehet létrehozni. + </simpara> + <simpara> + A "közvetlen SQL utasítás befecskendezés" olyan módszer, amellyel a támadó + a régi SQL utasításokat módosítja vagy újakat ad hozzájuk annak érdekébenm, + hogy titkos információkhoz jusson hozzá, vagy felülírja azokat, vagy veszélyes + rendszer szintű parancsokat futtasson az adatbázis gazdagépén. Ez olyan + alkalmazások esetén tehető meg, amelyek a felhasználótól származó adatokat + és statikus paraméterekből állítanak össze SQL lekérdezéseket. Sajnos, a + következő példák mind megtörtént eseteken alapulnak. + </simpara> + <para> + Az, hogy az adatbázishoz superuserként (olyan személyként, aki superusert + képes létrehozni) csatlakozott az alkalmazás, és a bevitt adatok ellenőrzésének + hiánya odavezethet, hogy a támadó superuser hozzáférést hozhat létre az + adatbázishoz. + <example> + <title> + A keresési eredmények lapokra tördelése ... és superuserek létrehozása + (PostgreSQL és MySQL) + </title> + <programlisting role="php"> +<![CDATA[ + +$offset = argv[0]; // Vigyázz, nincs beviteli ellenőrzés! +$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"; +// PostgreSQL +$result = pg_exec($conn, $query); +// MySQL +$result = mysql_query($query); +]]> + </programlisting> + </example> + A szokványos felhasználó az 'előző', 'következő' linkekre kattint, ahol + az <varname>$offset</varname> az URL-be van kódolva. A szkript azt várja, + hogy <varname>$offset</varname> decimális szám. Mégis, valaki megpróbálhatja + a következő utasítás <function>urlencode</function> alakját fűzi hozzá + az URL-hez (PostgreSQL): + <informalexample> + <programlisting> +<![CDATA[ +0; +insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd) + select 'crack', usesysid, 't','t','crack' + from pg_shadow where usename='postgres'; +-- +]]> + </programlisting> + </informalexample> + vagy MySQL esetén + <informalexample> + <programlisting> +<![CDATA[ +0; +UPDATE user SET Password=PASSWORD('crack') WHERE user='root'; +FLUSH PRIVILEGES; +]]> + </programlisting> + </informalexample> + Ha ez megtörténne, akkor a szkript megajándékozná a támadót egy superuser + hozzáféréssel. A <literal>0;</literal> arra való, hogy érvényes offset-et + biztosítson az eredeti lekérdezésnek. + </para> + <note> + <para> + Általános módszer, hogy a <literal>--</literal> jellel kényszerítik ki, + hogy az SQL elemző figyelmen kívül hagyja a lekérdezésként átadott + string fennmaradó részét, mivel ez a megjegyzés szabványos jelölése + SQL-ben. + </para> + </note> + <para> + Egy lehetséges módja a jelszavak megszerzésének, hogy kijátszák a kereső + oldalak találati listájának lekérdezéseit. A támadónak mindössze annyit + kell tennie, hogy végig próbálja melyik elküldött SQL lekérdezésben használt + változó nincs megfelelően lekezelve. Ezeket általában egy megelőző űrlapon + lehet beállítani, hogy testre szabjuk a <literal>SELECT</literal> utasítás + <literal>WHERE, ORDER BY, LIMIT</literal> és <literal>OFFSET</literal> + klauzuláit. Ha a használt adatbáziskezelő támogatja a <literal>UNION</literal> + szerkezetet, akkor a támadó esetleg hozzáfűzhet egy teljesen új lekérdezést + a már meglevőhöz, hogy kilistázza a valamilyen táblában tárolt jelszavakat. + Titkosított tárolás erősen ajánlott! + <example> + <title> + Árucikkek listázása ... és néhány jelszóé (valamilyen adatbázis kezelő) + </title> + <programlisting role="php"> +<![CDATA[ +$query = "SELECT id, name, inserted, size FROM products + WHERE size = '$size' + ORDER BY $order LIMIT $limit, $offset;"; +$result = odbc_exec($conn, $query); +]]> + </programlisting> + </example> + A lekérdezés statikus része egy másik <literal>SELECT</literal> utasítással + kombinálható, ami az összes jelszót kilistázza: + <informalexample> + <programlisting> +<![CDATA[ +' +union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from +usertable; +-- +]]> + </programlisting> + </informalexample> + Ha ez a lekérdezést (a <literal>'</literal> és <literal>--</literal> megfelelő + használatával) valamelyik <varname>$query</varname>-ben használt változóhoz + sikerülne hozzárendelni, akkor a szörny felébredne. + </para> + <para> + SQL UPDATEs ugyancsak ki vannak téve az adatbázisok elleni támadásoknak. + Ezeket az utasításokat is fenyegetik az előzőekben megismert megrövidítő és + hozzáfűző technikák. Ám emellett a támadó meghamisíthatja a +<literal>SET</literal> + klauzulát is. Ebben az esetben némi séma információval rendelkeznie kell a + támadónak, hogy sikerrel járjon. Ezeket az információkat az űrlapváltozók + neveiből szerezhetik meg, vagy egyszerűen próbálgatással. Az általánosan + használt elnevezések a felhasználói névre és jelszóra nem nagyon + különböznek egymástól. + <example> + <title> + Jelszó átírásától ... új jogok megszerzéséig (valamilyen adatbázis kezelő) + </title> + <programlisting role="php"> +<![CDATA[ +$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';"; +]]> + </programlisting> + </example> + A rosszindulatú felhasználó a <literal>' or uid like'%admin%'; --</literal> + értéket adja át a <varname>$uid</varname> változónak, és ezzel + megváltoztatja az adminisztrátor jelszavát, vagy egyszerűen a + <varname>$pwd</varname>-nek a <literal>"hehehe', admin='yes', trusted=100 +"</literal> + (lezáró szóközzel) értéket adva még több jogot szerez magának. Ezt az + SQL parancsot ezek így ferdítik el: + <informalexample> + <programlisting role="php"> +<![CDATA[ +// $uid == ' or uid like'%admin%'; -- +$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --"; + +// $pwd == "hehehe', admin='yes', trusted=100 " +$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;" +]]> + </programlisting> + </informalexample> + </para> + <para> + Egy ijesztő példa arról, hogyan lehet az adatbázis gazdagépén operációs + rendszerszintű parancsokat futtatni. + <example> + <title>Az adatbázis-gazdagép operációs rendszere elleni támadás (MSSQL +Server)</title> + <programlisting role="php"> +<![CDATA[ +$query = "SELECT * FROM products WHERE id LIKE '%$prod%'"; +$result = mssql_query($query); +]]> + </programlisting> + </example> + Ha a támadó az <literal>a%' exec master..xp_cmdshell 'net user test testpass +/ADD' --</literal> + értéket küldi el a <varname>$prod</varname> változónak, akkor a + <varname>$query</varname> a következőképp alakul: + <informalexample> + <programlisting role="php"> +<![CDATA[ +$query = "SELECT * FROM products WHERE id LIKE '%a%' exec master..xp_cmdshell 'net +user test testpass /ADD'--"; +$result = mssql_query($query); +]]> + </programlisting> + </informalexample> + MSSQL Server futtatja a kötegbe fogott SQL utasításokat, köztük azt + is, amelyik új felhasználót vesz fel az adatbázis kiszolgálógépen. Ha + az alkalmazás <literal>sa</literal> jogosultsággal fut és az MSSQLSERVER + service megfelelő jogokkal fut, akkor a támadónak most már hozzáférése van + ehhez a géphez. + </para> + <note> + <para> + A példák némelyike bizonyos adatbáziskezelőhöz kötődik. Ez nem azt jelenti, + hogy hasonló támadás elképzelhetetlen más termékkek ellen. Az általad + használt adatbázis-kezelő ugyanilyen sérülékeny lehet, akár más módon. + </para> + </note> + + <sect3 id="security.database.avoiding"> + <title>Elhárítási módszerek</title> + <simpara> + Ellenevetésként felmerülhet, hogy példák többségében a támadónak + rendelkeznie kell valamennyi előzetes információval az adatbázis + felépítéséről. Ez igaz, de soha nem lehet tudni, hogy mikor, hol, hogyan + szerezhetik meg ezeket, és ha ez megtörtént, az adatbázisod védtelenné + válik. A behatolók könnyen hozzájuthatnank a program egy darabjához nyílt + forráskódú, vagy olyan nyilvánosan elérhető adatbázis-kezelő programcsomag + használatakor, amelyik egy fórum vagy tartalomszolgáltató rendszer része. + Ez különösen veszélyes lehet, ha ezek kevéssé átgondoltak és gyengén + megtervezettek. + </simpara> + <simpara> + Ezek a támadások alapvetően azoknak a programoknak a kihasználásán alapulnak, + amelyek a védelmet/biztonságot figyelmen kívül hagyva születtek. Soha nem + lehet megbízni semmilyen bejövő adaton, főleg ha az a kliens oldalról + érkezik, még akkor sem, ha az egy általunk megadott süti (cookie), vagy + rejtett mező (hidden input) értéke esetleg egy legördülő lista eleme. + Még egy olyan ártatlan lekérdezés, mint ami az első példában látható, + katasztrófát okozhat. + </simpara> + + <itemizedlist> + <listitem> + <simpara> + Soha ne csatlakozz az adatbázishoz tulajdonosaként vagy superuser-ként. + Mindig kevés jogosultsággal rendelkező, testreszabott felhasználókat + használj! + </simpara> + </listitem> + <listitem> + <simpara> + Ellenőrizd a bejövő adat típusát, hogy az a vártnak megfelelő-e! + PHP bevitel ellenőrző függvények széles körével rendelkezik kezdve + a legegyszerűbbektől - pl.: <link + linkend="ref.variables">Változókkal kapcsolatos függvények</link> közül + <function>is_numeric</function> vagy a <link + linkend="ref.ctype">Character Type Functions</link> közül a + <function>ctype_digit</function> - a <link + linkend="ref.pcre">Perl kompatibilis reguláris kifejezések</link> + támogatásáig. + support. + </simpara> + </listitem> + <listitem> + <para> + Ha az alkalmazás számot vár, akkor megfontolandó az + <function>is_numeric</function> függvénnyel ellenőrizni a típusát, vagy + csendben megváltoztatni a típusát a <function>settype</function> + függvénnyel, vagy szám szerinti ábrázolását használni az + <function>sprintf</function> függvénnyel. + <example> + <title> + A lapozáshoz használt lekérdezés összeállításának biztonságosabb módja + </title> + <programlisting role="php"> +<![CDATA[ +settype($order, 'integer'); +$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"; + +// Figyelj a %d -re a formázó sztringben, a %s használat értelmetlen lenne +$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", +$offset); +]]> + </programlisting> + </example> + </para> + </listitem> + <listitem> + <simpara> + Idézőjelek közé kell tenni minden nem szám jellegű, felhasználótól + származó adatot, erre használható az <function>addslashes</function> + vagy az <function>addcslashes</function>. Lásd még + <link linkend="security.database.storage">az első példát</link>! + Ahogy a példák is mutatják, a statikus részbe égetett idézőjelek + nem elegendőek, és könnyen kijátszhatók. + </simpara> + </listitem> + <listitem> + <simpara> + Semmilyen adatbázisra jellemző információt - különösen + szerkezetit - nem szabad kiírni, ha törik, ha szakad. + Lásd még: <link + linkend="security.errors">Hibajelzés</link> és <link + linkend="ref.errorfunc">Hibakezelő és naplózó függvények</link>! + </simpara> + </listitem> + <listitem> + <simpara> + Tárolt eljársokat és előre definiált kurzorokat is használhatsz, hogy + az adatbáziselérést absztraháld annak érdekében, hogy a felhasználók + ne közvetlenül a táblákhoz vagy nézetekhez férjenek hozzá. Ennek a + megoldás azonban egyéb hatásai vannak. + </simpara> + </listitem> + </itemizedlist> + + <simpara> + Ezeken kívül, hasznot hajthat a lekérdezések naplózása akár a szkripteken + belül, akár ha az adatbázis kezelő maga teszi ezt. Nyilvánvaló, hogy ez nem + tudja megakadályozni egyetlen ártalmas próbálkozást sem, de segítséget + nyújthat annak felderítésében, hogy melyik alkalmazás lett kijátszva. A + naplózás önmagában nem, csak a benne megjelenő információkon keresztül + válik hasznossá: általában a több részlet, hasznosabb. + </simpara> + </sect3> + </sect2> </sect1> <sect1 id="security.errors">