PHPとMySQLを使用して、画像のアップロードを行っています。
独学のため、その際のセキュリティがわかりません。。
例えば、画像ファイルの語尾にダブルコーテーションやシングルコーテーション
など、不要なものがある場合、どのように処理しているのでしょうか?
画像ファイル名に対して、htmlspecialcharsですかね?
初歩的な質問ですが、ご教授願います><
追記
accept="image/gif, image/jpeg"
などを指定するだけで大丈夫なのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
画像のアップロードに限らずPHP開発者が知るべき
セキュリティ問題として以下のようなものがございます。
クロスサイト・スクリプティング(XSS)
SQL インジェクション
ディレクトリ・トラバーサル
OS コマンド・インジェクション
クロスサイト・リクエストフォージェリ(CSRF)
セッション・ハイジャック
HTTP ヘッダー・インジェクション
メールヘッダー・インジェクション
これらに対しては十分い対策がなされなければなりません。
セキュリティ対策例も含めて
https://blog.codecamp.jp/php_security
に色々と例が載っているので参考にされてはいかがでしょうか?
投稿2016/09/01 11:31
総合スコア1628
0
アップロードされた画像ファイルをサーバー上に保存するときにどのようなファイル名にするか、また、直接アクセスするURL(許すかどうか別として)はどうなるかという話で良いでしょうか?
ファイル名に使える文字というのはサーバーが動いているOSによって変わってきます。単純に漢字や平仮名などがが使えないかも知れないという話だけではなく、":"や"/"、""などの記号もOSによって違います。例えば":"はWindowsでは使えませんが、Linuxでは使えると言ったようにです。ただ、少なくともアルファベット(a-b)と数字(0-9)おおび一部の記号(._)などは使えます。ただ、"."は拡張子の区切り文字以外に使われることはお勧めできません。"."と".."という特殊なファイル名が存在することと、UNIX/Linuxでは"."から始まる文字は隠しファイルになるという性質があるからです。
そこで採用するのが、そういった使える文字以外は削除してしまう、または、規則的に書き換えてしまうと言う方法があります。重複してしまった場合は後ろに連番をつけるなどの工夫をします。また、ファイルシステムによってはファイル名の大文字小文字を区別するのか区別しないのか分かれる場合があります。そのような場合の混乱を避けるため、全て小文字にするという処理します。今はLinuxだけしか考えてないから…ではなく、これってWindowsでも動くよね?と言われることに備えるというのも大事です。
また、文字数にも気をつけなければなりません。これもOSによってはファイルの文字数が決まっています。また、パスによっても変わってきます。
最後に、拡張子を考慮しましょう。アップできるのがjpegやpngなど決まっているのであれば、拡張子があっていなければ弾いても良いでしょう。
忘れるところでした。ファイル名にはそれまでのディレクトリへのパスがつけてあるかもしれません。階層構造は不要ですし、時にはセキュリティ上の問題が起きる場合がありますので、ディレクトリの部分はすべて切り捨てましょう。
まとめると一例として次のような処理になります。
- ファイル名を拡張子を除いたファイル名部分と拡張子に分解します。pathinfo()を使うと良いでしょう。ファイルパスのディレクトリの部分は無視します。
- 拡張子が想定のフォーマットで無ければ拒否します。なお、フロント側でJavaScriptを使って拒否する場合であっても、必ずPHP側にも拒否する処理を入れてください。フロント側のJavaScriptによるチェックを回避した悪意あるアクセスをすることで、想定外のファイルがアップロードされる可能性があります。
- 拡張子以外のファイル名部分について次のように書き換えます。
(1) 英数字および""の記号以外は全ての文字を""にします。
(2) 英大文字は英子文字にします。
(3) 文字数が60文字(この文字数は適当にきめてください)を越える場合は60文字まで切り詰めます。
4. 処理したファイル名と拡張子(これも小文字化しておく)でファイル名を作ります。
5. もし、同じファイル名が存在する場合は、"ファイル名_1.拡張子"とつけます。_1もあれば_2、_3と増やしていきます。
細部は異なりますが、Drupalが上記のような方法を取っています。Drupalはアップロードされたファイルを直接見に行くURLになるため、ファイル名はなるべく変わらないようにしたいという配慮のようです。
さて、上の方法はあくまでアップロードされたファイルのファイル名をなるべく残したい場合です。特にそのような事情が無ければ、アップロードされたときのファイル名を無視して、サーバに保存するファイル名を決めた方が良いでしょう。ファイル名を変換していくという面倒な処理も少なくてすみます。
その1 連番
連番でつけるのは最も簡単に思えるかも知れません。しかし、あまりお勧めできません。なぜなら、重複しないように連番を管理している所(DB内のどこかのレコードになるでしょうか)について排他ロック処理をしなければたちまち重複しておかしくなってしまいます。もう一つ気をつけるのが番号から他のファイルの存在が知られることです。もし、URLで直接アクセス可能にしている場合、番号をずらして他のファイルに簡単にアクセスできるようになってしまうかも知れません。何をアップロードするかによりますが、セキュリティ上の不具合と見なされる場合があります。
その2 タイムスタンプ
現在時刻からファイル名を作る方法です。この方法の利点は排他ロックという重い処理が不要なことです。ただ、本当に同時にアップロードされてファイル名が重複する可能性はあります。fopen()
に"x"オプションをつけるなど、重複したときはわざと書き込みが失敗するなどの工夫が必要です。連番よりは他のファイルは推測しにくいですが、完全ではありません。
その3 ランダム
十分な長さのランダムな英数字にします。ファイル名が重なる可能性が極僅かに存在しますが「その2」と同じ対策を行えば十分でしょう。他のファイルのファイル名を推測することはほぼ不可能です。乱数に暗号論的擬似乱数(PHPではopenssl_random_pseudo_bytes()
などを使います)を使えばさらに推測は不可能になり、より安全です。
以上になりますが、他サービスがどのようになっているかを見てみるのもいいかもしれません。例えば、このteratailのユーザーのアイコン画像はランダムな英数字のファイル名になっています。アップロードされたときのファイル名をなるべく保ちたいという事情が無ければ、ランダムにするのが一番良いのではないかと思います。
投稿2016/09/01 12:51
編集2016/09/01 13:04総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
例えば、画像ファイルの語尾にダブルコーテーションやシングルコーテーション
アップロードの時に、ファイル名を指定させると言うことでしょうか?
ファイル名に使える文字を決めて、それ以外の文字があったら、自動的に削除や置換するので無く、エラーで再入力させるのがいいかと思います。
ユーザーの利便性を考えると、JavaScriptでそもそも決めた文字しか入力できないというのが優しいです。
その場合でもサーバー側でのチェックは必要です。
画像ファイル名に対して、htmlspecialcharsですかね?
htmlspecialcharsは、データをHTMLとして画面出力するときに使う関数なので、全く関係ありません。
投稿2015/09/27 10:20
編集2015/09/27 10:22総合スコア84555
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
入力チェックで不都合なファイル名は弾いてしまうか、
アップロードされた時点で、システム連番にファイル名を変えてしまうのはいかがでしょうか。
ファイル名をそのまま使う懸念は、マルチバイトだった時の文字化けです。
投稿2015/09/27 07:07
総合スコア1124
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/09/01 13:08