DNS でもセキュアにしたい

本記事に読み終えるころに身に着けている知識

- DNSの虚弱性
- DNSSECの基礎知識

必要とする知識

- DNSの概要

# DNSの虚弱性

## キャッシュポイズニング
以下の内容、及び図は[JPNIC](https://www.nic.ad.jp/ja/newsletter/No40/0800.html)を参照しています。

DNSへの攻撃手段の代表的なものとして、キャッシュポイズニングがあります。

![cache.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/e922b92b-e6a5-d7c4-5e48-bcb87a4f9a26.png)


DNSからの応答のIDを偽装することで、偽の情報をDNSキャッシュに押し込めるというものです。結果、偽りのWebサイトへ誘導しIDやパスワードを盗むことが可能となります。

## なんでこんなことできるのだ

と思う方もいらっしゃると思いますが、DNSは大変古い時代に考案されたものなので、小さいパケットで機能するように考えられています。発行元の身元確認もIDによってのみ行われています。昔の貧弱なネットワークをベースに考えられたものであることをお察し下さい。

## ひと昔前の回避方法

この攻撃自体は、キャッシュする時間(TTL)を長くすることで、攻撃が成功する可能性を軽減できます。そのことから、それほど脅威とは考えられていませんでした。※キャッシュされている場合は、DNSサーバーへの問い合わせが発生しないため。

![ttl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/5b5810e7-0980-131f-6083-b5965ec43ccd.png)


## カミンスキーメソッドの登場で状況が一変

セキュリティ研究者のカミンスキーさんにより、別のアプローチによる攻撃方法があることが示唆されました。
ドメインが保有しないサブドメインを問い合わせ、その応答を偽装して違うDNSサーバーへ誘導する、という手段です。例えば、攻撃対象がwww.example.comであれば、sdfa4q.example.comと問い合わせます。問い合わせるドメイン名を毎回ランダムな別のものにすれば、キャッシュを回避できます。詳しくは[JPNIC](https://www.nic.ad.jp/ja/newsletter/No40/0800.html)を参照してください。重要なのは、比較的容易にDNSを攻撃する手段が見つかってしまった、という点です。この方式の発見後、対策を余技なくされるようになりました。

![kam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/025fe4f0-d94e-0d07-f3e0-96b99df8f8e2.png)


# DNSSECの登場

キャッシュポイズニングの根本的な解決方法としてDNSSECが登場しました。DNSSECはDNSの親-子-孫の関係に着目し、公開鍵暗号方式を利用した信頼のチェーンを構築することでレコードの詐称を検知できる仕組みです。例はexample.comの信頼のチェーンです。

![dnssec-chain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326401/218afa28-deec-c678-d955-aadf80dbdfbd.png)



|種類|説明|
|----|----|
|DS|子のゾーンのKSKのハッシュ値|
|KSK|ZSKに署名をする鍵|
|ZSK|レコードに署名をする鍵|

KSK/ZSKの公開鍵はDNSKEYレコードとして公開されます。256がZSKで、257がKSKです。

```
***.jp. 299 IN DNSKEY 256 3 13 j/XLRP3OH4v5 (..省略)
***.jp. 299 IN DNSKEY 257 3 13 egJVk041 (..省略)
```

DNSサーバーはZSKの秘密鍵を使ってA, MX, TXTなどのレコードを署名します。署名はRRSIGレコードとして公開されます。下記例はAレコードと、それに対する署名です。

```
***.jp. 299 IN A 54.65.**.**
***.jp. 299 IN RRSIG A 13 2 300 202 20200914030034 20200831010034 40705 ***.jp. +dPQp(..省略)
```

リゾルバはZSK公開鍵を使ってRRSIG(署名)を検証します。

## 署名の検証

DNSSECが有効なリゾルバでは、DNSレコードと、それに対する署名の検証を行います。
DNSSECが有効なドメインに対してdigを実行した結果は以下です。

```
; <<>> DiG 9.16.1-Ubuntu <<>> @8.8.8.8 ***.jp +dnssec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47783
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;***.jp.                      IN      A

;; ANSWER SECTION:
***.jp.               299     IN      A       54.65.**.**
***.jp.               299     IN      RRSIG   A 13 2 300 20200914030034 20200831010034 40705 ***.jp. +dPQp5FmkJoAMNFstnLDKZku6iHUKuvN+wEAxNgsMNEtDYOLx1qpIVkK ZOV7neBfhe2iT4NUHAeVF3MYuo/0lQ==

;; Query time: 80 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Sep 04 10:39:58 JST 2020
;; MSG SIZE  rcvd: 157
```

flagsにadフラグがあれば、DNSSECの信頼のチェーンが有効であることを示しています。不正が見つかった場合は、statusがserver failとなります。dnssecにそもそも対応していない場合は、ad flagが表示されません。

## ロールオーバー

DNSをよりセキュアに保つため、定期的に鍵の交換や再署名する必要があります。

- zskによるレコードへの再署名
- zskの交換
- kskの交換

キー、署名等のキャッシュ時間を考慮した上で交換する必要があります。Pre-publish、ダブルシグネチャといったロールオーバーの方式が提案されていますが、手作業でこれらを行うのはかなり困難です。自動でロールオーバーを行う仕組みを利用するか、DNSSECに対応したDNSのサービスを利用するのをお勧めします。

ロールオーバーに関しては、少々難解ですので、機会があれば別途記事を書きたいと思います。現時点では、鍵の交換が必要、という認識を持っていただければ幸いです。

# まとめ
今回はDNSSECの基礎を説明しました。DNSSECそのものは、セキュリティの観点から優れた仕組みではありますが、残念ながら日本での普及率はまだまだのようです。しかし、 オランダのように政府主導で、DNSSECを基盤としたemail securityの規格であるDANEの対応が進んでいる国もあります。もしかしたら日本企業も対応が迫られる日が来るかもしれません。

本記事は細かい内容はかなり省略していますので、機会があればより深い内容を執筆しようと思います。

*本記事は @qualitia_cdevの中の一人、伊藤さんに書いていただきました。