背景
7月24日にGoogle Chrome 68がリリースされ、HTTPSでないサイトには警告が出るようになった。
自分の会社サイトでは、2016年12月から検証開始→2017年4月にHSTS Preloadまで設定完了、としていたので、
今回のChrome 68リリースでは高みの見物をしていたのだけれど、警告があまり目立たないのか意外と騒がれずちょっとがっかり。
私の会社の競合他社で今回SSLに対応したところは皆無だったのだが、
逆に「今後どのタイミングでSSL化するのだろう?」と下世話な興味が湧いたので、
ウェブサイトの常時SSL化対応状況を調べるスクリプトを作ってみた。
作ったもの
概要
他社サイトのHTTPS対応状況を調べてみると、
対応していないサイトではだいたい下記のパターンになることがわかった。
- HTTPS通信ができない
- HTTPSのポート(443/tcp)が空いてない
- 443ポートは開いてるけど、まともに応答しない
- 証明書がおかしい
- 自己署名証明書を使っている
- 証明書の期限が切れている
- SAN(Subject Alternative Name)が入っていない
- 常時SSLのための対応が不足
- HTTPページからHTTPSページへリダイレクトされていない
- HSTSヘッダがない
- HSTS Preloadに登録していない
なので、上記の点についてチェックする仕様とした。
トラストチェーンが正しいかの検証を行うのと、Mixed Contentsが含まれていないかの判定は
コマンドで簡単にはできそうじゃなかったので割愛。
Qualys SSL Labsやtestssl.shなどを使ってください。
(testssl.shのウェブサイトのSSL証明書の期限が切れてる!(笑))
スクリプト
#!/bin/bash
hstspreload=`mktemp`
curl https://cs.chromium.org/codesearch/f/chromium/src/net/http/transport_security_state_static.json -s -o $hstspreload
trap 'rm $hstspreload' EXIT
if [ -p /dev/stdin ]; then
cat -
else
echo $@ | sed -E 's/\s+/\n/g'
fi | while read domain; do
echo "${domain}"
if nmap -p 443 $domain | grep -q "443/tcp open https"; then
echo " Port 443: Open"
else
echo " Port 443: Closed"
continue
fi
cert=`mktemp`
openssl s_client -connect $domain:443 -servername $domain < /dev/null 2>/dev/null | openssl x509 -text >$cert 2>/dev/null
if [ "$?" -eq "0" ]; then
issuer=`grep "Issuer:" $cert | sed -e 's/^\s\+Issuer:\s\+//'`
subject=`grep "Subject:" $cert | sed -e 's/^\s\+Subject:\s\+//'`
if [ "$issuer" = "$subject" ]; then
echo " Issuer: Self Singed (Not OK)"
else
echo " Issuer: "$issuer
fi
startdate=`grep "Not Before:" $cert | sed -e 's/^\s\+Not Before://' | date -f - '+%s'`
enddate=`grep "Not After :" $cert | sed -e 's/^\s\+Not After ://' | date -f - '+%s'`
today=`date '+%s'`
if [ $today -gt $startdate -a $enddate -gt $today ]; then
echo " Date: Valid"
else
echo " Date: Expired"
fi
sancheck=`mktemp`
echo " SAN: Not OK" > $sancheck
grep -A1 "Subject Alternative Name" $cert | sed -e '1,1d' | sed -E 's/\s+DNS://g' | sed -E 's/,/\n/g' | while read i; do
pattern='^'`echo $i | sed -e 's/\./\\\./g' | sed -e 's/\*/[^.]\\\+\\\?/g'`'$'
if echo $domain | grep -q -e $pattern; then
echo " SAN: OK" > $sancheck
break
fi
done
cat $sancheck
rm $sancheck
rm $cert
else
echo " No SSL Certificates"
rm $cert
continue
fi
if curl --head http://$domain 2>/dev/null | grep -q "Location: https://$domain"; then
echo " HTTPS Redirect: Enabled"
else
echo " HTTPS Redirect: Disabled"
fi
hsts=`curl --head https://$domain 2>/dev/null | grep -i "strict-transport-security: "`
if [ "$hsts" != "" ]; then
echo " HSTS: Enabled"
if grep -q `echo $domain | sed -e 's/\www\.//'` $hstspreload; then
echo " HSTS Preload: Enabled"
else
echo " HSTS Preload: Disabled"
fi
else
echo " HSTS: Disabled"
fi
done
使い方
スクリプトの引数に調べたいドメインを並べてください。
./check_https.sh (調べたいドメイン1) (調べたいドメイン2)...
もしくは、別ファイルにドメインのリストを作っておき、パイプでつなげます。
www.cao.go.jp
www.kunaicho.go.jp
www.mof.go.jp
www.moj.go.jp
www.soumu.go.jp
cio.go.jp
cat domains.txt | ./check_https.sh
このやり方は標準入力を受け取れるシェルスクリプト、関数の作成(パイプで繋げられるようにする)を参考にしました。
上記サンプルでは政府のサイトをダミーで入れてます。
HSTS Preloadに登録済みのサイトを調べるため、
毎回6MB程度のファイルをChromiumのリポジトリからダウンロードするので、
ネットワークが細いところではご注意を。
あとwww.
以外のサブドメインではHSTS Preloadに含まれているか正しく判定できません。
相手サーバに対して行儀の悪いことはしていない(443ポートが開いてるかのチェックと、証明書とHTTPヘッダのダウンロードのみ)ので、1日1回チェックする程度であれば問題ないと思うのだけれど、もし問題であれば消します。
出力例
出力は以下のような感じ。
- 443ポートが開いているか
- 証明書のIssuer (Self Signedか、そうでなければ認証局)
- 証明書の期限が切れていないか
- 証明書のSANに自分のサーバのFQDNが入っているか(ワイルドカードにも一応対応)
- HTTPSへのリダイレクトが行われているか
- HSTSヘッダは出力されているか
- HSTS Preloadに登録されているか
を順に調べます。
上記のdomains.txt
にある政府系のサイトを調べた結果は以下のような感じ。
www.cao.go.jp
Port 443: Closed
www.kunaicho.go.jp
Port 443: Open
Issuer: C = JP, O = Japanese Government, OU = GPKI, CN = ApplicationCA2 Sub
Date: Valid
SAN: OK
HTTPS Redirect: Disabled
HSTS: Disabled
www.mof.go.jp
Port 443: Open
Issuer: C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
Date: Valid
SAN: OK
HTTPS Redirect: Enabled
HSTS: Disabled
www.moj.go.jp
Port 443: Open
Issuer: C = JP, O = Japanese Government, OU = GPKI, CN = ApplicationCA2 Sub
Date: Valid
SAN: OK
HTTPS Redirect: Disabled
HSTS: Disabled
www.soumu.go.jp
Port 443: Open
Issuer: C = JP, O = Japanese Government, OU = GPKI, CN = ApplicationCA2 Sub
Date: Valid
SAN: OK
HTTPS Redirect: Disabled
HSTS: Disabled
cio.go.jp
Port 443: Open
Issuer: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA
Date: Valid
SAN: OK
HTTPS Redirect: Enabled
HSTS: Enabled
HSTS Preload: Enabled
感想
この記事を書いている2018年7月30日現在、政府系のウェブサイト(.go.jp)で、HSTSのプリロードまで対応しているのは2件だけ。
マイナポータルは知ってたけれど、政府CIOポータルというサイトは初めて知った。
HSTS Preload対応かどうかはブラウザのソースコードにハードコーディングされているのだけれど、
今後対応サイトが増加していったらどうするのだろう?