▼▽ Instant Access Menu ▽▼

 ソースを外部ファイル化する(CGI編)   



BIGLOBEのおすすめ光ファイバー「BIGLOBE光 with フレッツ」
今なら入会した方全員に無線LANルータを無料で提供中。

 待望のHTML暗号化ソフト誕生!! 
株式会社プランセスの全面協力の元、HTML暗号化ソフト「SHTML」を2005年7月11日にリリースしました。

Javascriptの知識が全くない方でも利用可能なように設計されています。最短ステップの場合、暗号化したいソースを貼り付けて、「暗号化する」ボタンをクリックするだけです!!

右クリック禁止+ソースの暗号化+印刷禁止+テキスト選択禁止・・・が今までにないほど簡単に!!
(サンプル):
オリジナル: 株式会社プランセスのメインページ

暗号化したページ: こちら


前頁で紹介した、<script type="text/javascript" src="js.cgi"></script>について検証していくことにします。
外部ファイルをCGIで作成したサンプルをこちらに準備しました。

通常、CGIを作成する際に、print関数でHTMLを出力する際は、呪文のごとく、
print "Content-type: text/html\n\n";
を何か出力する前に必ずこのheader(ヘッダー)を書きますね。

あれは、HTMLファイルを出力しているからそう書くのであって、もしGIF画像ファイルならば、
print "Content-type: image/gif\n\n";
と書いてから、画像ファイルのデータを書き出します。

同様にして、JSファイルならば、
print "Content-Type: application/x-javascript\n\n";
とヘッダーを書いてからJavascriptの本体を書き出せば良いことになります。

実際にjs.cgiの中身を見ながら解説しましょう。
#!/usr/bin/perl
##↑↑perlのパスは各自の環境に合わせて、書き直してください。

##直接にjs.cgiへのURLをたたかれることによりダウンロードされることを防ぐために、Referer(リンク元)をチェックします。
    $browser = $ENV{'HTTP_USER_AGENT'};
##Mac版IE5.0とWindows版Netscape及びMac版ネットスケープでは、HTMLファイルから呼び出しがあってもRefererは空っぽである。つまり、refererのチェックで、正規のユーザーが正しいHTMLページを見ることができなくなってしまうのでチェックしない。
    if($browser =~ /MSIE/){ #ネットスケープは免除
      #Mac版IEは外部ファイルにはrefererを返さないので例外
      if($browser =~ /Mac/){

      } elsif($ENV{'HTTP_REFERER'} eq ""){
      print "Content-type: text/html\n\n";
      print "You can not access file directly";
      exit;
      }

    } elsif($browser =~ /Firefox/ || $browser =~ /Safari/){
      if($ENV{'HTTP_REFERER'} eq ""){
      print "Content-type: text/html\n\n";
      print "You can not access file directly";
      exit;
      }
    }

$dummy = "%u3042"; #「あ」のユニコード
#下記の$strがjscgi_sample.htmlでdocument.writeメソッドで出力させる文字列。JavaScriptで処理しやすいように先頭行が必ず全角文字になるように、「あ」を先頭に付けます。decode関数でdecodeする前なので実体は分かりにくい。
表示が乱れるブラウザがあるため改行させていますが、本当は1行です。
$str = $dummy . "%3Cfont%20color%3D%22red%22%3E%3Cb%3E%u304A
%u3081%u3067%u3068%u3046%u3054%u3056%u3044%u307E%u3059%u3002
%u6210%u529F%u3067%u3059%u3002%3C/b%3E%3C/font%3Ejs.cgi%u306E
%u30C0%u30A6%u30F3%u30ED%u30FC%u30C9%u306F%u901A%u5E38%u306E
%u65B9%u6CD5%u3067%u306F%u3067%u304D%u306A%u3044%u306F%u305A
%u3067%u3059%u3002";

