[13734] in bugtraq

home help back first fref pref prev next nref lref last post

Re: Perl's alleged tempfile vulnerabilities

daemon@ATHENA.MIT.EDU (Lupe Christoph)
Mon Feb 7 17:23:54 2000

Mail-Followup-To: Tom Christiansen <tchrist@CHTHON.PERL.COM>,
                  BUGTRAQ@SECURITYFOCUS.COM
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Message-Id:  <20000206103516.O12877@alanya.lupe-christoph.de>
Date:         Sun, 6 Feb 2000 10:35:17 +0100
Reply-To: Lupe Christoph <lupe@LUPE-CHRISTOPH.DE>
From: Lupe Christoph <lupe@LUPE-CHRISTOPH.DE>
X-To:         Tom Christiansen <tchrist@CHTHON.PERL.COM>
To: BUGTRAQ@SECURITYFOCUS.COM
In-Reply-To:  <24194.949672117@chthon>; from tchrist@CHTHON.PERL.COM on Fri,
              Feb 04, 2000 at 06:48:37AM -0700

On Friday, 2000-02-04 at 06:48:37 -0700, Tom Christiansen wrote:

> ...
> 	CODE:
>     #ifdef PerlIO
> 	    fp = PerlIO_tmpfile();
>     #else
> 	    fp = tmpfile();
>     #endif
> ...

> Which is just calling the standard POSIX tmpfile() function.  Well,
> sometimes.  If you use the Perl I/O abstraction, then you get either
> the real tmpfile(), or under sfio, some sftmp(0) thingie that I
> know nothing about.  The only hole I see is in my ignorance of the
> possible sfio-related sftmp(0) call.  Enlightenment in this area
> is welcome.

--- Also sprach Tom Christiansen ---

Both sfio97 and sfio98 have (except for one teensy change) the same
sftmp.c. sftmp.c has this file creation code:

        file = NIL(char*); fd = -1;
        for(t = 0; t < 10; ++t)
        {       /* compute a random name */
#if !_PACKAGE_ast
                static ulong    Key, A;
                if(A == 0 || t > 0)     /* get a quasi-random coefficient */
                {       reg int r;
                        A = (ulong)time(NIL(time_t*)) ^ (((ulong)(&t)) >> 3);
                        if(Key == 0)
                                Key = (A >> 16) | ((A&0xffff)<<16);
                        A ^= Key;
                        if((r = (A-1) & 03) != 0) /* Knuth vol.2, page.16, Thm.A */
                                A += 4-r;
                }

                Key = A*Key + 987654321;
                file = sfprints("%s/sf%3.3.32lu.%3.3.32lu",
                                Tmpcur[0], (Key>>15)&0x7fff, Key&0x7fff);
#else
                file = pathtmp(file,NiL,"sf",NiL);
#endif /*!_PACKAGE_ast*/

                if(!file)
                        return -1;
#if _has_oflags
                if((fd = open(file,O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY,SF_CREATMODE)) >= 0)
                        break;
#else
                if((fd = open(file,O_RDONLY)) >= 0)
                {       /* file already exists */
                        CLOSE(fd);
                        fd = -1;
                }
                else if((fd = creat(file,SF_CREATMODE)) >= 0)
                {       /* reopen for read and write */
                        CLOSE(fd);
                        if((fd = open(file,O_RDWR)) >= 0)
                                break;

                        /* don't know what happened but must remove file */
                        while(remove(file) < 0 && errno == EINTR)
                                errno = 0;
                }
#endif
        }

        if(fd >= 0)
                _rmtmp(f, file);

I suppose ast is a Win32 matter *I* know nothing about.

So sfio goes to some length to randomize the filename, and then insists
on creating a new file. The randomization seems to be reasonably safe
from denial of service. sftmp can also use TMPPATH and TMPDIR.

sftmp will remove the file (_rmtmp) immediately unless _tmp_rmfail is
defined. I found no #define for that in the sfio98 code. (?)

Lupe Christoph
--
| lupe@lupe-christoph.de       |        http://free.prohosting.com/~lupe |
| "jryy vg ybbxf yvxr gur l2x oht qvqa'g erne vg'f htyl urnq." "lrc. gur |
| qbbzfnlref unir orra cebira jebat lrg ntnva."  ....  "qvq lbh frr gung |
| gbb?" "ubhfgba. jr unir n ceboyrz."           User Friendly 2000-01-01 |

home help back first fref pref prev next nref lref last post