Snykでこんなに脆弱性検出できちゃうのかい（C# / .NET 編）

「Snykを使ってコードをセキュアにした記事を投稿しよう！ by Snyk Advent Calendar 2023」7日目の記事になります。

https://qiita.com/advent-calendar/2023/snyk

## Snyk がすごい

[Snyk](https://snyk.io/jp/) は DevSecOps のための統合プラットフォームのようです（雑）

無料で始めることができて、自身のソースリポジトリと紐付けて、継続的に脆弱性に目を光らせてくれるというすごいやつなんですが、これがなんと、自分のソースだけでなく、github の任意の public リポジトリを取り込んでソースコードに対するセキュリティスキャンをかけることができるのです。これも無料の範囲で！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/22ae9e03-d848-da0c-d768-655a97ab46a9.png)
No creadit card required なのが地味に嬉しい

つまり、自分のソースコードだけでなく、依存先の OSS ライブラリに対する脆弱性を監視することもできるし、OSS 選定のひとつの指標として使うこともできそうですね。

そこで今回は .NET で比較的スターの多い OSS をターゲットに、いくつかインポートしてみて、実際にどんな脆弱性が検出できるかを試してみました。

## プロジェクトをインポートしてみる

Add Projects > Monitor public GitHub repos を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/69b06dd9-f154-fbc0-fe61-9f342af8948f.png)

リポジトリの URL を入れるだけで簡単に取り込めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/c7e26dac-8b9f-4db3-922d-27558106feb4.png)

取込みが終わると自動的にスキャンされていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/ef84e4a2-ac15-4492-7b5e-048e1197014b.png)

なるほど。。（一応リポジトリ名を隠しておきました）
とりあえず、数だけ見ると予想以上に出てきてびっくりですね。
ヤバイ度順に、C, H, M, L として件数が表示されています。

ただし展開して見たところ、テストコードについて検出されたものなんかも含まれていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/f0f9e988-2711-38a7-e2c2-8f5ab39010aa.png)

リポジトリを指定してインポートすると、中に含まれるプロジェクトを自動で見つけて取り込んでくれますが、個別に選択して削除することもできます。
本来はテストコードのプロジェクトなど監視の必要がないものは削除しておいたほうが良いですね。

それでは、どんなものが検出されているか見ていきましょう。

## 使用ライブラリの既知の脆弱性

プロジェクトで利用しているライブラリの中に、既知の脆弱性があるものが含まれていると検出してくれます。

直接依存しているライブラリだけでなく、依存先のライブラリで利用している別のライブラリへの依存（推移的依存）も含めてチェックしてくれるようです。

### Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets - Denial of Service (DoS)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/ff97396d-2214-ab26-0107-9ef649ecaec2.png)

ライブラリが依存している `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets` について、 Microsoft.AspNetCore v2.1.0 で見つかった DoS の脆弱性の影響を受けていることが検出されています。

v2.1.40 で修正されているというところまで教えてくれていますね。

詳細情報として、脆弱性データベースの当該情報へのリンクも記載されています。

