ugrás a tartalomhoz

Session biztonsági ellenőrzés

peterkerdez · 2017. Szep. 11. (H), 19.32
Sziasztok! Adott egy weboldal, amin eddig úgy ment a felhasználók session adatainak ellenőrzése, hogy a felhasználó nevét, aktivitását stb. ellenőriztem, azonban minden különálló oldalon ugyanolyan módon, az oldal elejére beillesztve a kódot. Mivel szeretném áttekinthetőbbé tenni az oldalak kódját, ezért arra gondoltam, hogy kiraknám egy külső fájlba a webrooton kívül, ahonnan a phpval require_once beolvasnám és funkcióként minden oldal elejére helyezném. Két dolog jutott eszembe:

Mi van, ha nem létezik a bekért include? Ekkor automatikusan leáll a php fordítása fatális hibával már a kód elején, tovább nem lehet használni.

Mi van, ha nem létezik a szükséges function? Ebben az esetben szintén fatális hibával le fog állni a php fordító, tovább az oldal nem használható.

A require_once esetében kézzel (saját kódon belül, nem felhasználói input) felvitt útvonallal adom meg a biztonsági ellenőrzést végző függvény fájlját.

Okoz-e biztonsági problémát ez, mire kell figyelnem ezeken kívül?

illetve

Kevésbé lesz-e biztonságos a weboldal, ha ilyen módon történik a felhasználók jogosultság vizsgálata ahelyett, hogy minden oldal elején ugyanaz a kód szerepelne? A function sessiont vizsgál, amit eddig minden oldal eleje tett meg.

Köszönöm a segítséget!
 
1

Forditva

janoszen · 2017. Szep. 11. (H), 21.01
Sztem forditva próbálod megoldani mint ahogy meg kellene. Include-okkal való hadakozás helyett inkább csináld úgy, hogy az alkalmazásodnak van egy belépési pontja (index.php), és az betölt mindent amire szükséged van. Ha OOP-val programozol, akkor az autoloaddal ezt akár automatikusan is meg tudod csinálni.
4

Nem pontosan értem, hogy mire

peterkerdez · 2017. Szep. 13. (Sze), 23.04
Nem pontosan értem, hogy mire gondolsz. Esetleg tudnál egy példa kódot mutatni hozzá?
8

Igen

janoszen · 2017. Szep. 14. (Cs), 10.23
2

janoszen +1; Az OOP az jó, az

smokey · 2017. Szep. 12. (K), 00.17
janoszen +1; Az OOP az jó, az autoloader meg pláne.

Én keresnék a helyedben valami egyszerű keretrendszert (pl. Laravel vagy hasonló), amivel csinálnék egy hello worldöt, illetve kipróbálnék egy auth komponenst. Ez kb rá fog vezetni egy jó megoldásra.

Mivel szeretném áttekinthetőbbé tenni az oldalak kódját, ezért arra gondoltam, hogy kiraknám egy külső fájlba a webrooton kívül, ahonnan a phpval require_once beolvasnám és funkcióként minden oldal elejére helyezném.


Ettől még lesz kód duplikáció sajnos. Leszármaztatással jobban jársz. Egyszer egy keleti sráccal dolgoztam, és megkértem, hogy figyeljen a kód duplikációkra, mert rengeteg helyen előfordul ugyanaz az X sor kód. Erre ő azt válaszolta, hogy:
"Ok, akkor ezentúl minden módosítás után mindig gondoskodom róla, hogy a módosított kódot mindenhova átmásoljam!" > szerintem ne így állj neki :)

Mi van, ha nem létezik a bekért include? Ekkor automatikusan leáll a php fordítása fatális hibával már a kód elején, tovább nem lehet használni.

Mi van, ha nem létezik a szükséges function? Ebben az esetben szintén fatális hibával le fog állni a php fordító, tovább az oldal nem használható.

A require_once esetében kézzel (saját kódon belül, nem felhasználói input) felvitt útvonallal adom meg a biztonsági ellenőrzést végző függvény fájlját.


Tudsz példát mutatni? Nem világos pontosan, hogy hogyan küzdesz.
3

A nagy probléma az, hogy évek

