BBS-ek és anonymous FTP helyek, bitTorrent

Mind az üzemeltetok, mind a felhasználók számára sok biztonsági problémát vetnek fel a szabad (nyilvános) elérésu archívumok, mint pl. BBS-ek és anonymous FTP helyek. A gondok nagy része csak az üzemeltetoket érinti közvetlenül, ezekkel itt nem foglalkozunk.

A problémák egyik fo forrása, hogy e helyek vírusok és más programozott kórokozók terjesztoi lehetnek. A nevesebb FTP helyek archívumai, cégek support FTP helyei nagyon jól ellenorzöttek, gondosan megválogatják, hogy honnan kerülhetnek ide programok, valamint az üzemeltetok minden tolük telhetot megtesznek az ellenorzésre. Tökéletes védelem azonban nincs, a vírusok ellen a szigorú ellenorzés még csak hatásos, de trójai falovak idonként felbukkannak.

A felhasználó részérol a védekezés a következo lehet:

- nem tölt le programot;

- a programokat izolált környezetben teszteli (karantén);

- gondosan tesztel vírus azonosító szoftverekkel;

- szoftvert csak hivatalos disztribúciós helyérol vagy ennek hivatalos (vagy más szempontok miatt biztonságosnak tekintett) tükör (mirror) helyeirol tölt le.

Látható, hogy csak az utolsó pont az, amit igazán követhetünk. Megjegyezzük, hogy a vírusellenorzést nevesebb archívumok, disztribúciós helyek esetén nem tartjuk elengedhetetlennek. A vírusfertozések elenyészo töredéke vezetheto vissza anonymous FTP-rol letöltött file-okra.

A nyilvános elérésu helyekhez hasonló a helyzet a különféle helyi archívumokkal. Sajnos általános útmutatót nem lehet adni arra, hogy mely archívumok tekinthetok biztonságosnak, s melyek nem.

Egyes archívumokba bárki tölthet fel file-okat. Ha ezek az állományok azonnal nyilvánosan elérhetok, akkor ezek biztonsága kétes (a beérkezo file-on legfeljebb azonnali automatikus vírusellenorzés futtatható).

15. Egyfelhasználós rendszerek védelme

A legtöbb felhasználó PC-s DOS-t vagy MS Windows-t használ. Ezek egyfelhasználós rendszerek, eredendoen legfeljebb helyi hálózati használatra tervezettek, ahol a hálózat legfontosabb feladata az állománymegosztás és a háttértárolás. Ma ilyen operációs rendszerek (és hasonlóan a Macintosh, Amiga stb. gépek alapértelmezésu operációs rendszerei) alatt teljes Internet kiszolgálót, FTP szervert stb. futtathatunk. Számos ilyen program konfigurálható úgy is (sot alapértelmezésben ilyen vagy csak így futtatható), hogy pl. az FTP szerver futása alatt bárki bejelentkezhet a PC-nkre, s akár az egész állományunkat törölheti. A veszély ugyan kicsi, mert csekély a valószínusége, hogy valaki a PC-nkre vadásszon a szerver futási ideje alatt, de fennáll. Emiatt ajánlatos az adott szoftver dokumentációját védelmi szempontból is áttekinteni, s ha ilyen téren a dokumentáció vagy a védelem hiányos, akkor más szoftver után érdemes nézni.

A mai egyfelhasználós rendszerek már igazából nem egyfelhasználósak, peer to peer kapcsolatot, állomány-kiszolgálást stb. biztosíthatunk rajtuk. Ezekre végül is a többfelhasználós rendszerekre mondottak irányadók, annak figyelembevételével, hogy lehetoségeink (kontroll, auditálás) korlátozottabbak. Az eroforrás megosztás terén is szukek a kontroll lehetoségei (pl. az MS Windows kooperatív multitasking-ja miatt).

16. Speciális veszélyforrások, kérdések

