httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Slemko <>
Subject don't tell me this HPUX bogon is true...
Date Mon, 20 Apr 1998 02:19:29 GMT

>From: (John Cochran)
>Newsgroups: comp.unix.programmer
>Subject: Re: Secure fopen() algorithm wanted
>Date: 19 Apr 1998 21:45:28 -0400
>Organization: Express Access Online Communications, Greenbelt, MD USA
>Lines: 95
>Message-ID: <6he9bo$>
>References: <6gv80b$> <>
>Xref: comp.unix.programmer:59034     

In article <>,
Lawrence Kirby <> wrote:
>In article <>
>           Casper.Dik@Holland.Sun.Com
>           "Casper H.S. Dik - Network Security Engineer" writes:
>>If all you want is to safely create files, use:
>>        int fd = open(path, O_CREAT|O_EXCL|O_..., 0600);
>>which will not follow symbolic links and will fail if the file exists.
Not entirely true...
Take a look at the HP-UX prior to version 9.07. That version of Unix would
allow an open with O_EXCLIO_CREAT through a symbolic link to a file that
didn't exist. This caused a security flaw in sendmail that was corrected
in version 8.8.6. It also violates one of my requirements. Namely that I
want the same semanitics as for fopen(). This includes the possibility of
several copies of the same root privleged program accessing the same file.

>>If you want to open existing files, then it's more difficult,
>>        first you open w/ O_CREAT|O_EXCL
>>        if this fails, you try:
>>                open(..   *NO* O_CREAT, *NO* O_EXCL)
>I'm not sure that really buys you much, there's still a race condition
>between the 2 open calls.
>>        then you can lstat/fstat at your leisure and check link
>>        counts, st_mode, st_ino and st_dev.
>That is the key - open the file then test and maybe abort and close it.
>With that approach you can still use fopen().
>1. fopen() the file
>2. Call lstat() with the file name and check that it isn't a symlink,
>   and that st_mode and st_nlink are appropriate.
>3. Get the fd using fileno().
>4. Call fstat() with the fd and check st_dev and st_ino against the lstat()
>   values to ensure that they are referring to the same file.
>If any of the steps fail close the file (if necessary) and return a null
That approach seems the best for those cases where the file is being
either read from or being appended to. I'll admit that it might cause the
file timestamps to be altered, however the file contents shouldn't be
altered and in the case of read, the file contents shouldn't be revealed.

fopen(..., "r")
/* Code to test if symbolic or hard link. If a link, close file */
   1. File does not exist
      open fails, no security exposure
   2. File exists, not a link
      open succeeds, no security exposure
   3. File exists, is a link
      open succeeds, link detected prior to reading, file closed.
      file accessed timestamp modified, but file contents not revealed.
      No security exposure.

fopen(..., "a")
   1. File does not exist.
      file created. By definition, not a symbolic or hard link.
      no security exposure.
   2. File exists, not a link
      file opened, passes tests, not security exposure
   3. File exists, is a link
      file opened, link detected, file closed prior to appending data to
      file. file timestamps may be modified, however, file contents unaltered
      no security exposure.

the fopen(..., "w") case however causes the most problems. I can not test
after performing the fopen() because I don't know it the file truncation
semantics is performed via an unlink() or a ftruncate(). If it's performed
via an unlink() then everything's OK. If performed via a ftruncate(), then
it results in an unrecoverable alteration of a file. I'm leaning towards
the following action for fopen() with a mode of "w".
    1. Create a file in the same directory with an unique name.
    2. Rename the file to match the desired filename.

The semantics of the rename will cause a filename with the same name to
be unlinked. So if an attacker attempted to use a link to alias to a file
that shouldn't be modified or examined, the unlink will remove the link.

John Cochran

View raw message