Add ~40 index terms to this chapter. A couple of minor tweaks to
doc.docbook.mk are needed for this to work with GEN_INDEX defined but that will be committed soon enough. Reviewed by: -doc (months ago)
This commit is contained in:
parent
6296820335
commit
acd6619ae0
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=9451
2 changed files with 214 additions and 2 deletions
en_US.ISO8859-1/books/developers-handbook/secure
en_US.ISO_8859-1/books/developers-handbook/secure
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue