PowerDNS Security Advisory 2016-01(CVE-2016-5426)の実験

## 初めに

PowerDNS Authoritative Server(以後PowerDNS)は、[3.4.10](https://blog.powerdns.com/2016/09/02/authoritative-server-3-4-10/)がリリースされました。
3.4.9から3.4.10のChangeLogに、

> [commit 881b5b0](https://github.com/PowerDNS/pdns/commit/881b5b0): Reject qnames with wirelength > 255, chopOff() handle dot inside labels

があり、これで[PowerDNS Security Advisory 2016-01](https://doc.powerdns.com/md/security/powerdns-advisory-2016-01/)(CVE-2016-5426およびCVE-2016-5427)の対応をしています。ここでは、CVE-2016-5426の影響度について考察します。

### 注意事項

CVE-2016-5426についてPowerDNS BVおよび発見者から情報を得てはいませんので、ここに記載されている内容は、公開されている情報から推測したものです。

### CVE-2016-5426について

CVE-2016-5426の概要は、

* 細工したDNSクエリを送信することで、バックエンドのCPU使用率が上昇する。

というものです。

PowerDNSはゾーンの情報を、データベースやディレクトリサーバなどのバックエンドに持たせています。PowerDNSは受信したクエリをもとにバックエンドに問い合わせ、その応答を受信してDNSレスポンスを生成し、それを返します。ここで注意しなければならないのは、**ひとつ**のDNSクエリに対して、バックエンドへの**複数**の問い合わせが発生することです。

## 実験

### 環境

* PowerDNS サーバ(pdns-front)
   + 論理CPU x 4
   + メモリ4GB
   + OS CentOS 6.8 64bit
       - CPUごとの使用率に偏りがでるため、以下の設定を追加

```sh:
echo "f"   > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
```

   + PowerDNS 3.4.9
       - pdns.confのreceiver-threadとreceiver-threadsを20に変更。デフォルト値では、バックエンドの負荷があまり上昇しないため
   + net-snmp CPU使用率などの取得のためsnmpdを使用

+ バックエンドサーバ(pdns-back)
   + 論理CPU x 4
   + メモリ4GB
   + OS CentOS 6.8 64bit
       - CPUごとの使用率に偏りがでるため、以下の設定を追加

```sh:
echo "f"   > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
```

   + MySQL 5.1.73(mysql-server-5.1.73-7.el6.x86_64)
       + my.cnfは未修正
   + net-snmp CPU使用率などの取得のためsnmpdを使用

### 方法

以下のようなDNSクエリをPowerDNSへ送信し、pdns-frontとpdns-backのCPU使用率をSNMPを利用して計測しました。

* 20qpsまたは50qpsのクエリをpdns-front送信
* QNAMEはランダムに生成
* QNAMEの長さを250, 1000を変えて、それぞれの場合を計測
* QNAMEはバックエンドのクエリが多くなるように工夫
* クエリに対するレスポンスを待たない。QNAMEの長さが255を超えると、レスポンスのDNSメッセージを作成するときに、例外(C++)が発生してレスポンスがなくなるため

### 結果

pdns-frontとpdns-backのCPU使用率は以下のようになりました。グラフの山は左から

1. QNAMEを250として20qpsのクエリを送信
2. QNAMEを1000として20qpsのクエリを送信
3. QNAMEを250として50qpsのクエリを送信
4. QNAMEを1000として50qpsのクエリを送信

ときのものです。QNAMEの長さが1000の場合は、バックエンドサーバのCPUおよびPowerDNSサーバのCPU使用率も高くなりました。

#### pdns-front
 
![pdns-front_cpus.png](https://qiita-image-store.s3.amazonaws.com/0/61795/f99e5934-a378-c581-b10f-124c132d52c5.png)


#### pdns-back

![pdns-back_cpus.png](https://qiita-image-store.s3.amazonaws.com/0/61795/027a046c-9a3d-f07d-040f-039257dc803a.png)


## 考察

バックエンドサーバのCPU使用率が高くなったのは、PowerDNSから非常に多くのクエリがMySQLへ送信されたためです。QNAMEの長さが1000程度の場合、ひとつのDNSクエリに対して、1000以上のクエリをPowerDNSからバックエンドへ送信させることが可能です。このように多くのクエリが送信される理由については、MySQLのクエリログを参照してみてください。

50qps程度のクエリは一台のPCでも容易に生成することが可能ですので、CVE-2016-5426を利用することにより、PowerDNSのバックエンドサーバを過負荷にすることができます。PowerDNSサーバを利用したサービスをDDoSで落とすことは容易にできてしまうということです。

上記のCPU使用率の増加は、QNAMEの長さを短くすることで抑制することができます。PowerDNS 3.4.10では255以下に制限されているので、CPU使用率は大きくなりません。

## まとめ

PowerDNS Authoritative Server 3.4.9以下を利用している場合は、少ないクエリ数で容易にサービスを止められてしまいますので、早急に3.4.10にしましょう。


### おまけ

CVE-2015-1868, CVE-2015-5470, CVE-2015-5230, CVE-2016-5426と続いたドメイン名関係の脆弱性も、これで終わってくれるといいですね。