トップページに戻る
tokix.netはネットワーク・セキュリティ周辺から半径rな雑文を垂れ流す不定期更新個人サイト>>このサイトについて

初級CGIクラックガイド

<<トップカテゴリー「NetChildren」に戻る

初級CGIクラックガイド(0) (>>この記事のみを表示)

最初に断っておきますが、この連載は超初級CGIクラックガイドの内容を踏まえた「第二弾」です。
基本的に、当サイト内のコンテンツで「参考」として自サイト内他コンテンツや他サイトコンテンツを紹介するのは「より深い理解のために」というコトです。一応「単体での完結」を目指しているつもりです。ですが、この連載は「超初級CGIクラックガイド」の内容を理解した上で読んで下さい。そうしないと意味が分からないと思います。

「超初級CGIクラックガイド」で「何故『クラックという行為』が『可能な行為』としてこの世に存在するのか」を書いたつもりです。
おそらく、多くの人は「クラック」に対して果てしなく漠然としたイメージを持っていると思う訳です。ある人は「クラックとは映画の主人公にのみ許される特殊技能」・・・それこそ波動拳とかと同じようなモノとして捉えているでしょうし、ある人は「ツール落として起動してボタン押せばできる行為」と捉え、つまり「自分がクラックをできないのはツールとマニュアルを持っていないからだ」と思っているでしょう。そこらへんに関して書いたのが「超初級CGIクラックガイド」でした。この連載では、もう少し話を進めていきたいと思います。

と、いうことで次回から本編。

初級CGIクラックガイド(1) (>>この記事のみを表示)

関数。
y=f(x)=3x+5
xという入力をfという関数に通すとyが出てくる。「f」の実体は「入力を3倍して5を足して出力する」関数。

「CGI」とは・・・一般化して言うならば「プログラム」とは・・・関数です。入力から出力を生成する関数。入力・出力が複数であったり内部処理が(単純な一次関数と比較すれば)複雑怪奇なだけで。
CGIに関して言うならば、「入力」と「出力」は例えばこんな感じです。
入力出力
環境変数query_string
標準入力
サーバー内データファイル
現在時刻
その他環境変数群
etc...
html表示
単純なアクセスカウンターだったら。
入力処理出力
サーバー内データファイル(現在のアクセス数)
データファイルから取得した数字に1を加える
サーバー内データファイルにその数字を書き込む
「1加えた結果(=アクセス数)」をhtml出力
超初級CGIクラックガイドを読んでくれた方ならば分かっていると思いますが、CGIクラックとは即ち「CGIのバグ探し」です。そして「バグ」とは簡単に言うと「想定されていない入力に対してプログラムが想定されていない処理を行ってしまう」ということです。
FC版ドラクエ4でコイン買う時に極端に多い枚数を指定すると値段が安くなるって裏技があったの覚えてますか?あの原理は単純ですよね。
「買い物でいくら払うか」という変数が0-16777215の領域までしか用意されていない。だから20000000Gの買い物ならば値段は20000000-16777215Gになる。
超初級CGIクラックガイドの冒頭で触れたこの裏技。もう少し分析してみます。
  1. 変数には「領域」があり、その領域を超えた値を代入することはできない
  2. 領域以上の値を代入させようとしたら、値がリセットされるのでは?「領域以上の値を代入しようとしたらエラーメッセージを出す」みたいな例外処理が組み込まれていない可能性はある
  3. 「買い物でいくら払うか」という変数は(普通の買い物では一回で払う金額なんて大したことはない訳だし)「領域」が比較的小さいのでは?
  4. 「買い物でいくら払うか」という変数に巨大な値を代入させようとすれば良い
  5. 「コイン」ならば枚数を自由に決められるから「巨大な値を代入させる」ということが可能だ
「プログラム上の処理の穴をつつかせる」から「購入するコインの枚数」まで、以上のような思考を辿れば辿り着くことができる。そして実際試してみれば「例外処理(=『そんなにたくさん一度に買えません』とか出力)が組み込まれていない」ということが分かる。
我々に出来ることは「想定されていない入力を行う」ということだけです。「想定されていない入力を行う」ことで「想定されていない処理を行わせる」ことが可能ならば、それは「裏技」であり「クラック」にもなりうる。ある言い方をすれば、上記のような思考を辿り「もしかしたらこんな裏技があるのでは?」と「試してみる」ことが、「ハッキング」なのです。

初級CGIクラックガイド(2) (>>この記事のみを表示)

