Githubの新しいセキュリティ機能 CodeQLを使ってみる
CodeQLは、Semmleが提供しているコードセマンティック解析に使用するツールで、脆弱性やコードの品質の可視化を行うことができます。
2019年9月18日にGithubがCodeQLを開発しているSemmleを買収し、現在「GitHub Code Scanning」(リミテッドベータ)として利用することができるようになりました。
Welcoming Semmle to GitHub - The GitHub Blog
GitHub、コードの脆弱性を発見してくれる「GitHub Code Scanning」発表、修正方法のアドバイスも。GitHub Satellite 2020 - Publickey
現在でもSemmleのLGTMからCodeQLを利用することができます。
CodeQLを少し使ってみたので紹介したいと思います。
CodeQLを使ってみる
Github連携
CodeQLを使い始めるのは凄く簡単です。
lgtmへアクセスし、「Log in」よりGithub連携を行うことで利用することができます。
今回、TDDで開発した簡単なGoのCLIツールにCodeQLを利用してみたいと思います。
go-cve-search 作ってみた - TDD, Circleci, Terminal Gif, Cliツール開発の話 - Security Index
ログイン後はまだ何も対象プロジェクトが選択されていない状態なので、自分のリポジトリのURLを入れ、Followボタンを押します。
これだけでCodeQLによる脆弱性の確認、コードの品質チェックを行うことができます。
私のプロジェクトでは「0 Alert」と表示され、何も問題がないという結果になりました。
結果はこのリンクから誰でも確認することができます。
OSSプロジェクトヘの評価結果なので誰でも確認することができます。
CodeQLでは他のプロジェクトの結果も見ることができ、例えば、「kubernetes」の結果をみてみると
このように、Alert 19件のうち、16 Warnings、3 Recommendationsという結果がわかります。
左上をみると、kubernetesがGo Python Javascriptが使われており、Code qualityがCであることもわかります。
現在、Go言語はベータ版のため、私のプロジェクトではCode qualityは表示されてませんでしたが、他の言語では確認することができます。
Alert : 問題点の指摘
kubernetesのWarningsのAlertを2件紹介します。
・Disabled TLS certificate check
TLSの証明書のチェックがoffになっていることを指摘しています。
・Missing regular expression anchor
正規表現のアンカー ^ や $ が利用されていないことを指摘しています。
「Read more」より指摘内容の詳細を確認することもできます。
Missing regular expression anchorでは、この指摘を直すための方法「アンカーを付けること」と、具体的な脆弱なコードの例とどういう場合に問題になるのか「http://evil-example.net/?x=http://example.com/のような URLを入力された場合にバイパスできる恐れがある」、ReferenceとしてOWASPのリンクとCWEが紹介されています。
Code quality : 品質のグレード評価
kubernetesのCode qualityを詳しくみてみるとPythonがC、JavascriptはA+という評価になっています。
A+やCなどの評価はどのように付いているかというと、CodeQLによって分析された他のOSSとの品質の比較によって行われています。
A+は同じくらいのコード行数の中で95-100%に位置しているということです。
kubernetesのPythonの結果を見てみると、395 Lines of codeで5 Alert。
ほぼ同じコード行数の「kubernetes/autoscaler」は0 AlertのためA+になっています。
(Alertの中には「Errors」「Warnings」「Recommendations」の3種類があり、重みづけされた評価になっています。参考)
(縦軸がCode quality、横軸がLines of code)
単純にAlertが何件以上だったらCode qualityはB、のように評価するのではなく他のOSSとの比較から品質を可視化するという部分が面白いです。
Compare : 他のOSSと比較する
「Compare」のタブで他の同じ言語のOSSと品質を比較することができます。
縦軸 Alertの数、横軸 コード行数の点グラフで表現されています。
Contributorsの数によって円の大きさが変わってきます。
Queries : CodeQLで指摘する内容一覧
各言語毎にどんな指摘を行うのかを示したクエリー一覧を見ることができます。
goのquery
goでは36個のクエリーが用意されており、先ほどAlertで指摘があったTLSの証明書や正規表現の指摘に加え、意味のない、絶対に通らないパスをもつif文、switchケースの指摘などもあります。
JavaScriptのquery
JavaScriptでは166ものクエリーが用意されています。
let宣言する前の変数にアクセスを行うとランタイムエラーになることの指摘や、ElectronでwebSecurityの設定をfalseにしていることなどをチェックしてくれます。
JavaScriptのアンチパターンが166個紹介されているようなものなのでここのクエリーを見て学ぶこともできそうです。
CodeQLを使うことでセキュリティだけでなく、よくない書き方をした場合にコミットしたタイミングなどでチェックしてくれるので意図せず悪いコードが組み込まれることを不正でくれます。
lintツールを使うことで同様に確認できるものもあると思いますが、CodeQLではコードを一度全て解析してデータベースとしたものへクエリーを使ってチェックをするため、精度が高くなったりlintでは発見できないようなものもチェックできると思います。
History : 過去のAlertの数の推移
これまでのコード行数とAlertの数の推移を見ることができる。
実際にCodeQLを開発に組み込んで使っていくのであれば面白い機能だと思います。
開発が進みコード行数が増えていく中でAlertの数を増やさずに、システム全体の品質を維持しながらちゃんと開発できているのか確認できたり、Alertが増加したタイミングはいつで、何があったのかをちゃんと追えるようになります。
CodeQLはCIに組み込んで使うものだと思いますので、AlertでErrorのものが一つでもあったらCIでエラーになる、などの運用をしっかり回せれば品質を維持できそうです。
このような運用を回すためにもCodeQLのErrorがFalse Positiveではないことが必須です。
Integrations : Pull RequestのAuto Review & READMEのbadge & IDE
Pull Request Auto Revie
Githubに CodeQLのアプリをインストールすることで Pull Requestがきた時点でCodeQLが自動で解析を行うようになります。
Github上ですぐに新しく増えたAlertの数や fixされたAlertの数がわかるようになります。
About automated code review - LGTM
README Badge
READMEに貼れる Badgeも提供されています。
個人的にBadgeを貼るのが好きなので嬉しいです!
実際に自分のプロジェクトのREADMEにも貼りました。
GitHub - s-index/go-cve-search: lightweight CVE search
Releaseバージョン、Circle CI、go report、lgtm、ライセンスのBadgeと5つも付けてます。
IDEでAlert確認
Eclipse IDEのプラグインも用意されており、IDE上からAlertの数の確認もできるようです。
CodeQL (LGTM)のWeb上でコードのどこが間違っているのかを確認せずに、IDE上でどこにどんな問題が出ているのかlintツールでのアラートのような形でチェックできるようです。
今はEclipseのみ対応ですが、今後他のIDE、おそらくVSCodeに対応していくと思います。
IDEでクエリー (Local Analysis)
VSCodeを使って、自分で書いたクエリーを自分のプロジェクトに実行し、解析することができます。
対象プロジェクトのソースコードをCodeQLのクエリーで解析できる形にしたものをCodeQL databaseといい、そのデータベースを使って解析することができます。
詳しい内容は後述する「Github Learning Lab」で学ぶことができます。
対応言語
CodeQL (LGTM)の対応言語はここに書いてあるように以下の6つです。
- C, C++
- C#
- Go
- Java
- JavaScript / TypeScript
- Python
また、上記のJavaScriptのqueryの例で書いたように各言語のフレームワークやライブラリーの一部も対応しており、それに応じたAlertを出すことができます。
一部紹介すると
- C# : ASP.NET、ASP.NET Core
- Java : JDBC、Spring MVC、Struts
- JavaScript : angularjs、electron、jquery、react
- Python : Bottle、Django、Flask
詳しくはFrameworks and libraries — Supported languages and frameworksに書かれています。
CodeQLを学んでみる
自分でCodeQLのクエリーを書くこともできます。
Goはまだ標準の build-in query が少ないので自分で書いて脆弱性や品質チェックを行うこともできます。
比較的書きやすいものではありますが、 False Positive / False Negative なく自分の確認したいものだけを検知させる綺麗なクエリーを書くこともやはり難しいように感じます。
Github Learning Lab
CodeQL U-Boot Challenge (C/C++) | GitHub Learning Lab
GithubのLearning LabでCodeQLのクエリーを実際に書いて学べるコースが提供されています。
10 Stepあり、最終的にはU-Bootで実際にCodeQLを使って発見したRCE (Remote Code Execution)の脆弱性(CVE-2018-4259)を見つけるというものになっています。
進め方はコースを始めるとリポジトリがクローンされ、Issueが発行されるのでそのIssueに書かれた説明を読みながらプルリクを発行し、答えがあっていたらマージされ、次のIssueが発行される、という流れです。
Githunを使ってe-Learningができるというのが個人的にとても面白かったです。
Step1のIssueはこのような感じです。
CTF
CodeQLのCTFも開催されています。
Capture the flag - GitHub Security Lab
Best submissionに選ばれると
Second and third best submissionsに選ばれると
Nintendo Switch with gray Joy-Con
が貰えるみたいです!
(このBoseのヘッドフォンは45,000円ほどする結構いいもの)
今回が4回目の開催で過去3回分のCTFの問題も公開されています。
3回目のCTF 3: XSS-unsafe jQuery pluginsでは一部回答とFeedbackも掲載されているので参考になります。
3回目のCTFもjQueryの過去に実際に問題となったもの(CVE-2018-14040など)が題材となっているため面白いです。
最後に
今後 Githubから正式に利用可能になり、ますます利用されるようになると思います。
OSSであればSemmleから無料で利用可能で、導入も簡単です。
より高度に使うのであればCodeQLを学んで、自分でクエリーを書けるようになることでdefaultで入っているチェック以上のこともできるようになります。
独自のクエリーを書くメリットとしては、例えばCTFの題材になっていたようにjQueryで一つ脆弱性となるコードを見つけたときに、そこと同じような書き方の問題のある部分をクエリーを使って特定する、というような形です。
クエリーにすることでjQueryの中の全てのコードをチェックできるだけでなく、jQuery以外のプロジェクトにも横展開してチェックできるようになります。
ただ、False Positive / False Negativeのないクエリーを書くことは難しく、品質の高いクエリーを多く作り出すことがSemmleにとっても資産になるために、CTFやe-Learningを作成し、コミュニティ活動も行っているように思われます。
CodeQLだけではなく、海外の最新の情報を得ることは重要だと思いますのでオライリー本などを読むとより最新でかつ深い内容を知ることができます。
O’Reilly online learningを使うことで英語版のオライリー本が比較的安価で読み放題にできるのでおすすめです。
英語のオライリー本読み放題サブスクO’Reilly online learningを使ってみたらとても良かった - Security Index