Hacker módszerek 2018. július 23., hétfő - 22:30


Milyen... csalogató bejegyzéscím ez. A script kiddiek kedvenc elfoglaltsága, hogy ilyesmi kulcsszavakra keresve egyszerű megoldást találjanak midenféle hackerkedéssel kapcsolatos anyaghoz, hogy aztán letöltve 1-2 programot 2 kattintással feltörjék a NASA-t. Vagy hát a céljuk ilyesmi, de ez persze nem így megy. Kis koromban engem is érdekelt az ilyesmi, ezért én is egy rakat infót keresgéltem.

Valójában a hacker (aki én nem vagyok, félreértés ne essék) - bár ma már egy szétromantizált fogalom, de a valódi jelentése - egy olyan embert jelent, akinek az informatikai, azon belül sok témakörre kiterjedő szaktudása (részben security, részben op.rendszerek, programnyelvek, mindenféle ismeret) lévén ismernie kell (és ismeri is) a lehető legtöbb hibalehetőséget, minden helyzetben. Weblapoknál, programoknál, hálózatoknál, alkalmazásoknál. Ahol csak kell.

No, ezért nem vagyok, leszek én hacker. Ehhez tényleg nagy "kockafejnek" kell lenni. Szuper-szakbarbárnak. Én meg lusta dög vagyok, hogy akár csak gondoljak is ilyesmire.

Az én elenyésző tudásom, ami van, leginkább weblapos dolgokban merül ki, csak a hackerkedés felszínét súrolja. Ez is amiatt, hogy a legfőbb, legtipikusabb biztonsági réseket ismernem kell, hogy az általam megírt weblapok már védve legyenek ilyesmikkel szemben.

Tulajdonképp ma már csak azért érdekel, és azért tanulok mindenféle módszerről, amivel tönkre lehet tenni egy weboldalt, vagy elhelyezni rajta fájlokat, szöveget, kódot, vírust, hogy ne történhessen meg az én kreálmányaimnál. Maradjunk a weblapoknál..

