【応用編: CGI API】格安中華セキュリティ・カメラのWeb設定を探検する HTMLをハッキングしてみて今更わかったこと総まとめ
前回の記事で、セキュリティ・カメラのHTMLをハッキングしてわかったことの基本編をお送りしました。今回は、応用編。前回軽く触れたCGI APIを深堀りします。
前回の記事では、カメラのWeb設定画面の内部で使われているCGI (Common Gateway Interface)がちょっと奇妙だ感じる筆者テック大家さん。その違和感を具体的に示すことにしましょう。
CGIってそもそもなに?
CGI(Common Gateway Interface)と呼ばれる仕組みは、動的なコンテンツを生成するためのサーバー側の仕組みです。HTTPやHTMLが登場した当初から使われている、かなり古いものです。
具体的な話をしましょう。サーバーがブラウザにファイルシステムにあるファイルそのものを送る場合、それはスタティックなHTMLということになります。いつも同じコンテンツです。しかし例えば、アクセスカウント数を表示したいような場合を考えましょう。そのようなサイトでは、ブラウザがリクエストするたびに異なるHTMLを吐き出す仕組みが必要だったわけです。
HTMLやCGIが流行りだした頃はよくサイトに「〇〇人目のお客様です」などといった表示をしているサイトがあったものです(懐かし…)。昨今の技術用語でいうと「サーバー・サイド・レンダリング」を実現するためのサーバー側の仕組みと言えるでしょう。
つまり、以下の図のようにブラウザからページをリクエストすると、サーバーではデータベースを参照するなどして最新データページ(HTML)を構築してブラウザに動的なコンテンツを送り返すというわけです。
REST APIってなに?
一方、時代が代わり、コンテンツ作成の仕組みが少し進化して、ブラウザで動作するJavaScriptが動的にデータをサーバーに取りに行く世界観が登場します。
これの何がいいかと言うと、CGIだとデータを更新するたびにサーバーに新しいHTMLページを取りに行くことになります。ユーザがアクションを起こす度に、ページ全体が更新されることになるのでUIが複雑になると使いにくいという問題が発生します。
それを解決するのがJavaScriptから呼び出せるようにした、REST APIです。UIを更新したいいデータだけを取りに行くという仕組みです。これが考え出された当初は画期的なものでした。2000年代中頃のことです。AJAXと呼ばれて世の人々は喝采したものです(大げさ)。
そして、昨今はWeb APIと呼ばれたり、REST APIと呼ばれたりしています。仕組みとしては、以下のようなものです。
データを取得したい場合は、JavaScriptのプログラムが、XML HttpRequestやfetchといったブラウザが備えるHTTP機能でサーバーを呼び出します。これで必要なデータを取得しHTMLページの必要な箇所のみを表示更新するのです。これならページの全書き換えは起こりません。
最近では、要求時のパラメータも戻って来る戻り値も、JSON( JavaScript Object Notation )というフォーマットを使うケースをよく目にするようになりました。
具体的なAPIの例を見てみましょう。郵便番号から住所を調べたい場合に使えるサービスがAPIを提供しています。ブラウザでこのURLを開くとどうなるか見てみましょう。
https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
以下のようなデータがブラウザ画面に表示されます。つまり、サーバーはこのHTTP要求に対して、以下のようなテキスト(JSON)を作成してクライアントに返してくれたというわけです。
中華格安セキュリティ・カメラのCGI API
ここまでは一般的な技術の補足でした。ここからが本番です。
中華格安セキュリティ・カメラのWeb設定画面もいわゆる動的なWebページになるわけです。なぜならば設定値によってHTMLを変更しなければいけませんので。
そこで使われているのが、ActiveX や Flash Playerのような古い技術でびっくりだ、というのが前回の記事でした。しかし、ActiveX や Flash のような古いコンポーネントがなくても設定画面は動作します。
それで気になって調べたものが、先の記事の最後の方で補足したCGI(と名前がついている)機能(URL)でした。
このURLは、ブラウザで直接呼び出すと、カメラ内部の設定値が上記のREST APIのようにテキストとして返ってきます。しかし、そのフォーマットはJSONのような広く普及している形式ではありません。JavaScriptの変数にパラメータを代入するコードです。
例えば、以下のようなURLをブラウザで表示します。(カメラのIPアドレスが192.168.0.112の場合)
http://192.168.0.112/web/cgi-bin/hi3510/param.cgi?cmd=getnetcattr
すると応答は、以下のような形で返ってきました。
var dhcpflag="on";
var ip="192.168.0.101";
var netmask="255.255.255.0";
var gateway="192.168.0.1";
var dnsstat="1";
var fdnsip="192.168.0.1";
var sdnsip="";
var macaddress="00:C2:31:8F:C0:DB";
var networktype="LAN";
まさにJavaScriptのコードの一部。JavaScriptでこのAPIを呼び出す際にはあまり問題にならないのかも知れません。でも、他のプログラミング言語で呼び出すにはこのテキストを解釈するのが少々厄介だろうな、おせっかいに推測します。
そこで、少しネットで調べてみました。するとどうでよう。以下のリンクにあるようなカメラのAPIの仕様書が見つかるではありませんか。ドキュメントには、コマンドの種類とそれぞれのコマンドがどんな機能で、どんな値が返ってくるのかが記載されていました。
いかにもAPIです。なるほど。よく整理されているように見えます。
中華格安セキュリティ・カメラのCGIの仕組み
CGIは上で説明しましたが、もともとの経緯を知っているとページ全体を送るものとして考えてしまいます。ですが、この格安カメラがやっているようなことも技術的にはできなくはありません。それをCGIと呼ぶのかどうかは別問題でしょう。
では、このCGI API(と仮に呼ぶ)をどのように使っているのでしょう。
カメラのWeb設定画面のコードを調べてみると、どうやら以下の図のようなイメージで使われていることがわかりました。
最初に受け取るHTMLにはJavaScriptのコードが含まれています。ただし、これをそのまま実行するとエラーになるようなものなのです。そして、<script>タグによりブラウザが上記のCGI APIを呼び出して「変数」を全て取得します。すると全てのJavaScriptのコードが完成しブラウザが実行できるようになる、という流れです。
<script>タグを使って取り込むものって普通、関数とかモジュールとかいうレベルのものでしょう。一方、このCGI APIはほんとにコードの断片でしかないようなものを返すわけです。
関数とかモジュールレベルならそこで定義されている変数の名前がほかで使われていないように保証することもできるわけです。でも、このコードの断片。変数名が二重に定義されちゃったらエラーになっちゃうよな、バグになっちゃうよな、とか気になってしまいます。
テック大家さん的にはこの設計、わからなくはないけど、なんか気持ち悪いな…
REST API 的に使えないか検討してみた
そこで、「わからなくはないけど、テック大家としてはちょっと微妙」なCGI APIを別のプログラムから呼び出してみることにしました。
以下のGithubリポジトリにコードがあります。
このコードはTypescript + Nodejsで書かれたサンプルコードです。上記のCGI APIを呼び出してその結果をJSONフォーマットで返すというWrapperのようなものを作ってみたのでした。
ポイントは、CGI APIが返してくる変数を含むテキストを、JavaScriptのプログラムとして実行することころです。JavaScriptのFunctionコンストラクタの仕組みを使っています。サーバーから送られてきたテキストをそのまま実行することになるので、セキュリティの専門家からはやいのやいの言われそうなしくみで実装しています。
細かいことは、上記リポジトリのREADME.mdに書いていますので、ご興味があれば参考にしてみて下さい。
では、本日はここまで。
ディスカッション
コメント一覧
まだ、コメントがありません