前回、初級CGIクラックガイド(1)
我々に出来ることは「想定されていない入力を行う」ということだけです
と書いたんですが、これの意味をもう少し。

例えば、以前僕は「User-Agentを使えば掲示板に対するタグ荒らしができるかもしれない」という話を書きました。
参考: User-Agentで掲示板荒らし
CGIで参照できる環境変数User-Agentは閲覧者の制御下にある「入力」の一つです。想定されていない入力・・・つまり、想定されていないUser-Agent・・・によって掲示板を荒らす。「User-Agentで掲示板荒らし」という話を既に読んでくれているならば、是非もう一度そうした視点で読み直してみて下さい。

「掲示板の『本文』にタグを書き込む」という手口は一番初歩的な「掲示板荒らし」です。従って、多くの掲示板は以下のような処理を行っている。
$content =~ s/</&lt;/g;
$content =~ s/>/&gt;/g;
変数$content(本文)の中に「<」があったら「&lt;」に、「>」があったら「&gt;」に置換する。こうすれば本文中のタグは無効化される(※)。

ブラウザ上で「<」を表示させるにはソースに「&lt;」、「>」を表示させるにはソースに「&gt;」と記述します。「<」「>」は普通に書いたら「タグの始まり」「タグの終わり」と解釈されてしまいますからね。
参考:初心者のためのホームページ作り内「実体参照符号/HTML応用編」
つまり。
この置換処理の結果、例えば本文に「<font size=7>氏ね」と書いたならば変数$contentの中身は「<font size=7>氏ね」から「&lt;font size=7&gt;氏ね」になります。よって、これをブラウザで表示したとしても「<font size=7>氏ね」になり、タグは無効化される訳です。
「本文中にタグがあったら無効化すべく置換処理を行う」というのは「掲示板を作るならば常識」とも言えるコトです。理由は既に書いてますね。
「掲示板の『本文』にタグを書き込む」という手口は一番初歩的な「掲示板荒らし」です。
「掲示板荒らし」も(「タグをデータファイルに書き込ませる」という「想定されていない処理」をプログラムに行わせる・・・つまり「バグ」を起こさせる・・・という視点で)「クラック」の一種です。誰もが思いつくようなバグならば、塞がれているのが当たり前ですよね。

しかし「本文の内容」が書き込む人の制御下にあるのと同様に、「メールアドレス」「名前」といった項目もまた書き込む人の制御下にあります(当たり前ですけど)。だから「本文」中のタグが無効化されるならば、「メールアドレス」「名前」といった項目に目をつければ良い。ひょっとしたら「メールアドレス」や「名前」に関しては上記のような置換処理が行われていないかもしれない。そしてそれも駄目だった(=置換処理が行われていた)場合。同じように「書き込む人の制御下にある」User-Agentにも目をつければ良い。

「データファイルにタグを書き込ませる(=データファイルから書き込みデータを読み込み表示させた時タグが表示されるようにする)」が目的だとしても、「直接『データファイルに書き込ませる文字列』を制御する」なんて芸当は不可能です。だから「何が自分の制御下にあるのか」を考える。「掲示板の書き込み内容」と「環境変数User-Agent」は荒らす側から見れば並列な存在です。両者とも「自分の制御下にある入力である」という点で並列です。
「自分の制御下にある入力(=formからCGIに送信される標準入力・環境変数User-Agent・・・)」を「想定されていない値」にすることが「『データファイルに書き込ませる文字列』を制御する」に繋がるならば。それが「クラック」です。

User-Agentで掲示板荒らし」の背景は以上です。次回からもう少し話を進めます。

初級CGIクラックガイド(3) (>>この記事のみを表示)

「CGIプログラム」を「関数」・・・「『入力』から『出力』を生成する関数」・・・と捉えるならば、重要なのは「何が『自分の制御下にある入力』なのか」というコトです。

「超初級CGIクラックガイド」では、こんな書き方をしました。
CGIとは一言で言えば「状況に応じカスタマイズされたhtmlファイルを閲覧者に引き渡すための手段」です。
CGIに「閲覧者の意志」を伝えるための方法はformです。
ではその「閲覧者の意志」はどのように送信されるのか。
二種類あるんですよ、送信方法には。
CGIに対して「閲覧者の意志」を送信することもできるし送信しないこともできる。送信するならば、その方法は「get」「post」の二種類。

こういう考え方をやめましょう。もっと一般化しましょう。