A legtipikusabb esetek egy weblapon minden esetben a backenden történnek, azaz az én esetemben PHP-n. Mik az ilyen esetek (összefoglalóan: exploitok)?
  • XSS - amikor van egy űrlap, kitöltheti a felhasználó, az bekerül az adatbázisba, és a beírt adat megjelenik egy másik lapján az oldalnak. Pl. a profilodon beírhatsz egy mottót, amit mások láthatnak. És ez az egész folyamat, amit írtam, nincs levizsgálva, semmilyen módon védve. Ebből mi következik? Konkrétan bármilyen kóddal bővítheti a weblapot, és az le fog futni a profilt megnyitó személynél. Ezzel adatokat is lehet lopni, és más dolgokat is lehet művelni.
  • SQL injection - az előző esethez hasonló a dolog. Hozzáteszem, itt még van esély arra is, hogy a HTML részek szűrve vannak, pl. egy elég gyenge strip_tags PHP parancs által. Ez a módszer még az adatbázisba bekerülés előtt/közben csap le. Úgy, hogy a mottó mezőbe nem a mottónkat írjuk be, hanem aposztrófokat, amivel lezárjuk az adatbázis művelet parancsát, és utána kiegészíthetjük egyéb PHP kódokkal, amit a szerver lefuttat; simán úgy veszi, mintha az általunk beírt kód eredetileg is a fájl része lett volna. Ez veszélyes. Így lehet 2 perc alatt tönkretenni egy oldalt, elmenteni az adatbázisát, szóval adatokat lopni, stb. Ez persze könnyen kivédhető, ha minden esetben a legrosszabbra számítunk. Az összes mezőt ártalmatlanítani kell, ahol user képes adatot felvinni az oldalra. Ha számról beszélünk, legalább egy implicit típuskonverziót, szóval $szam = (int) $_POST['szam'], ha szöveg, akkor pedig legalább egy htmlspecialcharst írjunk a post adat köré, legalább egy ENT_QUOTES második paraméterrel!
  • multibyte character exploit - vagy valami hasonló. Erről, illetve ilyesmiről egyszer olvastam valamerre. A lényeg az, hogy a weben sok helyen kell megadni a karakterkódolást. Ettől függ, hogy van-e pl. Ő és Ű betű az oldalon, vagy csak ilyen háztető formájú izé van az O és U felett. Azok nem igazi ŐŰ betűk. Ezt most nem magyarázom feleslegesen. Viszont olvastam ilyet régebben, hogy bár szűrve voltak az aposztrófok az adatbázisba érkezve, DE bizonyos karakterkódolású aposztrófokat nem escapeelt a védelem szerveroldalon. Escapeel = ártalmatlanít, mondjuk így röviden. Ami nem lett volna baj, de mivel más karakterkódolású volt a kliensoldal, meg a PHP, meg még az adatbázis is, így a beírás megtörtént (valahogy így volt), de bekerülni már a rendes aposztróf került be. Kiolvasásnál meg szintén az került ki. És amikor ez az adatbázis adat ki lett írva egy oldalon, és megnyitotta az oldalt egy ember, akkor viszont lefutott a kód, kitörve a PHP-s kiírásból. Ezért sem szabad tökölni hatvan féle kódolással, mindenhol UTF-8.
  • MIME type exploit - sok oldalon lehet feltölteni képet, vagy esetleg fájlokat/mást, de a leggyakoribb a kép. Na most, tisztázzunk valamit. Ha készíteni kell egy (fájl, vagy) képfeltöltő cuccot, PHP-ban, minimum korlátozzuk elfogadólistásra a feltölthető dolgokat. Ugyanis, ha valaki fogja magát, feltölt egy PHP fájlt, akkor felkerült a szerverre egy PHP fájl. Ez tudjuk mit jelent. Bővítette a weblapot, és bármit csinálhat a fájlból; törölheti az egész weblapot, letöltheti az adatbázist, stb. Elég megnyitnia a feltöltött fájlját. Ilyet nem játszunk. Ha már képet várunk feltöltési elemnek, azt nem árt több módon is megvizsgálni, hogy valóban kép-e. Ne bízzunk a content type-ban ($_FILES['file']['type']). Ez manipulálható, elég egy régi/egyedi böngésző. És máris annyi az ellenőrzésnek, hisz ez is kliensoldalról küldött információ. A fájlnév vizsgálat sem árt. De vigyázni kell. Lehet csinálni olyat, hogy a feltöltött fáljnál az utolsó pont utáni részt megnézzük, akkor viszont legyünk alaposak. Ne pontos egyezést nézzünk, hanem egy globális cserével szedjük ki a php végződést, és hasonló dolgokat a kiterjesztésből. Ugyanis pontos egyezésnél ha csak a PHP-t vizsgáljuk, akkor simán feltölthet egy megszivtad.php3 fájlt. Ami ugyanúgy lefut, ha megnyitja. És nem ez az egyetlen lehetőség. Legtutibb, ha írsz egy jó regexet, ami mindent töröl ettől a ponttól, ami p-től kezdődik, van benne h, és még a végén is van legalább egy p betű.
És ez a pár eset csak olyan, amikkel én összefutottam, vagy amiket megtanultam figyelni. Mert ha ezekre figyel az ember, akkor a weblapjának nem lesz baja, hacsak nem kezdi érdekelni egy igazán komoly hacker(csapatot) valami okból kifolyólag. Attól ritkán kell félnünk, azt hiszem.

Ennek a posztnak egyébként, így belegondolva semmi értelme. Talán annyi, hogy ezeket leírva egy nálam kezdőbb tanulhat valami minimálisat, vagy kap ötletet, hogy mire keressen rá. Az mégiscsak több, mint a semmi.

Megjegyzés: ha valamilyen számítást kliensoldalon elvégeztél, JS-sel, akkor mielőtt kiírod adatbázisba, ugyanazon lépésekkel számoltasd át a PHP-val is, és ha egyeznek, akkor (is a) PHP általi értéket írd a DB-be. Biztos ami biztos. Főleg, ha webshopot kezdesz fejleszteni valakinek. Elég gáz, ha egy input mező átírásával féláron, vagy tizedáron lehet rendelni egy árucikket.
Megjegyzés2: ha rejtvényt csinálsz, vagy kuponos rendszert, vagy bármilyen ellenőrizendő adatbevitelt: ajax-szal csináld, ellenőrzésekkel és megszakításokkal. Ne a kliensoldalba rakd a "megoldást", vagy a kinyerhető adatokat. Még titkosítva se. Ha te vissza tudod fejteni (pl. a kuponkódot, annak adatait), akkor más is. Főleg, ha kliensoldali a visszafejtő funkció..

Filmajánló /sorozat/: Mr. Robot, A célszemély, Snowden

Eloszlás (distribution) #matek 2018. július 14., szombat - 1:31