peterkerdez · 2017. Szep. 13. (Sze), 23.03
A nagy probléma az, hogy évek óta íródik már a kód és az egész egy procedurális rémálom, ami az elején könnyűnek tűnt, az most irtó nehéz lett, kezdem elveszíteni a kontrollt. Néhány jellemzően ugyanúgy használt kódsort szeretnék functionba rendezni, hogy ha már voltam olyan hülye, hogy nem OOP formában készült az egész, akkor legalább function könnyítésem legyen, amit még mindig egyszerűbb kivitelezni, mint az összes gyakori kódot kikeresni és classokat irkálni rájuk. (Egyszer ennek is el fog jönni az ideje, de már így is brutális sok munkám van benne.)

"Tudsz példát mutatni? Nem világos pontosan, hogy hogyan küzdesz."

Oldal eleje például:

require_once('../../kod/function_lista.php');


Ha valamilyen okból kifolyólag megszűnne létezni a function_lista.php, akkor a php elvileg fatális hibával leáll és nem fordul tovább, tehát hiába nem létezik a fájl, az oldal többi részének adatai nem lesznek elérhetőek.

Esetleg, ha a function nem létezne:

if(function_exists("pelda"))
{
   biztosagi_session_ellenorzes();
} else
{
   session_start();
   session_unset();
   session_destroy();
   header("location: login.php");
   exit;
}


Mivel szeretek minden eshetőségre felkészülni, ezért az esetleg a nem létező function esetén is biztosítottam magamat ezzel a kóddal. Természetesen maga az ellenőrzés indítja a sessiont és jogosulatlan használat esetén hasonlóan jár el.

Eddig minden oldal elején volt megtalálható a körülbelül 300 sornyi biztonsági ellenőrzés, kezdve a session adatok vizsgálatával és hasonlókkal. Attól, hogy én ezt egy külső function_lista.php fájlba szerveztem, más biztonsági kockázata remélem nincs azokon kívül, amiket leírtam. A session változó globálisan elérhető, functionon belül is tudom vizsgálni szerencsére.
5

Van aminek a létezését

smokey · 2017. Szep. 14. (Cs), 01.19
Van aminek a létezését feltételezned kell, egyébként nem fog működni az alkalmazásod. A helyedben én egy biztosan létező funkció létezését feltételezném, ami biztos, hogy az alkalmazás első kódsoraiban létrejön.

Egyszerű lesz a példa:

<?php

//index.php

//...

require_once('auth.php');

<?php

//auth.php

function auth($file, $function) {
    $filename = $file . '.php';
    if (!file_exists($filename)) {
        return false; //vagy redirect, vagy bármi
    }
    require_once($filename);
    if (!function_exists($function)) {
        return false; //vagy redirect, vagy bármi
    }
    if ($function()) {
        return false; //vagy redirect, vagy bármi
    };
    return true;
}

<?php 

//oldal.php

auth('../../kod/function_lista', 'pelda'); 
//megróbálja behúzni a fájlt és lefuttatni a funkciót
//ha return true a funkciód visszatérése, akkor mehet tovább az alkalmazás
//ha return false a funkciód visszatérési értéke, akkor megállítod / redirecteled / egy helyen csinálsz bármit, stb
//az auth hívható bárhonnan az alkalmazáson belül
A példádnak egyébként nem szabadna mindennapos jelenségnek lennie, nem szabad, hogy egy ilyen jellegű funkció egyik pillanatról a másikra megszűnjön - fejlesztői hiba. Az, amit szeretnél megoldani, az nem szabad, hogy így feltételesen működjön. Ha eltűnik a fájl és nem fut le az alkalmazás, akkor ne az alkalmazást hegeszd addig, amíg jól le nem tudod kezelni a feltételesen létező fájlokban található szintén feltételesen létező funkció használatát, hanem találd ki az okát annak, hogy miért tűnt el a fájl - nem gond ha eltűnik, de az ne runtime derüljön ki...

A te problémádra ne alkalmazás szinten keresd a megoldást, hanem tervezés és megvalósítás szinten.
6

Szervezés és tervezés

Hidvégi Gábor · 2017. Szep. 14. (Cs), 08.20
A programod attól nem lesz jobb, ha átírod OOP-re. A mai napig rengeteg procedurális kód hajtja a világot, kezdve az összes népszerű linuxos rutinkönyvtártól a kernelekig bezárólag, azaz a linuxos világ stabil alapja.