[Snyk: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets - Denial of Service (DoS)](https://security.snyk.io/vuln/SNYK-DOTNET-MICROSOFTASPNETCORESERVERKESTRELTRANSPORTSOCKETS-5834420?_gl=1*1fsyjpe*_ga*MTE0Mzc2NTk3NC4xNzAwODIxODUz*_ga_X9SH3KP7B4*MTcwMTQyODY1MC4yLjEuMTcwMTQyOTE0MS4wLjAuMA..)

### System.Text.Encodings.Web - Remote Code Execution (RCE)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/00f1c5d8-5275-efbe-d462-fe18fc397705.png)

こちらは `System.Text.Encodings.Web` に含まれる、リモートコード実行の脆弱性ですね。
テキストエンコードの処理方法に問題があり、任意のコードを実行される脆弱性が存在したようです。

[Microsoft Security Advisory CVE-2021-26701 | .NET Core Remote Code Execution Vulnerability #49377](https://github.com/dotnet/runtime/issues/49377)

こちらも `System.Text.Encodings.Web` のバージョンを上げることで解消されるようです。

実際には、AspNetCore v2.1.0 の参照先にこのライブラリが含まれていたようですね。

### Newtonsoft.Json - Insecure Defaults

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/81518db4-cf2c-16f9-a015-46d3e5fdb01c.png)

こちらは Newtonsoft.Json に含まれていた、Insecure Defaults の脆弱性が検出されています。

デフォルト設定のまま、ネストの深い JSON をシリアライズしようとすると StackOverflowException が発生する問題があったということのようです。
修正としては、処理するネストの深さのデフォルト値を変更したようで、脆弱性情報のページから github の修正プルリクエストまでたどることができました。

[Snyk: Newtonsoft.Json - Insecure Defaults](https://security.snyk.io/vuln/SNYK-DOTNET-NEWTONSOFTJSON-2774678?_gl=1%2a182yr6s%2a_ga%2aMTE0Mzc2NTk3NC4xNzAwODIxODUz%2a_ga_X9SH3KP7B4%2aMTcwMTQyODY1MC4yLjEuMTcwMTQzMDM0My4wLjAuMA..)
[Change JsonReader and JsonSerializer default max depth to 128 #2462](https://github.com/JamesNK/Newtonsoft.Json/pull/2462)

そしてなんとこちらも参照元は AspNetCore v2.1.0！
問題の多いバージョンだったんですね。。

### その他

ほかには以下のような既知の脆弱性が検出されていました。

* [System.Net.Http - Denial of Service (DoS)](https://security.snyk.io/vuln/SNYK-DOTNET-SYSTEMNETHTTP-60045?_gl=1%2a14b3vtu%2a_ga%2aMTE0Mzc2NTk3NC4xNzAwODIxODUz%2a_ga_X9SH3KP7B4%2aMTcwMTc3Njk1NS4zLjEuMTcwMTc3ODUwMS4wLjAuMA..) (CVE-2017-0247)
* [System.Net.Http - Improper Certificate Validation](https://security.snyk.io/vuln/SNYK-DOTNET-SYSTEMNETHTTP-60046?_gl=1%2a1ichevx%2a_ga%2aMTE0Mzc2NTk3NC4xNzAwODIxODUz%2a_ga_X9SH3KP7B4%2aMTcwMTc3Njk1NS4zLjEuMTcwMTc3ODY0MS4wLjAuMA..) (CVE-2017-0248)
* [System.Net.Http - Information Exposure](https://security.snyk.io/vuln/SNYK-DOTNET-SYSTEMNETHTTP-72439?_gl=1%2a12e1h70%2a_ga%2aMTE0Mzc2NTk3NC4xNzAwODIxODUz%2a_ga_X9SH3KP7B4%2aMTcwMTc3Njk1NS4zLjEuMTcwMTc3ODgwNy4wLjAuMA..) (CVE-2018-8292)
* [System.Text.RegularExpressions - Regular Expression Denial of Service (ReDoS)](https://security.snyk.io/vuln/SNYK-DOTNET-SYSTEMTEXTREGULAREXPRESSIONS-174708?_gl=1%2a1qj804z%2a_ga%2aMTE0Mzc2NTk3NC4xNzAwODIxODUz%2a_ga_X9SH3KP7B4%2aMTcwMTc3Njk1NS4zLjEuMTcwMTc3OTAwOC4wLjAuMA..) (CVE-2019-0820)

## コード分析

参照ライブラリの脆弱性だけでなく、ソースコードに対する静的解析により、危険なにおいのするコードを検出してくれます。

### Use of Hardcoded Credentials

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/1d1b39e0-962f-ed1d-4db4-9750d55825e2.png)

認証情報がハードコーディングされているっぽいところを検出していますね。

今回はテストコードでしたが、うっかりデバッグ中のコードをそのままコミットしてしまうようなケースもあるので助かります。

### Path Traversal

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/136af6b3-8653-fa34-551b-d479cc7070db.png)

コマンドラインの入力に対し、サニタイズせずそのまま `File.Exists()` に渡しているため、`../../foo.txt` みたいな指定が通ってしまうということですね。

これ、すごいのは、実際に `File.Exists()` を実行しているのは、呼び出し先メソッドの中からさらに呼び出したメソッドの先くらいなんですよね。
静的解析でそこまで追いかけて検出してくれるのはすばらしいです。

### Deserialization of Untrusted Data

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/e4c86439-e906-b7af-d468-fe85ddde2b10.png)

オブジェクトを JSON にシリアライズする際のオプションで `TypeNameHandling.All` が指定されていることを警告しています。

たとえば `IPerson` インターフェースを持つ `Person` クラスのオブジェクトをシリアライズする際、元の型が `Person` であったという情報が失われるとデシリアライズの際に困ることがあります。

TypeNameHandling の指定を使うと、元の型名 `Person` を含めて JSON にシリアライズすることができますが、これを悪用すると、シリアライズされた JSON の型名を `BadPerson` に書き替えた状態でデシリアライズさせて悪意あるオブジェクトを挿入することができてしまう、ということですね。

### Use of Password Hash With Insufficient Computational Effort

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/817dc646-96bc-bee7-9ba3-c00ecd537ffc.png)

MD5 のハッシュは安全でないので、SHA-256 とかを使いましょうというやつですね。

## 修正プルリクエストの作成

github との連携機能により、検出された脆弱性に対する修正のプルリクエストまで作成できます。

Snyk の管理画面から Settings > GitHub で、まず GitHub のアクセストークンを設定しておく必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/52c13874-5849-99da-cd0b-33de26bc35f0.png)

アクセストークンは、GitHub の個人アカウント設定から、Settings > Developer Settings > Personal access tokens で作成できますね。

Tokens (classic) と、ベータ版の Fine-grained personal access tokens がありました。
今回は Fine-grained のほうで作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/82e9a7c9-531c-02fc-6636-67413ba49a1c.png)

Generate new token から、期限や権限を選択します。
snyk からのプルリクエスト作成には、書き込み権限が必要ということでした。
なので、所属していない OSS リポジトリに対してはさすがに勝手に PR を作ったりはできなさそうですね。

修正 PR 作成可能な脆弱性については、「Fix this vulnerability」のボタンが表示されるようでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/6c95e19b-0fcd-539c-eb76-dae84aa8b2f1.png)

また、GitHub 統合の設定ページから、検出された脆弱性の修正や、依存ライブラリのバージョンアップのための PR を自動で生成することもできるようでした。
こちらは今回は試していません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/324a7343-d283-6ca2-aa0d-cbd626326200.png)

OSS リポジトリで見つかった脆弱性に対しては、公開の issues やプルリクエストよりは、リポジトリの Security タブにポリシーや報告先の記載があればそれに従うのがベターですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2903443/aee14b82-bf2a-ac4a-d2aa-c608fe0567b1.png)

## おわりに

Snyk は AWS との連携機能も充実しているようで、実際の開発では、CodePipeline に組み込んで CI でのビルドをトリガにスキャンを実行する、といった使い方もできそうです。

下記ページで詳しく紹介されていました。
[Snyk を利用した AWS における脆弱性管理のベストプラクティス](https://aws.amazon.com/jp/blogs/psa/vulnerability-management-with-snyk/)

今日のシステム開発では何百という OSS に依存したソフトウェアとなるケースも普通ですから、自分のコードだけに責任を持てばよいというわけにもいかなくなっています。

こういうツールをうまく活用して DevSecOps をまわしていきたいですね。