Synchronize with English 1.26
Submitted by: Vitaly Bogdanov <gad@gad.glazov.net> Obtained from: The FreeBSD Russian Documentation Project
This commit is contained in:
parent
3a44d0360e
commit
7b63d5a37c
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=25102
1 changed files with 163 additions and 50 deletions
|
|
@ -2,21 +2,29 @@
|
|||
The FreeBSD Russian Documentation Project
|
||||
|
||||
$FreeBSD$
|
||||
$FreeBSDru: frdp/doc/ru_RU.KOI8-R/books/developers-handbook/secure/chapter.sgml,v 1.1 2001/02/19 06:57:41 andy Exp $
|
||||
$FreeBSDru: frdp/doc/ru_RU.KOI8-R/books/developers-handbook/secure/chapter.sgml,v 1.4 2005/07/11 11:54:33 gad Exp $
|
||||
|
||||
Original revision: 1.1
|
||||
Original revision: 1.26
|
||||
-->
|
||||
|
||||
<chapter id="secure">
|
||||
<title>Безопасное программирование</title>
|
||||
<chapter id="secure">
|
||||
<chapterinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Murray</firstname>
|
||||
<surname>Stokely</surname>
|
||||
<contrib>Материал предоставил: </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</chapterinfo>
|
||||
|
||||
<para>Эту главу написал Мюррей Стокели (Murray Stokely).</para>
|
||||
<title>Безопасное программирование</title>
|
||||
|
||||
<sect1>
|
||||
<sect1 id="secure-synopsis">
|
||||
<title>Обзор</title>
|
||||
|
||||
<para>Эта глава описывает некоторые из проблем обеспечения безопасности,
|
||||
которые десятилетиями преследовали программистов Unix, а также
|
||||
которые десятилетиями преследовали программистов &unix;, а также
|
||||
несколько новых доступных инструментов, помогающих программистам
|
||||
избежать написания небезопасного кода.</para>
|
||||
</sect1>
|
||||
|
|
@ -32,45 +40,80 @@
|
|||
код должен использоваться там, где только это возможно для избежания
|
||||
общих ошибок, которые могли быть уже исправлены другими.</para>
|
||||
|
||||
<para>Одной из неприятностей в среде Unix является легкость в
|
||||
<para>Одной из неприятностей в среде &unix; является легкость в
|
||||
предположении безопасности этого окружения. Приложения никогда не
|
||||
должны верить пользовательскому вводу (во всех его формах), ресурсам
|
||||
системы, межпроцессному взаимодействию или времени выполнения событий.
|
||||
Процессы Unix выполняются не синхронно, так что логические операции
|
||||
Процессы &unix; выполняются не синхронно, так что логические операции
|
||||
редко бывают атомарными.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<sect1 id="secure-bufferov">
|
||||
<title>Переполнения буфера</title>
|
||||
|
||||
<para>Переполнения буфера появились вместе с появление архитектуры
|
||||
Фон-Неймана <xref linkend="COD">. Впервые широкую известность они
|
||||
получили в 1988 году вместе с Интернет-червем Мурса (Moorse). К
|
||||
сожалению, точно такая же атака повторилась и в наши дни. Из 17
|
||||
бюллетеней безопасности CERT за 1999 год, 10 были непосредственно
|
||||
вызваны ошибкам в программном обеспечении, связанным с переполнениями
|
||||
буфера. Самые распространенные типы атак с использованием переполнения
|
||||
буфера основаны на разрушении стека.</para>
|
||||
Фон-Неймана <xref linkend="COD">.
|
||||
|
||||
<indexterm><primary>переполнение буфера</primary></indexterm>
|
||||
<indexterm><primary>Фон-Нейман</primary></indexterm>
|
||||
|
||||
Впервые широкую известность они получили в 1988 году вместе с
|
||||
Интернет-червем Морриса (Morris). К сожалению, точно такая же атака
|
||||
|
||||
<indexterm><primary>интернет червь Морриса</primary></indexterm>
|
||||
|
||||
остаётся эффективной и в наши дни. Из 17 бюллетеней безопасности CERT за 1999 год,
|
||||
|
||||
<indexterm>
|
||||
<primary>CERT</primary><secondary>бюллетени безопасности</secondary>
|
||||
</indexterm>
|
||||
|
||||
10 были непосредственно вызваны ошибкам в программном обеспечении, связанным
|
||||
с переполнениями буфера. Самые распространенные типы атак с использованием
|
||||
переполнения буфера основаны на разрушении стека.</para>
|
||||
|
||||
<indexterm><primary>стек</primary></indexterm>
|
||||
<indexterm><primary>аргументы</primary></indexterm>
|
||||
|
||||
<para>Самые современные вычислительные системы используют стек для
|
||||
передачи аргументов процедурам и сохранения локальных переменных. Стек
|
||||
является буфером типа LIFO (последним вошел первым вышел) в верхней
|
||||
части области памяти процесса. Когда программа вызывает функцию,
|
||||
создается новая "граница стека". Эта граница состоит из аргументов,
|
||||
|
||||
<indexterm><primary>LIFO</primary></indexterm>
|
||||
<indexterm>
|
||||
<primary>область процесса</primary>
|
||||
<secondary>указатель стека</secondary>
|
||||
</indexterm>
|
||||
|
||||
переданных в функцию, а также динамического количества пространства
|
||||
локальных переменных. "Указатель стека" является регистром, хранящим
|
||||
|
||||
<indexterm><primary>граница стека</primary></indexterm>
|
||||
<indexterm><primary>указатель стека</primary></indexterm>
|
||||
|
||||
текущее положение вершины стека. Так как это значение постоянно
|
||||
меняется вместе с помещением новых значений на вершину стека, многие
|
||||
реализации также предусматривают "указатель границы", который
|
||||
расположен около начала стека, так что локальные переменные можно легко
|
||||
адресовать относительно этого значения. <xref linkend="COD"> Адрес
|
||||
|
||||
<indexterm><primary>указатель границы</primary></indexterm>
|
||||
<indexterm>
|
||||
<primary>область процесса</primary>
|
||||
<secondary>указатель границы</secondary>
|
||||
</indexterm>
|
||||
<indexterm><primary>возвращаемый адрес</primary></indexterm>
|
||||
<indexterm><primary>переполнение стека</primary></indexterm>
|
||||
|
||||
возврата из функции также сохраняется в стеке, и это является причиной
|
||||
нарушений безопасности, связанных с переполнением стека, так как
|
||||
перезаписывание локальной переменной в функции может изменить адрес
|
||||
возврата из этой функции, потенциально позволяя злоумышленнику
|
||||
выполнить любой код.</para>
|
||||
|
||||
<para>Хотя атаки с переполнением стека являются замыми распространенными,
|
||||
<para>Хотя атаки с переполнением стека являются самыми распространенными,
|
||||
стек можно также перезаписать при помощи атаки, основанной на выделении
|
||||
памяти (malloc/free) из "кучи".</para>
|
||||
|
||||
|
|
@ -78,7 +121,7 @@
|
|||
автоматической проверки границ в массивах или указателях. Кроме того,
|
||||
стандартная библиотека C полна очень опасных функций.</para>
|
||||
|
||||
<informaltable>
|
||||
<informaltable frame="none" pgwide="1">
|
||||
<tgroup cols=2>
|
||||
<tbody>
|
||||
<row>
|
||||
|
|
@ -132,8 +175,7 @@
|
|||
следующей непосредственно за вызовом функции. (По мотивам <xref
|
||||
linkend="Phrack">)</para>
|
||||
|
||||
<programlisting>
|
||||
#include <sgmltag>stdio.h</sgmltag>
|
||||
<programlisting>#include <sgmltag>stdio.h</sgmltag>
|
||||
|
||||
void manipulate(char *buffer) {
|
||||
char newbuffer[80];
|
||||
|
|
@ -151,8 +193,7 @@ int main() {
|
|||
i=2;
|
||||
printf("The value of i is : %d\n",i);
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
|
||||
<para>Давайте посмотрим, как будет выглядеть образ процесса, если в
|
||||
нашу маленькую программу мы введем 160 пробелов.</para>
|
||||
|
|
@ -170,10 +211,23 @@ int main() {
|
|||
использование только памяти фиксированного размера и функций
|
||||
копирования строк. Функции <function>strncpy</function> и
|
||||
<function>strncat</function> являются частью стандартной библиотеки
|
||||
|
||||
<indexterm>
|
||||
<primary>функции копирования строки</primary>
|
||||
<secondary>strncpy</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>функции копирования строки</primary>
|
||||
<secondary>strncat</secondary>
|
||||
</indexterm>
|
||||
|
||||
C. Эти функции будут копировать не более указанного количества байт
|
||||
из исходной строки в целевую. Однако у этих функций есть несколько
|
||||
проблем. Ни одна из них не гарантирует наличие символа NUL, если
|
||||
размер входного буфера больше, чем целевого. Параметр длины также
|
||||
|
||||
<indexterm><primary>завершение символом NUL</primary></indexterm>
|
||||
|
||||
по-разному используется в strncpy и strncat, так что для
|
||||
программистов легко запутаться в правильном использовании. Есть
|
||||
также и значительная потеря производительности по сравнению с
|
||||
|
|
@ -182,27 +236,47 @@ int main() {
|
|||
NUL пространство до указанной длины.</para>
|
||||
|
||||
<para>Для избежания этих проблем в OpenBSD была сделана другая
|
||||
|
||||
<indexterm><primary>OpenBSD</primary></indexterm>
|
||||
|
||||
реализация копирования памяти. Функции <function>strlcpy</function>
|
||||
и <function>strlcat</function> гарантируют, что они они всегда
|
||||
терминируют целевую строку нулевым символом, если им будет передан
|
||||
аргумент ненулевой длины. Более подробная информация об этом
|
||||
находится здесь <xref linkend="OpenBSD">. Инструкции OpenBSD
|
||||
<function>strlcpy</function> и <function>strlcat</function> были
|
||||
во FreeBSD начиная с 3.5.</para>
|
||||
<function>strlcpy</function> и <function>strlcat</function> существуют
|
||||
во FreeBSD начиная с версии 3.3.</para>
|
||||
|
||||
<indexterm>
|
||||
<primary>функции копирования строки</primary>
|
||||
<secondary>strlcpy</secondary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>функции копирования строки</primary>
|
||||
<secondary>strlcat</secondary>
|
||||
</indexterm>
|
||||
|
||||
<sect3>
|
||||
<title>Вкомпилированная проверка границ во время выполнения</title>
|
||||
|
||||
<para>К несчастью, все еще широко используется очень большой объем
|
||||
<indexterm><primary>проверка границ</primary>
|
||||
<secondary>вкомпилированная</secondary></indexterm>
|
||||
|
||||
<para>К сожалению, все еще широко используется очень большой объём
|
||||
кода, который слепо копирует память без использования только что
|
||||
рассмотренных функций с проверкой границ. Однако есть другое
|
||||
решение. Существует несколько расширений к компилятору и
|
||||
библиотекам C/C++ для выполнения контроля границ во время
|
||||
выполнения.</para>
|
||||
библиотек для выполнения контроля границ во время
|
||||
выполнения (C/C++).</para>
|
||||
|
||||
<indexterm><primary>StackGuard</primary></indexterm>
|
||||
<indexterm><primary>gcc</primary></indexterm>
|
||||
|
||||
<para>Одним из таких добавлений является StackGuard, который
|
||||
реализован как маленький патч к генератору кода gcc. Согласно
|
||||
сайту StackGuard, http://immunix.org/stackguard.html:
|
||||
реализован как маленький патч к генератору кода gcc. Согласно <ulink
|
||||
url="http://immunix.org/stackguard.html">web сайту StackGuard</ulink>:
|
||||
|
||||
<blockquote>
|
||||
<para>"StackGuard распознает и защищает стек от атак,
|
||||
не позволяя изменять адрес возврата в стеке. При вызове
|
||||
|
|
@ -219,12 +293,14 @@ int main() {
|
|||
кода gcc, а именно процедур function_prolog() и
|
||||
function_epilog(). function_prolog() усовершенствована для
|
||||
создания пометок в стеке при начале работы функции, а
|
||||
function_epilog() проверяет челостность пометки при возврате из
|
||||
function_epilog() проверяет целостность пометки при возврате из
|
||||
функции. Таким образом, любые попытки изменения адреса
|
||||
возврата определяются до возврата из функции."</para>
|
||||
</blockquote>
|
||||
</para>
|
||||
|
||||
<indexterm><primary>переполнение буфера</primary></indexterm>
|
||||
|
||||
<para>Перекомпиляция вашего приложения со StackGuard является
|
||||
эффективным способом остановить большинство атак переполнений
|
||||
буфера, но все же полностью это проблемы не решает.</para>
|
||||
|
|
@ -234,6 +310,11 @@ int main() {
|
|||
<title>Проверка границ во время выполнения с использованием
|
||||
библиотек.</title>
|
||||
|
||||
<indexterm>
|
||||
<primary>проверка границ</primary>
|
||||
<secondary>основана на библиотеке</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>Механизмы на основе компилятора полностью бесполезны для
|
||||
программного обеспечения, поставляемого в двоичном виде, которое вы
|
||||
не можете перекомпилировать. В этих ситуациях имеется некоторое
|
||||
|
|
@ -246,7 +327,7 @@ int main() {
|
|||
<itemizedlist>
|
||||
<listitem><simpara>libsafe</simpara></listitem>
|
||||
<listitem><simpara>libverify</simpara></listitem>
|
||||
<listitem><simpara>libparnoia</simpara></listitem>
|
||||
<listitem><simpara>libparanoia</simpara></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>К сожалению, эти защиты имеют некоторое количество недостатков.
|
||||
|
|
@ -260,16 +341,27 @@ int main() {
|
|||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<sect1 id="secure-setuid">
|
||||
<title>Проблемы с установленным битом UID</title>
|
||||
|
||||
<indexterm><primary>seteuid</primary></indexterm>
|
||||
|
||||
<para>Имеется по крайней мере 6 различных идентификаторов (ID), связанных
|
||||
с любым взятым процессом. Поэтому вы должны быть очень осторожны с
|
||||
тем, какие права имеет ваш процесс в каждый момент времени. В
|
||||
частности, все seteuid-приложения должны понижать свои привилегии, как
|
||||
только в них отпадает необходимость.</para>
|
||||
|
||||
<para>ID реального пользователя может быть изменен только процессом
|
||||
<indexterm>
|
||||
<primary>идентификаторы пользователя</primary>
|
||||
<secondary>реальный ID пользователя</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>идентификаторы пользователя</primary>
|
||||
<secondary>эффективный ID пользователя</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>Реальный ID пользователя может быть изменен только процессом
|
||||
администратора. Программа <application>login</application>
|
||||
устанавливает его, когда пользователь входит в систему, и он редко
|
||||
меняется.</para>
|
||||
|
|
@ -283,10 +375,12 @@ int main() {
|
|||
предыдущее значение сохраняется в сохраняемом set-user-ID.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="chroot">
|
||||
<sect1 id="secure-chroot">
|
||||
<title>Ограничение среды работы вашей программы</title>
|
||||
|
||||
<para>Традиционно используемым методом ограничения доступа к процессу
|
||||
<indexterm><primary>chroot()</primary></indexterm>
|
||||
|
||||
<para>Традиционно используемым методом ограничения процесса
|
||||
является использование системного вызова <function>chroot()</function>.
|
||||
Этот системный вызов меняет корневой каталог, относительно которого
|
||||
определяются все остальные пути в самом процессе и всех порожденных ими
|
||||
|
|
@ -312,6 +406,8 @@ int main() {
|
|||
<sect2>
|
||||
<title>Функциональность джейлов (jail) во FreeBSD</title>
|
||||
|
||||
<indexterm><primary>jail</primary></indexterm>
|
||||
|
||||
<para>Концепция джейлов (Jail) расширяет возможности
|
||||
<function>chroot()</function>, ограничивая власть администратора
|
||||
созданием настоящих `виртуальных серверов'. Как только тюремная
|
||||
|
|
@ -337,16 +433,16 @@ int main() {
|
|||
<function>setregid</function> и
|
||||
<function>setlogin</function></simpara>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><simpara>Устанавливать ограничения на использование
|
||||
ресурсов при помощи
|
||||
<function>setrlimit</function></simpara>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><simpara>Модифицировать некоторые sysctl-переменные
|
||||
(kern.hostname)</simpara>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><simpara><function>chroot()</function></simpara></listitem>
|
||||
|
||||
<listitem><simpara>Устанавливать следующие флаги на vnode:
|
||||
|
|
@ -358,7 +454,7 @@ int main() {
|
|||
доступа к файлу, изменять его владельца, группу, размер, время
|
||||
доступа и модификации.</simpara>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><simpara>Осуществлять привязку к привилегированному порту
|
||||
в области портов Интернет (порты с номерами < 1024)</simpara>
|
||||
</listitem>
|
||||
|
|
@ -374,38 +470,46 @@ int main() {
|
|||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Возможности процессов POSIX.1e</title>
|
||||
<title>&posix;.1e возможности процессов</title>
|
||||
|
||||
<para>Posix выпустил рабочий документ, который добавляет аудит событий,
|
||||
<indexterm><primary>POSIX.1e возможности процессов</primary></indexterm>
|
||||
<indexterm><primary>TrustedBSD</primary></indexterm>
|
||||
|
||||
<para>&posix; выпустила рабочий документ, который добавляет аудит событий,
|
||||
списки управления доступом, тонко настраиваемые привилегии, метки
|
||||
информации и жесткое управление доступом.</para>
|
||||
|
||||
<para>Этот документ находится в работе и находится в центре внимания
|
||||
проекта <ulink url="http://www.trustedbsd.org">TrustedBSD</ulink>.
|
||||
проекта <ulink url="http://www.trustedbsd.org/">TrustedBSD</ulink>.
|
||||
Некоторая начальная функциональность уже была добавлена во
|
||||
FreeBSD-current (cap_set_proc(3)).</para>
|
||||
&os.current; (cap_set_proc(3)).</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<sect1 id="secure-trust">
|
||||
<title>Доверие</title>
|
||||
|
||||
<para>Приложение никогда не должно полагать, что среда пользователя
|
||||
безопасна. Сюда включается (но этим не ограничено): ввод пользователя,
|
||||
сигналы, переменные среды, ресурсы, IPC, отображаемая в файл память,
|
||||
сигналы, переменные среды, ресурсы, IPC, отображаемая в файл память (mmap),
|
||||
рабочий каталог файловой системы, дескрипторы файлов, число открытых
|
||||
файлов и прочее.</para>
|
||||
|
||||
<indexterm><primary>позитивная фильтрация</primary></indexterm>
|
||||
<indexterm><primary>подтверждение правильности данных</primary></indexterm>
|
||||
|
||||
<para>Никогда не думайте, что сможете предусмотреть все формы
|
||||
неправильного ввода, который может дать пользователь. Вместо этого
|
||||
ваше приложение должно осуществлять позитивную фильтрацию, пропуская
|
||||
только конечное множество возможных вариантов ввода, которые вы
|
||||
считаете безопасными. Неполная праверка данных была причиной многих
|
||||
считаете безопасными. Неполная проверка данных была причиной многих
|
||||
нарушений защиты, особенно CGI-скриптов на веб-сайтах. Для имен файлов
|
||||
вам нужно уделять особое внимание путям ("../", "/"), символическим
|
||||
ссылкам и экранирующим символам оболочки.</para>
|
||||
|
||||
<para>В perl имеется такая очень полезная вещь, как "безупречный" (taint)
|
||||
<indexterm><primary>Безупречный режим в Perl</primary></indexterm>
|
||||
|
||||
<para>В Perl имеется такая очень полезная вещь, как "безупречный" (taint)
|
||||
режим, который можно использовать для запрещения скриптам использовать
|
||||
данные, порожденные вне программы, не безопасным способом. Этот режим
|
||||
проверяет аргументы командной строки, переменные окружения, информацию
|
||||
|
|
@ -414,7 +518,7 @@ int main() {
|
|||
<function>getpwxxx()</function> и весь файловый ввод.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<sect1 id="secure-race-conditions">
|
||||
<title>Неожиданное поведение</title>
|
||||
|
||||
<para>Неожиданное поведение - это аномальное поведение, вызванное
|
||||
|
|
@ -422,6 +526,15 @@ int main() {
|
|||
событий. Другими словами, программист неправильно предположил, что
|
||||
некоторое событие всегда случается перед другим.</para>
|
||||
|
||||
<indexterm><primary>неожиданное поведение</primary>
|
||||
<secondary>сигналы</secondary></indexterm>
|
||||
|
||||
<indexterm><primary>неожиданное поведение</primary>
|
||||
<secondary>проверки на доступ</secondary></indexterm>
|
||||
|
||||
<indexterm><primary>неожиданное поведение</primary>
|
||||
<secondary>открытия файлов</secondary></indexterm>
|
||||
|
||||
<para>Некоторые из широко распространенных причин возникновения таких
|
||||
проблем являются сигналы, проверки доступа и открытия файлов. Сигналы
|
||||
по своей природе являются асинхронными событиями, так что по отношению
|
||||
|
|
@ -436,4 +549,4 @@ int main() {
|
|||
<function>open()</function> во избежание беспорядочных вызовов
|
||||
<function>chmod()</function>.</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue