一覧SP-18-2 · 脆弱性管理・ASM:資産と弱点の発見

外部公開資産の特定

発見した候補と管理主体が確認できた資産を分け、追加確認すべき情報を示します。

説明

ASMは外部から見える名前、アドレス、証明書、サービス応答などを使って露出を調べます。共有IPや似た名称だけでは、その資産が自組織の管理下にあると確定できません。

固定DNS・応答資料と公開試験証明書を読み、管理台帳へ照合します。新しく見つかったホストと、同じIPを共有する別ホストを調べます。

発見した候補と管理主体が確認できた資産を分け、追加確認すべき情報を示します。

1名前とアドレスの対応を読む

観測時刻tを含む固定DNS資料です。

from sp18 import * from sp02 import show名前とアドレスの対応を読む db=connect() show(db,"SELECT * FROM dns ORDER BY t,host")

proxyとunrelatedは同じ192.0.2.30です。共有アドレスでは別の利用者やサービスが同居する場合があります。

2共有IPから候補を抽出する

proxyと同じIPを持つ名前を取得します。

show共有IPから候補を抽出する(db,"SELECT host FROM dns WHERE ip=(SELECT ip FROM dns WHERE host='proxy.example.test') ORDER BY host")

2件出ます。IPの一致は関連候補の抽出に使えますが、所有の確証には不足します。

3証明書の名前を開く

公開試験証明書のSubject Alternative Nameを読みます。

cert=x509.load_pem_x509_certificate(CERT_PATH.read_bytes()) names=cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value.get_values_for_type証明書の名前を開く(x509.DNSName) print(names)

proxy.example.testが含まれます。証明書が示す名前と、現在の管理台帳の所有者は別の情報です。

4同じ証明書を識別する値を計算する

DER形式の証明書全体をSHA-256へ渡します。

from cryptography.hazmat.primitives import serialization print(hashlib.sha256同じ証明書を識別する値を計算する(cert.public_bytes(serialization.Encoding.DER)).hexdigest())

フィンガープリントは証明書の同一性を比較する値です。名称や表示文字列を曖昧に比較する代わりに使えます。

5管理台帳へ照合して未登録を残す

LEFT JOINで未登録のホストも表示します。

show(db,"SELECT d.host,i.owner,i.account FROM dns d LEFT JOIN管理台帳へ照合して未登録を残す inventory i USING(host) ORDER BY d.host")

proxyはteam-a/account7に対応します。他の2件の所有者は未確認です。

6新たに発見した公開資産と応答を対応付ける

20秒以降に発見された名前を応答資料へ照合します。

show新たに発見した公開資産と応答を対応付ける(db,"SELECT d.host,d.t,r.status,r.server FROM dns d LEFT JOIN response r USING(host) WHERE d.t>=20")

new.example.testに200応答があります。HTTPで到達できる証拠と、組織への所属の証拠を分けて扱います。

7所属確認後に台帳を更新する

account7の資源一覧で所属を確認したという固定条件で追加します。

db.execute("INSERT INTO inventory VALUES ('new.example.test','team-a','account7')") show所属確認後に台帳を更新する(db,"SELECT d.host,i.owner FROM dns d LEFT JOIN inventory i USING(host) ORDER BY d.host")

newの所属は埋まり、unrelatedはNULLのままです。裏付けのある対象だけを管理資産へ取り込みます。

まとめ

共有IPや名前の類似だけで所有を確定しません。

観測時点と証明書の同一性を記録します。

外部露出と管理台帳の所属を照合します。

操作履歴と解説を振り返れます。

Python 3.15 / 固定scan資料・公開試験証明書

1
from sp18 import * from sp02 import show db=connect() show(db,"SELECT * FROM dns ORDER BY t,host")
host | ip | t
proxy.example.test | 192.0.2.30 | 10
unrelated.example.test | 192.0.2.30 | 10
new.example.test | 192.0.2.31 | 20
2
show(db,"SELECT host FROM dns WHERE ip=(SELECT ip FROM dns WHERE host='proxy.example.test') ORDER BY host")
host
proxy.example.test
unrelated.example.test
3
cert=x509.load_pem_x509_certificate(CERT_PATH.read_bytes()) names=cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value.get_values_for_type(x509.DNSName) print(names)
['proxy.example.test']
4
from cryptography.hazmat.primitives import serialization print(hashlib.sha256(cert.public_bytes(serialization.Encoding.DER)).hexdigest())
f165a5515aceda9551c834c820612d047fa89990eeeb3804c7749c37ec1119e8
5
show(db,"SELECT d.host,i.owner,i.account FROM dns d LEFT JOIN inventory i USING(host) ORDER BY d.host")
host | owner | account
new.example.test | NULL | NULL
proxy.example.test | team-a | account7
unrelated.example.test | NULL | NULL
6
show(db,"SELECT d.host,d.t,r.status,r.server FROM dns d LEFT JOIN response r USING(host) WHERE d.t>=20")
host | t | status | server
new.example.test | 20 | 200 | sample-http
7
db.execute("INSERT INTO inventory VALUES ('new.example.test','team-a','account7')") show(db,"SELECT d.host,i.owner FROM dns d LEFT JOIN inventory i USING(host) ORDER BY d.host")
host | owner
new.example.test | team-a
proxy.example.test | team-a
unrelated.example.test | NULL

演習完了