Переполнение буфера - наиболее "популярная" и в то же время наиболее коварная ошибка, которой не избежало практически ни одно сколь ни будь сложное приложение. Коротко объясним ее суть: если размера выделенного программистом буфера вдруг окажется недостаточно для вмещения всех, копируемых в него данных, то содержимое памяти за концом буфера окажется разрушено (а точнее - замещено) не вместившимися в буфер данными. В зависимости от ситуации за концом буфера могут находится:
а) другие буфера и переменные программы;
б) служебные данные - в частности, адрес возврата из функции;
в) исполняемый код;
г) незанятая или д) отсутствующая страница памяти.
Наибольшую опасность представляют пункты б) и в) так как они чреваты возможностью полного захвата контроля над уязвимой программой. Пункт д) менее коварен и в худшем случае приводит к возможности реализации атаки отказа в обслуживании (при обращении к отсутствующей странице памяти процессор выбрасывает исключение, приводящее к аварийному завершению уязвимого приложения). Угроза от пункта а) в значительной степени зависит от рода и назначения переменных, находящихся за концом переполняющегося буфера и хотя теоретически уязвимое приложение способно на что угодно на практике угроза оказывается не столь уж и велика.
Есть еще одно обстоятельство, - для полноценного захвата управления хакер должен иметь возможность исполнять на удаленной машине собственный код, обычно передаваемый непосредственно через сам переполняющийся буфер. В зависимости от расположения уязвимого буфера и "характера" операционной системы, исполнение переданного хакером кода может быть как разрешено, так и нет.
Все системы: и UNIX, и NT потенциально допускают существование пунктов а), б), г) и д), исключая лишь единственный из них - пункт в). Следовательно, они в равной мере подвержены угрозе переполнения буфера. Кроме того, и UNIX, и NT имеют исполняемый стек (то есть разрешают выполнение кода в стеке) и запрещают его выполнение в сегменте данных. А это значит, что переполнение буферов, содержащихся в автоматических (т.е. стековых) переменных несет в себе угрозу полного захвата управления над уязвимой программой. Правда, для некоторых UNIX существуют заплаты, отнимающие у стека право выполнения, но сфера их применения весьма ограничена (исполняемый стек необходим множеству вполне легальных программ, в частности, компиляторов).
Самое забавное, что и UNIX, и NT написаны на Си - языке программирования, не поддерживающим автоматический контроль границ массива и потому подверженному ошибкам переполнения. Старожилы говорят, что в некоторых версиях UNIX ошибка переполнения присутствовала даже на вводе имени пользователя при регистрации в системе.