old-www/HOWTO/Secure-Programs-HOWTO/protect-secrets.html

245 lines
6.4 KiB
HTML

<HTML
><HEAD
><TITLE
>Specially Protect Secrets (Passwords and Keys) in User Memory</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Secure Programming for Linux and Unix HOWTO"
HREF="index.html"><LINK
REL="UP"
TITLE="Special Topics"
HREF="special.html"><LINK
REL="PREVIOUS"
TITLE="Random Numbers"
HREF="random-numbers.html"><LINK
REL="NEXT"
TITLE="Cryptographic Algorithms and Protocols"
HREF="crypto.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Secure Programming for Linux and Unix HOWTO</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="random-numbers.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Chapter 11. Special Topics</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="crypto.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="PROTECT-SECRETS"
></A
>11.4. Specially Protect Secrets (Passwords and Keys) in User Memory</H1
><P
>If your application must handle passwords or non-public keys
(such as session keys, private keys, or secret keys), try to hide them
and overwrite them immediately after using them so they have minimal exposure.</P
><P
>Systems such as Linux support the mlock() and mlockall() calls to
keep memory from being paged to disk (since someone might acquire the
kep later from the swap file).
Note that on Linux this is a privileged system call, which causes its
own issues (do I grant the program superuser privileges so it can call
mlock, if it doesn't need them otherwise?).</P
><P
>Also, if your program handles such secret values, be sure to disable creating
core dumps (via ulimit). Otherwise, an attacker may be able to halt the
program and find the secret value in the data dump.</P
><P
>Beware - normally processes can monitor other processes through
the calls for debuggers (e.g., via ptrace(2) and the /proc pseudo-filesystem)
[Venema 1996]
Kernels usually protect against these monitoring routines if the process is
setuid or setgid
(on the few ancient ones that don't, there really isn't a good way to
defend yourself other than upgrading).
Thus, if your process manages secret values, you probably should make it
setgid or setuid (to a different unprivileged group or user) to forceably
inhibit this kind of monitoring.
Unless you need it to be setuid, use setgid (since this grants fewer
privileges).</P
><P
>Then there's the problem of being able to actually overwrite the value, which
often becomes language and compiler specific.
In many languages, you need to make sure that you store
such information in mutable locations, and then overwrite those locations.
For example,
in Java, don't use the type String to store a password because Strings are
immutable (they will not be overwritten until garbage-collected and
then reused, possibly a far time in the future).
Instead, in Java use char[] to store a password, so it can be
immediately overwritten.
In Ada, use type String (an array of characters),
and not type Unbounded_String, to make sure
that you have control over the contents.</P
><P
>In many languages (including C and C++),
be careful that the compiler doesn't optimize away the "dead code"
for overwriting the value - since in this case it's not dead code.
Many compilers, including many C/C++ compilers, remove writes
to stores that are no longer used - this is often referred to as
"dead store removal."
Unfortunately, if the write is really to overwrite the value of a secret,
this means that code that appears to be correct will be silently discareded.
Ada provides the pragma Inspection_Point; place this after the
code erasing the memory, and that way you can be certain that
the object containing the secret will really be erased
(and that the the overwriting won't be optimized away).</P
><P
>A Bugtraq post by Andy Polyakov (November 7, 2002) reported that
the C/C++ compilers gcc version 3 or higher, SGI MIPSpro, and the Microsoft
compilers eliminated simple inlined calls to memset
intended to overwrite secrets.
This is allowed by the C and C++ standards.
Other C/C++ compilers (such as gcc less than version 3) preserved the inlined
call to memset at all optimization levels, showing that the issue
is compiler-specific.
Simply declaring that the destination data is volatile doesn't
help on all compilers; both the MIPSpro and Microsoft compilers
ignored simple "volatilization".
Simply "touching" the first byte of the secret data doesn't help either;
he found that the MIPSpro and GCC&#62;=3 cleverly nullify only the first byte
and leave the rest intact (which is actually quite clever - the problem
is that the compiler's cleverness is interfering with our goals).
One approach that
seems to work on all platforms is to
write your own implementation of memset with internal "volatilization"
of the first argument (this code is based on a
<A
HREF="http://online.securityfocus.com/archive/82/298061/2002-10-27/2002-11-02/0"
TARGET="_top"
>workaround proposed by Michael Howard</A
>):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="PROGRAMLISTING"
> void *guaranteed_memset(void *v,int c,size_t n)
{ volatile char *p=v; while (n--) *p++=c; return v; }</PRE
></FONT
></TD
></TR
></TABLE
>
Then place this definition into an external file to force the function to
be external (define the function in a corresponding .h file, and #include
the file in the callers, as is usual).
This approach appears to be safe
at any optimization level (even if the function gets inlined).</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="random-numbers.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="crypto.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Random Numbers</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="special.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Cryptographic Algorithms and Protocols</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>