Security Index

セキュリティやソフトウェアについてのあれこれ

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を少し使ってみたので紹介したいと思います。

 

f:id:security_index:20200601083116p:plain

 

  

CodeQLを使ってみる

Github連携

CodeQLを使い始めるのは凄く簡単です。

lgtmへアクセスし、「Log in」よりGithub連携を行うことで利用することができます。

 

f:id:security_index:20200601084551p:plain

 

今回、TDDで開発した簡単なGoのCLIツールにCodeQLを利用してみたいと思います。

 

go-cve-search 作ってみた - TDD, Circleci, Terminal Gif, Cliツール開発の話 - Security Index

 

f:id:security_index:20200601085525p:plain

 

 

ログイン後はまだ何も対象プロジェクトが選択されていない状態なので、自分のリポジトリのURLを入れ、Followボタンを押します。

これだけでCodeQLによる脆弱性の確認、コードの品質チェックを行うことができます。

 

f:id:security_index:20200601084933p:plain

 

私のプロジェクトでは「0 Alert」と表示され、何も問題がないという結果になりました。

結果はこのリンクから誰でも確認することができます。

OSSプロジェクトヘの評価結果なので誰でも確認することができます。

 

 

CodeQLでは他のプロジェクトの結果も見ることができ、例えば、「kubernetes」の結果をみてみると

 

f:id:security_index:20200601091335p:plain

 

このように、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

正規表現のアンカー ^ や $ が利用されていないことを指摘しています。 

 

f:id:security_index:20200602214512p:plain

 

「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+という評価になっています。

 

f:id:security_index:20200601092032p:plain

 

A+やCなどの評価はどのように付いているかというと、CodeQLによって分析された他のOSSとの品質の比較によって行われています。

 

f:id:security_index:20200601093200p:plain

 

A+は同じくらいのコード行数の中で95-100%に位置しているということです。

kubernetesPythonの結果を見てみると、395 Lines of codeで5 Alert。

ほぼ同じコード行数の「kubernetes/autoscaler」は0 AlertのためA+になっています。

(Alertの中には「Errors」「Warnings」「Recommendations」の3種類があり、重みづけされた評価になっています。参考)

 

 

f:id:security_index:20200601093411p:plain

 

f:id:security_index:20200601093515p:plain

(縦軸がCode quality、横軸がLines of code)

 

単純にAlertが何件以上だったらCode qualityはB、のように評価するのではなく他のOSSとの比較から品質を可視化するという部分が面白いです。

 

Compare : 他のOSSと比較する

「Compare」のタブで他の同じ言語のOSSと品質を比較することができます。

 

f:id:security_index:20200601210025p:plain

 

縦軸 Alertの数、横軸 コード行数の点グラフで表現されています。

Contributorsの数によって円の大きさが変わってきます。

 

 

f:id:security_index:20200601090846p:plain

 

Queries : CodeQLで指摘する内容一覧

各言語毎にどんな指摘を行うのかを示したクエリー一覧を見ることができます。

 

goのquery

goでは36個のクエリーが用意されており、先ほどAlertで指摘があったTLSの証明書や正規表現の指摘に加え、意味のない、絶対に通らないパスをもつif文、switchケースの指摘などもあります。

 

f:id:security_index:20200603223027p:plain

 

JavaScriptのquery

JavaScriptでは166ものクエリーが用意されています。

let宣言する前の変数にアクセスを行うとランタイムエラーになることの指摘や、ElectronでwebSecurityの設定をfalseにしていることなどをチェックしてくれます。

 

JavaScriptアンチパターンが166個紹介されているようなものなのでここのクエリーを見て学ぶこともできそうです。

CodeQLを使うことでセキュリティだけでなく、よくない書き方をした場合にコミットしたタイミングなどでチェックしてくれるので意図せず悪いコードが組み込まれることを不正でくれます。

 

lintツールを使うことで同様に確認できるものもあると思いますが、CodeQLではコードを一度全て解析してデータベースとしたものへクエリーを使ってチェックをするため、精度が高くなったりlintでは発見できないようなものもチェックできると思います。

 

History : 過去のAlertの数の推移

これまでのコード行数とAlertの数の推移を見ることができる。

 

f:id:security_index:20200602223039p:plain

 

実際に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が自動で解析を行うようになります。

 

f:id:security_index:20200605181504p:plain

 

 Github上ですぐに新しく増えたAlertの数や fixされたAlertの数がわかるようになります。

 

About automated code review - LGTM

 

README Badge

READMEに貼れる Badgeも提供されています。

個人的にBadgeを貼るのが好きなので嬉しいです!

 

f:id:security_index:20200605182110p:plain

 

実際に自分のプロジェクトのREADMEにも貼りました。

 

f:id:security_index:20200605182206p:plain

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を使って、自分で書いたクエリーを自分のプロジェクトに実行し、解析することができます。

 

f:id:security_index:20200605183322p:plain

 

対象プロジェクトのソースコードをCodeQLのクエリーで解析できる形にしたものをCodeQL databaseといい、そのデータベースを使って解析することができます。

解析のためにはVSCodeプラグインが必要になります。

詳しい内容は後述する「Github Learning Lab」で学ぶことができます。

 

 

対応言語

CodeQL (LGTM)の対応言語はここに書いてあるように以下の6つです。

f:id:security_index:20200605085920p:plain

 

また、上記のJavaScriptのqueryの例で書いたように各言語のフレームワークやライブラリーの一部も対応しており、それに応じたAlertを出すことができます。

 

一部紹介すると

 

詳しくは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のクエリーを実際に書いて学べるコースが提供されています。

 

f:id:security_index:20200602224047p:plain

 

10 Stepあり、最終的にはU-Bootで実際にCodeQLを使って発見したRCE (Remote Code Execution)の脆弱性(CVE-2018-4259)を見つけるというものになっています。

 

進め方はコースを始めるとリポジトリがクローンされ、Issueが発行されるのでそのIssueに書かれた説明を読みながらプルリクを発行し、答えがあっていたらマージされ、次のIssueが発行される、という流れです。

 

Githunを使ってe-Learningができるというのが個人的にとても面白かったです。

 

Step1のIssueはこのような感じです。

 

f:id:security_index:20200602224812p:plain

 

 

CTF

CodeQLのCTFも開催されています。

f:id:security_index:20200602222139p:plain

 

Capture the flag - GitHub Security Lab

 

Best submissionに選ばれると

 

Bose Noise Cancelling Headphones 700 with Charging Case

 

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

 

(@security_index) | Twitter