「http」というプロトコルは、基本的に「サーバーにリクエストを行い送られてくるデータを受け取る」という仕組みです。前回まで書いてきた「閲覧者の制御下にある入力」というものの実体は、この「リクエスト」に他ならない。
参考: アダルトサイトで学ぶHTTP基礎
HTTPというプロトコルにおける「リクエスト」について。
我々はよく「http://www.tokix.net/about.htmlを開く」というような言い方をします。この「http://www.tokix.net/about.html」なる「URL」というものは
  • httpというスキーム(※)で
  • www.tokix.netに対し
  • /about.htmlをリクエストする
という意味です。
※参考
Wikipedia内「URL」
「スキーム?」と思った人はとりあえず「httpとはhttpというプロトコルのためのスキーム」という禅問答のような説明で分かった気になってくれれば(この連載的には)それでいいんですが興味があれば適当に調べてみて下さい。
しかし、実のところ「/about.html」をリクエストした結果渡されたデータが本当にサーバー上の「/about.html」なのかは分からない。
httpというスキームでwww.tokix.netに対して/about.htmlなるリクエストを送った結果渡されたデータ
それが、閲覧者にとっての「http://www.tokix.net/about.html」です。
例えば。「http://www.tokix.net/about.html」は「/about.htmlの内容に/header.htmlと/footer.htmlの内容を埋め込んだデータ」かもしれない。SSIを使えばそういうことだって出来ます。
参考: とほほのSSI入門
「『〜.html』で終わるURLを開いた場合はサーバー内の1htmlファイルがそのまま表示されるんだ」というのは幻想です。「httpというプロトコルでwww.tokix.netに対して/about.htmlなるリクエストを送った結果渡されたデータ」は「www.tokix.netサーバー内の/about.htmlそのもの」かもしれないし違うかもしれない(※)。

「上のSSIの話はよく分からないけど無料スペースでサイト運営したことはあるよ」という方には以下の説明を。
「無料スペースにhtmlファイルをアップしてブラウザで開いたらバナー広告付きで表示された」とします。この時、そのhtmlファイルには「バナー広告を表示する」というタグが埋め込まれています。しかしFTPで接続しそのhtmlファイルをダウンロードした場合「バナー広告を表示する」というタグは見えない。
これは、サーバーが例えば「httpで『/tokix/index.html』をリクエストされた場合『/tokix/index.html』に『/adv.html』を埋め込んだデータを渡す」という設定になっているからです。
「『〜.html』で終わるURLを開いた場合はサーバー内の一htmlファイルがそのまま表示されるんだ」というのは幻想だ、ということの一例として。
・・・と、いうような「ブラウジングの仕組み」を書いた上で次の話に。
CGIとは一言で言えば「状況に応じカスタマイズされたhtmlファイルを閲覧者に引き渡すための手段」です。
「CGI」というモノの特徴は、この「状況に応じ」という部分です。CGIは状況(=「入力」)に応じてカスタマイズされたデータ(=「出力」)を閲覧者に引き渡す。
httpというスキームでwww.tokix.netに対して/bbs.cgiなるリクエストを送った結果渡されたデータ
それが、閲覧者にとっての「http://www.tokix.net/bbs.cgi」です。この「渡されたデータ」は状況によって変化する。CGIは状況に応じた処理を行う。だからこそ、そこには「バグが存在するかもしれない」という期待がある。「『想定されていない状況下』では『想定されていない処理』が行われるのではないか」という期待。

「ネットサーフィン」において、CGIを実行するパターンというのは四パターンだと思います。
  1. http://www.tokix.net/bbs/bbs.cgiのようなURLを「アドレス」欄に打って「移動」(orハイパーリンクで移動)
  2. http://www.tokix.net/bbs/bbs.cgi?mode=resのような「?」つきの(つまり環境変数query_stringつきの)URLを「アドレス」欄に打って「移動」(orハイパーリンクで移動)
  3. method=getのformからCGIを実行
  4. method=postのformからCGIを実行
「超初級CGIクラックガイド」では以下のような書き方をしました。
  • 1からの(CGIに「閲覧者の意志」を伝えるための)発展形が2〜4
  • 2と3は同じ(どちらもquery_stringで「閲覧者の意志」を伝えている)
もう一歩、進みましょう。1〜4は、全て「サーバーに対してリクエストを送っている」という点で同じである。methodの違い等は「『入力』の内容の差」。つまり「リクエスト内容の差」であって「リクエスト方法の差」ではない。