#urldecodeしておく。「<」「>」「&」「"」「 」「=」などの文字は元の文字に変換される。日本語やアルファベットはそのまま
$str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
#### 「"」対策。エスケープしておく。
$str =~ s/"/\\"/g;

### 改行対策

$str =~ s/\r\n/\\n/g;
##IEの場合、下記に挙げるようなキャッシュを残さないようにheaderを送っておかないと、js.cgiへのURLをたたいたとき、refererが空であるにも関わらず、ダウンロードできてしまう。実は、ダウンロードはサーバからダウンロードされているのではなく、キャッシュファイルからダウンロードされている。したがって、キャッシュファイルから読み込まないようにこのヘッダーが必要のようです(テスト環境の環境的要因も考えられますが、その点は皆さんでテストしてみてください。)。ネットスケープ6では、これらのヘッダーをつけておいてもjs.cgiのダウンロードが可能です。また、ネットスケープ7では、javascript記述部分がブラウザにそのまま出力されてしまいます。

    print "Pragma: no-cache\n";
    print "Cache-Control: no-cache\n";
    print "Expires: Thu, 01 Dec 1994 16:00:00 GMT\n";

    ##jsファイルだというヘッダーをつけてあげる
    print "Content-Type: application/x-javascript\n\n";

    ##javascriptの関数を出力
      print <<"END";
      	function get_message(){
      		var s = \"$str\";
      	  return decode(s);
      	}
      	function decode(s){
      		var seq = \"\";
      		var abc = \"\";
      		var uni = \"\";
      		var buf = s.split( \"%u\" );
      		for( var i=1 ; i<buf.length ; i++ ){
      			if(buf[i].length > 4){
      				abc = buf[i].substr(4,buf[i].length-4);
      			} else {
      				abc = \"\";
      			}
      			uni = buf[i].substr(0,4);
      			seq += String.fromCharCode(parseInt(uni,16)) + abc;
      		}
      		return seq;
      	}
      
      END


このサンプルのHTMLファイル(jscgi_sample.html)では、ソースを見てもらえれば分かりますように、get_message関数でメッセージを取得し、document.writeしているわけです。そして、このget_message関数はjs.cgiで定義されていますが、refererのチェックがあるために、get_message関数の戻り値である$strにどのようなタグが書かれているのかが分かりにくくなっています。

ただソースを読んでもらえれば分かりますように、Mac版IE5では正規のHTMLファイルからjs.cgiを要求していても、refererを返しません。そのため"無実の善良なる?"ユーザーをはじかないためにも、チェックをはずさざるを得ません。refererのチェックがありませんので、Mac版IE5でjs.cgiのURLにアクセスすると、
	function get_message(){
		// var s の中身は実際には改行されていません。
		var s = "%u3042<font color=\"red\"><b>%u304A%u3081%u3067%u3068%u3046%u3054%u3056
%u3044%u307E%u3059%u3002%u6210%u529F%u3067%u3059%u3002</b></font>js.cgi%u306E%u30C0%u30A6%u30F3
%u30ED%u30FC%u30C9%u306F%u901A%u5E38%u306E%u65B9%u6CD5%u3067%u306F%u3067%u304D%u306A%u3044%u306F
%u305A%u3067%u3059%u3002"; return decode(s); } function decode(s){ var seq = ""; var abc = ""; var uni = ""; var buf = s.split("%u"); for( var i=1 ; i<buf.length ; i++ ){ if(buf[i].length > 4){ abc = buf[i].substr(4,buf[i].length-4); } else { abc = ""; } uni = buf[1].substr(0,4); seq += String.fromCharCode(parseInt(uni,16)) + abc; } return seq; }
とブラウザに、ファイルの中身がそのまま表示されます。これこそがjs.cgiの実体です。と言っても、js.cgiのソースそのものではありません。あくまでも、js.cgiの中でprint関数で出力している結果のみがブラウザには出力されます。

もし、Windows版IEでrefererのチェックを行っていなければ、js.js(拡張子に注目してください。cgiではなく、Mimeヘッダーを尊重してjsファイルとして認識されています。)としてダウンロードされ、中身は一緒です。

【広告】セルライト対策にターボセル      【広告】格安ノートパソコン      【広告】ゾンビ打 THE TYPING OF THE DEAD

ネットスケープではRefererチェックを行っていませんが、幸いなことに4.Xではjs.cgiのURLを直接たたいてもダウンロードされません(ネットスケープ6.xではwinではダウンロード画面が表示されました。ネットスケープ7.xでは、Windows版でもMac版でもソースがそのままブラウザに表示されました。refererのチェックを入れるとjavascriptが動かなくなりますのでいたし方ありません)。ネスケ4.Xでは、拡張子が通常の.jsでも.cssでも表示されません。これらはブラウザの表示の対象外なのかな? よく分かりませんが、とにかく私のテスト環境ではダウンロード画面にはなりませんでした。

ということはMac版IE、ネスケ6.xや7.x(win、mac)以外のブラウザからはソースを隠すことが完全に可能なのでしょうか? いいえ、そのようなことはありません。実は、referer(リンク元)というのは、ユーザー側の方で簡単に設定が可能なのです。本当はブラウザにURLを直接たたいても、あたかもrefererはHTMLファイルであるかのようにすることが可能なのです。しかも、アングラソフトなどではなく、vectorなどでも入手できる正規のproxy設定ソフトなどで可能です。



専用サーバが月額19,800円〜

さらに、厄介なことに、windows版IEユーザーであっても、refererのチェックで外部ファイルのダウンロードを制御しようとした場合、refererを偽装する意思はない正規のユーザーをはじいてしまう可能性があります。「Norton Internet Security」というシマンテック社の製品を使っているユーザーはデフォルトでrefererを返さない設定にしているために、外部ファイルが読み込まれず、その結果、そのユーザーが見るホームページが正しく表示されないことになってしまいます。これは意図した結果と異なることになってしまいます。

ですから、refererのチェックでダウンロードを制御するやり方は、善意のユーザーを犠牲にする可能性があるため、その点は十分に考慮して採用不採用を決めるべきだと思います。

そもそも、refererをチェックしてダウンロードされるのを防ぐなどの作業が必要になってくるのは、jscgi_sample.htmlのソース自体が見られてしまうことに根本原因があります。jscgi_sample.htmlのソースが見られてしまうから外部ファイルのファイル名(ここではjs.cgi)が漏れ、さらにjs.cgiに書かれたJavascriptのソースも入手されてしまうのです。このjscgi_sample.htmlのソース自体を見せないようにする(難しくする)方法をこれから紹介していきます。まずは、「右クリックを禁止する(カスタマイズメニューの表示)」です。

--------------------------------------------------------------------------
(補則説明1)
実は、サンプルのjs.cgiにはさらに問題があります。Mac版IE4.5ではdocument.writeメソッドで出力した文字が文字化けします。これはMicrosoftの文書「[M_IE45] JavaScript で出力した日本語文字列が不正」で説明されていますように、document.writeメソッドなどで書き込む際にutf-8の文字列として書き込んでしまうためです。Mac版IE4.5では、外部ファイルの文字コードにかかわらずutf-8の文字列と認識して出力するため、文字化けが発生するのです。

通常、この問題を解決するためには、Mac版IE4.5用に外部ファイルを別に準備して、js_utf8.cgiなどとして保存します。Mac版IE4.5の場合だけ読み込む外部ファイルを変更するように、js.htmlにてブラウザの判別を行い、document.writeメソッドで外部ファイルを読み込みます。しかし、これは非常に面倒です。外部ファイルが二つあるために、何かメンテナンスするたびに二つのファイルをいじくらなければなりません。

【広告】 動的なHTMLソースのリアルタイム難読化用Perlライブラリ「サーバサイドSHTML」


そこで、上の例で言えば、外部ファイルはShift_JISのものだけを準備して、Mac版IE4.5でのアクセスの場合は$strの中身をutf-8に変換してあげればいいことになります。JavaScriptだけでも、工夫すればshift_jisからutf-8への変換も不可能ではないかもしれませんが、これは大変そうです。また、CGIでもJcode.pm(jcode.plの機能を拡張したもの)などを使えばutf-8変換も可能そうです。ただし、私はJcode.pmのことはよく知りませんので、PHPでjs.phpという外部ファイルを作成してみましたサンプルのソースコードがこちらにあります。js.phpをインクルードしたjsphp_sample.htmlはこちらにあります。

もしくは、「Javascriptのescape関数を利用する」の項目で紹介したような、IEでもネスケでも利用できるエンコード関数で日本語部分をunicodeなどに変換しておけば、Mac版IE4.5でも文字化けせずに表示が可能です。具体例は、「専用ソフトで暗号化する」の中で紹介しています。

【広告】パソコン・デジカメ・DVDレコーダーをお探しならAmazonへ      【広告】ビッダーズで中古パソコン!!

(補足説明2)
外部ファイルをCGIにした場合、ローカル(C:\*********\js.htmlなど)でのテストが難しくなります。HTMLファイルはそのままブラウザに表示させればいいのですが、ローカルでCGIファイルを実行するためには、ローカルサーバを立ちあげるか、外部ファイルへのパスを「http://」で始まるURLにしておく必要があります。ただ、これだと、外部ファイルへのソースをダウンロードされるのがより簡単になります。

たとえ、小手先であっても、外部ファイルへのパスは相対パスで記述したほうが、HTMLソースを隠すという目的にはかなっています。したがって、このような場合、ローカルサーバを立ち上げるか、面倒でもHTMLファイルや外部ファイルをいちいちFTPでアップして確認する必要があります。普通にローカルでHTMLファイルをブラウザ内に表示させても外部ファイルであるCGIが実行されないためにJavascriptエラーが発生します。

(補足説明3)
「ネットスケープ4.Xでは、js.cgiのURLを直接たたいてもダウンロードが始まらない」と本文で書きましたが、これとて、無理やりダウンロードする方法はあります。メモ帳を開いて、
<a href="js.cgiのURL">ここ</a>
と一行書いて、これを適当なファイル名(例えばdummy.html)で保存します。これをネットスケープで表示させます。「ここ」という文字がハイパーリンクになっているはずですから、そのリンクにカーソルを合わせ、Windowsの場合、右クリックをします。そして、「リンクを名前を付けて保存」を選びますとjs.cgiのダウンロードが始まります。もしくは、「view-source:http://www.broadband-xp.com/hidesource/js.cgi」などと打ち込めばダウンロードできます。(Windows版IEでは、refererのチェックを行っていますので、view-source〜でダウンロードできるのは、「You can not access file directly」というエラーメッセージです。)

(補足説明4)
上で紹介しましたjs.cgiのサンプルコードでは、Javascriptソースのファイルをそのままprintしていますが、JavaScriptコードが長くなる場合は、JavaScriptコード自体はテキストファイルに保存し、CGIでファイルオープンして中身を取得するコードを書いたほうが良いでしょう。ただし、そのJavaScriptコードの本体であるテキストファイルをDOCUMENT_ROOT外に置こうが、.htaccessで制御のかかったディレクトリーに置こうが、最終的にjs.cgiの中でprintされている以上は、ブラウザによっては外部ファイルのソースを入手することが可能です。隠しようがありません。

--------------------------------------------------------------------------
それでは、js.htmlのソースを見ることさえできないようにするための手段として、「右クリックを禁止する(カスタマイズメニューの表示)」から見ていきましょう。

Back ← |  |  |  |  |  |  | |  | 10 | 11 | 12 |13 | → Next


連絡先:info@broadband-xp.com
(免責事項)このホームページの内容に起因する如何なるトラブルに対しても責任を持ちえません。必ず自己責任でご利用ください。