Ha évek alatt procedurális rémálmot sikerült összehoznod, akkor feltételezhető, hogy a váltás után OOP rémálom lesz belőle.

Először inkább programozni kéne megtanulnod, meg hogy hogyan kell a kódot szervezni. Érdemes átgondolni, mi történik az egyes oldalakon: felhasználó azonosítása -> bejövő adatok ellenőrzése -> akció lefuttatása -> kimenő adatok (pl. HTML) legenerálása és kiküldése.

Az összes weboldal és webes alkalmazás ráhúzható erre a sablonra, ami, ha belegondolsz, egyszerű cselekmények láncolata, azaz procedurális. Ezekből készíthetsz nagy függvényeket, amik kisebbeket hívnak.
7

A programod attól nem lesz

smokey · 2017. Szep. 14. (Cs), 09.43
A programod attól nem lesz jobb, ha átírod OOP-re. A mai napig rengeteg procedurális kód hajtja a világot, kezdve az összes népszerű linuxos rutinkönyvtártól a kernelekig bezárólag, azaz a linuxos világ stabil alapja.


Kivételesen egyetértek.... Végülis nem is csak az idézettel, hanem az egésszel :).

Azt viszont hozzátenném, hogy az OOP ismerete és megfelelő használata megkönnyíti az egységbezárást és a hibakeresést, hibajavítást. Hangsúlyozom a MEGFELELŐ szót. Erre ha rájön egy jól megtervezett keretrendszer ismerete, akkor az eléd rakhat egy rakat tervezési mintát is és best practice-t, amiket hosszú távon érdemes alkalmazni.
10

Elmaradt döntések

Pepita · 2017. Szep. 15. (P), 13.06
Ahogy a többiek is írták, egy szoftver (jelen esetben webalkalmazás) fejlesztése úgy kezdődik, hogy tervezés, tervezés és tervezés...
Ezalatt az idő alatt rengeteg döntést meg kell hoznod előre, mint pl:

- Mik az alapvető működéshez elengedhetetlen funkciók
- Ezeket milyen kisebb részekre érdemes bontani
- Ezek közül mik globálisak (minden, vagy csaknem minden funkció / oldal működéséhez szükségesek)
- Melyek azok, amik szintén sűrűn használatosak, de pl nagy erőforrásigényűek, emiatt csak akkor kéne elérhetőnek lenniük, ha adott feltétel teljesül
- Mindezt milyen szervezési struktúrában kívánod megvalósítani.

ha már voltam olyan hülye, hogy nem OOP formában készült az egész

..., akkor Hídvégi Gábor "AntiOOP specialista" készséggel fog neked segíteni.

