Knihovny

Úvod

Po menší úvaze jsem se rozhodl zvolit jiný přístup k popisu problematiky bezpečnosti. Je sice fajn umět pomocí tutoriálu provést přetečení zásobníku, ale bez pochopení interních procesů v systému se už hůře aplikují naučené postupy na reálné případy. Pro popis problematiky sdílených knihoven jsem si vybral operační systém Linux, jelikož poskytuje velké množství nástrojů a tím se na něm dobře demonstrují zde zmíněné principy. Znalosti získané z Linuxu se ale hodí i pro pochopení vlastností operačního systému Windows, protože leckteré myšlenky jsou podobné. V rámci tohoto příspěvku pracuji na operačním systému Ubuntu 16.04 32 bit.

Na tento tématický okruh jsem narazil při zkoumání struktury souborů typu ELF, přičemž k pochopení jejich struktury je potřeba i znalost této problematiky. Takže začnu definicí, jak knihovny v Linuxu (ale principy platí i pro jiné operační systémy) chápu já.

Knihovny představují soubor funkcí, u kterých je vhodné je mít po ruce pro více programů. Je to výhodné, protože každý programátor nemusí pokaždé definovat například svůj výpis do konzole, ale využije již existujícího rozhraní.

Několik základních poznámek k této mé definici. Víceméně každý program ke svému chodu používá některou z knihoven (například i pro již zmíněný výpis do konzole). Ač obsahují instrukce, tak je nelze spustit (když si otevřu seznam procesů, pak se tam žádné knihovny nenachází). Rozlišujeme dva druhy knihoven, sdílené (shared, také se říká dynamické) a statické (static). Tyto dvě varianty se od sebe liší způsobem, jakým jsou využívány. Ve zkratce, pokud jsou knihovny sdílené (dynamické), pak jsou používány více programy a existují v jedné kopii, zatímco statické jsou zkopírovány do každého programu, který je využívá (existují ve více kopiích).

Statické knihovny

Statické knihovny jsou takové knihovny, které si program nese s sebou (existuje více kopií).

Výsledný program má tím pádem potřebné funkce v sobě a nepotřebuje ke svému spuštění jejich připojení. To se hodí v případě, že bychom chtěli náš program distribuovat takovým způsobem, aby jej uživatel mohl spustit na svém počítači bez dodatečných instalací. S tím je ovšem spojeno několik problémů. Jmenovitě, výsledný program může nabývat relativně velkých rozměrů a také, pokud dojde ke změně knihovny, pak je potřeba znovu přeložit kód.

Sdílené (dynamické) knihovny

Sdílené (dynamické) knihovny jsou takové knihovny, které se nenacházejí v programu a jsou připojeny až dodatečně při spuštění nebo při běhu.

Sdílené knihovny jsou takové knihovny, které jsou přidány až při spuštění (někdy až při běhu). Výsledkem tohoto způsobu řešení závislosti je to, že program je relativně malý (oproti svému protějšku se statickými knihovnami). To dovoluje také i jistou modularitu, protože lze změnit obsah (aktualizovat) knihovny, aniž bychom museli přeložit všechno, co ji využívá. Nevýhodou může být zvýšená režie s instalací (chybějící závislosti a podobně).

Přípony

Podle druhu knihovny a operačního systému rozlišujeme tyto přípony.

  • Sdílené(Shared)
    • Windows – *.dll
    • Linux- *.so
    • OS X – *.dylib
  • Statické(Static)
    • Windows – *.lib
    • Linux- *.a

Názvy

Tato podkapitola je čistě specifická pro Linuxové distribuce. Sdílenou knihovnu lze v rámci linuxu označit několika různými názvy (verzování statických knihoven není třeba v tomto článku řešit, protože každý program si nese potřebnou kopii v sobě).

  • Označení použité linkerem – název knihovny (začíná na lib) + .so. Například libpthread.so.
  • Označení knihovny s hlavní verzí – název knihovny (začíná na lib) + .so + .hlavní verze. Například libc.so.6.
  • Celé označení – podobné jako označení knihovny s hlavní verzí, jen přibude označení podverze a popřípadě volitelné release number. Například libcap.so.2.24 nebo libpcre.so.3.13.2.

Platí několik jednoduchých pravidel. Číslo hlavní verze se změní, jestliže dochází ke změně, která by mohla mít vliv na kompatibilitu (například odebrání některé funkce). Podverze se mění v případě, že na kompatibilitu změna nemá žádný vliv (například v případě, že je vydána záplata).

Příklad

Na konec tohoto článku ukáži, jak v operačním systému Linux zobrazit sdílené knihovny, které jsou požadovány daným programem. Použijeme k tomu programu readelf s přepínačem -d. Vyberu si program na kopírování souborů cp.

readelf dynamic libraries

Obr 1. – Výpis požadovaných sdílených knihoven pro program cp
Potřebné sdílené knihovny jsou uvedeny hodnotou ve sloupci Type (NEEDED).

V dalších článcích se k této problematice ještě vrátím, protože je zcela zásadní z hlediska pochopení fungování systému.

Stack overflow protection 1

