SECCON 2018 Online CTF Writeup - Forensics Unzip

概要

SECCON 2018 Online CTF にチャレンジしました。

用事の合間にしか取り組めませんでしたが、ひとまず一番簡単だと思われる Unzip 問題が解けたため writeup を残しておきます。(さらに解けたらまた書くかも)

f:id:yuu2634:20181028133907p:plain


Forensics Unzip

フォレンジック系の出題です。
渡されたファイル (unzip.zip) からフラグを探し出します。


まずはファイルをダウンロード、ついでにリネーム。

$ wget https://score-quals.seccon.jp/files/296d9f0e60456b666e962f25df63de86/unzip.zip_26c0cb5b40e9f78641ae44229cda45529418183f
$ mv unzip.zip_26c0cb5b40e9f78641ae44229cda45529418183f unzip.zip


unzip コマンドで普通に展開してみます。

$ unzip unzip.zip
Archive:  unzip.zip
 extracting: flag.zip
  inflating: makefile.sh

flag.zipmakefile.sh が抽出できました。
flag.zip の中にフラグが含まれていそうですね。


makefile.sh を読み解く

しかし肝心の flag.zip にはパスワードが掛かっています。

$ unzip flag.zip
Archive:  flag.zip
[flag.zip] flag.txt password:


makefile.sh の中身も確認します。2行だけのスクリプトでした。

echo 'SECCON{'`cat key`'}' > flag.txt
zip -e --password=`perl -e "print time()"` flag.zip flag.txt

flag.txt を作成して、ZIP ファイルに固めていることが分かります。
perl -e "print time()" の結果がパスワードになっています。


ZIP ファイルの生成時刻=パスワード

perl で print time() を実行すると現在の unixtime が取得できます。

$ perl -e "print time()"
1540700100     // 2018-10-28 13:15:00 の実行例


つまり、makefile.sh が実行された時刻を特定できればパスワードが判明します。
ls --full-time で ZIP ファイルの生成日時を確認してみます。

$ ls --full-time flag.zip
-rw-r--r-- 1 yuu26 yuu26 225 2018-10-27 00:10:42.000000000 +0900 flag.zip


flag.zip を展開する

2018-10-27 00:10:42 を unixtime にすると 1540566642 です。
date コマンドや Unixtime相互変換ツール などで変換できます。

$ date "+%s" -d "2018-10-27 00:10:42.000000000 +0900"
1540566642


パスワードを 1540566642 として試したものの失敗。

$ unzip -P 1540566642 flag.zip
Archive:  flag.zip
   skipping: flag.txt                incorrect password


ファイル書き出しのラグを考慮して 1秒前の時刻 1540566641 で試すと成功しました。

$ unzip -P 1540566641 flag.zip
Archive:  flag.zip
  inflating: flag.txt


正しいアプローチであったかは不明ですが、無事にフラグ獲得です。

$ cat flag.txt
SECCON{We1c0me_2_SECCONCTF2o18}


おすすめ記事

blog.yuu26.com

blog.yuu26.com

AWS Loft Tokyo (AWS の無料コワーキングスペース) に行ってきた

概要

AWS が提供する無料コワーキングスペース「AWS Loft Tokyo」に行ってきました。

2018年10月にオープンしたばかりの新スポットです。
広いスペースに充実した設備、とても快適な空間でしたので紹介します。


AWS Loft Tokyo とは

AWS の新オフィスにある利用者向けの開放施設です。
公式サイト によると、以下3つの役割を持った場所とされています。


コワーキングスペース

  • 平日 10:00 ~ 18:00
  • AWS アカウント所有者であれば利用可能
  • 無料
  • 事前予約不要
  • 電源と Wi-Fi あり

有効な AWS アカウントを持っていれば利用できます。
AWS アカウント自体は誰でも作れるため、制約は実質無いといえるでしょう。


Ask An Expert カウンター

AWS のスペシャリストに技術相談ができるコーナーです。
AWS の利用方法やアーキテクチャ・パフォーマンス改善の相談を受けてくれます。

このカウンターも予約不要・無料で利用できます。
休みの日もあるため、公式サイトで事前に確認しておきましょう。


AWS セミナーやイベント会場

AWS に関する技術セミナーの会場としても利用されています。
夕方に始まるイベントも多いため、仕事帰りに立ち寄ることもできそうです。

イベント一覧はこちらから


AWS Loft Tokyo の場所と行き方

「目黒セントラルスクエア」というビルの17階です。

最寄り駅は「目黒駅」で、駅からは徒歩1分です。
JR 山手線、東急目黒線、南北線、三田線からすぐ行けます。