Néhány nagyon gyakori, elterjedt biztonsági problémát külön is szeretnénk kiemelni, melyek bár némileg alkalmazás-specifikusak, de általánosan elterjedtek, s jellegüknél fogva állandó biztonsági problémák okozói.

Az X Window

Az X Window a legelterjedtebb osztott grafikus (ikonos/ablakos) felhasználói felület (rendkívüli elonye, hogy platform-független). Alkalmazása esetén a felhasználó gépén fut egy ún. terminál (X) szerver, melyet alkalmazás-szerveren futó alkalmazások, mint kliensek szolgálnak ki. A X felület rendkívül rugalmas, könnyen kezelheto, hatékony és sokoldalú, de használata veszélyeket rejt, különösen, ha nincs megfeleloen konfigurálva. Itt részletesen nem kívánjuk az X Window biztonsági kérdéseit tárgyalni, csak a biztonsági hiányosságra mutatunk példát:

Az ún. 'xhost +' parancs engedélyezi, hogy bármely hostról kliens csatlakozzon az X szerverünkhöz. Kevésbé veszélyes, ha tréfából kollégáink X ablakokat jelenítenek meg terminálunkon, de nyilvánvaló, hogy ennél több is megteheto. Egyébként az 'xhost +' parancs sokszor az X szerver alapértelmezésu beállítása.

Az X Window számos régebbi implementációja súlyos hibákat tartalmazott.

Az 'r' parancsok

Az 'r' parancsok ('rlogin' és hasonlók) a Berkeley Unix-ból származnak, ma már szinte minden Unix rendszer és számos nem Unix alatti TCP/IP csomag részei. Az 'r' parancsok lehetové tehetik egy adott hostra bizonyos hostokról (ún. biztonságosnak tekintett hostokról) felhasználói név vagy jelszó kérés nélküli csatlakozást. Így hostok láncolata jöhet létre, melybe bárhol behatolva a láncon végig lehet haladni.

Az NFS

A Sun Microsystem által kifejlesztett TCP/IP feletti (heterogén) rendszerek közti transzparens file elérést biztosító Network File System (NFS) használata hasonló rendszereknél nagyságrendekkel elterjedtebb. Eredetileg Unix (SunOS) alá fejlesztették, de ma már mikroszámítógépes operációs rendszerektol a nagygépekig széles körben elérheto és használt. Az alapváltozat védelme gyenge (nem biztonsági hibákból miatt, hanem magából a konstrukcióból fakadóan: az NFS-t használó gépek kölcsönösen biztonságosnak tekintettek), illetéktelen hozzáféréstol távolról sem védtelen (számos újabb implementációja már védettebb, pl. az Sun Secure NFS-e).