Elkezdtem csinálni egy "fél órás" projektet. Egy Cleverbothoz hasonló csetbotot. Alapesetben ezt közel sem fél óra lenne megcsinálni, főleg, ha csicsázzuk a dolgot mindenféle extra dologgal, elágazásokkal, vizsgálatokkal, fene tudja. Alapvetően az egyszerűsége annyiban van egy YAML struktúrát használó bothoz képest (vagy valami ilyen, már nem emlékszek, bátyám foglalkozott ezzel többet), hogy nem kell előre megírni ötmillió beszélgetést, hogy értelmesnek látszódjon, hanem magától tanul.

Ezt majd részletezem másik bejegyzésben, viszont szükségem volt egy normál eloszláshoz hasonló véletlenszerű generálásra. A chatbothoz. De nem találtam, vagy nem értelmeset, vagy magas gépigényűt, stb. Miért?

Mármint, minek ez nekem, meg mi ez? Egyszerű. Igazából egy súlyozott véletlenszerűen választó szkript kellett nekem. Példa: a "hogy vagy?" kérdésre tegyük fel, hogy 100-ból 70 ember azt írja, hogy "jól.", 20 azt, hogy "megvagyok.", és 10 azt, hogy "rosszul". Ez százalékban is pont így jön ki.

Az én tanuló chatbotom az ugyanolyan kérdésre ugyanolyan adott válaszokat nem jegyzi fel magának többször, helyette egy számlálót növel mindössze. Ez a számláló mutatja, hogy mire mennyiszer mondták azt, hogy ... blablabla. Pl. az előző példa - hogy a chatbottal való beszélgetés közben hányszor mondták a "hogy vagy?" kérdésre, hogy "jól.".

Ez a chatbot visszafelé is így működik. Tehát ha Te írod neki, hogy "hogy vagy?", erre ő válaszol az ezutáni emberi válaszok közül valamelyikkel, véletlenszerűen. De minél többen mondtak egy adott választ, annál valószínűbb, hogy ő is azt fogja rá mondani. Na, erre kellett nekem ez a normál eloszlás. Ha valamit 500-an mondtak, és valamit csak 1x, akkor szinte soha ne azt a "csak egyszer" választ adja, hanem azt, amit 500 ember.

De erre épkézláb megoldást nem találtam (emberi nyelven / JÓ programozói megoldással; nem matematikusi megfogalmazást), csak 2-3 feltett, de nagyjából megválaszolatlan Stack Overflow kérdést. De az egyik béna tömbös megválaszolása után eszembe jutott egy viszontlag memória- és CPU kímélő megoldás a problémára. Most teszteltem is, jónak tűnik.

Előbb leírom a konkrét PHP kódot (phptester.net-en nyomtam le, de bárhogy lehet tesztelgetni):

$results = array('Jól', 'Megvagyok', 'Rosszul'); $odds = array(70, 20, 10); $max = 0; for($i = 0; $i < count($results); $i++) $max += $odds[$i]; $rand = mt_rand(0, $max); $choosenIndex = 0; /* echo "Esély: $rand<br />"; */ for($i = 0; $i < count($results); $i++) { $rand = max(0, $rand - $odds[$i]); if($rand == 0) break; else $choosenIndex++; } echo ' - Hogy vagy? <br /> - ' . $results[$choosenIndex];

Van egy tömbnyi választandó elemem, meg egy tömbnyi ugyanolyan sorrendbe feltöltött esélyem. Persze, megoldható kétdimenziós tömbbel is, vagy ilyesmi, de én most az egyszerűség kedvéért így csináltam.

Nem is bonyolult így nézve, ugye? Az esélyek bármennyik lehetnek. Végül van egy maximum számom, a randomizálás tetőpontja. Ez az összes elem esélye összeadva. 70+20+10 (lehetne 5000+20+10 is, működik úgy is, ofc).

Majd egy változót tényleg randomizálunk 0 és max közt. Kell még egy index változó, ami a számok alapján kiválasztottnak ítélt tömbindexet mutatja majd.

Innentől logikus. Csinálunk egy akkora for ciklust, mint a tömb elemeinek száma. A randomunkból minden "körben" kivonjuk az épp ciklusváltozó szerinti sorrendben következő esélyek tömb számát. Nem muszáj 0-ra redukálni, de úgy szebb. Ezután ellenőrizzük, hogy a randomunk kevesebbegyenlő-e, mint 0. Ha igen, akkor elértünk oda, hogy a jelenlegi index esik abba a szakaszba, amivel párosul a választott tömbelem a másik tömbben. Ha nem, akkor túlléptünk egy elemnek a lehetőségén. Ennyi.

Ezt nem is igazán tudom elmagyarázni, ezért lerajzolom, így befejezésképp: