Posts Tagged ‘php’

JavaScript のソースは隠蔽するべきか? Vol.4


2011
04.21

皆さんこんにちわ、JavaScript のソース隠蔽について考えるコラムも今回で一応の結論を出そうと思います。

今回はもう既に色々出来上がっているので、無駄な前置きはググッと我慢して進めます。

 

それではこのミッションを遂行するための手持ち武器をまとめます。

  • JavaScript による navigator.userAgent と navigator.platform のチェックで偽装を認めない認証
  • Ajax による非同期なソース展開、送受信は POST とする事で URL 欄からの単純な攻撃を防ぐ
  • 開発は通常通り JavaScriptファイル(.js)で行い、呼び出す時は PHP 内でファイルを読み込んで文字列のみ送信
  • 認証を通らない時は何か画面に表示する
  • JS を切られたらもうそれは無視する

こんな感じですね、それでは解説を交え早速実装して行きましょう。

 

取りあえずファイル構成はこんな感じで想定してます。

/index.html
/js/jquery.js
/js/hoge.js
/js/foo.js
/js/piyo.php

適当なディレクトリに上記構成でファイルを作成してください、foo.js隠蔽したいファイルです。
条件を満たすと非同期に foo.js の中身が index.html に送信されるようにします。

 

まずは html 部分から、今回と言うか当 blog ではほぼ毎回 jQuery を使います、言うまでも無く色々と捗るので。

head 要素内に…

1
2
3
<script src="./js/jquery.js" type="text/javascript"></script>
<script src="./js/hoge.js" type="text/javascript"></script>
<script id="moge" type="text/javascript"></script>

jquery.js はご存知のライブラリ、まず呼び出しておきましょう。
hoge.js は判定文を書きます。
3行目は入れ子です、最終的に全て条件を満たすとこの中にソースを送信します。

 

次は hoge.js の中身です、前回の条件を踏まえて2つの condition を書いて上げましょう。

1
2
3
4
5
6
7
$(function() {
    if(navigator.platform.indexOf('iPhone') != -1 && navigator.userAgent.indexOf('iPhone') != -1) {
        $('#hoge').load('./js/piyo.php', {mode:'hoge'});
    } else {
        alert('error');
    }
});

iPhone シミュレータもハネたい場合は2行目を

1
if(navigator.platform == 'iPhone' && navigator.userAgent.indexOf('iPhone') != -1) {

にすれば良いかと思います。

navigator.userAgent も判定しているのは、将来的に webkit じゃないブラウザが出て来たら…と思うのですが  iOS の仕様的にあり得ない気もするので無くても良いと思います。

 

最後に piyo.php の中身です、使い回しが効くように switch で書いてみました。

1
2
3
4
5
6
7
8
9
switch($_POST['mode']) {
    case 'hoge':
        print(file_get_contents('./foo.js'));
        break;

    default:
        print('error');
        break;
}

 

えーと、これでおしまいです。

今回前置きを書かなかったのは、このシンプルなコードを書くために計3回もの記事を消費した訳で。このコラム自体が壮大な前置きだったんだよ!!と言う事に気づいたからです。

いや、まぁ実際に検証してみるってのは大事な事だと思うので無駄では無い。ハズ。

 

気を取り直して解説、

  • http request が来た
  • hoge.js Line:2 で判定
    • どちらも条件を満たした(次へ)
    • どちらかの条件が満たせなかった(エラー出力などして終了)
  • hoge.js Line:3 で id=hoge(script の入れ子)に piyo.php を呼び出す、mode と言うキーで hoge と言う文字列を POST する
  • piyo.php はコールされると $_POST[‘mode’] を見て分岐処理を行う、何も渡されずに呼ばれたら error と言う文字列を返す
  • piyo.php Line:3 にだけ書かれた foo.js のパスからファイルの内容をロードして print を実行、サーバサイドなのでブラウザからは解らない
  • PHP でプリント(出力)されたものは POST 値としてブラウザに返される、jQuery の .load() の効果で index.html に書かれた入れ子の<script id="hoge">〜</script>の間に返された文字列が出力される
  • 出力されると同時にその JS は勝手に実行される

こう言う動きになります、シンプルで良いですね。

 

切ない人の為に上記を実装したサンプルをこちらにアップしました、iPhone 以外からだときっと動かないハズ。

iPhone でアクセスするとやっつけ感満載のパズルゲームが始まると思います、何となく html5 の canvas 使ってみたくてサ。

 

そしてこれは下記環境下なら恐らく上手く隠蔽出来るハズ

  • ソースの保存や Firebug 系のツールが無い環境
  • JS の navigator.platform が偽装出来ない環境

あんまり調べてないからアレですけど、iOS 系なら大丈夫なんじゃなかろうか?どちらにせよ結構な手間をかけないとソースは見えないと思います。

 

 

いやー、長かったですね。お付き合い頂いた皆様、お疲れさまです。

今回良く解ったのは普通の Web ブラウザ上で JS のソースを完全に隠蔽するのは不可能、と言う事です。

完全に隠蔽した Web App を作りたいのなら、一旦素の状態で完成させた物をネイティブアプリの入れ子にリソースを全て埋め込んで、アプリの機能で html を表示して使うアプリをリリースする。と言う方法しか無いんじゃなかろうかと思います、何だか敗北感が凄いですがそう言うモノなんでしょうね。

 

では、最後に締めの言葉を。

 

デバイス限定だけど、そんなに手間をかけずに見え辛くするのは可能だよ!
やりたい人はやっても良いと思うよ!!

 

嗚呼、やはりこうなってしまうんですね。

今回の事は雑学として覚えておけば、妥協点のポイントとして役立つ時が来るかもしれません。

 

それではまた。

 

1 | 2 | 3 | 4

 

JavaScript のソースは隠蔽するべきか? Vol.2


2011
04.20

皆さんこんにちわ、JS のソースを見られるのが恥ずかしくて頭が沸騰しちゃいそうなんだけど、どうにかならない?と言う話の第2弾です。

今回は UserAgent の偽装について検証してみます、考えて見れば本物と偽装の UA 文字列を見比べる機会って意外と無いんじゃないでしょうか?

私と同じく見比べチェリーなデベロッパーの皆様は、是非これを機に偽装の精度がどれ程のものかを認識して、今後様々なシーンで苦笑いと洒落込もうではありませんか。

ちなみにこの blog は大体こんな感じで行きます、めんどくさい感じで行きます。

 

まずは前回のおさらいとして、このミッションをクリアする為の作戦内容の確認から。

  1. 最強の脅威である PC の Web ブラウザ各種で見ているときはソースを出力しない
  2. 猪口才な UserAgent 偽装を見破り容赦なく例外処理を叩き込む
  3. 唯一の対象機が来た時のみ非同期にソースを出力する
  4. 隠蔽は解るけど開発効率もちゃんと考えた作りにする

実は条件を満たした後の処理は既に出来ています(判定処理を組み込んだ上で、非同期な分岐テクニックとして後ほど紹介します)ので、やはり偽装を見破れるかどうかがカギになっています。

今回の検証内容は完全に偽装する事が出来るブラウザが存在するのか?です。

では早速検証して行きましょう、PHP が動くサーバに適当な html ファイルを .php で作って下さい。

 

script 要素内に

1
alert(navigator.userAgent);

body 要素内に <?php?> で括って

1
print($_SERVER['HTTP_USER_AGENT']);

これで準備完了です、ローカルサイドとサーバサイドから UserAgent が出力されますのでその違いについてなんかも見れたら良いな。

ソース用意すんの面倒だよー、切ないよーと言う困ったさんはこちらにアップロードしたものを用意しましたので色んなデバイスのブラウザで試してみて下さい。

 

iPhone4 実機の Safari5

JS からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5

なんと言うか同じですね、当然っちゃ当然。次からが本番、次から本気出す。

 

Firefox の FireMobileSimulator

ド定番と言うかもはやこれ無しじゃ寂しい夜を乗り越えられないレベルのアドオン、UA 偽装と同時に表示までシミュレートしてくれる世紀末開発者の救世主。なんと iPhone までシミュレートしちゃうスゴイヤツです。

WordPress とか EC-CUBE の携帯検証とかでお世話になってる人数多である事でしょう、使ってない人は今すぐ本家サイトへGO。
※今気づいたんですが、前はかわゆい蛙のアイコンだったと思うんだけど Firefox4 バージョンはなんかしなびたキュウリと言うかピータンみたいなアイコンになってますね?それはそれでかわゆい気がするけど。

では、早速 iPhone に偽装して調べてみましょう。

 

JS からの出力

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0) Gecko/20100101 Firefox/4.0

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5B108 Safari/525.20

キタ!なんかサーバサイドの方はまんまと騙されてるけどローカルサイドの方は正直なのね。とにかく Firefox にはこれで勝つる!!

 

Safari の開発ツール

開発には専ら Firefox & Firebug なので知らなかったんですが…Safari の開発ツールってこんなに凄い事なってるんですね。
Safariの開発メニュー
これは最早兵器レベルじゃないか、Win 機で検証するのが面倒だからこれで良いですか?と言いたくなる程豊富なユーザーエージェント。

 

JS からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7

ん…?

 

これはマズい、完全に偽装されています。

 

この検証で確認したかった事は完全に偽装出来るブラウザが有るかどうかなので、なんの事は無い。ここに有るじゃん、この時点で検証終了です。

と言うのも完全偽装可能なブラウザが1つでも存在するならば、そのブラウザを使えばサーバをだまくらかしてソースを引っ張って来れる事になるので今回のミッションは失敗となってしまうからです。

 

ぐぬぬ、やはり楽はさせてくれないですね。しかしまだ諦めません、まだ可能性はあります。

 

今回のまとめ

  • サーバサイドの UserAgent は渡された物を疑わずに信じ込む純真な子なので使わない方が良い
  • Safari は自らの UserAgent をも欺く恐ろしい子
  • 単純な UA 比較だけでは全く持って通用しない

こんな感じなので、サーバサイドでブラウザと言うかデバイスの判定はしない方が良いですね。あくまでローカルサイドでやってしまいましょう、どうせ JS を切られたら非同期で送信されるソースも飛ばない(ここ重要!)から目的は達成される訳ですし!

 

次回は更に踏み込んだデバイス判定処理を考えて行きます、一応の目星は付けています。
JS の UA は navigator と言うオブジェクトから取得しているので、この navigator オブジェクトを突っつけば iPhone とその他デバイスの差異を発見出来る可能性が高いと思います。

それではまた。

 

1 | 2 | 3 | 4