以下の方法で中に入れます。

  • エスカレーターで3階に上がる
  • 受付はスルーしてエレベーター前へ
  • 警備員に「Loft に行く」と伝える
  • エレベーターで17階に上がる


AWS Loft Tokyo の利用方法

17階に付くと受付カウンターがあります。
ログイン済みの AWS コンソールを見せてアカウント番号を確認してもらいます。

無事に済むとシールが発行され、スペース利用中は常に付けておく必要があります。


作業スペースは100席以上

殆どの空間がコワーキングスペースとなっており、100席以上(200席近く?)が用意されています。火曜の昼に行きましたが、埋まり具合は半分弱ほどでした。

1席の幅が広く、隣に人がいてもゆったり使えます。
座席は何種類か用意されており、1人でも複数人でも困ることはなさそうです。

  • ソファ席
  • 4人で座れる丸テーブル
  • 6人や10人で座れる広い席
  • スタンディングも可能なハイデスク

Kindle や Dash Button など、Amazon 製品の展示コーナーもあります。
Amazon なだけあって、電源タップなどの小物が全体的に段ボール色でした(笑)


AWS の近くにある? 高速 Wi-Fi

提供されている Wi-Fi は 802.11ac で、速度も安定しており快適です。
AWS の AS かと思って確認しましたがそんなことはなく、某大手キャリアの AS でした。

ただ、ネットワーク的には AWS に近いようです。
traceroute したところ、3ホップほどで東京リージョンにたどり着きました。


カフェコーナー (売店)

飲み物やお菓子・軽食が購入できるカフェがあります。
コーヒーが100円からと、価格もリーズナブルです。

面白いのがカフェラテで、その場で撮影した顔画像がラテアートとして出てきます。
その裏側では Amazon Rekognition が動いているそうです。

なお、支払いはクレジットカードか Amazon Pay のみで、現金は使えません。
カフェ以外にも、自販機(現金のみ)と無料ウォーターサーバーが設置されています。


まとめ

AWS Loft Tokyo について紹介しました。
席数や設備が充実していて非常に快適な空間です。

いつもと違う環境で作業をすることで捗ることが分かったため、今後も積極的に活用していきたいと思います。


おすすめ記事

blog.yuu26.com

blog.yuu26.com

WPSeku で WordPress の脆弱性をスキャンする

概要

脆弱性スキャンツール「WPSeku」で、WordPress の脆弱性をスキャンできます。

WordPress の URL を指定するだけで、ブラックボックスのテストが実行されます。
外から取得できる WP 情報を可視化したり、脆弱性情報の確認が行えます。

ツールの詳細や利用方法、スキャン結果の例についてまとめました。


WPSeku とは

オープンソースの WordPress 脆弱性スキャンツールです。
Python で書かれており、簡単に WordPress のセキュリティチェックが行えます。

スキャンには大きく2種類あります。

  • 外部の WordPress へリクエストを送信して検証
  • サーバ内でファイルをスキャン

WPSeku - Wordpress Security Scanner github.com

同様のツールとしては、WPScan などが存在します。


WPSeku で取得できる脆弱性情報

外部から WordPress を検証する場合、環境にもよりますが以下の情報が取得できます。

  • Web サーバ
  • WordPress が格納された物理パス
  • アクセス可能なバックアップファイル
  • 使用中のテーマ
  • 使用中のプラグイン
  • ログインユーザ一覧

WordPress の実ファイルにアクセスできる場合、PHP の脆弱性をスキャン可能です。
以下のディレクトリがスキャン対象となります。

  • WordPress 本体
  • テーマ
  • プラグイン

パスワード辞書を用いてブルートフォースを行う機能もありますが、悪用は厳禁です。


WPSeku の動作に必要な環境

Python 3 が動く環境であれば OK です。
インストール時に pip を使用するため、pip も準備しておきます。

  • Python 3
  • pip


WPSeku のセットアップ

Python が動作する環境で git clone します。

git clone git@github.com:m4ll0k/wpseku.git
 もしくは
git clone https://github.com/m4ll0k/wpseku.git

pip で依存モジュールをセットアップ。

cd wpseku
pip3 install -r requirements.txt

引数なしで実行すると、オプションを確認できます。

$ python3 wpseku.py
----------------------------------------
 _ _ _ ___ ___ ___| |_ _ _
| | | | . |_ -| -_| '_| | |
|_____|  _|___|___|_,_|___|
      |_|             v0.4.0

WPSeku - Wordpress Security Scanner
by Momo Outaadi (m4ll0k)
----------------------------------------

