这个PHP函数是否保护文件横向? [英] Does this PHP function protect against file transversal?

查看:85
本文介绍了这个PHP函数是否保护文件横向?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网址,向我的用户提供受保护的文件。



文件名在上传文件时由我的应用程序重写,不管名称是什么,并存储在我的数据库中。所以我知道它永远不会包含一个/或..



文件名是:USER_ID_RANDOMMD5.FILE_EXT
USER_ID=当前登录的用户ID和RANDOM MD5。



ie 5_ji3uc237uckj92d0jf3932t09ut93f2.pdf



这是我为此文件提供的函数:

  function user_file($ file_name =)
{
if($ file_name)
{
//确保没有有趣的商家名称:
$ file_name = str_replace '..','',$ file_name);
$ file_name = str_replace('/','',$ file_name);

//检查用户是否被允许访问此文件
$ user_id = substr($ file_name,0,strpos($ file_name,_));

//现在做检查用户登录的逻辑,用户是文件的所有者
(($ this-> ion_auth-> logged_in())&& ($ user_id === $ this-> user-> id))
{
//通过readfile()提供文件
}
}
}

问题:这是确保没有

编辑1: ion_auth是我的身份验证库,而$可以访问其他文件等。 this-> user-> id是存储在我的构造中的用户ID



编辑2:用户文件存储在public_html因此只能通过我的应用程序访问AFAIK



编辑3:我改进的代码,使用来自Amber的想法,考虑到我需要的事实为了适应不同的文件扩展名,我将尝试避免数据库命中:

  function user_files($ file_name = )
{
//出于安全考虑,检查文件名是否正确
//这将检查32位md5值,后跟一个单独的。,后跟一个3-4扩展(只有az)
if(preg_match('^ [A-Za-z0-9] {32} + [。] {1} [A-Za-z] {3,4} ,$ file_name))
{
//现在检查用户是否登录
if($ this-> ion_auth-> logged_in())
{
//将请求重写到我的服务器上的路径 - 并将user_id附加到文件名
//这确保用户只能访问他们自己的文件,他们上传
//因为他们的用户ID在上传期间附加到文件名!
$ file = MY_SECURE_FOLDER。$ this-> user-> id .'_'。$ file_name;

//现在检查文件是否存在
if(file_exists($ file))
{
//服务文件
header类型:'.get_mime_by_extension($ file));
readfile($ file);
}
}
}
}


解决方案

更好的想法:让用户提供MD5,并自己构造文件名。这样你不必做任何疯狂的检查用户输入与文件名 - 你可以确保MD5是一个40个字符的字符串 [0-9a-f] ,然后你就是好的。


I have a URL which will serve a protected file to my user.

The file name is re-written by my application when the file is uploaded, regardless of the name, and stored in my database. So I know it will never contain a "/" or ".."

The filename is: "USER_ID"_"RANDOMMD5".FILE_EXT With "USER_ID" = current logged in user ID and "RANDOM MD5" exactly that.

i.e. 5_ji3uc237uckj92d0jf3932t09ut93f2.pdf

This is my function to serve the file:

function user_file($file_name = "")
{
    if ($file_name)
    {
         // Ensure no funny business names:
         $file_name = str_replace ('..', '', $file_name);
         $file_name = str_replace ('/', '', $file_name);

         // Check if the user is allowed to access this file
     $user_id = substr($file_name, 0, strpos($file_name, "_"));

         // now do the logic to check user is logged in, and user is owner of file
         (($this->ion_auth->logged_in()) && (($user_id === $this->user->id))
         {
                // Serve file via readfile()
         }
    }
}

Question: Is this a secure way to ensure that there is no other way for the person to transverse directories, gain access to other files etc?

edit 1: ion_auth is my authentication library, and "$this->user->id" is the user id stored in my construct

edit 2: The user files are stored outside public_html - and thus only accessible via my application AFAIK

edit 3: My improved code, using the ideas from Amber below, taking into account the fact I need to accomodate for different file extensions, and I'm going to try and avoid a database hit:

function user_files($file_name = "")
{
    // for security reasons, check the filename is correct
    // This checks for a 32bit md5 value, followed by a single "." followed by a 3-4 extension (of only a-z)
    if (preg_match('^[A-Za-z0-9]{32}+[.]{1}[A-Za-z]{3,4}$^', $file_name))
    {
        // Now check the user is logged in
        if ($this->ion_auth->logged_in())
        {
            // Rewrite the request to the path on my server - and append the user_id onto the filename
            // This ensures that users can only ever access their own file which they uploaded
            // As their userid was appended to the filename during the upload!
            $file = MY_SECURE_FOLDER.$this->user->id.'_'.$file_name;

            // Now check if file exists
            if (file_exists($file))
            {
                // Serve the file
                header('Content-Type: '.get_mime_by_extension($file));
                readfile($file);
            }
        }
    }
}

解决方案

Better idea: have the user supply the MD5, and construct the filename yourself. That way you don't have to do all sorts of crazy checking for user input versus filenames - you can just ensure that the MD5 is a 40-character string of [0-9a-f] only, and then you're good.

这篇关于这个PHP函数是否保护文件横向?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