Hatena::ブログ(Diary)

趣味の延長線 RSSフィード

2010/02/23

[] mediaプラグインのGIFAR対策

Mediaプラグインは、アップロードファイルしたファイルそのもの(transfer/以下)への直接アクセス表示を非推奨として、代わりにfilter/以下に出力したVersionファイルの表示を推奨しています。

特に画像ファイル等に、セキュリティ上の理由があるためだそうですが、その例として上げられていた、「GIFAR」について、Versionファイル作成で対策になっているのか検証しました。


どうやらVersionファイル化することで、画像のGIFAR対策はOKのようです (^^)


直接アクセスした場合の問題

transferディレクトリへのアクセスを禁止する理由は、こちらの「4.」を参考にしました。

はてなダイアリー

具体例として、以下の2つが挙げられています。

  1. IE MIME Sniffing

内容: IEのMIME Sniffing - てきとうなメモ

こちらは、Versionファイル作成の際、mineTypeチェック行なっているので対策になるのだろうと納得*1

  1. GIFAR

こちらが初耳でした。


GIFARって何?

調べてみると、ユーザにファイルアップロードさせるのが怖くなります。。。

セキュリティ・ウォッチ - GIFを隠れ蓑に悪性Javaを勝手に実行:ITpro

現代ハッカーの基本テクニック - JARを利用した攻撃手法「GIFAR」【後編】 | ScanNetSecurity (特集、特集のニュース)

アップロードした画像表示だけでは問題ないのに・・・というあたりがイヤらしい (>_<)

GIFARの脅威って - 赤羽橋日記


上記、2番目と3番目の記事に、再現方法が記載してあったので、これらを参考にして検証してみました。


GIFAR画像の作成

まず、jarファイルを用意します。

HelloWorldを出力するだけの、ごく単純なjarです。

[cake@cake webroot]$ java -jar hello.jar
Hello World

このhello.jarを、GIF画像と繋ぎ合わせてGIFARを作ります。

[cake@cake webroot]$ cat Image3.gif hello.jar > gifarImage3.gif

これだけです。


これだけで、ファイル種類を調べると、元の画像と同じGIF

[cake@cake webroot]$ file hello.jar
hello.jar: Zip archive data, at least v2.0 to extract
[cake@cake webroot]$ file Image3.gif
Image3.gif: GIF image data, version 89a, 100 x 100
[cake@cake webroot]$ file gifarImage3.gif
gifarImage3.gif: GIF image data, version 89a, 100 x 100

でも、Javaとして実行可能なGIFARファイルのできあがり・・・

[cake@cake webroot]$ java -jar gifarImage3.gif
Hello World

GIFARファイルをアップロード

このGIFARファイルをmediaプラグインアップロードすると、一見なんの変哲もないGIF画像としてアップロードされました。

transfer以下の画像は、GIFファイルなのに、Javaとして実行可能なままで保管されていました。

[cake@cake webroot]$ file media/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif
media/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif: GIF image data, version 89a, 100 x 100

[cake@cake webroot]$ java -jar media/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif
Hello World

では、filter以下に出力された画像は・・・?

[cake@cake webroot]$ file media/filter/m/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif
media/filter/m/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif: GIF image data, version 87a, 100 x 100

[cake@cake webroot]$ java -jar media/filter/m/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif
Invalid or corrupt jarfile media/filter/m/transfer/img/4b8395a6-2714-42a2-83aa-0a8bc0a80b08.gif

みごと、Java実行エラーになりました!!

ブラウザ上でも、画像表示に問題ありませんでした。


その他、JPEG, PNGでも試して見ましたが、どちらも結果はGIFと同様でした。

[cake@cake webroot]$ cat Image1.jpg hello.jar > gifarImage1.jpg
[cake@cake webroot]$ java -jar gifarImage1.jpg
Hello World

[cake@cake webroot]$ java -jar media/transfer/img/4b839846-a0e0-4c76-a671-0a8dc0a80b08.jpg
Hello World
[cake@cake webroot]$ java -jar media/filter/m/transfer/img/4b839846-a0e0-4c76-a671-0a8dc0a80b08.jpg
Invalid or corrupt jarfile media/filter/m/transfer/img/4b839846-a0e0-4c76-a671-0a8dc0a80b08.jpg


[cake@cake webroot]$ cat Image2.png hello.jar > gifarImage2.png
[cake@cake webroot]$ java -jar gifarImage2.png
Hello World

[cake@cake webroot]$ java -jar media/transfer/img/4b8398c3-226c-4175-9e63-0a8ac0a80b08.png
Hello World
[cake@cake webroot]$ java -jar media/filter/m/transfer/img/4b8398c3-226c-4175-9e63-0a8ac0a80b08.png
Invalid or corrupt jarfile media/filter/m/transfer/img/4b8398c3-226c-4175-9e63-0a8ac0a80b08.png

結論

主要な画像ファイル(JPEG, GIF, PNG)に関しては、MediaプラグインでVersionファイルを作成し、それを表示すべし、です。

[] mediaプラグイン応用(9) 元のファイル形式を保持して縮小

mediaプラグインでVersionファイルは、core.phpなどでconvertに設定した形式で出力されます。

元のファイル形式ままで出力する設定を追加しました。

注:この記事は、Viewで呼び出し時にVersionファイルを作成する 改修済みのソースをベースに記載しています。


MediaプラグインにファイルのmimeTypeを判別するライブラリが同梱されているので、それを使います。

使い方は、Mediaビヘイビアの357〜372行目付近を参考に。