初級CGIクラックガイド(4) (>>この記事のみを表示)

IE等を使ってブラウジングを行う時・Irvine等を使ってhttpダウンロードを行う時・・・に裏で行われている「リクエスト」。telnet等を使えばマニュアルで行うことができる「リクエスト」。
クライアント(=閲覧者)側から見て、「リクエスト」の一般形は以下です。
リクエストコマンド(メソッド) リクエスト対象 HTTPのバージョン
環境変数群
(改行)
標準入力
「リクエストコマンド(メソッド)」は一般的に「GET」「POST」の二種類。
「リクエスト対象」は「/index.html」だったり「/himitsu_hoshi.jpg」だったり「/bbs.cgi」だったり「/bbs.cgi?myname=tokix&content=hello」だったり。
「HTTPのバージョン」は「HTTP/1.0」とか「HTTP/1.1」とか。
「標準入力」は「超初級CGIクラックガイド」で「裏で送信されるデータ」と誤魔化した箇所です。IE等ブラウザを使ってmethod=postなformからCGIを実行した場合、「送信するデータ」はここに記載されます。
参考: 超初級CGIクラックガイド(5)

例を三つほど挙げておきます。
□普通のhtmlページをハイパーリンクで開く場合の例
GET /about.html HTTP/1.1
Referer: http://www.tokix.net/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: www.tokix.net
Connection: Keep-Alive
□CGIを(GETメソッドにより)環境変数query_stringつきで実行する場合の例
GET /bbs.cgi?myname=tokix&content=hello HTTP/1.1
Referer: http://www.tokix.net/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: www.tokix.net
Connection: Keep-Alive
□CGIを(POSTメソッドにより)標準入力つきで実行する場合の例
POST /bbs.cgi HTTP/1.1
Referer: http://www.tokix.net/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Host: www.tokix.net
Connection: Keep-Alive

myname=tokix&content=hello
上記三者を「同じモノ」として捉えることができたでしょうか?上記三者の違いというのは「リクエスト(=入力)内容の差」に過ぎない、と。

ここから本題に移ります。上記のようなリクエストの「形式」というのは、どこまで閲覧者の制御下にあるのか。
  • リクエストコマンド
    閲覧者の制御下にありますが、「KURE」とかにしてもサーバーが解釈してくれません。リクエストコマンドはRFCという世界統一規格で決まってます。
    参考: Studying HTTP内「リクエスト
  • リクエスト対象
    完全に閲覧者の制御下にあります。例えば「/YouAreFat」とかリクエストしたらサーバー内に「『/YouAreFat』とリクエストされたけどどうすりゃいいのか分からなかったよ」という意味のエラーログが残るでしょうね。また、「?」以降はCGIから環境変数query_stringとして参照されます。
    参考: 超初級CGIクラックガイド(3)
  • HTTPバージョン
    閲覧者の制御下にありますが、「sya-senyou」とかにしてもサーバーが解釈してくれません。リクエストコマンドと同じく、RFCという世界統一規格があります。
  • 環境変数群
    完全に閲覧者の制御下にあります。「完全に」です。次回書きます。
  • 標準入力
    完全に閲覧者の制御下にあります。
・・・何が言いたいのか。
「これが『リクエストの例』ですよ」と書くと、「あぁそうか、この形式通りにリクエストしなくちゃいけないのか」と思う人が多いと思うのですよ。それは違います。上記のように「リクエスト内容」は基本的に全て閲覧者の制御下にあります。
「環境変数」に関しても同じです。よく「環境変数には***と***と***があり、こうした情報がサーバーに伝わるのです」という論調な解説を見ることがあるでしょう。アレはある意味では正しいが、ある意味では間違っている。

初級CGIクラックガイド(5) (>>この記事のみを表示)

偉そうな言い方をすれば、「知識」とは以下のようなプロセスを辿ることで手に入る代物だと思います。
  1. 漠然とした全体像の把握
  2. 整然とした分類
  3. 体系立てられた全体像の把握
つまり、最初は漠然と「一つ」として捉えていたモノを「分類」し「再統合」する。一見無駄に思えるこの順序を辿らなければ「知識」を手に入れることはできない、と。
「環境変数」というテーマに関しては、今回の連載では「2」までにします。

