SSHの暗号設定

#動機
新たなサーバを準備するにあたって過去の作業メモを読み返したら、まったく念頭になかった作業を発見した。以前セキュリティ監査でポートスキャンが行われた際、SSHで脆弱な暗号方式が使用可能になっていると指摘があり、その時は場当たり的に対応をしてしまったため記憶から消えていたものだ。今回きちんと整理することで記憶を強化しておきたい。

* 2020/12/23 17:03 @ttdodaさんのご指摘に基づき改訂
* 2020/12/23 17:31 再改訂

#予備知識
公開鍵暗号方式についてざっくりとした知識しかないこと自体、不味いと言えば不味いのだけど、まあそれはこの際置いておいてざっくり知識の復習。
*[理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話](https://tkengo.github.io/blog/2015/12/01/https-details/)

セキュリティ監査で指摘されたのはCBCモードは脆弱だから拒絶せよという話だった。ただ具体的にどう脆弱なのかは今ひとつ分からない。そもそも2008年の[大元のアドバイザリCPNI-957037](http://www.cpni.gov.uk/Docs/Vulnerability_Advisory_SSH.txt)にはアクセスできなくなっている。[OpenSSHの見解](http://www.openssh.com/txt/cbc.adv)はそれほどシリアスなものではないと言っており、[OpenSSH 5.2](http://www.openssh.com/txt/release-5.2)でCTRモードを優先にした上で、CBCモードへの攻撃をしにくくする変更が成されている。その後[OpenSSH 6.7](https://www.openssh.com/txt/release-6.7)以降では、デフォルトのsshdはCBCモードが無効になっている。結局どうなのかはわからないのだけど、CTRモードを利用できるならわざわざCBCモードを利用可能にしておく意味はないということか。

#環境
* FreeBSD 12.2-RELEASE-p1
* OpenSSH 7.9p1

#確認法

まず対応しているCipherを確認する。

```shell-session
> ssh -Q cipher
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
rijndael-cbc@lysator.liu.se
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
```

これはクライアントであるsshのバイナリが潜在的に利用可能なCipherの一覧であって、厳密にはサーバであるsshdのそれと一致している保証はないけれども、まあ普通の環境であれば同じになっているであろう。ご覧の通りバイナリ上CBCモードがサポートされている。

ではサーバで有効になっているCipherはどれだろうか？一番確実なのは、実際に接続したときのデバッグ情報から抽出すること。

```shell-session
> ssh -vv localhost : 2>&1 |grep ciphers |tail -1 |cut -d ' ' -f 4 |rs -c, 0 1 # cut以降は見やすさのためなので省略可
chacha20-poly1305@openssh.com
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
aes128-cbc
aes192-cbc
aes256-cbc
```

おっと、 ~~優先順位は最低だが~~ （@ttdodaさんのご指摘により削除）CBCモードが有効になっている。上流のOpenSSHではデフォルト無効になっているが、FreeBSDでは有効にされているということ。

#設定法

/etc/ssh/sshd_configに`Ciphers`を指定することで設定を変更する。カンマ区切りで羅列していけば良いのだが、プラス記号やマイナス記号をつかってデフォルト設定を変更することもできる（cf. [sshd_config(5)](https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5&manpath=FreeBSD+12.2-RELEASE)）。

```shell-session
> sudo sed -i.orig -f <(echo '/# Ciphers/a\'; echo 'Ciphers -arcfour*,*-cbc') /etc/ssh/sshd_config
> diff -u /etc/ssh/sshd_config{.orig,}
--- /etc/ssh/sshd_config.orig   2020-12-23 15:11:59.422781000 +0900
+++ /etc/ssh/sshd_config        2020-12-23 15:12:14.379629000 +0900
@@ -24,6 +24,7 @@
 #HostKey /etc/ssh/ssh_host_ed25519_key

 # Ciphers and keying
+Ciphers -arcfour*,*-cbc
 #RekeyLimit default none

 # Logging
> sudo service sshd reload
Performing sanity check on sshd configuration.
```

確認する。

```shell-session
> ssh -vv localhost : 2>&1 |grep ciphers |tail -1 |cut -d ' ' -f 4 |rs -c, 0 1 # cut以降は見やすさのためなので省略可
chacha20-poly1305@openssh.com
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
```

無事CBCモードを無効にできた。

#おまけ

クライアント側がどんな暗号方式を使用したがっているのかは`ssh -G <target host>`で調べることができる。

```shell-session
>ssh -G localhost |grep ciphers |cut -d ' ' -f 2 |rs -c, 0 1 # cut以降は見やすさのためなので省略可
chacha20-poly1305@openssh.com
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
aes128-cbc
aes192-cbc
aes256-cbc
```

同様にサーバ側も`sshd -T`で調べることができるが、これは設定ファイルを読み込んだ評価結果を表示しているので、実際に今走っているサーバの状態と一致しているとは限らない。設定ファイルの反映漏れというのはよくあること。

```shell-session
> sshd -T |grep ciphers |cut -d ' ' -f 2 |rs -c, 0 1 # cut以降は見やすさのためなので省略可
chacha20-poly1305@openssh.com
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
aes128-cbc
aes192-cbc
aes256-cbc
```