app/plugins/media/libs/upfile.php

@@ -4,6 +4,7 @@
  */
 App::import('Core', 'Shell');
+App::import('Vendor', 'Media.MimeType');

@@ -38,8 +39,16 @@ class Upfile extends Object {
    // mimeType設定
    if (isset($options['mime_type']) && !empty($options['mime_type'])) {
+    if ($options['mime_type'] == 'original') {
+        $File = new File(MEDIA. $orig_filepath);
+        if (!$File->readable()) {
+            return false;
+        }
+        $options['mime_type'] = MimeType::guessType($File->pwd());
+        }
        $filter[$dir]['convert'] = $options['mime_type'];
     }
     Configure::write('Media.filter.'. strtolower($name), array($dir => $filter[$dir]));

以上で、core.phpなどに'convert' => 'original'を指定すれば、元ファイルのmimeTypeと同じ形式でVersionファイルが出力されます。

[] mediaプラグイン応用(8) VersionファイルのmimeTypeを任意で出力

Mediaプラグインの「Versionファイル機能」で出力される縮小画像の、ファイルタイプを任意に選べる改修を追加しました。

注:この記事は、Viewで呼び出し時にVersionファイルを作成する 改修済みのソースをベースに記載しています。


mimeTypeの設定

VersionファイルのmimeTypeを変更するには、convert設定を適宜変更します。

Configure::write('Media.filter.image', array(
-	'xxs' => array('convert' => 'image/png', 'fitCrop' => array(16, 16)),
+	'xxs' => array('convert' => 'image/jpeg', 'fitCrop' => array(16, 16)),

core.phpやbootstra.phpで設定すると、全ての画像のxxsサイズ縮小ファイルが jpg 固定になります。


mimtType適宜指定したい場合は、例えば以下の様に改修します(引用ソースの委細は こちら 参照)

  1. Versionファイル出力時、$options['mimeType']の指定がある場合、convert設定を$options['mimeType']で上書き。

app/plugins/media/libs/upfile.php(Versionファイル出力ライブラリ)

/* Versionファイルの個別作成 */
function make_version($path, $orig_filepath, $options=array())
{
(中略)
    // Confirgureの設定
    $name = Medium::name($orig_filepath);
    $filters = Configure::read('Media.filter.'. strtolower($name));
    if (!isset($filters[$dir])) {
        return false;
    }
-    Configure::write('Media.filter.'. strtolower($name), array($dir => $filters[$dir]));
+    $filter[$dir] = $filters[$dir];
+    // mimeType設定
+    if (isset($options['mime_type']) && !empty($options['mime_type'])) {
+        $filter[$dir]['convert'] = $options['mime_type'];
+      }
+      Configure::write('Media.filter.'. strtolower($name), array($dir => $filter[$dir]));

    // Versionファイル出力
    $Media->setup($Model);
    $result = $Media->make($Model, $orig_filepath);
  1. 上記関数を呼び出す箇所で、適宜$options['mime_type']を設定。

app/plugins/media/views/elements/medium_edit.ctp(改修Attachmentエレメント)

$file = $upfile->file(
    'filter/'.$previewVersion,
    $item,
    array(
        'model_name' => $model,
+        'mime_type' => 'image/jpeg',
    )
);

[][] 手軽にお試しZen-Coding

HTMLCSSコーディングを高速に行なえるプラグイン、「Zen-Coding」なるものが話題になっています。

TextMate+Zen-Codingで超速コーディング? | gaspanik weblog


使っているエディタがZen-Codingに対応していない場合、

あるいはプラグインの追加の手間をかけずに機能を試してみたい場合。

ブラウザだけで、Zen-Codingの主要機能を使える「Zen Coding for textarea」が配布されているので、これを試してみると良いかと思います。


Zen-Codingのデモ動画を見て、まず「これは凄い」と思いました。

HTMLおよびCSSDOM指定ベースで変換するので、jQueryに馴染んだ身としては、取っ掛かり易そうでもあります。


しかし。


このZen-Codingは主にMacOnlyエディタプラグインであり、

Windows版でフリーで試せるものも、情報は主にEclipse系のみ。

知らない人は損してる?コーディングが3倍速くなるZen-Codingを導入してみた - EC studio デザインブログ

そして私は、個人的にEclipseがあまり好きではないため、微妙に気乗りしません・・・


また正直、今CakePHPメインでやっていると、ヘルパー使うからメリットがどのくらいあるかと考えると、微妙でもあります。


探してみたら、ブラウザ上でZen-Codingの一部機能を使える「Zen Coding for textarea v0.6」というものがあったので、ひとまずこれで使い勝手を試してみることにしました。

http://code.google.com/p/zen-coding/downloads/list


  1. 「Zen Coding for textarea v0.6」ダウンロード&解凍
  2. example.htmlブラウザで開き、
  3. TEXTAREA内にZen-condingで変換したいコードを記入。
  4. [Ctrl+適宜キー](DOM→タグ変換ならCtrl+E)

 でZen-Codingの主要機能を使えます*2

テキストエリアの下にある、「Powered by Zen Coding」という青いボタンを押すと、どのショートカットキーを使えばよいか、簡易ヘルプも表示されます(英語ですが)


しばらくこれでZen-Codingの変換機能→エディタコピペ で使ってみて、エディタで直接使いたいくらいに思ってきたら、正式にプラグイン導入検討しようと思います。

*1アップロードの際もチェックしてますが・・・

*2:動作確認FireFox3.6