\誰でもできる!/エックスサーバーを半額以下安くする方法

【JavaScript】なんでもアップロードできると情報漏洩するのでその対策方法

プログラミング
記事内に広告が含まれています。

ITmedia NEWSにて気になる記事があり、アップロード機能で情報漏洩できてしまうインシデントが取り上げていました。
開発者であれば割とやってしまう可能性が高い事例だったので、これについての対処方法についてまとめていきたいと思います。

ITmedia NEWSでの概要

アップロード機能を付けたときに、どんなファイルでもアップロードできてしまうインシデントについて取り上げています。
phpファイルをアップロードし、そこから情報を取得できてしまい、情報漏洩してしまうことを指摘されています。
これに対しての具体的な例と対処方法についてまとめていきます。

スポンサーリンク

問題であるアップロード機能を作ってみる

inputタグでtypeをfileを指定する

アップロード機能
<input  type="file">

なんでもアップロードできると問題あり

多くは画像や動画などをアップロードするイメージがありますが、この状態だとなんでもアップロードできてしまいます。
実行ファイルやExcel、PowerPointなど様々です。

アップロードしたphpファイルを実行できてしまう

ITmedia NEWSで取り扱っているのはphpファイルをアップロード後にコマンド実行できてしまうことです。
例えば以下のようなtest.phpを作成し、アップロードします。
そしたらアップロードされた場所をブラウザで開くと、PHPの設定情報が出力されます。

<?=  phpinfo()  ?>

サーバー内のデータにアクセスでき、情報漏洩や削除ができてしまう

ユーザーが操作することないサーバー内のデータにアクセスできてしまうため、機密情報が取得できてしまったり、最悪削除することもで出来てしまいます。

なんでもアップロードしないようにする対処方法

acceptでアップロードするファイルを絞り込む

inputタグにはacceptを設定することでアップロードするファイルを絞り込むことができます。
ただこれだとすべてのファイルに戻すことでなんでもアップロードできてしまいます。

アップロード機能(画像のみ)
アップロード機能(.png、.jpegのみ)

ファイルを選択したタイミングで絞り込む

inputタグが変わったタイミングで発火するようにし、ファイルがあれば判別していきます。
アップロードできる拡張子を配列extensionsに格納し、増減してもいいようにしております。
今回はpngとjpegのみアップロードできるようにし、アップロードできないかどうかを変数isNotExtensionで判別しています。

const filterAccept  = ()  => {
    const extensions  = ['png',  'jpeg'];
    document.querySelector('input')?.addEventListener('change', (event)  => {
        const {files}  = event.target;
        for (const file  of files) {
            const {name, size, type}  = file;
            const isNotExtension  =  !extensions.some((v)  => type.includes(v));
            if (isNotExtension) {
                 alert(`${name}はアップロードできません。`);
                document.querySelector('input').value = '';
                 return;
            }
        }
    });
}

あとはaddEventListenerで作成した関数filterAcceptを呼び出すだけでよいです。

window.addEventListener('load', ()  => {
    filterAccept();
});
アップロード機能(.png、.jpegのみ、アラート付)
スポンサーリンク

その他に容量チェックもする必要あり

アップロードする容量を制限した方がよいです。
1GBの画像がアップロードできてしまうとサーバーの容量が圧迫されてしまい、それが複数回やられてしまうと最悪サーバーが止まってしまいます。

先ほどのソースにあったsizeがそのままファイル容量(byte)なのですが、少しわかりづらいのでMBに変換します。
1KB = 1000byte、1MB = 1000KBなので、1000を2回割るとMBで出すことができます。

const {name, size, type}  = file;
const mb  = size  /  1000 /  1000;

そして 10MBを超えた場合は同じようにアラートを出してアップロードできないようにします。

if (mb  >  10) {
     alert(`${mb}MBで10MB越えているので、アップロードできません。`);
    document.querySelector('input').value  =  '';
     return;
}
アップロード機能(容量制限)

まとめ

アップロード機能で情報漏洩できてしまうインシデントについて、対処方法についてまとめました。
phpファイルをアップロード後に実行して情報漏洩してまう事例のため、アップロードできるファイルを絞り込む必要があります。
実装する際は必ずアップロードできるものを絞るように心掛けてください。