Po dlouhém hledání na internetu jsem dospěl k názoru, že není příliš zdrojů střední úrovně na téma obrany proti přetečení zásobníku. Ve svých toulkách jsem našel články buď příliš technické, ke kterým je zapotřebí předešlých znalostí a nebo naopak až příliš obecné, určené jen pro nejširší publikum. Rád bych proto tuto nerovnováhu napravil a zkusil ze svého vlastního výzkumu vytvořit mezičlánek mezi těmito dvěma úrovněmi. Předem podotýkám, že jsem v této oblasti také na začátku a je tudíž možné, že v jistých místech budou nepřesnosti. Dále si tato série článků neklade za cíl uvést vyčerpávající popis všech existujících řešení.

Pro výklad obranných mechanismů si vyberu operační systém Linux. Konkrétně systém Debian ve verzi 8.6 64 bit (a v některých případech Ubuntu 16.04 32 bit, vždy rozliším). 64 bitová architektura má jistá specifika, které zatím vynechám pro jednoduchost. Později se k těmto specifikům vrátím. Jak jsem totiž sám zjistil, mnoho tutoriálu uvádí postupy pro 32 bitový systém, ale už hůře se dohledává, jakým způsobem provést přetečení na 64 bitové architektuře.

DEP

Data Execution Prevention zabraňuje aplikaci, aby spustila kód z oblasti paměti, která je označena jako nespustitelná.

DEP – Data Execution Prevention je základní technika obrany proti přetečení zásobníku. Stojí na velmi jednoduchém principu, že místo v paměti, které je zapisovatelné, nemůže být současně spustitelné. Jinak řečeno, pokud tedy dojde k přetečení zásobníku a je na něj vložen kód, pak jej nelze spustit. Ač se to jeví jako samozřejmost, je třeba si uvědomit, že tato technika nebyla implementována relativně dlouhou dobu od prvního známého případu přetečení zásobníku. V hlavičce spustitelného souboru je uvedeno, jaká část paměti je spustitelná. Strukturu zápisu ukáži na konkrétním programu. Zdrojový kód:


#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
    char buf[256];
    strcpy(buf,argv[1]);
    printf("Input:%s\n",buf);
    return 0;
}

Uvedený kód zkompiluji za pomocí programu gcc a nechám si vypsat strukturu program headers za pomocí programu readelf.

readelf program structure
Struktura program headers – Ubuntu 16.04

Zajímavý je sloupec Flg (Flag), který ukazuje, jestli je sekce zapisovatelná (W), čitelná (R) nebo spustitelná (E). Zásobník, označený jako GNU_STACK, je zapisovatelný i čitelný. Cokoliv nacházející se v této oblasti paměti ovšem nelze spustit.

Program headers říkají systému, jakým způsobem má být program načten do paměti.

DEP lze implementovat softwarově i hardwarově.

Úžasný Mauric a jeho vzdělaní hlodavci

Aneb o pouti za jedním krysím snem.

Tuto knížku napsal Terry Pratchett, přičemž situovaná je do světa Zeměplochy. Pro přečtení není ovšem potřeba mít předešlých znalosti z jiné tvorby autora, ani já jsem je neměl. Toto dílo lze tedy přečíst i jako první ze série zcela bez problémů. Jediný problém jsou pak jen odkazy na postavy z ostatních knih. Například smrtka se svým krysím pomocníkem v kápi, což je pro znalce série určitě starý známý.

Vzhledem k tomu, že hlavními hrdiny knihy jsou mluvící kocour, inteligentní a věčně filozofující krysí společníci a kluk, jehož hlavní předností je schopnost hrát na flétnu, lze nabýt dojmu, že se jedná převážně o pohádku. Ač z části se dá o této knížce tak přemýšlet, příliš často mi při četbě tento pocit hlavou neproběhl. Není to tak, že by příběh byl vyloženě temný nebo měl až přílišný důraz na napětí, jen někdy dochází ke zlým zvratům. Řekl bych, že dobré a špatné okamžiky pro celou skupinku jsou tak trochu vyrovnány. Rozhodně bych si nedovolil tvrdit, že se jedná o knížku jen pro děti a už vůbec ne pro nejmenší.

Celý příběh provází i komediální složka. Některé části, jako například krysí jednotka pro zneškodňování pastí, působí úsměvně. Celkově je knížka psána nekomplikovaným způsobem, velký důraz je kladen na vyprávění a občas i na monology postav v hlavě. To z počinu dělá odpočinkovou četbu, která se hodí na cesty nebo na večery před spaním. Žádné zdlouhavé popisy v díle nenajdete, příběh se tedy odvíjí rychlým a nepřerušovaným tempem.

Příběh je spíše kratšího rázu, vášnivý čtenář tuto knihu dokáže přečíst během dvou, maximálně tří dnů. Ač je pravda, že rozsah zápletky by možná nedovolil udržet stejnou kvalitu i při delším zpracování, ještě chvíli bych o osudech skupinky rád četl. Jinak řečeno, když už si čtenář na všechny postavy zvykne a svým způsobem si je oblíbí, tak příběh končí. To bych asi nazval jediným negativem, alespoň pro mne.

Celkově hezká knížka pro dlouhé a deštivé odpoledne. Spíše pro nenáročného čtenáře, ale myslím, že si v ní dokáže najít i zkušený čtenář svůj díl oddychu a odreagování. Pro znalce série není dle mého názoru jediného důvodu, proč nerozšířit svoji sbírku. Jedinou pihou na kráse je, že knížka mohla být o kapánek delší. Rozsah příběhu je ovšem zpracován akorát.

9/10

img_0281