証明書情報取得とTIPS
宣言通りスクリプトを作ってみました。
その際のノウハウをつらつらと。
使わせていただいているサービスやパッケージは以下。
https://crt.sh
SSL証明書の事業者であるSECTIGO(旧コモド)の公開してくださっている証明書の検索サイト。
今回のスクリプトでは結構大量にアクセスしてしまうので、心苦しい。。
https://www.radb.net/
別記事でまとめた、ミシガン州の大学群によって設立された団体のサービス(?)を利用させて頂いています。
。。。こういう用途で使うもんじゃないんだろうけど、、、
https://cryptography.io/en/latest/
Pythonの暗号化用パッケージ。
今回はcrt情報のデコードにしか使わないのでオーバスペックな気はしつつですが、デコードだけしかしないパッケージなんてもんも見つかりませんし、素直に使わせていただきます。
証明書の概要情報の取得
$ curl "https://crt.sh/?q=<Your Domain>&?output=json"
これで、対象ドメインの情報をjson形式で取得できます。
'common_name'という要素にCN情報、'name_value'という欄にSANの情報が入ってくるっぽいです。
ただ、厄介なのが、SANについて検索につかったの文字列を含むものに絞り込まれてしまっているようなんですね。。
例えば自組織がXXXX.example.netというドメインを使っているとして。
そこに、メインではないけど関連システムとしてYYYY.example.netも追加シなければいけない時。
YYYY用の証明書を新たに1枚取るのも構成上都合が悪いので、既存のXXXX.example.netの証明書のSANにYYYY.example.netを追加してしまう、、ということがあります。
その場合、XXXX.example.netで検索すると、SANには実はYYYY.example.netが記載されているのですが、crt.shの応答の'name_value'にはYYYY.example.netが入ってこない、ということになります。
これはちょっとうれしくない。
証明書の詳細情報の取得
$ curl "https://crt.sh/?d=<certid>"
最初に取得したjsonについて、'id'という要素があります。
これはcrt.sh上での証明書情報の一意識別子のようなのですが、これを使って、上記を叩くと、証明書の.crtデータをダウンロードさせてもらえます。
非常にありがたい。
。。ありがたいんだけど、この用途だとかなりの量引き抜かせてもらうことになってしまうので、大変申し訳がない、、
証明書の詳細情報の展開
import cryptography import 509
with open('./cert.crt', 'r') as fd:
crt = fd.readline()
# CNの抽出
ce = x509.load_pem_x509_certificate(cert)
st = ce.subject
cns = st.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)
fqdns = [x.value for x in cns]
# SANの抽出
ce = x509.load_pem_x509_certificate(cert)
es = ce.extensions
sans = es.get_extension_for_calss(x509.SubjectAlternativeName)
fqdns = sans.value.get_value_for_type(x509.general_name.DNSName)
コード目視で手打ちしたから、タイポしてたらすみません。
ざっとこんなで、証明書ベースで自身の管理するドメインに紐づく公開(されてしまってる)ドメインがわかります。
作ったもの
こんなです。
https://github.com/nfwprod/certcheck
過去の証明書まで全部遡ってダウンロードしているので、処理に結構時間かかります。
申し訳ないので一回落とした証明書はローカルの.dlo_dumpというフォルダに保存して、2回目以降は聞きに行かないようにしてはいるのですが、怒られそうだなぁ。。