はじめに
この記事はDocker2 Advent Calendar 2016 の20日目の記事です.
所属している部活の部内コンテストで,部員にDockerの宣伝も兼ねてOSコマンドインジェクションが出来るSlack botを作ったので,そのことについて書きます.
動機
元々オンラインジャッジに興味がありDocker実戦活用ガイド を読んで自分も似たようなものを開発したい,部活のメンバーにDockerを布教したいなどの思いから開発しました.
またideoneのようなオンラインコンパイラのAPIを利用しなかったのは自身の勉強のためです.
Dockerとは
Dockerとはコンテナ型仮想化を行うソフトウェアのことで,起動が早く軽量なことが特徴です.オンラインジャッジは任意コードを実行可能なサービスであり,環境が破壊されないように仮想化技術などで保護してやる必要があります.また,レスポンスの速さを考えるとDockerはその軽量さからオンラインジャッジに向いていると言えます.
OSコマンドインジェクションとは
ググると次のように書いてありました.
閲覧者からのデータの入力や操作を受け付けるようなWEBサイトで、プログラムに与えるパラメータにOSに対する命令文(コマンド)を紛れ込ませて不正に操作する攻撃。
作ったもの
odanado/slackbot-os-command-injection においてあります.
botアカウントの取得
https://slack.com/apps/build を開きます.
右のMake a Custom Integration
を選択します.
Bots
を選択します.
作りたいbotの名前を入力します.今回はos-command-injection
という名前にしました.
これでbotアカウントの取得は完了です.
API Token
を控えておきます.
Docker in Docker
Dockerコンテナの中でDockerを利用することはDocker in Dockerと呼ばれ公式のリポジトリでそのイメージが配布されていました.
https://hub.docker.com/_/docker/
Docker in Dokcerを実現する方法には2種類あり http://qiita.com/sugiyasu-qr/items/85a1bedb6458d4573407 で解説されています.
今回は,ホストマシン上の Docker daemon を共有することでDockerの中でDockerを利用しました.
そのためdocker-compose.yml
ではホスト側のdocker.sock
をコンテナにマウントしています.
python-rtmbot
言語は普段書き慣れているpython
を使い,Slack botのフレームワークを調べるとpython-rtmbot
がヒットしたのでこれを利用しました.
使い方としてはplugins
以下に自分のbot用のディレクトリを掘り,その中にメソッドprocess_message
を持つpythonスクリプトを配置するだけです.process_message
の引数data
にbotが参加しているメッセージが流れてくるのでそれを処理してやります.
リソースの割り当て
任意コマンドを実行するコンテナにはDocker実戦活用ガイドを参考にある程度の制限を設けています.
StartArgs = {}
StartArgs['--net'] = 'none'
StartArgs['--cpuset-cpus'] = '0'
StartArgs['--memory'] = '128m'
StartArgs['--memory-swap'] = '128m'
StartArgs['-w'] = '/workspace'
StartArgs['--hostname'] = 'os-command-injection'
StartArgs['--ulimit'] = ['fsize=1000000']
StartArgs['--pids-limit'] = '10'
今回の場合だと,ネットワークは無効,CPUは0番目を割り当てる,メモリとスワップは128MB,生成できるファイルの上限は1MB,プロセスの上限は10個となっています.
実行方法
$ git clone https://github.com/odanado/slackbot-os-command-injection
$ cd slackbot-os-command-injection/
$ docker-compose run -d -e SLACK_TOKEN=$SLACK_TOKEN bot
OSのコマンドを実行する環境だけでなく,botが動作する環境もDokcer上で構築したため,新しいソフトウェアのインストールをすることがなく,少ないコマンドをただ叩くだけで動作します.美しい