「環境変数」に関する「漠然とした全体像の把握」は以下でしょう。
例えば確認くんを開いてみて下さい。あなたのIPアドレスや使用ブラウザやリンク元アドレス(このページのURL)や様々な情報が表示されたと思います。こうした「閲覧者に関する情報」は「環境変数」としてCGIから参照されます。
閲覧者は、例えば「User-Agent(使用ブラウザ)」を一部タブ型ブラウザ等によって制御することができます。
参考: User-Agentで掲示板荒らし
結論から先に書きます。「環境変数」は大きく二つに分類できる。
  • 頭に「HTTP_」がついていないもの
  • 頭に「HTTP_」がついているもの
□頭に「HTTP_」がついていないもの
サーバーは「自分が閲覧者について知っている情報」をCGIに引き渡します。そうした情報群が「頭にHTTP_がついていない環境変数」。例えば「閲覧者のIPアドレス」はこっちですね。環境変数REMOTE_ADDR。
こうした環境変数は「CGIに対する入力」ですが基本的に閲覧者の制御下にはありません(例えばIPアドレスを任意に偽装することが可能か?ということです。HTTPプロクシなどを使い「本来と異なる値にする」ことは可能ですがそれでは「任意に」にはならない)。
□頭に「HTTP_」がついているもの
リクエスト内の「環境変数群」に記述された文字列「A: B」がそのまま「環境変数AはB」という具合に参照されます。ただし「A」に関しては、小文字は大文字に・「-」は「_」に置換され、頭に「HTTP_」がくっつきます。例えば、「User-Agent: unknown」と書いたならば「環境変数HTTP_USER_AGENTは『unknown』」になります。

そして、これがこの連載の主題です。
「環境変数」と言われると「自分に関する情報が知らない間にCGIに引き渡されているんだ」というイメージを持っている人が多いと思います。たしかにIPアドレスとかはそうです。しかし、頭に「HTTP_」がつく環境変数は完全に「閲覧者の制御下にある入力」なんです。通常のブラウジングではIE等ブラウザが勝手に「入力」を行っている(=「環境変数群」に様々な情報を書き込みリクエストを行っている)から閲覧者から見えにくいだけで。
極端な話、リクエスト内に「Favorite-Cup: E-Cup」と書けば、CGIからの「環境変数HTTP_FAVORITE_CUPは『E-Cup』」という情報参照が可能になります。

もちろん、例えば「f(x)=3x+5」という関数に「a=5」を代入しても仕方がない。「環境変数HTTP_FAVORITE_CUPは『E-Cup』」という情報がCGIで利用されることはまずないでしょう。しかし、この世には「全ての環境変数をデータファイルにログる」というCGIも存在する。その場合、データファイル内に「環境変数HTTP_FAVORITE_CUPは『E-Cup』」という情報が書き込まれることになります。・・・「データファイルを見た管理人を笑わせる」という目的ならば有効かもしれません。

さて、「頭にHTTP_がつく環境変数」にはどんなものがあるのか。
ただ。上記を踏まえれば「当たり前」なんですが、「HTTP_」で始まる環境変数ってのはクライアント(=閲覧者)が自由に追加できる代物です(※)。

例えば、僕がIE,NN,Operaに続く第四のブラウザ「tokix-browser」を開発したとしましょう。tokix-browserはインストール画面で「あなたの好きなカップは?」と質問し答えを「環境変数Favorite-Cup」として「(ブラウズ時サーバーに引き渡す)リクエスト」の中に記述するとしましょう。そんなtokix-browserがシェアを伸ばせば、世に出回る「アクセス解析CGI」は環境変数HTTP_FAVORITE_CUPを記録するのが当たり前になるかもしれませんよ。
・・・まぁ、「HTTP_」で始まる環境変数ってのは本質的にその程度の存在です。ということを言いたかった。
ということで、「一般的なモノ」を羅列します。「HTTP_」で始まる環境変数・・・「完全に閲覧者の制御下にある」入力・・・の中で、CGIから参照されることが多いもの。
  • HTTP_REFERER - いわゆる「リンク元URL」
  • HTTP_USER_AGENT - 閲覧者が使用しているブラウザ
  • HTTP_ACCEPT_LANGUAGE - 閲覧者が受け入れ可能な言語
  • HTTP_ACCEPT_ENCODING - 閲覧者が受け入れ可能なエンコード
  • HTTP_CONNECTION - データ受信後のサーバーとのコネクション
  • HTTP_COOKIE - いわゆる「クッキー」
「クッキー」、と。
dammy

Credit

SeeAlso

OtherSubCategory

Footprint

Navigation