0

保護されたファイルをユーザーに提供するURLがあります。

ファイル名は、名前に関係なく、ファイルがアップロードされたときにアプリケーションによって書き直され、データベースに保存されます。したがって、「/」または「..」が含まれることはありません。

ファイル名は次のとおりです。"USER_ID"_ "RANDOMMD5" .FILE_EXT "USER_ID" =現在ログインしているユーザーIDで、"RANDOMMD5"はまさにそのとおりです。

すなわち5_ji3uc237uckj92d0jf3932t09ut93f2.pdf

これは、ファイルを提供するための私の関数です。

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()
         }
    }
}

質問:これは、人がディレクトリを横断したり、他のファイルにアクセスしたりする他の方法がないことを保証するための安全な方法ですか?

編集1: ion_authは私の認証ライブラリであり、「$ this->user->id」は私の構成に保存されているユーザーIDです

編集2:ユーザーファイルはpublic_htmlの外部に保存されているため、アプリケーションAFAIKを介してのみアクセスできます

編集3:さまざまなファイル拡張子に対応する必要があるという事実を考慮に入れて、以下の琥珀色のアイデアを使用して、改善されたコード。データベースのヒットを回避しようとしています。

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);
            }
        }
    }
}
4

2 に答える 2

2

より良いアイデア:ユーザーにMD5を提供してもらい、ファイル名を自分で作成してもらいます。そうすれば、ユーザー入力とファイル名のあらゆる種類のクレイジーなチェックを行う必要はありません。MD5が40文字の文字列[0-9a-f]のみであることを確認するだけで、問題はありません。

于 2012-05-08T05:19:21.067 に答える
2

任意のディレクトリに移動できますが、ユーザーIDで始まるファイル名に制限されます。

検討

$file_name = '/./.\\1234_anything.anything';
         $file_name = str_replace ('..', '', $file_name);
         echo $file_name = str_replace ('/', '', $file_name);

また、ファイルパスの区切り文字に関する限り、/と\は一般的に同等です。

于 2012-05-08T05:46:13.213 に答える