diff --git a/en_US.ISO8859-1/books/developers-handbook/secure/chapter.sgml b/en_US.ISO8859-1/books/developers-handbook/secure/chapter.sgml index b6530bd43a..651cfa7d57 100644 --- a/en_US.ISO8859-1/books/developers-handbook/secure/chapter.sgml +++ b/en_US.ISO8859-1/books/developers-handbook/secure/chapter.sgml @@ -1,7 +1,7 @@ <!-- The FreeBSD Documentation Project - $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml,v 1.3 2001/04/18 19:33:27 dd Exp $ + $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml,v 1.4 2001/05/14 03:15:19 murray Exp $ --> <chapter id="secure"> @@ -40,26 +40,61 @@ <para>Buffer Overflows have been around since the very beginnings of the Von-Neuman <xref linkend="COD"> architecture. + + <indexterm><primary>buffer overflow</primary></indexterm> + <indexterm><primary>Von-Neuman</primary></indexterm> + They first gained widespread notoriety in 1988 with the Morris Internet worm. Unfortunately, the same basic attack remains + + <indexterm><primary>Morris Internet worm</primary></indexterm> + effective today. Of the 17 CERT security advisories of 1999, 10 + + <indexterm> + <primary>CERT</primary><secondary>security advisories</secondary> + </indexterm> + of them were directly caused by buffer-overflow software bugs. By far the most common type of buffer overflow attack is based on corrupting the stack.</para> + <indexterm><primary>stack</primary></indexterm> + <indexterm><primary>arguments</primary></indexterm> + <para>Most modern computer systems use a stack to pass arguments to procedures and to store local variables. A stack is a last in first out (LIFO) buffer in the high memory area of a process image. When a program invokes a function a new "stack frame" is + + <indexterm><primary>LIFO</primary></indexterm> + <indexterm> + <primary>process image</primary> + <secondary>stack pointer</secondary> + </indexterm> + created. This stack frame consists of the arguments passed to the function as well as a dynamic amount of local variable space. The "stack pointer" is a register that holds the current + + <indexterm><primary>stack frame</primary></indexterm> + <indexterm><primary>stack pointer</primary></indexterm> + location of the top of the stack. Since this value is constantly changing as new values are pushed onto the top of the stack, many implementations also provide a "frame pointer" that is located near the beginning of a stack frame so that local variables can more easily be addressed relative to this value. <xref linkend="COD"> The return address for function + + <indexterm><primary>frame pointer</primary></indexterm> + <indexterm> + <primary>process image</primary> + <secondary>frame pointer</secondary> + </indexterm> + <indexterm><primary>return address</primary></indexterm> + <indexterm><primary>stack-overflow</primary></indexterm> + calls is also stored on the stack, and this is the cause of stack-overflow exploits since overflowing a local variable in a function can overwrite the return address of that function, @@ -157,12 +192,25 @@ int main() { stack-overflows is to always use length restricted memory and string copy functions. <function>strncpy</function> and <function>strncat</function> are part of the standard C library. + + <indexterm> + <primary>string copy functions</primary> + <secondary>strncpy</secondary> + </indexterm> + <indexterm> + <primary>string copy functions</primary> + <secondary>strncat</secondary> + </indexterm> + These functions accept a length value as a parameter which should be no larger than the size of the destination buffer. These functions will then copy up to `length' bytes from the source to the destination. However there are a number of problems with these functions. Neither function guarantees NUL termination if the size of the input buffer is as large as the + + <indexterm><primary>NUL termination</primary></indexterm> + destination. The length parameter is also used inconsistently between strncpy and strncat so it is easy for programmers to get confused as to their proper usage. There is also a significant @@ -172,6 +220,9 @@ int main() { specified.</para> <para>In OpenBSD, another memory copy implementation has been + + <indexterm><primary>OpenBSD</primary></indexterm> + created to get around these problem. The <function>strlcpy</function> and <function>strlcat</function> functions guarantee that they will always null terminate the @@ -181,8 +232,21 @@ int main() { <function>strlcat</function> instructions have been in FreeBSD since 3.5.</para> + <indexterm> + <primary>string copy functions</primary> + <secondary>strlcpy</secondary> + </indexterm> + + <indexterm> + <primary>string copy functions</primary> + <secondary>strlcat</secondary> + </indexterm> + <sect3><title>Compiler based run-time bounds checking</title> + <indexterm><primary>bounds checking</primary> + <secondary>compiler-based</secondary></indexterm> + <para>Unfortunately there is still a very large assortment of code in public use which blindly copies memory around without using any of the bounded copy routines we just discussed. @@ -190,6 +254,9 @@ int main() { add-ons and libraries exist to do Run-time bounds checking in C/C++.</para> + <indexterm><primary>StackGuard</primary></indexterm> + <indexterm><primary>gcc</primary></indexterm> + <para>StackGuard is one such add-on that is implemented as a small patch to the gcc code generator. From the StackGuard website, http://immunix.org/stackguard.html : @@ -212,6 +279,8 @@ int main() { returns."</para></blockquote> </para> + <indexterm><primary>buffer overflow</primary></indexterm> + <para>Recompiling your application with StackGuard is an effective means of stopping most buffer-overflow attacks, but it can still be compromised.</para> @@ -220,6 +289,11 @@ int main() { <sect3><title>Library based run-time bounds checking</title> + <indexterm> + <primary>bounds checking</primary> + <secondary>library-based</secondary> + </indexterm> + <para>Compiler-based mechanisms are completely useless for binary-only software for which you cannot recompile. For these situations there are a number of libraries which @@ -248,12 +322,23 @@ int main() { <sect1><title>SetUID issues</title> + <indexterm><primary>seteuid</primary></indexterm> + <para>There are at least 6 different IDs associated with any given process. Because of this you have to be very careful with the access that your process has at any given time. In particular, all seteuid applications should give up their privileges as soon as it is no longer required.</para> + <indexterm> + <primary>user IDs</primary> + <secondary>real user ID</secondary> + </indexterm> + <indexterm> + <primary>user IDs</primary> + <secondary>effective user ID</secondary> + </indexterm> + <para>The real user ID can only be changed by a superuser process. The <application>login</application> program sets this when a user initially logs in and it is seldom changed.</para> @@ -270,6 +355,8 @@ int main() { <sect1 id="chroot"><title>Limiting your program's environment</title> + <indexterm><primary>chroot()</primary></indexterm> + <para>The traditional method of restricting access to a process is with the <function>chroot()</function> system call. This system call changes the root directory from which all other @@ -297,6 +384,8 @@ int main() { <sect2><title>FreeBSD's jail functionality</title> + <indexterm><primary>jail</primary></indexterm> + <para>The concept of a Jail extends upon the <function>chroot()</function> by limiting the powers of the superuser to create a true `virtual server'. Once a prison is @@ -344,6 +433,9 @@ int main() { <sect2><title>POSIX.1e Process Capabilities</title> + <indexterm><primary>POSIX.1e Process Capabilities</primary></indexterm> + <indexterm><primary>TrustedBSD</primary></indexterm> + <para>Posix has released a working draft that adds event auditing, access control lists, fine grained privileges, information labeling, and mandatory access control.</para> @@ -364,6 +456,9 @@ int main() { resources, IPC, mmaps, the file system working directory, file descriptors, the # of open files, etc.</para> + <indexterm><primary>positive filtering</primary></indexterm> + <indexterm><primary>data validation</primary></indexterm> + <para>You should never assume that you can catch all forms of invalid input that a user might supply. Instead, your application should use positive filtering to only allow a @@ -373,6 +468,8 @@ int main() { extra careful about paths ("../", "/"), symbolic links, and shell escape characters.</para> + <indexterm><primary>Perl Taint mode</primary></indexterm> + <para>Perl has a really cool feature called "Taint" mode which can be used to prevent scripts for using data derived outside the program in an unsafe way. This mode will check command line @@ -390,6 +487,15 @@ int main() { other words, a programmer incorrectly assumed that a particular event would always happen before another.</para> + <indexterm><primary>race conditions</primary> + <secondary>signals</secondary></indexterm> + + <indexterm><primary>race conditions</primary> + <secondary>access checks</secondary></indexterm> + + <indexterm><primary>race conditions</primary> + <secondary>file opens</secondary></indexterm> + <para>Some of the common causes of race conditions are signals, access checks, and file opens. Signals are asynchronous events by nature so special care must be taken in dealing with them. diff --git a/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml b/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml index b6530bd43a..651cfa7d57 100644 --- a/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml +++ b/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml @@ -1,7 +1,7 @@ <!-- The FreeBSD Documentation Project - $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml,v 1.3 2001/04/18 19:33:27 dd Exp $ + $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/secure/chapter.sgml,v 1.4 2001/05/14 03:15:19 murray Exp $ --> <chapter id="secure"> @@ -40,26 +40,61 @@ <para>Buffer Overflows have been around since the very beginnings of the Von-Neuman <xref linkend="COD"> architecture. + + <indexterm><primary>buffer overflow</primary></indexterm> + <indexterm><primary>Von-Neuman</primary></indexterm> + They first gained widespread notoriety in 1988 with the Morris Internet worm. Unfortunately, the same basic attack remains + + <indexterm><primary>Morris Internet worm</primary></indexterm> + effective today. Of the 17 CERT security advisories of 1999, 10 + + <indexterm> + <primary>CERT</primary><secondary>security advisories</secondary> + </indexterm> + of them were directly caused by buffer-overflow software bugs. By far the most common type of buffer overflow attack is based on corrupting the stack.</para> + <indexterm><primary>stack</primary></indexterm> + <indexterm><primary>arguments</primary></indexterm> + <para>Most modern computer systems use a stack to pass arguments to procedures and to store local variables. A stack is a last in first out (LIFO) buffer in the high memory area of a process image. When a program invokes a function a new "stack frame" is + + <indexterm><primary>LIFO</primary></indexterm> + <indexterm> + <primary>process image</primary> + <secondary>stack pointer</secondary> + </indexterm> + created. This stack frame consists of the arguments passed to the function as well as a dynamic amount of local variable space. The "stack pointer" is a register that holds the current + + <indexterm><primary>stack frame</primary></indexterm> + <indexterm><primary>stack pointer</primary></indexterm> + location of the top of the stack. Since this value is constantly changing as new values are pushed onto the top of the stack, many implementations also provide a "frame pointer" that is located near the beginning of a stack frame so that local variables can more easily be addressed relative to this value. <xref linkend="COD"> The return address for function + + <indexterm><primary>frame pointer</primary></indexterm> + <indexterm> + <primary>process image</primary> + <secondary>frame pointer</secondary> + </indexterm> + <indexterm><primary>return address</primary></indexterm> + <indexterm><primary>stack-overflow</primary></indexterm> + calls is also stored on the stack, and this is the cause of stack-overflow exploits since overflowing a local variable in a function can overwrite the return address of that function, @@ -157,12 +192,25 @@ int main() { stack-overflows is to always use length restricted memory and string copy functions. <function>strncpy</function> and <function>strncat</function> are part of the standard C library. + + <indexterm> + <primary>string copy functions</primary> + <secondary>strncpy</secondary> + </indexterm> + <indexterm> + <primary>string copy functions</primary> + <secondary>strncat</secondary> + </indexterm> + These functions accept a length value as a parameter which should be no larger than the size of the destination buffer. These functions will then copy up to `length' bytes from the source to the destination. However there are a number of problems with these functions. Neither function guarantees NUL termination if the size of the input buffer is as large as the + + <indexterm><primary>NUL termination</primary></indexterm> + destination. The length parameter is also used inconsistently between strncpy and strncat so it is easy for programmers to get confused as to their proper usage. There is also a significant @@ -172,6 +220,9 @@ int main() { specified.</para> <para>In OpenBSD, another memory copy implementation has been + + <indexterm><primary>OpenBSD</primary></indexterm> + created to get around these problem. The <function>strlcpy</function> and <function>strlcat</function> functions guarantee that they will always null terminate the @@ -181,8 +232,21 @@ int main() { <function>strlcat</function> instructions have been in FreeBSD since 3.5.</para> + <indexterm> + <primary>string copy functions</primary> + <secondary>strlcpy</secondary> + </indexterm> + + <indexterm> + <primary>string copy functions</primary> + <secondary>strlcat</secondary> + </indexterm> + <sect3><title>Compiler based run-time bounds checking</title> + <indexterm><primary>bounds checking</primary> + <secondary>compiler-based</secondary></indexterm> + <para>Unfortunately there is still a very large assortment of code in public use which blindly copies memory around without using any of the bounded copy routines we just discussed. @@ -190,6 +254,9 @@ int main() { add-ons and libraries exist to do Run-time bounds checking in C/C++.</para> + <indexterm><primary>StackGuard</primary></indexterm> + <indexterm><primary>gcc</primary></indexterm> + <para>StackGuard is one such add-on that is implemented as a small patch to the gcc code generator. From the StackGuard website, http://immunix.org/stackguard.html : @@ -212,6 +279,8 @@ int main() { returns."</para></blockquote> </para> + <indexterm><primary>buffer overflow</primary></indexterm> + <para>Recompiling your application with StackGuard is an effective means of stopping most buffer-overflow attacks, but it can still be compromised.</para> @@ -220,6 +289,11 @@ int main() { <sect3><title>Library based run-time bounds checking</title> + <indexterm> + <primary>bounds checking</primary> + <secondary>library-based</secondary> + </indexterm> + <para>Compiler-based mechanisms are completely useless for binary-only software for which you cannot recompile. For these situations there are a number of libraries which @@ -248,12 +322,23 @@ int main() { <sect1><title>SetUID issues</title> + <indexterm><primary>seteuid</primary></indexterm> + <para>There are at least 6 different IDs associated with any given process. Because of this you have to be very careful with the access that your process has at any given time. In particular, all seteuid applications should give up their privileges as soon as it is no longer required.</para> + <indexterm> + <primary>user IDs</primary> + <secondary>real user ID</secondary> + </indexterm> + <indexterm> + <primary>user IDs</primary> + <secondary>effective user ID</secondary> + </indexterm> + <para>The real user ID can only be changed by a superuser process. The <application>login</application> program sets this when a user initially logs in and it is seldom changed.</para> @@ -270,6 +355,8 @@ int main() { <sect1 id="chroot"><title>Limiting your program's environment</title> + <indexterm><primary>chroot()</primary></indexterm> + <para>The traditional method of restricting access to a process is with the <function>chroot()</function> system call. This system call changes the root directory from which all other @@ -297,6 +384,8 @@ int main() { <sect2><title>FreeBSD's jail functionality</title> + <indexterm><primary>jail</primary></indexterm> + <para>The concept of a Jail extends upon the <function>chroot()</function> by limiting the powers of the superuser to create a true `virtual server'. Once a prison is @@ -344,6 +433,9 @@ int main() { <sect2><title>POSIX.1e Process Capabilities</title> + <indexterm><primary>POSIX.1e Process Capabilities</primary></indexterm> + <indexterm><primary>TrustedBSD</primary></indexterm> + <para>Posix has released a working draft that adds event auditing, access control lists, fine grained privileges, information labeling, and mandatory access control.</para> @@ -364,6 +456,9 @@ int main() { resources, IPC, mmaps, the file system working directory, file descriptors, the # of open files, etc.</para> + <indexterm><primary>positive filtering</primary></indexterm> + <indexterm><primary>data validation</primary></indexterm> + <para>You should never assume that you can catch all forms of invalid input that a user might supply. Instead, your application should use positive filtering to only allow a @@ -373,6 +468,8 @@ int main() { extra careful about paths ("../", "/"), symbolic links, and shell escape characters.</para> + <indexterm><primary>Perl Taint mode</primary></indexterm> + <para>Perl has a really cool feature called "Taint" mode which can be used to prevent scripts for using data derived outside the program in an unsafe way. This mode will check command line @@ -390,6 +487,15 @@ int main() { other words, a programmer incorrectly assumed that a particular event would always happen before another.</para> + <indexterm><primary>race conditions</primary> + <secondary>signals</secondary></indexterm> + + <indexterm><primary>race conditions</primary> + <secondary>access checks</secondary></indexterm> + + <indexterm><primary>race conditions</primary> + <secondary>file opens</secondary></indexterm> + <para>Some of the common causes of race conditions are signals, access checks, and file opens. Signals are asynchronous events by nature so special care must be taken in dealing with them.