We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 33101
    • 46 Posts

    I found a script for forcing a window to allow people to download a known filetype and I’m looking into the security of passing the variable. I have a filename to an audio file that people can click on to listen in their browser or a "download" link and I was going to pass it like this
    dl.php?file=$filename

    Is the following sufficient to protect against misuse?

    $filename = $_GET['file'];
    // do filename checking
    
    if (ereg('\.\.', $filename))
        die('bad filename'); //die, do not process


    If not, any other suggestions? Thank you,

      • 31337
      • 258 Posts
      Hex encoded characters and UTF-8 characters can be used to bypass this test and trick the browser into downloading files it shouldn’t. What you should is first normalized any data you get, then filter out anything that’s not [A-Za-z0-9] before a ’.’ and then prepend a known path to $filename to avoid getting out of known directories.
        • 33101
        • 46 Posts
        Can you tell me what I would type in to bypass it? I tried typing in
        /%2E%2E/ instead of /../ and the ereg caught it. I’m not sure how to pass unicode in the querystring.

          • 31337
          • 258 Posts
          Rather than trying to filter out bad characters (which is next to impossible), have a list of "safe" characters, and anything that’s not in that, reject. That way you don’t have to worry about specific attack vectors.
            • 33101
            • 46 Posts
            Here’s what I’ve come up with.

            I call the script like this:
            /dl.php/audiofiles/goodstuff/great.mp3

            // use PATH_INFO so filename looks real
            $filename = $_SERVER['PATH_INFO'];
            
            $realfile=realpath($_SERVER['DOCUMENT_ROOT'].$filename);
            
            $subdir="audiofiles";
            
            if (strpos($realfile,$_SERVER['DOCUMENT_ROOT']."/".$subdir)===FALSE)
                die('bad filename'); //die, do not process
            
            // send out file as content-disposition...
            


            I’m not sure yet whether I even need to do the realpath check if I use the path_info but I put it in while I was still passing the filename as a GET variable.

            Does anyone see any problems with this?

            Thanks,