Usage: wpseku.py [options]

        -u --url        Target URL (e.g: http://site.com)
        -b --brute      Bruteforce login via xmlrpc
        -U --user       Set username for bruteforce, default "admin"
        -s --scan       Checking wordpress plugin code
        -p --proxy      Use a proxy, (host:port)
        -c --cookie     Set HTTP Cookie header value
        -a --agent      Set HTTP User-agent header value
        -r --ragent     Use random User-agent header value
        -R --redirect   Set redirect target URL False
        -t --timeout    Seconds to wait before timeout connection
        -w --wordlist   Set wordlist, default "db/wordlist.txt"
        -v --verbose    Print more informations
        -h --help       Show this help and exit

Example:
         wpseku.py --url http://site.com/
         wpseku.py --url http://site.com --brute --user test
         wpseku.py --url http://site.com/ --brute --user admin --wordlist wordlist.txt


WPSeku の使い方 (WordPress サイトをスキャン)

--url オプションで WordPress サイトを指定します。
--verbose を付加すると詳細表示となります。

$ python3 wpseku.py --url https://wordpress.example.com/ --verbose

スキャン結果の一例です。 一部省略していますが、WP バージョン・物理パス・テーマ・プラグイン・ユーザ情報などが一部取得できています。

----------------------------------------
 _ _ _ ___ ___ ___| |_ _ _
| | | | . |_ -| -_| '_| | |
|_____|  _|___|___|_,_|___|
      |_|             v0.4.0

WPSeku - Wordpress Security Scanner
by Momo Outaadi (m4ll0k)
----------------------------------------

[ + ] Target: https://wordpress.example.com/
[ + ] Starting: 12:47:18

[ + ] Server: nginx
[ + ] Uncommon header "X-Mod-Pagespeed" found, with contents: Powered By mod_pagespeed
[ + ] Full Path Disclosure: /home/hoge/wordpress.example.com/public_html/wp-includes/rss-functions.php
[ + ] wp-config.php available at: https://wordpress.example.com/wp-config.php
[ + ] readme.html file was found at: https://wordpress.example.com/readme.html
[ i ] Checking WordPress version...
[ + ] Running WordPress version: 4.9.8

[ i ] Passive enumeration themes...
[ + ] Name: yswallow
  |   Not found vulnerabilities

[ + ] Name: yswallow_custom
  |   Not found vulnerabilities

[ i ] Passive enumeration plugins...
[ + ] Name: contact-form-7
  |   Not found vulnerabilities

[ + ] Name: add-to-any
  |   Not found vulnerabilities

[ + ] Name: jetpack
  |   Not found vulnerabilities

[ i ] Enumerating users...
------------------------------
| ID | Username  | Login     |
------------------------------
|  0 | hoge-user | hoge      |
|  1 | hoge-user | None      |
------------------------------

検出したプラグインで既知となっている脆弱性情報も出力されます。
使用中のバージョンは把握できないため、参考程度の情報です。

[ i ] Checking plugin vulnerabilities...
b'{"add-to-any":{"latest_version":"1.7.30","last_updated":"2018-09-15T01:09:00.000Z","popular":true,"vulnerabilities":[{"id":8885,"title":"AddToAny Share Buttons <= 1.7.14 - Conditional Host Header Injection","created_at":"2017-08-16T08:32:36.000Z","updated_at":"2017-08-16T08:32:48.000Z","published_date":"2017-08-16T00:00:00.000Z","references":{"url":["https://plugins.trac.wordpress.org/changeset/1713858/add-to-any"]},"vuln_type":"UNKNOWN","fixed_in":"1.7.15"}]}}'


WPSeku の使い方 (サーバローカル)

WordPress と同じサーバ内にインストールした場合の例です。
物理パスを --scan オプションで指定すると、PHP ファイルをスキャンできます。

$ python3 wpseku.py --scan /path/to/wordpress/
----------------------------------------
 _ _ _ ___ ___ ___| |_ _ _
| | | | . |_ -| -_| '_| | |
|_____|  _|___|___|_,_|___|
      |_|             v0.4.0

WPSeku - Wordpress Security Scanner
by Momo Outaadi (m4ll0k)
----------------------------------------

[ + ] Checking PHP code...
[ + ] Scanning directory...

[ i ] Scanning /path/to/wordpress/wp-content/plugins/contact-form-7/modules/checkbox.php file
---------------------------------------------------------
| Line | Possibile Vuln.      | String                  |
---------------------------------------------------------
|  151 | Cross-Site Scripting | $_POST[$free_text_name] |
---------------------------------------------------------

[ i ] Scanning /path/to/wordpress/wp-content/plugins/jetpack/modules/contact-form/admin.php file
-------------------------------------------------------------------------
| Line | Possibile Vuln.            | String                            |
-------------------------------------------------------------------------
|  180 | Cross-Site Request Forgery | check_admin_referer('bulk-posts') |
-------------------------------------------------------------------------

[ i ] Scanning /path/to/wordpress/wp-content/plugins/jetpack/sync/class.jetpack-sync-actions.php file
------------------------------------------
| Line | Possibile Vuln.    | String     |
------------------------------------------
|   75 | Authorization Hole | is_admin() |
------------------------------------------

XSS や CSRF など、脆弱性に繋がる恐れのあるコードが指摘されています。

ドキュメントルートを指定すると大量に出力されてしまいます。
独自カスタマイズした PHP や、特定プラグインのみをスキャンする方が現実的です。


WPScan Vulnerability Database の脆弱性情報

WPSeku では、WPScan Vulnerability Database のデータベースを使用しています。 https://wpvulndb.com/

WordPress の脆弱性に関する公開データベースで、プラグインやテーマに関する情報も含まれています。また、脆弱性の発見した場合は Web から情報提供も可能です。


参考記事

blog.adachin.me

computingforgeeks.com


まとめ

  • WPSeku で WordPress のセキュリティチェックが行なえます
  • 外部から見えている WordPress のメタ情報を調査できます
  • PHP ファイルのスキャン機能も搭載しています

WordPress を構築した際や、既存サイトのセキュリティを確認する際に便利です。
対策をしていないと外から見える情報も多いため、注意が必要そうです。

iPhoneからSSHコマンド実行・Webhook連携もできる公式アプリ「ショートカット」を活用する

概要

iPhone で SSH コマンドを実行したり、Webhook 連携を組み立てることが可能となりました。Apple 公式アプリの「ショートカット」を使って実現できます。

「ショートカット」アプリの概要と、簡単な活用事例をまとめました。

iPhone から SSH や curl が実行できる

「ショートカット」アプリでは、多くのアクションが用意されています。その中には「SSH」や「URL 取得」などが含まれており、かなり遊べるアプリになりそうです。

URL 取得は GET に限らず POSTPUT も可能で、簡単なリクエストであれば iPhone からサクッと実行できます。簡易 curl のように使えます。

SSH では複数のコマンドを一度に実行できるほか、他アクションとの連携も可能です。

f:id:yuu2634:20180920222607p:plain


iOS 12 で Apple 公式アプリ「ショートカット」を使用

これらの操作には、iOS 12 以降でサポートされている Apple 提供の無料アプリ「ショートカット」を使用します。

「ショートカット」アプリで実行できるアクションは多数ありますが、特に面白そうなものをピックアップしてみました。

  • 指定した URL にリクエストを送信する(POST も可)
  • SSH 経由でコマンドを実行する
  • iPhone のデバイス状態を変更する

f:id:yuu2634:20180920215904p:plain

プログラミングのように、ユーザ入力を受け付けたり、変数操作やループ処理も実行できます。(小さい画面でポチポチ組むのは辛いかもですが)

f:id:yuu2634:20180920215906p:plain

これらを組み合わせることで、幅広いアクションが可能となります。


iPhone から SSH コマンドを実行する

App Store から「ショートカット」アプリをインストールしておきます。

アプリを起動後、ショートカットを作成 をタップ。

f:id:yuu2634:20180922110550p:plain

アクションの検索欄が出てくるので ssh を検索して選択。

f:id:yuu2634:20180920224702j:plain

接続情報とコマンドを入力し、上部中央にある実行ボタンで開始。

f:id:yuu2634:20180920225219j:plain

結果が出力されました。アクションを後ろに繋げると、この文字列がパイプのように渡されていきます。

(複数アクションを組み合わせたサンプルは後述します)

右上の変なボタンから、保存する際の名称やアイコンが設定可能です。

ホーム画面やウィジェットからワンタップ実行

作成した処理は、ホーム画面やウィジェットに追加できます。

アイコン色やロゴも自由に設定可能です。

f:id:yuu2634:20180920224157p:plain

特にウィジェットは便利で、アプリを立ち上げずにサクッと実行できます。家電操作系のコマンドと特に相性が良いでしょう。

iPhone で REST API を叩いて JSON をパースする

せっかくなので、一つ例を作ってみました。

以下の URL にリクエストを投げ、スプラトゥーン2の現在のステージ情報を JSON で取得、JSON をパースしてステージ情報だけを抜き出してみます。

https://spla2.yuu26.com/regular/now

今回の要件を実現するためには、5種類のコンポーネントを用います。

  • URL コンポーネントで、REST API の情報を指定
  • 取得コンポーネントで、URL のレスポンスを取得(メソッドは GET)

f:id:yuu2634:20180920221526p:plain


今回取得したいデータは、JSON 内の .result.maps[] となります。

  • パース用コンポーネントで、.result を抽出
  • パース用コンポーネントで、.maps を抽出

f:id:yuu2634:20180920222123p:plain

テキストのみ抽出できました。取得結果が2件あるため、横フリックで確認できます。


仕上げとして、通知メッセージに出力します。

  • 結合コンポーネントで、2項目を改行で繋げる
  • 通知コンポーネントで、結果を通知させる

f:id:yuu2634:20180922010359p:plain

これで完成です。(作業中にステージが変わってしまいましたが)

ウィジェットから呼び出すと、ワンタップでステージ情報を確認できます。

f:id:yuu2634:20180922010751p:plain


なお、ここで使用した REST API の詳細については、イカの記事に書いてあります。 blog.yuu26.com


ちなみに User-Agent は以下の値でした。URLエンコードで「ショートカット」ですね。

%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88/700 CFNetwork/974.2.1 Darwin/18.0.0


ギャラリーで公開されているショートカットを使う

自分で作成するだけでなく、公開されているショートカットも利用できます。
「指定した URL を iCloud にダウンロード」というサンプルも。

f:id:yuu2634:20180922105544p:plain


作成したショートカットを共有する

ギャラリーへの投稿機能はありませんが、作成したショートカットは別のユーザに共有できます。ただのリンクなので SNS でシェアすることも容易です。

f:id:yuu2634:20180922110830j:plain

参考として、ナワバリバトルのリンクを張っておきます。
https://www.icloud.com/shortcuts/0e4cc2619d3740509faed8d0826a3a40


まとめ

iPhone で利用できる公式アプリ「ショートカット」を紹介しました。

利用できるアクションが豊富なため、外部のシステムや API と連携させて遊べる面白いアプリです。

iOS 12 を利用している方は、ぜひお試しください。


blog.yuu26.com

AWS ALB を HTTPS リダイレクトサーバ&メンテナンスサーバとして利用する

概要

AWS の ALB (Application Load Balancer) に新機能がリリースされ、リダイレクトおよび固定レスポンスを返せるようになりました。 公式アナウンス

ALB 単体でレスポンスを返せるため、様々な活用法が考えられます。

  • HTTPS へのリダイレクトに使用する
  • メンテナンス時の静的ページを ALB から返す
$ curl -I http://example.yuu26.com/
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0  ←←← ALB 単体でリダイレクトを返却できる!
Location: https://example.yuu26.com:443/

今回は example.yuu26.com でアクセスできる ALB を作成して検証しました。

ALB の HTTPS リダイレクトを設定する

リスナーの設定にある「ルールの表示/編集」から入れます。HTTP: 80 の項目を変更。

f:id:yuu2634:20180808003241p:plain


画面上の鉛筆マーク、画面左の鉛筆マークとクリックし、編集画面を開きます。今入っている転送先は不要なので、ゴミ箱マークで削除。 f:id:yuu2634:20180808003816p:plain


「アクションの追加」→「リダイレクト先」を選べば OK です。転送先のポート番号は HTTPS なので「443」を入力。チェックマーク→更新 をクリックして保存。 f:id:yuu2634:20180808004200p:plain


curl で呼んでみると awselb/2.0 なるサーバでリダイレクトされたことが分かります。

$ curl -I http://example.yuu26.com/
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0
Location: https://example.yuu26.com:443/


ALB をメンテナンスサーバとして利用する

次は、HTTPS のリスナーに固定ページを設定してみます。

「アクションの追加」→「固定レスポンスを返す」を選べば OK です。任意のレスポンスコード、Content-Type、レスポンス本体の HTML を設定します。

f:id:yuu2634:20180808005625p:plain


上記で設定した内容のレスポンスが返ってくるようになりました。

$ curl --verbose https://example.yuu26.com/
HTTP/2 503
server: awselb/2.0
content-type: text/html; charset=utf-8

<html>
Under maintenance.
</html>

f:id:yuu2634:20180808012940p:plain

ステータスコードを指定できるため、503 とすることでメンテナンスサーバ代わりになるかもしれません。(現時点では日本語未対応ですが……)


シンプルな HTTPS サーバとして ALB を利用する

HTTPS で特定のレスポンスを返すだけであれば、上記2つを組み合わせて ALB 単体で実現できます。別途 Web サーバを用意する必要がありません。

HTTP リスナーにリダイレクト、HTTPS リスナーに固定レスポンスを設定すれば OK です。

$ curl -LI http://example.yuu26.com/
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0
Location: https://example.yuu26.com:443/

HTTP/2 200
server: awselb/2.0
content-type: text/html; charset=utf-8


まとめ

  • ALB だけでリダイレクトができるようになりました
  • ALB だけで固定レスポンスが返せるようになりました
  • レスポンスコードやリダイレクト先は任意に設定可能です

フル HTTPS 化が広がるなか、リダイレクトを使う機会は増えているように感じます。Web サーバ側の設定を追記することなく ALB 単体で済むのはとても便利ですね。


前回の記事がさっそく不要になってしまいました。変化が早い。。。 blog.yuu26.com

S3 + CloudFront を HTTPS 対応リダイレクトサーバとして活用する

概要

AWS S3 のウェブサイトホスティング機能にはリダイレクト機能があります。

S3 単体では HTTP のリクエストが捌けますが、CloudFront を組み合わせることで HTTPS にも対応できます。EC2 や Lambda を用意する必要もありません。

今回は、例として https://hoge.yuu26.com へのアクセスを https://blog.yuu26.com にリダイレクトさせてみます。


S3 バケットのリダイレクト機能を有効化

S3 コンソール から新規バケットを作成します。


ドメイン名に合わせて hoge.yuu26.com で作成しました。好きなリージョンを選んだだけで残りはすべてデフォルト設定です。 f:id:yuu2634:20180708230010p:plain


バケットのプロパティから Static website hosting の設定を有効化します。リダイレクト先のドメイン名とプロトコル欄を埋めます。 f:id:yuu2634:20180708235402p:plain

画面に記載されているエンドポイント (xxxxx.s3-website-xxx.amazonaws.com) をメモしておきます。


curl で呼び出してみるとリダイレクトされることが確認できます。

$ curl -I http://hoge.yuu26.com.s3-website-ap-northeast-1.amazonaws.com
HTTP/1.1 301 Moved Permanently
Location: https://blog.yuu26.com/
Server: AmazonS3


ACM で CloudFront 用の証明書を取得

S3 のウェブサイトホスティングでは、独自ドメインの HTTPS リクエストを受け付けられません。そのため、一度 CloudFront を経由することで対応します。

ACM (Amazon Certificate Manager) から証明書を発行しておきます。無料です。

f:id:yuu2634:20180708232319p:plain


注意点として、CloudFront で利用する証明書は バージニア北部リージョン (us-east-1) で取得する必要があります。東京リージョンで取得しても使えません。


CloudFront を組み合わせて HTTPS 対応

CloudFront の Distribution (Web) を新規作成します。

  • Origin Domain Name : S3 のウェブサイトホスティング用エンドポイント
  • Viewer Protocol Policy : HTTP and HTTPS
  • Alternate Domain Names (CNAMEs) : ドメイン名 (hoge.yuu26.com)
  • SSL Certificate : Custom SSL Certificate から ACM で作成した証明書を選択


オリジンには S3 のウェブサイト用エンドポイントを入力します。予測で出てくる S3 のバケット名ではないため注意が必要です。

f:id:yuu2634:20180708235320p:plain


設定が有効になれば準備完了です。数分~長いときは数時間ほどかかります。

f:id:yuu2634:20180708234449p:plain


curl でも確認しておきます。

$ curl -I http://dyzmyxzffsq8f.cloudfront.net
HTTP/1.1 301 Moved Permanently
Location: https://blog.yuu26.com/
Server: AmazonS3
X-Cache: Miss from cloudfront

$ curl -I https://dyzmyxzffsq8f.cloudfront.net
HTTP/2 301
location: https://blog.yuu26.com/
server: AmazonS3
x-cache: Hit from cloudfront


Route 53 で ALIAS レコードを設定

CloudFront 経由でリダイレクトされることを確認したら、Route 53 に登録します。

今回は hoge.yuu26.comdyzmyxzffsq8f.cloudfront.net となるように設定します。CNAME でも良いのですが、向き先が AWS 内部なので ALIAS レコードが適しています。

f:id:yuu2634:20180708235714p:plain


独自ドメインで、HTTP および HTTPS のリダイレクトができるようになりました。

$ curl -I http://hoge.yuu26.com
HTTP/1.1 301 Moved Permanently
Location: https://blog.yuu26.com/
Server: AmazonS3
X-Cache: Hit from cloudfront

$ curl -I https://hoge.yuu26.com
HTTP/2 301
location: https://blog.yuu26.com/
server: AmazonS3
x-cache: Hit from cloudfront


まとめ

  • S3 と CloudFront を組み合わせて HTTPS 対応のリダイレクトサーバにしました
  • EC2 や Web サーバを用意することなくサーバレスで実現できます
  • CloudFront 用の証明書は us-east-1 の ACM で発行しましょう

規模にもよりますが、リダイレクトのみであれば S3 や CloudFront の費用も無視できるレベルかと思います。機会があればぜひご活用ください。


【追記】Application Load Balancer (ALB) でも同様の処理が可能となりました。 blog.yuu26.com

Route 53 のレコードを S3 に定期バックアップする

概要

Route 53 の設定を定期的に S3 バックアップする仕組みが構築できたため、使用したツールやスクリプトを紹介します。

AWS Lambda への実装も考えられますが、今回はサーバ上での定期実行としています。


S3 バケット作成

まずはバックアップ格納先の S3 バケットを用意します。バケット内に Route 53 専用のディレクトリを作成しました。

f:id:yuu2634:20180620205932p:plain


S3 書き込みポリシー作成

必要なディレクトリにのみ書き込める権限を用意します。以下のような IAM ポリシーを s3-backup_route53 として作成しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::hoge-backup/route53/*"
        }
    ]
}


IAM ユーザ作成

スクリプトが利用するためのユーザを作成します。route53-backup というユーザ名で、以下2つの権限を付与しました。

  • AmazonRoute53ReadOnlyAccess ※Route 53 の読み取り用
  • s3-backup_route53 ※S3 の書き込み用

f:id:yuu2634:20180620211634p:plain


AWS プロファイル登録

作成した IAM ユーザのアクセスキーを任意のサーバに登録します。今回は明示的に route53-backup という名称でプロファイル保存しています。

$ aws configure --profile route53-backup
AWS Access Key ID [None]: AKIAIXXXXXXXXXXXXXX
AWS Secret Access Key [None]: HTFqyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
Default region name [None]: ap-northeast-1
Default output format [None]: json


cli53 準備

Route 53 をコマンドから操作するツール「cli53」を活用します。Releases ページ から環境に適合したファイルを選んでダウンロードしてきます。

# wget -O /usr/local/bin/cli53 https://github.com/barnybug/cli53/releases/download/0.8.12/cli53-linux-amd64
# chmod +x /usr/local/bin/cli53

$ cli53 -v
cli53 version 0.8.12


先ほど登録した AWS プロファイルが利用できるかテストします。Route 53 で管理しているゾーンが取得できれば OK です。

$ cli53 list --profile route53-backup
ID        Name         Record count Comment
ZS5XXXXX  yuu26.com.   16
Z2DXXXXX  hoge.local.  3


バックアップスクリプト作成

全レコードをバックアップするためにスクリプトを作成します。


初めにゾーン一覧を取得した後、レコード内容をテキストファイルに書き出す仕様としました。これらを S3 に転送するまでがスクリプトの処理です。

バックアップ先/
  ├ _zone-list.txt  ←ゾーン一覧
  ├ yuu26.com.    ← yuu26.com. の全レコード
  └ hoge.local.    ← hoge.local. の全レコード


S3 転送結果確認

スクリプト実行後、S3 に格納されたことを確認します。
問題がなければ cron 等で定期実行の設定をして完了となります。

f:id:yuu2634:20180620214746p:plain


参考リンク


まとめ

  • Route 53 のバックアップを自動化しました
  • Route 53 をコマンド操作するツール「cli53」を活用しました
  • 取得したファイルは S3 に格納しています

冒頭に書きましたが Lambda 上で定期実行させたり、そもそも Route 53 の設定自体を Git 等でバージョン管理すると、よりスマートかもしれません。

RTX1210 で DHCP リース時間を強制する方法

概要

RTX1210 の DHCP サーバ機能を利用して、リース時間を強制する方法を紹介します。

RTX シリーズのルータでは expiremaxexpire の2つの設定を適用 することで、クライアントの要求に関わらずリース時間を制限することができます。

DHCP リース時間の決定方法

IP アドレスのリース時間は DHCP サーバにより指定されますが、クライアント側が リース時間の希望を出す ことも認められています。

ルータ指定のリース時間を超えている端末が発見されて原因を調査したところ、上記の仕様があることを知りました。対策として後述の設定を適用しています。


expire と maxexpire の違い

RTX シリーズのルータには、リース時間に関する設定項目が2つ存在します。

expire : デフォルトのリース時間です。クライアントからの要求が特になければこのオプションで指定した時間が適用されます。

maxexpire : リース時間の上限です。クライアントからリース時間の要求があった場合でも、このオプションで指定した時間を上回ることはできません。


設定前後の比較

スコープ設定の末尾に maxexpire を追加して検証しました。

dhcp scope 1 10.0.xxx.10-10.0.xxx.199/24 gateway 10.0.xxx.1 expire 2:00 maxexpire 2:00


設定前(expire 2:00 のみ)→ 24時間

1: eth0:
    inet 10.0.xxx.91/24 brd 10.0.xxx.255 scope global dynamic eth0
       valid_lft 86400sec preferred_lft 86400sec

設定後(expire 2:00, maxexpire 2:00)→ 2時間

1: eth0:
    inet 10.0.xxx.91/24 brd 10.0.xxx.255 scope global dynamic eth0
       valid_lft 7200sec preferred_lft 7200sec


クライアントの環境に関わらず最大2時間のリースとなったことが確認できます。


参考記事

DHCP の仕様および、ルータの設定コマンドについて下記資料を参考にしました。


まとめ

  • RTX1210 で DHCP リースの最大時間を制限しました
  • DHCP のリース時間はクライアント側から要求されることがあります
  • 完全に制御したい場合は expire に加えて maxexpire も設定が必要です

H2O + Let's Encrypt で SSL Server Test A+ 評価を取る設定

概要

H2O と Let's Encrypt を利用して、SSL 脆弱性診断サービス SSL Server Test で最高ランク A+ を取得できたため、設定内容を公開します。

f:id:yuu2634:20180618235626p:plain

(注)ランク A+ 達成後にも設定を複数追加しているため、下記の内容を全て揃える必要はありません。よりセキュアにするための項目も含まれています。


環境

今回利用した環境を以下に示します。必ずしも同一バージョンでなくても実現は可能です。

  • CentOS 7.5 (1804)
  • OpenSSL 1.0.2k
  • H2O 2.2.5
  • Let's Encrypt
  • サイトは完全 HTTPS 化済み


H2O の設定

h2o.conf の中から評価に影響する部分のみを抜粋して解説します。

hosts:
  "*:443":
    listen:
      port: 443
      ssl:
        minimum-version:  TLSv1
        certificate-file: "/etc/letsencrypt/live/xxxxxxxx/fullchain.pem"
        key-file: "/etc/letsencrypt/live/xxxxxxxx/privkey.pem"
        cipher-preference: server
        cipher-suite: "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:!DSS"
    paths:
      "/":
        file.dir: "/var/www/html"

    header.add: "Strict-Transport-Security: max-age=31536000"


HTTPS 通信の最低バージョンを TLSv1 としましたが、必要に応じて TLSv1.2 などに変更します。証明書と鍵は、Let's Encrypt で生成される場所を利用しています。

ssl:
  minimum-version:  TLSv1
  certificate-file: "/etc/letsencrypt/live/xxxxxxxx/fullchain.pem"
  key-file: "/etc/letsencrypt/live/xxxxxxxx/privkey.pem"


cipher-preference: server で、クライアント側ではなくサーバ側の暗号設定を優先させます。その上で、 cipher-suite: で利用できる暗号スイートを限定しています。

cipher-preference: server
cipher-suite: "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:!DSS"

ここは実際にテストを流して、指摘された暗号スイートを地道に取り除きました。OpenSSL 暗号スイート名のマッピングページ が参考になります。


HSTS の設定

ブラウザに HTTPS を強制させるための HSTS を設定します。この項目は一度設定すると取り消すことが困難なため、ただコピペせずに意味を理解してから設定してください。

header.add: "Strict-Transport-Security: max-age=31536000"

HSTS を設定する前提として、該当するドメインのリソースは全て HTTPS でアクセスできるようにしておきます。サイトの完全 HTTPS 化後に設定しましょう。


CAA レコードの設定

上記までで A+ 評価は取得可能ですが、追加設定を行ないました。DNS に CAA レコードを登録すると、証明書発行元の認証局を指定することができます。

Let's Encrypt の認証局を指定することで、それ以外の認証局では証明書を発行できなくなります。(全認証局が対応しているわけではないですが)

f:id:yuu2634:20180618234440p:plain

Route53 上で CAA レコードを登録し、dig コマンドで確認しました。CAA の問い合わせに対応していない場合は G Suite Toolbox などでも確認できます。

$ dig +short spla2.yuu26.com CAA
0 issue "letsencrypt.org"

SSL Server Test でも認識されました。 f:id:yuu2634:20180618234955p:plain


まとめ

  • H2O + Let's Encrypt で A+ 評価を取得しました
  • 暗号スイートの限定と HSTS の有効化がポイントです
  • 可能であれば CAA レコード も設定しましょう

今回サンプルとして出した診断結果は次のリンクから確認できます。 https://www.ssllabs.com/ssltest/analyze.html?d=spla2.yuu26.com