概要
OpenSSH の緊急度の高い脆弱性 CVE-2024-6387 (regreSSHion) が公開されました。リモートコード実行の可能性があるため、影響を受けるサーバーでは早期の OpenSSH のアップデートが推奨されており、対応に追われている方も多いと思います。
取り急ぎ対処が必要なのは、脆弱性があるバージョンのOpenSSHを実行している外部に公開されたホストです。OpenSSH に含まれる ssh-keyscan コマンドを使えば、ホストで実行中の OpenSSH サーバーのバージョンをホストの外部からでも調べることができます。
今回は、AuzreのパブリックIPアドレスのリソースをリストアップして、それらのホストに実際にアクセスしてOpenSSHのバージョンを調べるBashスクリプトを作ってみましたので紹介します。
スクリプト
list.sh
と scan.sh
の2つのスクリプトにより構成されます。実行には Azure CLI (az コマンド) が必要です。ホストのスキャンには ssh-keyscan コマンドを使用します。
#!/bin/bash
tab=$'\t'
az account list -o tsv --query "[].[id,name]" |
while read id name; do
az network public-ip list --subscription $id -o tsv --query "[].[ipAddress,id]" |
while read ip id; do
IFS=/ read a b c d e f g h i j <<< $id
echo "$ip$tab$name($c)$tab$e$tab$i"
done
done
#!/bin/bash
tab=$'\t'
while read ip rem; do
scan=$(test "$ip" != None && ssh-keyscan $ip 2>&1 | head -1)
echo "$ip$tab${rem%$tab#*}$tab# ${scan#\# }"
done
使用法
az login
でAzureの認証を済ませたあと、 list.sh
でパブリックIPアドレスリソースのリストを生成し、次に scan.sh
でそのIPアドレスのホストをスキャンします。OpenSSHサーバーに接続できたホストについてそのバージョンを出力します。
$ az login
$ ./list.sh >hosts.txt
$ ./scan.sh <hosts.txt >result.txt
2つのスクリプトをパイプでつなげて実行することも可能です。
$ az login
$ ./list.sh | ./scan.sh >result.txt
出力ファイル result.txt
は次回の scan.sh
実行の入力にすることもできます。なお入力と出力をうっかり同じファイル名にすると中身が消えてしまいますので注意してください。
$ ./scan.sh <result.txt >result.txt # result.txt が空になる
スクリプト出力の説明
list.sh
を実行すると、次のような各行ごとにタブ文字区切りのテキストを出力します。
<IPアドレス> <サブスクリプション名(サブスクリプションID)> <リソースグループ名> <リソース名>
以下は出力例です。
20.37.101.104 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_almalinux9 almalinux9-ip
172.207.241.131 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_freebsd141 freebsd141-ip
52.156.56.199 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_rhel94 rhel94-ip
20.37.97.17 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_ubuntu2204 ubuntu2204-ip
104.41.185.6 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_ubuntu2404 ubuntu2404-ip
None Azure Sub B(bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb) VM_dxdt1 dxdt1
20.37.106.122 Azure Sub B(bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb) VM_coder1 coder1
IPアドレスが None
となることがありますが、これは動的なパブリックIPアドレス(Basic)のリソースで仮想マシンが停止状態であるためにIPアドレスが割り当てられていない場合などが該当します。
scan.sh
は入力ファイルの各行の最初のフィールドをIPアドレスとして ssh-keyscan コマンドを実行し、その結果で各行の末尾の #
文字以降を置き換えて出力します。#
文字がなければ追加します。
以下は出力例です。
20.37.101.104 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_almalinux9 almalinux9-ip # 20.37.101.104:22 SSH-2.0-OpenSSH_8.7
172.207.241.131 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_freebsd141 freebsd141-ip # 172.207.241.131:22 SSH-2.0-OpenSSH_9.7 FreeBSD-20240701
52.156.56.199 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_rhel94 rhel94-ip # 52.156.56.199:22 SSH-2.0-OpenSSH_8.7
20.37.97.17 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_ubuntu2204 ubuntu2204-ip # 20.37.97.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10
104.41.185.6 Azure Sub A(aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa) VM_ubuntu2404 ubuntu2404-ip # 104.41.185.6:22 SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.3
None Azure Sub B(bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb) VM_dxdt1 dxdt1 #
20.37.106.122 Azure Sub B(bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb) VM_coder1 coder1 #
スキャンに成功したホストでは # SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.11
のような結果文字列となりOpenSSHのバージョンやディストリビューション情報がわかります。
Linuxの場合はDebian系であれば対処済みのパッケージバージョンかどうかもわかりますが、RHEL系ではその情報は得られないようです。
結果文字列が空の場合は次のような理由が考えられます。
- 仮想マシンが起動していない
- スクリプトを実行したホストから標準SSHポートに到達できない
空であることは対策が完了したといえるわけではないことに注意してください。 host.sh の出力のアドレスリストは保存しておき、scan.sh
を時間や場所を変えて実行することをおすすめします。
ssh-keyscan バージョン文字列リファレンス
Azure Marketplaceで利用可能なOS・ディストリビューションについて、ssh-keyscan によって得られるOpenSSHバージョン・ディストリビューション情報文字列の情報をまとめます。
ディストリビューション | リリース | OpenSSHバージョン | ディストリビューション情報 (脆弱性対処済みバージョン) |
---|---|---|---|
Ubuntu | 22.04 LTS | SSH-2.0-OpenSSH_8.9p1 |
Ubuntu-3ubuntu0.10 |
Ubuntu | 24.04 LTS | SSH-2.0-OpenSSH_9.6p1 |
Ubuntu-3ubuntu13.3 |
Debian | 12 | SSH-2.0-OpenSSH_9.2p1 |
Debian-2+deb12u3 |
RHEL | 9.4 | SSH-2.0-OpenSSH_8.7 |
情報は得られない |
FreeBSD | 14.1 | SSH-2.0-OpenSSH_9.7 |
FreeBSD-20240701 |