本専門講座の演習は、演習者各自にインターネットのクラウド上のサーバを1つ割り当て、管理者権限を使って作業を進めます。
演習サーバは実際にインターネットにつながっているため、世界中から絶えず不正侵入を試みる攻撃を受けています。仮に外部から演習サーバへ侵入を許すと、他のシステムに攻撃する踏み台やDDoSを行うノードとして利用され、全く関係のない第3者に迷惑を及ぼすことがあります。
このようなリスクを避けるため、演習サーバ上の作業では細心の注意を払い、演習に必要な作業のみ行ってください。講師やチュータの許可なく、資料に記載されている以外のソフトウェアを演習サーバにインストールしたり、演習に不要なオペレーションを行ったりすることは禁止です。
また、サーバ上で何か不正侵入されているような疑わしい挙動を見つけた場合には、講師・チューター・事務局に速やかに連絡してください。
常にセキュリティリスクを意識して作業に取り組むことが大事です。
事前学習で公開鍵の登録されていますので seccamp アカウントでログインできます。
- 12/12(土) 18:30〜21:00 2:30
- 12/13(日) 9:00〜12:00 3:00
- 12/13(日) 13:00〜14:00 1:00
特に細かい時間割を決めていません。講義中休憩は適宜入れる予定ですが、演習中は自由に休憩をとっても構いません。 体調が悪くなったと感じたら講師やチューターに相談してください。
初日と2日目で会場が異なります。初日の会場ネットワークは、外部へ ssh できないので替りのネットワークを一時的に用意する予定ですが、もしネットワークが提供できなければ初日は講義中心の時間割に切り替えます。 2日目は ssh で作業できる環境で演習を行います。
演習当日に seccamp アカウントのパスワードを伝えます。sudo を使ってパスワードを入力すると管理者権限でコマンドが実行できます。
OSをインストール直後からアップデートをしていないので、演習作業に入る前に環境を apt-get 最新のものに更新します。 おそらく再起動が必要になるので再起動を行います。
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
$ sudo reboot
再起動後 ssh でログインできることを必ず確認してください。もしログインできない場合は講師・チュータに相談してください。
- サーバのエントロピー プール量を確認します。
- 人為的に Disk I/Oを発生させます。
- エントロピー プールが増加したことを確認します。
- /dev/urandom から乱数データを抽出します。
- エントロピー プールが減少したことを確認します。
ubuntu@server21:~$ cat /proc/sys/kernel/random/entropy_avail
340
ubuntu@server21:~$ find / > /dev/null 2>&1
ubuntu@server21:~$ cat /proc/sys/kernel/random/entropy_avail
347
ubuntu@server21:~$ head -10 /dev/urandom > /dev/null
ubuntu@server21:~$ cat /proc/sys/kernel/random/entropy_avail
336
https://nopfs.hokkaido.koulayer.com/exam.pcap にアクセスして pcap データをダウンロードします。
wireshark を起動して exam.pcap を読み込みます。
以下のディレクトリから最新版のソースをサーバにダウンロードします。
-
nginx-1.9系 http://nginx.org/en/download.html
-
openssl-1.0.2系 https://www.openssl.org/source/
-
pcre-8.3系 http://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
-
zlib-1.2系 http://zlib.net/
ダウンロードツールはなんでもいいですが、ターミナルで行うなら wget や curl など使いましょう。
$ wget https://www.openssl.org/source/openssl-1.0.2e.tar.gz
ダウンロードしたソースを展開します。ディレクトリはお好みの場所で構いません。
seccamp@server21:~/src$ tar zxvf nginx-1.9.8.tar.gz
他のソースも展開
全部展開したら nginx のソース中でビルド・インストールします。インストールパスは /usr/local/nginx 以下です。
seccamp@server21:~/src$ ./configure --with-openssl=../openssl-1.0.2e/ --with-http_ssl_module --with-pcre=../pcre-8.38 --with-zlib=../zlib-1.2.8 --with-http_v2_module --with-debug
seccamp@server21:~/src$ make
seccamp@server21:~/src$ sudo make install
Wo Signから発行された証明書のzipファイル中には nginx用の証明書zip (for Nginx.zip) が入っているが、ここでは手動で準備します。
nginxではサーバ証明書と中間証明書を一つのファイルに結合したものを設定ファイルで渡します。ただしサーバ証明書を必ず先頭にする必要があります。
-rw-r--r-- 1 seccamp adm 2300 Nov 29 16:53 1_cross_Intermediate.crt
-rw-r--r-- 1 seccamp adm 2029 Nov 29 16:53 2_issuer_Intermediate.crt
-rw-r--r-- 1 seccamp adm 1708 Nov 29 16:53 3_user_server21.hokkaido.koulayer.com.crt
ここでは server.crt ファイル名をつけます。
seccamp@server21:~/cert$ touch server.crt
seccamp@server21:~/cert$ cat 3_user_server21.hokkaido.koulayer.com.crt >> server.crt
seccamp@server21:~/cert$ cat 2_issuer_Intermediate.crt >> server.crt
seccamp@server21:~/cert$ cat 1_cross_Intermediate.crt >> server.crt
この server.crt と private.key を /usr/local/nginx/conf ディレクトリへコピーします。 private.key が root の read only になっていることを確認します。
seccamp@server21:~/cert$ sudo cp server.crt private.key /usr/local/nginx/conf/
[sudo] password for seccamp:
seccamp@server21:~/cert$ ls -l /usr/local/nginx/conf/private.key
-r-------- 1 root root 1679 Dec 11 18:08 /usr/local/nginx/conf/private.key
/usr/local/nginx/conf/nginx.conf を修正します。ファイルの修正位置は下記の nginx.conf の最終形を参照してください。 http:// は利用しないので、listen 80 が記載されているサーバ設定をコメントアウトします。
# server {
# listen 80;
# server_name localhost;
(中略)
#
# }
次にhttps:// で利用する 443 ssl を listen するサーバの設定部分のコメントを削除して有効にします。 server_name のフィールドに自分のサーバ名(以下の例では server21.hokkaido.koulayer.com)を記載します。 1.3.3でコピーした証明書と秘密鍵ファイルも設定します。
server {
listen 443 ssl;
server_name server21.hokkaido.koulayer.com;
ssl_certificate server.crt;
ssl_certificate_key private.key;
(中略)
}
nginx のサーバを起動させます。
seccamp@server21:~/src/nginx-1.9.8$ sudo /usr/local/nginx/sbin/nginx
seccamp@server21:~/src/nginx-1.9.8$ tail /usr/local/nginx/logs/error.log
2015/12/11 17:18:03 [notice] 3008#0: signal process started
nginx のサーバを強制停止させる場合は -s stop オプションを使います。
seccamp@server21:~/src/nginx-1.9.8$ sudo /usr/local/nginx/sbin/nginx -s stop
seccamp@server21:~/src/nginx-1.9.8$ ps aux |grep nginx
seccamp 3029 0.0 0.0 11740 932 pts/0 S+ 17:19 0:00 grep --color=auto nginx
プロセス起動中に設定ファイル /usr/local/nginx/conf/nginx.conf を変更して、設定再読み込みしたい場合は -s reload オプションを利用します。
seccamp@server21:~/src/nginx-1.9.8$ sudo vi /usr/local/nginx/conf/nginx.conf
seccamp@server21:~/src/nginx-1.9.8$ sudo /usr/local/nginx/sbin/nginx -s reload
ブラウザで自分のサーバにアクセスします。アクセスログ /usr/local/nginx/logs/access.log でアクセスを確認します。
seccamp@server21:~/src/nginx-1.9.8$ tail -f /usr/local/nginx/logs/access.log
210.160.37.27 - - [11/Dec/2015:17:30:36 +0900] "GET / HTTP/2.0" 304 168 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"
nginx の defaultのページが醜いと思う人は自分で好きなようにページを変えてもいいです。 (ただし公序良俗に反しないコンテンツに限ります。) また最後の HTTP/2 の演習で html のディレクトリを変更しますのでそのつもりで。
seccamp@server21:~/src/nginx-1.9.8$ sudo vi /usr/local/nginx/html/index.html
default の設定のままSSLLabのテストを行います。
https://www.ssllabs.com/ssltest/index.html
"Do not show the results on the boards" をチェックすると記録が他人に見られることはありません。 今回は演習目的なので結果を公開する必要なありません、チェックしておきましょう。
2048bit のDHパラメータファイルを生成します。
$ openssl dhparam -out dhparam.pem 2048
seccamp@server21:/usr/local/nginx/conf$ openssl dhparam -text -in dhparam.pem -noout
PKCS#3 DH Parameters: (2048 bit)
prime:
00:bc:17:c2:76:93:f1:83:d0:50:a6:ad:07:49:f3:
20:5a:1d:35:08:cb:da:b9:e5:65:7f:f8:69:ff:df:
be:15:57:16:8e:60:82:2a:98:79:38:e5:35:c6:95:
57:a6:5a:e2:79:34:f2:ff:6b:e5:fd:ab:3a:57:25:
bc:43:ee:a5:ef:d2:55:f6:7b:f3:44:ad:a4:3c:a7:
05:a3:78:d3:fb:39:73:7d:ea:0f:f3:63:a6:84:b0:
3b:ee:fd:59:7e:3c:d0:90:93:b5:88:ab:84:57:cb:
98:0f:94:0a:90:91:d3:8b:af:eb:bb:3a:a5:32:f1:
75:3f:a2:c9:74:00:84:99:c1:95:a6:11:6e:db:f5:
1f:a7:76:db:f2:b3:2d:7e:67:bb:f9:35:4f:cb:10:
fc:c9:9b:9b:6c:d3:61:52:60:82:62:cb:10:2b:c8:
24:3a:a5:02:9f:a5:a4:74:c7:28:95:d0:35:ad:f9:
37:13:ec:b3:75:44:ab:31:9e:7e:59:7b:0d:54:34:
74:d0:ab:5f:9e:f7:a1:47:c5:37:35:2d:a4:5b:26:
b9:35:23:77:fc:2d:bb:2e:74:a7:b4:5d:fd:e9:cf:
4f:8e:de:2f:8a:78:dc:a3:49:e4:29:43:d9:ee:5a:
f0:4b:91:4a:05:19:ff:85:7f:6d:12:8f:c2:9b:f8:
cc:ab
generator: 2 (0x2)
dhparamファイルを /usr/local/nginx/conf ディレクトリにコピーします。 nginx.con の設定ファイルのsslサーバの部分にDHパラメータのファイルを加えます。
ssl_dhparam dhparam.pem;
nginxのプロセスを設定ファイルを読み込みをさせます。
seccamp@server21:/usr/local/nginx/conf$ sudo /usr/local/nginx/sbin/nginx -s reload
[sudo] password for seccamp:
終わったらブラウザで接続を確認します。 再度 SSLLab のテストを行い、A判定が出たら終わりです。 SSLlabの結果にキャッシュが残っている場合はクリアしておきましょう。
A+ のスコアを取るため HSTSヘッダを返すように以下の設定を ssl のサーバに追加します。 max-age は、半年: 15768000秒 に設定しておきます。(長くないとスコアがよくならない)
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains";
nginxのプロセスを再起動し、エラーが出力されていないことを確認したらブラウザーで https ページにアクセスして問題なく表示がされるか確認します。確認後 http:// でアクセスします。ブラウザが自動的に https:// に変換してアクセスできていることを確認します。
ブラウザでの設定を確認するため
chrome://net-internals/#hsts
を開きます。Query Domain に自分のサーバ名を入力し Query ボタンをクリックします。
dynamic_sts_domain: server21.hokkaido.koulayer.com
dynamic_upgrade_mode: STRICT
dynamic_sts_include_subdomains: true
dynamic_sts_observed: 1449822637.075221
dynamic_pkp_domain:
dynamic_pkp_include_subdomains:
dynamic_pkp_observed:
dynamic_spki_hashes:
上記のように mode が STRICT になっていれば成功です。
最後に SSLlab のテストを行います。 A+ のスコアが出れば終了です。
https://nopfs.hokkaido.koulayer.com/exam.pcap のデータを破ります。
WoSignからの証明書は、 https://nopfs.hokkaido.koulayer.com/nopfs.hokkaido.koulayer.com_sha256_en.zip にあります。for Other Server.zip中のサーバサーバ証明書を openssl x509 -text コマンドで出力します。 Modules と Exponent の公開鍵情報が出力されますので、Modulesを因数分解します。
因数分解のヒントは口頭で伝えます。
因数分解の答えである素数(1つだけでよい)と証明書中の公開鍵情報(Modules, Exponent)を https://hokkaido1.hokkaido.koulayer.com/ に入力します。PKCS1形式の秘密鍵データのPEMが出力されます。
Wiresharkから ClientKeyExchange のデータを取得します。バイナリーが扱える環境ならbinary保存のほうが楽です。 テキスト形式でコピーした場合は、xxd を使って Hex 文字列をバイナリー(DER形式)に変換します。
$ cat > encrypted_premaster_secret.txt
0d9909953798f・・・・・721
$ xxd -p -r encrypted_premaster_secret.txt > encrypted_premaster_secret.der
Wiresharkから抽出した暗号化されたPreMasterSecretデータを因数分解して生成した秘密鍵を使って復号化します。 PKCS1形式で暗号化されているので -pkcs オプションが必要です。出力を16進数で表示するため -hexdump をつけます。
$ openssl rsautl -decrypt -pkcs -inkey private.key -in encrypted_premaster_secret.der -hexdump
0000 - ・・・・・・ ..F.y.....)i,`.0
0010 - ・・・・・・ P......}.?C..c..
0020 - ・・・・・・ .x..Z.p..OK..ep.
全体のバイト数と頭の2オクテットのデータを求めてください。
PreMasterSecret取得以降は、
- PreMasterSecretからMasterSecretの求め方、
- MasterSecretから各利用鍵の導出
- AES-GCMのデータ書式
などが必要です。情報は、 http://www.slideshare.net/shigeki_ohtsu/security-camp2015-tls にありますが、RFC5246を直接参照するのもありです。
後は、好きにやってください。解けたら平文データを教えて下さい。 正解だったらTLSコース修了です。
TLS演習で利用したTLSサーバで http2 を有効化します。 まず listen 設定に http2 を追加するだけです。
server {
listen 443 ssl http2;
server_name server21.hokkaido.koulayer.com;
ssl_certificate server.crt;
ssl_certificate_key private.key;
(中略)
}
nginxのプロセスを再読み込みしてブラウザーでアクセスします。
INADEQUITE SECURITY のエラーを以下の設定を追加して修正します。
ssl_ciphers ECDHE+AESGCM:DHE+AESGCM:HIGH:!aNULL:!MD5;
nginxのプロセスを再読み込みしてブラウザーでアクセスします。 WireSharkでTLSハンドシェイクを確認します。 ClientHello/ServerHelloの Extension で ALPN が交換されていることを確認します。
イメージサーバは https://github.com/shigeki/seccamp-imageserver/ から git で取得します。 画像表示用の html ファイルも seccamp-imageserver/html ディレクトリ以下にあるので nginx.conf の設定を変更し / 宛のリクエストが seccamp-imageserver/image を参照するよう設定を変更します。
ここではホームディレクトリ(/home/seccamp/)以下に git clone する場合を例とします。
seccamp@server21:~$ git clone https://github.com/shigeki/seccamp-imageserver/
seccamp@server21:~$ ls -l seccamp-imageserver/
total 16
drwxr-xr-x 2 seccamp adm 4096 Dec 8 13:39 html
drwxr-xr-x 2 seccamp adm 4096 Dec 9 01:14 lib
-rw-r--r-- 1 seccamp adm 1081 Dec 8 13:39 LICENSE
-rw-r--r-- 1 seccamp adm 67 Dec 8 13:39 README.md
html ディレクトリがあることを確認したら nginx.conf の location をこのディレクトリに変更します。 また image server は localhost の port 8080 で動作します。 /image ディレクトリのアクセスを image server 側に回すよう proxy_pass の設定も加えます。 nginx.conf は以下のようになります。
location / {
root /home/seccamp/seccamp-imageserver/html;
index index.html index.htm;
}
location /images {
proxy_pass http://localhost:8080;
}
nginx のプロセスを reload して設定を再読み込みを行い、seccamp-imageserver/lib 以下にある server.js を node から起動します。 (port 8080 なので一般ユーザ権限で動作します。バックグラウンドプロセスにしても構いませんが、標準出力にログが出ます。)
seccamp@server21:~/seccamp-imageserver/lib$ sudo /usr/local/nginx/sbin/nginx -s reload
seccamp@server21:~/seccamp-imageserver/lib$ node server.js
Litening on port 8080
/usr/local/nginx/log 以下のログを見てエラーが出てなければ、ブラウザでトップページを確認します。
トップページからのリンクにある、2つのページを見てみます。 10枚と50枚のイメージの2種類のページです。 http2 でのページの確認が終わったら nginx.conf で http2 の設定を外し、nginx プロセスを再読込してみましょう。 http/1.1 で同じページを見た時にどう表示が変わるか確認してください。
メニューから Chrome Developer Tool を起動し、ネットワークのタブを開けてアクセスしてみましょう。 スライドにあるようHTTPリクエストとレスポンスまでの時間グラフが出力されますので http/1.1 で HoLが発生していることがわかはずです。
今度は html ファイルを自由に変えてみましょう。
<img src="/images/face-00.png"/>
<img src="/images/face-01.png"/>
<img src="/images/face-02.png"/>
face-00.pn の 00 の番号が3で割り切れる番号は泣き顔画像で3秒後にレスポンスが帰ります。(数字は 00-99まで2桁) 自分なりに画像の番号を増やしてどうなるのか確認してみましょう。
nginx.conf の最終形を添付しておきますので、つまずいた時は参考にしてください。
1.3.3 証明書の準備 の
server.cert
はserver.crt
の typo だと思います。