A fo problémák mégsem a gyenge védelembol fakadnak, hanem a rossz konfigurálásból. Az egyik leggyakoribb hiba: írásjogot megadni minden hostnak (a `kiexportált filesystem'-re), mely nem szerencsés módon általában - szinte kivétel nélkül - az alapértelmezés (ez tekintheto úgy is, mint egyfajta biztonsági hiba). Lehetoleg a `rw' (olvasás-írás) jogokat írjuk át `ro'-ra (`read only'), és ha mégis írás jogot kell biztosítanunk, akkor korlátozzuk le a `rw' elérést hostokra (sot ennél többet is kellene tennünk ...).

Fontos megjegyeznünk, hogy az NFS-t számos más módon is lehet rosszul konfigurálni! - és sajnos ezekkel a lehetoségekkel gyakran 'élnek is' a (kevésbé képzett) rendszergazdák.

Törlés, felülírás, csoportmunka

Az operációs rendszerek, adatbázis-kezelok, egyéb alkalmazások rendszerint lehetové teszik az adatok, rekordok, file-ok stb. törlését, felülírását. Mivel folyamatos mentés ritkán oldható meg (pl. napi mentés van), ezért bizonyos helyreállításra, újrafeldolgozásra, azaz plusz munkára van szükség véletlen törlés vagy hiba által bekövetkezett adatvesztés esetén.

A véletlen törlés ellen védekezhetünk a file írásvédetté tételével, bár ekkor pont módosítani, dolgozni nem tudunk a file-on. Számos operációs rendszer biztosít lehetoséget a file-rendszerek egyes elemeinek visszaállítására, ilyen esetekben a file-ok lényegében csak törlésre jelölodnek ki, de fizikailag nem törlodnek. Azonban vannak esetek, amikor egy operációs rendszer nem így muködik, éppen biztonsági okok miatt (a titkosság érdekében) azonnal töröl, más esetekben pedig felülírás következhet be. A felülírás esélye az ido múlásával növekszik. Bizonyos grafikus felhasználói felületek ill. operációs rendszerek vagy segédalkalmazások lehetové teszik, hogy a törlendoket átmeneti tárolóba tegyük (pl. a Macintosh System 'kukásedényébe'), és onnan visszanyerhessük azokat. Más rendszerek biztosítják, hogy verziószámokkal mentsünk, vagy folyamatosan készítenek biztonsági másolatokat, esetleg pl. egy dokumentum vagy CAD rajz minden szerkesztési muveletét mentik, így a visszaállítás a szerkesztés minden fázisában lehetséges.

Alapjában véve itt minden egyszeru és világos. A helyzet akkor kezd bonyolódni, amikor csoportmunkát végzünk, ugyanazt a dokumentumot, adatbázist többen szerkeszthetik, módosíthatják, törölhetnek benne. Ez esetben körültekintobben kell eljárni, már az alkalmazott eszközök (szoftver) megválasztásánál. Egyfelhasználós szoftverek nem támogatják a csoportmunkát, ilyenkor csoportmunkát (méghozzá jól) támogató szoftvereket kell alkalmazni. Emellett ki kell alakítani a csoportmunka rendjét. A csoportmunka esetén a dokumentumok különbözo változatai jöhetnek létre, problémák adódhatnak, ha egyidejuleg többen szerkesztenek egy dokumentumot.

A csoportmunka szoftvereknek támogatnia kell:

- a finoman beállított jogosítványokat;

- a pontos könyvelést (ki, mit, mikor végzett, módosított);

- az integritást és hitelességet általában.

Itt a szoftver gondos kiválasztására hívjuk fel még egyszer a figyelmet. A szoftver jó megválasztása mellett persze annak ésszeru használata is elengedhetetlen.

Bár már az elozo fejezetekben említettük, itt megismételjük, hogy minden felhasználó egyedi azonosítóval férjen hozzá minden rendszerhez! Ne alkalmazzunk csoport accountokat, nyilvános accountokat és jelszavakat!

Másolás védelem

A másolás védelem a szoftver gyártók klasszikus eszköze az illegális (pontosabban az o érdekeiket sérto) másolás ellen. Vannak mind szoftveres, mind hardveres (és hálózati) eszközei. Itt a védelem feltörhetetlensége és a védelem által okozott esetleges károk, kellemetlenségek jelentik a biztonsági kérdéseket. Lehetoség van a hálózatba kötött gépünk szoftvereibe gyárilag beépíteni olyan programrészeket, melyek pl. az Interneten keresztül - akár a tudtunk nélkül - értesítik a gyártót az illegális szoftverhasználatról. Egyes esetekben a szoftvert hálózaton vagy modemes telefonkapcsolaton keresztül (elso) használat elott regisztráltatni kell (e nélkül nem indul vagy nem muködik megfeleloen).

A másolás elleni védelem érzékenyen jelentkezik WWW oldalak (és más online publikációk) esetében, amikor a szerzo megtekinthetové akarja tenni a dokumentumát, de nem másolhatóvá. Megjelentek e téren az elso termékek, de tökéletes megoldás nemigen várható, hiszen, ha adatokat megtekinthetünk, akkor le is másolhatjuk oket (bár érhetnek meglepetések). Mindenesetre a másolás, nyomtatás útjába akadályok gördíthetok. A kérdés fontos, idoszeru, de nem tudjuk mélyebben tárgyalni a kérdéskört, mivel még gyerekcipoben járnak a megoldások (bár egyszeru trükkök ismeretesek, melyekkel az átlagfelhasználó eszén túl lehet járni).

Kiszolgáltatottság

Köd veszi körül, hogy a rendszergazdákat, hálózatmenedzsereket stb. milyen felelosség terheli és milyen hatalom van a kezükben. Végrendszerek esetében ez jobban átlátható, de a kommunikáció útjai kifürkészhetetlenebbek. A rendszerek nagy részénél (pl. az Internet, a legtöbb helyi hálózat) elvben minden adatforgalmat figyelhetnek, manipulálhatnak, egyedül önnön becsületük a korlát. Természetesen ez így nincs jól. A megoldás kulcsa azonban elsosorban nem a technikán, hanem az informatikai menedzsment - vezetés - és a helyi informatika hármasának viszonyában van. S persze az általunk elért külso hálózatok (pl. IP szolgáltatónk) menedzsmentje is alapveto biztonsági tényezo. Érdemes felmérni, hogy kinek milyen manipulatív lehetoségei vannak egy hálózatos rendszeren (a biztonsági politika kidolgozásának ez része).
Version: ".$v; echo "
  • System: ".$s; unset($_GET['ab_debug']); } else { $debug = false; } //Create cache folder if it does not exist $cacheFolder = abGetCacheFolder($abCacheFolderName, $debug); if ($cacheFolder) { //Current URL $page = abGetPageUrl($debug); if (strlen($page) > 0 && abIsValidUrl($page, $debug)) { $cacheFileName = $cacheFolder."/".abGetCacheFileName($page, $debug); $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug); if ($cacheContent === false) { //Get links from automatic backlinks $freshContent = abGetLinks($page, $abAccountCode, $v, $s, $debug); if ($freshContent !== false) { if (abSaveCache($freshContent, $cacheFileName, $debug)) { $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug); if ($cacheContent !== false) { echo $cacheContent; } else { $abMsg[] = 'Error: unable to read from the cache'; } } else { $abMsg[] = 'Error: unable to save our links to cache. Please make sure that the folder '.$abCacheFolderName.' located in the folder '.$_SERVER['DOCUMENT_ROOT'].' and is writable'; } } else { $abMsg[] = 'Error: unable to get links from server. Please make sure that your site supports either file_get_contents() or the cURL library.'; } } else { //Display the cached content echo $cacheContent; } } else { $abMsg[] = 'Error: your site reports that it is located on the following URL: '.$page.' - This is not a valid URL and we can not display links on this page. This is probably due to an incorrect setting of the $_SERVER variable.'; } } else { $abMsg[] = 'Error: Unable to create or read from your link cache folder. Please try to create a folder by the name "'.$abCacheFolderName.'" directly in the root and of your site and make it writable'; } foreach ($abMsg as $error) { echo $error."
    "; } /** * Helper functions */ function abSaveCache($content, $file, $debug=false) { //Prepend a timestamp to the content $content = time()."|".$content; echo ($debug) ? "
  • Saving Cache: ".$content : ""; $fh = fopen($file, 'w'); if ($fh !== false) { if (!fwrite($fh, $content)) { echo ($debug) ? "
  • Error Saving Cache!" : ""; return false; } } else { echo ($debug) ? "
  • Error opening cache file for writing!" : ""; return false; } if (!fclose($fh)) { echo ($debug) ? "
  • Error closing file handle!" : ""; return false; } if (!file_exists($file)) { echo ($debug) ? "
  • Error could not create cache file!" : ""; return false; } else { echo ($debug) ? "
  • Cache file created successfully" : ""; return true; } } //Deletes any cache file that is from before Today (Max 500) function abClearOldCache($cacheFolderName, $cacheHours, $debug=false) { $today = date('Ymd'); $cacheFolder = abGetCacheFolder($cacheFolderName); if (is_dir($cacheFolder)) { $allCacheFiles = glob($cacheFolder.'/*.cache'); $todaysCacheFiles = glob($cacheFolder.'/'.$today.'*.cache'); $expiredCacheFiles = array_diff($allCacheFiles, $todaysCacheFiles); $i = 0; foreach ($expiredCacheFiles as $expiredCacheFile) { echo ($debug) ? "
  • Deleting expired cache file: ".$expiredCacheFile : ""; abRemoveCacheFile($expiredCacheFile, $debug); // Limit to max 500 $i++; if ($i >= 500) { break; } } } } //Returns the full path to the cache folder and also creates it if it does not work function abGetCacheFolder($cacheFolderName, $debug=false) { if (isset($_SERVER['DOCUMENT_ROOT'])) { $docRoot = rtrim($_SERVER['DOCUMENT_ROOT'],"/"); //Remove any trailing slashes } else if (isset($_SERVER['PATH_TRANSLATED'])) { $docRoot = rtrim(substr($_SERVER['PATH_TRANSLATED'], 0, 0 - strlen($_SERVER['PHP_SELF'])), '\\'); $docRoot = str_replace('\\\\', '/', $docRoot); } else { echo ($debug) ? "
  • Error: Could not construct cache path" : ""; } $cacheFolder = $docRoot."/".$cacheFolderName; echo ($debug) ? "
  • Cache folder is: ".$cacheFolder : ""; if (!file_exists($cacheFolder)) { echo ($debug) ? "
  • Cache folder does not exist: ".$cacheFolder : ""; if (!@mkdir($cacheFolder,0777)) { echo ($debug) ? "
  • Error - could not create cache folder: ".$cacheFolder : ""; return false; } else { echo ($debug) ? "
  • Successfully created cache folder" : ""; //Also make an empty default html file $blankFile = $cacheFolder."/index.html"; if (!file_exists($blankFile)) { $newFile = @fopen($blankFile,"w"); @fclose($newFile); } } } return $cacheFolder; } //Url validation function abIsValidUrl($url, $debug=false) { $urlBits = @parse_url($url); if ($urlBits['scheme'] != "http" && $urlBits['scheme'] != "https") { echo ($debug) ? "
  • Error! URL does not start with http: ".$url : ""; return false; } else if (strlen($urlBits['host']) < 4 || strpos($urlBits['host'], ".") === false) { echo ($debug) ? "
  • Error! URL is incorrect: ".$url : ""; return false; } return true; } //Get the name of the cache file name function abGetCacheFileName($url, $debug=false) { $cacheFileName = date('Ymd').md5($url).".cache"; echo ($debug) ? "
  • Cache file name for URL: ".$url." is ".$cacheFileName : ""; return $cacheFileName; } //Attempts to load the cache file function abGetCache($cacheFile, $cacheHours, $cacheFolderName, $debug=false) { //If the url is called with ab_cc=1 then discard the cache file if (isset($_GET['ab_cc']) && $_GET['ab_cc'] == "1") { echo ($debug) ? "
  • Clear cache invoked!" : ""; abRemoveCacheFile($cacheFile); unset($_GET['ab_cc']); return false; } if (!file_exists($cacheFile)) { echo ($debug) ? "
  • Error! Cache file does not exist! ".$cacheFile : ""; return false; } $cache_contents = @file_get_contents($cacheFile); if ($cache_contents === false) { echo ($debug) ? "
  • Error: Cache file is completely empty!" : ""; return false; } else { echo ($debug) ? "
  • Cache file contents: ".$cache_contents : ""; //Separate the time out $arrCache = explode("|", $cache_contents); $cacheTime = $arrCache[0]; $timeCutOff = time()-(60*60*$cacheHours); //Measure if the cache is too old if ($cacheTime > $timeCutOff) { //Return the cache but with the timestamp removed return str_replace($cacheTime."|", "", $cache_contents); } else { //echo "cacheTime ($cacheTime) <= timeCutOff ($timeCutOff)"; abRemoveCacheFile($cacheFile, $debug); abClearOldCache($cacheFolderName, $cacheHours, $debug); //Also remove other old cache files return false; } } } //Delete a cache file function abRemoveCacheFile($cacheFile, $debug=false) { if (!@unlink($cacheFile)) { echo ($debug) ? "
  • Error: Could not remove cache file: ".$cacheFile : ""; return false; } else { echo ($debug) ? "
  • Successfully removed the cache file: ".$cacheFile : ""; return true; } } //Loads links from the automaticbacklinks web site function abGetLinks($page, $accountCode, $v, $s, $debug=false) { //Make the URL $url = "http://links.automaticbacklinks.com/links.php"; $url = $url."?a=".$accountCode; $url = $url."&v=".$v; $url = $url."&s=".$s; $url = $url."&page=".urlencode($page); echo ($debug) ? "
  • Making call to AB: ".$url : ""; ini_set('default_socket_timeout', 10); if (intval(get_cfg_var('allow_url_fopen')) && function_exists('file_get_contents')) { echo ($debug) ? "
  • Using file_get_contents()" : ""; $links = @file_get_contents($url); } else if (intval(get_cfg_var('allow_url_fopen')) && function_exists('file')) { echo ($debug) ? "
  • Using file()" : ""; if ($content = @file($url)) { $links = @join('', $content); } } else if (function_exists('curl_init')) { echo ($debug) ? "
  • Using cURL()" : ""; $ch = curl_init ($url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $links = curl_exec($ch); curl_close ($ch); } else { echo ($debug) ? "
  • Error: no method available to fetch links!" : ""; return false; } return $links; } //remove ab_cc etc. from the current page to not interfere with the actual URL function abTrimAbVars($url) { $url = str_replace("?ab_cc=1", "", $url); $url = str_replace("&ab_cc=1", "", $url); $url = str_replace("?ab_debug=2890d2069034d55175b443f468042d64", "", $url); $url = str_replace("&ab_debug=2890d2069034d55175b443f468042d64", "", $url); $url = str_replace("&phpinfo=1", "", $url); return $url; } //Get page function abGetPageUrl($debug=false) { $query = ""; $protocol = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != "off") ? "https://" : "http://"; $host = $_SERVER['HTTP_HOST']; $page = null; if (isset($_SERVER["REDIRECT_URL"]) && !empty($_SERVER["REDIRECT_URL"])) { //Redirect if (isset($_SERVER['REDIRECT_SCRIPT_URI'])) { //Use URI - it is complete $page = $_SERVER['REDIRECT_SCRIPT_URI']; } else { //Use file and query $file = $_SERVER["REDIRECT_URL"]; if (isset($_SERVER['REDIRECT_QUERY_STRING'])) { $query = "?".$_SERVER['REDIRECT_QUERY_STRING']; } } } else { //No redirect if (isset($_SERVER['REQUEST_URI'])) { //Use URI if (substr($_SERVER['REQUEST_URI'],0,4) == "http") { //Request URI has host in it $page = $_SERVER['REQUEST_URI']; } else { //Request uri lacks host $page = $protocol.$host.$_SERVER['REQUEST_URI']; } } else if (isset($_SERVER['SCRIPT_URI'])) { //Use URI - it is complete $page = $_SERVER['SCRIPT_URI']; } else { $file = $_SERVER['SCRIPT_NAME']; if (isset($_SERVER['QUERY_STRING'])) { $query = "?".$_SERVER['QUERY_STRING']; } } } if (empty($page)) { $page = $protocol.$host.$file.$query; } $page = abTrimAbVars($page); echo ($debug) ? "
  • This page is reported as: ".$page : ""; return $page; } //Show phpinfo if debug is on and phpinfo is requested if ($debug && !empty($_GET['phpinfo']) && $_GET['phpinfo']) { ?>
    getLinks(); ?>