Viccet félretéve: az objektumorientált programozás nem valamiféle csodaszer, ami képes pótolni pl a rendszerszemlélet hiányát, vagy a kódszervezésben való járatlanságot.
Gábornak ebben teljesen igazat adok: ha procedurálisan is egy nagy katyvasz, akkor "OOP-ben" is az lesz, csak a fájlok így fognak kezdődni: class Valami { ....

NEM ez az OOP. Nem pusztán "classok gyűjteménye".

Mostani helyzetedben a legfontosabb döntés, hogy - attól függően, mennyire tudsz azonosulni a szemlélettel - a nagyon nagy refact után procedurális lesz-e az eredmény, vagy valamennyire OOP. Látatlanban is azt mondom, hogy nagyjából ugyanannyi munkára számíts.

A fő lényeg az, hogy lehetőség szerint az összes kód-duplikációt szüntesd meg.
require_once('../../kod/function_lista.php');
Habár ez nem programkód, hanem nyelvi elem, mégis kód-duplikáció, és abból is a lehető legrosszabb.
Hibái:
- Relatív path. Ha az a fájl, "aki" behúzza, vagy a function_lista.php máshova kerül, rögtön meghal.
- Nem 128 db különálló kis scriptbe kell behúzni mindig ugyanazt, hanem az egész fölé kell tenni egy root réteget, ami betölti, esetleg futtatja is az állandóan kellő részeket.

Amit Janoszen írt, az mindenképp hasznos megoldás. Kicsit kibontva, átértelmezve:
- Legfontosabb, hogy minden egyes HTTP kérés az index.php - t indítsa el (Apache / Nginx conf)
- index.php - d kb max 50 sornyi, elvégzi a routing-ot, betölti, amiket mindig kell.
- Ezután betölti, ami az adott oldal specifikus kódja (routing alapján persze).
- Ha procedurális / strukturált megoldáson gondolkodsz, akkor is felveszi konstansokba a fontosabb könyvtárakat (abszolút path), amikkel a kis scriptek könnyen intézhetik majd a helyi betöltéseket (fájlkezelésekhez is jól jön).
- Ha procedurális, akkor egy megfelelő gyűjtőhelyre mehetnek a funkciók, innentől már a te szervezőkészségeden múlik, hogy ne duplikálj kódot.

Mindkét esetben fontos, hogy okosan nevezd el az egyes feature-öket, fájl- és class- (függvény-) név beszédesen mondja el, hogy mit is fog csinálni.
A másik nagyon fontos dolog, hogy egy metódus egyetlen dolgot csináljon.
Ez kb azt jelenti, hogy egy max 5 szavas tőmondatban le tudod írni a teljes működését. (És ez nem az például, hogy "Mindent intéz, ami autentikáció" :) )
Smokey 5-ös válaszában írt auth függvénye nagyon jó példa a helytelen beágyazásra. Ahelyett, hogy autentikálná a látogatót, próbál loaderként működni, de közben ha sikertelen a tényleges autentikáció betöltése, akkor azt az esetet is próbálja valahogy lekezelni, pedig köze sincs az eredeti (auth) feladathoz.
Nos, pont így lehet borzasztó kesze-kusza spagettikódot gyártani, amiben mindig fog maradni jónéhány kezeletlen kivétel, emellett rendkívül átláthatatlan lesz, megőszülsz, mire végigmész egy láncon..

(Smokey bocsi, nem szekálni akartalak, de szerintem iskolapélda, hogyan rejtsem el magam elől a működést.)
9

Köszönöm az útmutatást és a

peterkerdez · 2017. Szep. 14. (Cs), 19.09
Köszönöm az útmutatást és a példa kódot is, nagyon tetszik. Az igazság az, hogy az egyetemen sem tanítanak ilyen szinten programozást nálunk, így gyakorlatilag az internetre és saját ötleteimre kell támaszkodnom. Ha az ismétlődéseket sikerülne kiszűrnöm, esetleg egy-két ugyanúgy működő programrészt osztályokba rendezni, akkor sokkal átláthatóbb lenne a program, mint most. Ez a funkció eltűnik, meg egy fájl eltűnik dolog azért kerül nálam ilyen furcsán vizsgálatra, mert a php híresen durva sebezhetőségei miatt régóta rémálmok gyötörnek és már mindenben rosszat látok, már egy sima echoban is csak a hibalehetőségekre figyelek, hogy azzal hogyan lehet visszaélni.
11

Mutass több kódot

Pepita · 2017. Szep. 15. (P), 13.16
az egyetemen sem tanítanak ilyen szinten programozást nálunk
Milyen egyetem? Egyébként fontos a gyakorlat, tapasztalt programozó csak úgy lehetsz, ha csinálod. :)
esetleg egy-két ugyanúgy működő programrészt osztályokba rendezni
Jó ötlet, érdemes figyelni a közös tulajdonságokra - működésre, kulcsszavak: öröklődés, láthatóság, absztrakció.
a php híresen durva sebezhetőségei miatt
Ezt az állítást támaszd alá pár linkkel kérlek, mert szerintem itt nem a php nyelvvel van a hiba... Ha egy nyelvben minden egyes utasítást ; - el kell zárni, és ezt Te egyetlen helyen kihagyod, akkor bizony az a fránya fordító - amilyen "sebezhető" - a következő utasítással egyben fogja megpróbálni a végrehajtást - jellemzően szép kis syntax error az eredmény.
(Ugyanez igaz a nemlétező fájl require / include - ra, az nem a php hibája, vagy szerinted ilyen esetben "neki" kéne legyártani / más helyen keresni a rosszul megadott útvanalat? :) )