GH-500(GitHub Advanced Security:GHAS)学習記録

全体

GHAS三大要素

  • シークレットスキャン
  • コードスキャン
  • Dependabot

ライセンス

  • Github Secret Protection
  • Github Code Security

無料で使える機能もある。パブリックリポジトリであれば大体の機能は無料で使える。プライベートリポジトリでも無料で使える機能ある(Dependabot系の一部の機能)

シークレットスキャン

シークレット スキャンは、ソース コード内で API キーやトークンなどの機密情報が誤って公開されるのを識別し、防止する

  • すべてのパブリックリポジトリで無料で利用可能

2つのシークレットスキャン

リポジトリに対するシークレットスキャン(Secret Protection、シークレット保護)

既にリポジトリ内にあるコードに対して、シークレットが含まれていないかチェックする。

プッシュに対するシークレットスキャン(push protection、プッシュ保護)

プッシュされるタイミングで、コードにシークレットが含まれていたらプッシュをブロックできる(=リポジトリに格納される前に、ブロックできるのでよりセキュア)

特定のファイルをシークレットスキャンの対象外とする方法

例えば、コードの中に、ランダムに生成される文字列を含まないといけないような場合は、シークレットスキャンが誤検知してしまう可能性があるため、そもそも対象外にしたいようなケースがある。

■手順

.github/secret_scanning.yml ファイルをリポジトリに作成。

以下のように除外するパスを指定する

シークレットのカスタムパターン

組織で利用しているシークレットの形式が、Github既定のシークレットスキャンで検出されない場合に、独自に定義して検出させることができる。

■作成できるカスタムパターンの上限

・組織またはエンタープライズ単位:最大500

・プライベートリポジトリ単位:最大100(そもそも、パブリックリポジトリではカスタムパターン使えない)

■定義方法

Hyperscanの正規表現で定義する必要があ鵜r。

Hyperscanの正規表現とは、拘束に大量の文字列をスキャンするための表現。普通の正規表現の一部だけサポートされている(スキャン高速化のために簡素化された正規表現というイメージ)

シークレットをリポジトリに載せてしまった場合

まずは、そのシークレットをサービス側で無効にする。

さらにリスクを減らすために、リポジトリ上からシークレット(無効済のもの)を削除しておくとよいでしょう。その際に、以下が注意点です。

■単純にリポジトリ上のコードがからシークレットを消せばよいという訳ではない。

コミット履歴にもシークレット情報が残ってしまう。

また、チームメンバがそのリポジトリをローカルリポジトリにクローンしていた場合、再プッシュされることで、再度シークレットがリポジトリにアップロードされてしまう可能性があるため、チームメンバのローカルリポジトリ側の対応も必要(コミット履歴削除等)

コードスキャン

コードの脆弱性やエラーを検出する機能。スキャンするタイミングは、色々設定できる(定期的に実施、PR時、プッシュ時等)

CodeQL

コード解析エンジン。コードスキャンで使われる

CodeQLによる解析の流れ(ユーザの目に触れないところで行われている)

・コードをデータとして抽出(★)して、専用のリレーショナルデータベースが作られる

・そのデータベースに対して、CodeQLクエリを実行して問題を見つける

(★)抽出器によって実施される。抽出器はCodeQLの機能の一部。ソースコードを解析してデーターベース形式に変換するための専用プログラム(言語毎に用意されている)

CodeQLを使ったコードスキャンの実施方法3つ

①既定の方法(スキャンするタイミングとか決まっている)

  • GitHub Actionsが使われる
  • この方法だと、DB作成、クエリによる分析/SARIF作成、SARIFのGithubへアップロードが、裏側で勝手に行われる(ユーザの目に触れない)

②カスタムの方法(CodeQLクエリをカスタマイズできたりする)

  • GitHub Actionsが使われる
  • この方法だと、DB作成、クエリによる分析/SARIF作成、SARIFのGithubへアップロードが、裏側で勝手に行われる(ユーザの目に触れない)
  • クエリのカスタマイズは、「.github/workflows/*yml」の中に個別に定義可能(小規模向け)し、別ファイルを用意して、「.github/workflows/*yml」から参照させることも可能(大規模向け。クエリを繰り返し使いたいときにも有効)

③外部CIからCodeQLを利用

  • Github Actionsを使わない方法
  • 既にGithub以外でCI基盤を使っている場合の選択肢
  • 外部のCI基盤にCodeQL CLIをインストールして、実行する
  • CodeQLクエリによる分析によって作成されたSARIFファイル(分析の結果)をGithubにアップロード(CodeQL CLIのコマンドによりコードスキャンAPIに送信される)することで、分析結果をGitHubに取り込むことができる(Giされるb上でのアラート発出につなげられる)

サードパーティCIで作成されたSARIFをGithubにアップロードすることも可能

SARIFは標準仕様なので、コードスキャン自体のエンジンとしてCodeQLを利用せずに、別のエンジンでコードスキャンを実施して、SARIFを作れれば、それをGIThubにアップロードすることは可能

コードスキャンがあれば人によるレビューは不要か(ChatGPTへ確認)

人によるレビューは必要。コードスキャンによって、定型的な脆弱性など一定の検出は可能。ただし、業務ロジックに関わるコードなどコードスキャンでは善悪が判断できなものもある。

コンパイル言語に対するコードスキャン

コンパイル言語においては、単純にコードをスキャンするだけでは、脆弱性の発見できないケースがあります。そのため、GHASのコードスキャンではビルドのプロセスを観測します。

★インタプリタ言語(コンパイル不要の言語)のコードスキャンは、そのままコードに対して実施されます。

GitHub Actionsで、コードスキャンが実施される場合、以下の3つのアクションが使われます。

①github/codeql-action/init、②github/codeql-action/autobuild、③github/codeql-action/analyze

①③は、コンパイル言語/インタプリタ言語の両方で利用されるアクションですが、

②は、コンパイル言語でのみ利用されるアクションです(②はビルドするためのアクションのため、ビルドという概念がないインタプリタ言語は関係のないアクション)

コードスキャン未対応の言語

PHPなど、未対応の言語があるので、要注意です。

以下は、対応言語の一覧です。

https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/#languages-and-compilers

CodeQLの強み

単純なパターンマッチだけではなく、データの流れまで解析できます。「ユーザからの入力が安全でない形で使われる」ようなコードになっている場合、脆弱性として検出できます。

Dependabot

リポジトリの依存関係の管理を自動化する GitHub ツール

依存関係における脆弱性の抽出

SBOMとAdvisory Databeseが突合され、脆弱性が抽出され、Depandabot Alertsが発出されるという流れ出る

■SBOMとは

Software Bill of Materials(ソフトウェアの部品表)

業界標準の ソフトウェア パッケージ データ交換 (SPDX) 形式で、Githubからエクスポート可能(UI or REST API)

■SBOMが作成される流れ

ロックファイル/マニフェスト

Depedency Graph(ロックファイル/マニフェストから作られる)

SBOM(ソフトウェアを構成する部品(ライブラリ・モジュール・依存関係)の一覧表(Dependency Graphから作られる)

★業界標準の ソフトウェア パッケージ データ交換 (SPDX) 形式で、Githubからエクスポート可能(UI or REST API)

■Advisory Databeseとは

オープンソフトウェアの脆弱性情報を集約した、GH公式の脆弱性データベース

Dependabot 自動トリアージルール

一定の条件(影響度が低い場合等)に一致するDependabotアラートを自動的に却下する機能(アラート疲れ防止などのために)

ルールは2種類ある

①GitHub プリセットルール

②カスタム自動トリアージルール(プリセットルールでは要件満たさないときに使う)

2つの更新管理

時間の経過とともに、新たなセキュリティ脆弱性が見つかったり、利用しているライブラリが古くなってしまった際に、通知してくれる機能

① Dependabot セキュリティ更新プログラム

・脆弱な依存関係が見つかった際に、それを自動的に更新するためのプルリクエストを作成してくれる(Dependabotアラートが裏側では使われており、Dependabotアラートをトリガーに、このプルリクエストが走るイメージ)

② Dependabot バージョンの更新

 ・脆弱性がなかったとしても、依存ライブラリを最新に保つための機能(古くなったら、PR要求を出してくれる機能)

 ・有効化には dependabot.yml (.githubディレクトリに配置)が必要

依存関係レビュー

プルリクエストで導入された脆弱なパッケージをプレビューし、安全でない依存関係がマージされることを防止できる

レビューにはGithubアクションを利用

依存関係レビューは、Githubアクションの機能が必要にある。

YAMLファイルに定義した条件(危険なPKGが含まれている等)に合致しているかチェックする。

条件の定義の仕方は以下の2種類

①.github/workflows/*.yml に直接記載

Githubアクションのワークフローファイルに直接記載。小規模向け

②別の.ymlファイルに記載

Githubアクションのワークフローファイルの中で、そのYAMLファイルを指定する。複数のGithubアクションのワークフローファイルから参照できるので、大規模向け(組織の共通ルールとして利用できる)

ブランチ保護規則

条件に合致した場合に、実際にどうするか(ブロックするか)を決めるのは、「ブランチ保護規則」の設定に依存

GHAS関連その他

セキュリティポリシー

SECURITY.mdファイルに記載する(リポジトリ直下や、「.github」フォルダに配置する)

システム的に何かを制御するためのファイルというよりは、単純にリポジトリ(または組織)内のルール(脆弱性の報告方法等)を明文化したもの

リポジトリのルールセット

ルールセットを使うことで、リポジトリのセキュリティ性を向上させることができる

以下が、実現できることの例です。

・署名付きコミットを要求する(コミット改ざん対策)

・強制プッシュの禁止

・プッシュできるユーザの制限

ログの保存期間

 Enterprise Cloud での 90 日間。Enterprise Server で 120 日

期間が限定的なので、長期的な分析が必要な場合は、外部へのエクスポート&保管が必要

GHASを学習する上で知っておくべきこと

ソフトウェア開発関連の基礎知識

マニフェストファイルとロックファイル

どちらもプロジェクトがどんなライブラリに依存しているかを記録しているファイルです。

マニフェストファイルの方が抽象度が高めです。ファイル名は各エコシステム毎(Node.jsのマニフェストファイル名はpackage.json等)に固定で決まっている。npm等のツールは固定されたファイル名を前提に自動検出するため。

■マニフェストファイル

「このプロジェクトは何のライブラリを使いたいか」宣言するファイル。設計図・希望リストのようなイメージ。人間が読むことを想定されて作られているファイルというイメージ。

例:Node.jsのpackage.json

ファイル中身の中身は以下(18系ならOKという意味。あいまいに書かれることが多い)

react: ^18.0.0

■ロックファイル

実際にインストールされた“正確なバージョン”を記載するファイル。

ロックファイルにより、推移的な依存関係をGHASは把握できます(=正しいdependabot Graphが作成できるイメージ)

例:Node.jsのackage-lock.json

ファイル中身の中身は以下(完全に確定したバージョン が書かれる)

react 18.2.0
react-dom 18.2.0
scheduler 0.23.0

■推移的な依存関係とは?

あるアプリがライブラリAを使っている。ライブラリAが別のライブラリBを使っている。ライブラリBがまた別のライブラリCを使っている。

この場合、ライブラリA、ライブラリB、ライブラリCは推移的な依存関係がある

GHAS観点でいうと、アプリが直接的に利用しているライブラリAの脆弱性をチェックするだけでは不足しているので、推移的な依存関係にある、ライブラリB、ライブラリCもチェックしないといけない。推移的な依存関係を、把握するためにロックファイルが使われる。

■GHASとの関連

Depadabot Graphは、マニフェストファイルやロックファイルをもとに作成される

CI/CDツールを使ったデプロイにおいて、コンパイルされるタイミング

コンパイルは、CI/CDツールの中で実行されるのが一般的です(開発者のデバイスでコンパイルした後の実行ファイルをCI/CDに乗せるということは一般的ではありません)

コンパイルをビルドのプロセスを、CI/CDツールが観測できないと、コードの脆弱性を正確に把握することができません。

pipでインストールしたライブラリ自体が、他のライブラリ(lib②とする)を使っている場合は、lib②もpipを実行したPCにダウンロードされるか

ダウンロードされる

pipは、インストールしようとしているライブラリの依存ライブラリを調べ、必要なものをすべて再帰的にダウンロードします。

Github関連の基礎知識

フォーク

他人のGithubリポジトリを、自分のGithub環境にコピーすること(あくまでGithub内の話)。

OSSに貢献したい場合や、他人のリポジトリのコンテンツを使って自由に検証したいときなどに使う

★クローンとの違い

クローンは、Githubリポジトリを、ローカルPCにコピーすること

プル

既に存在しているローカルリポジトリを、最新の状態更新すること

★クローンとの違い

クローンは、ローカルリポジトリがない状態で、リモートリポジトリを丸ごとコピーする操作です(「更新」ではない)

チェックアウト

ローカルリポジトリにおいて、作業するリポジトリを切り替える操作

プルリクエストに対する承認とマージ

承認を実施したら、即マージされるわけではありません。

①承認した上で、②マージを実施することでマージが完了します。

①承認

②マージ

Github Actionsの仕組み

.github/workflow/配下にあるYAMLファイル(ワークフローファイルと呼ばれる)を実行します。

実行するタイミングや具体的にどのようなActionを実行するかも、このYAMLファイルに記載します。

Github Enterprise Server

オンプレ版のGithub。

GitHub Connectを使うことで、Github(クラウド)と連携ができるようになり、クラウド側(Dependabotアラート等)を利用できるようになる

githubディレクトリ

githubディレクトリは、Githubが参照する設定ファイル(CI、セキュリティ等に関する)が保存されている場所

Gitフック

Git操作の特定のタイミングで実行されるスクリプトのこと。Gitを操作しているローカルPCにおいて利用できる機能です。

実行したいスクリプトは、ローカルリポジトリの.git/hooks/配下に配置します。

ローカルリポジトリにおけるコミット前に、”コードにシークレットが含まれていないか”をチェックしてくれるようなスクリプトを動かしたりします。

個人アカウントレベルで、シークレットのプッシュを防ぐ機能

複数のパブリックリポジトリで作業をしているような場合で、そのパブリックリポジトリでプッシュ保護が有効でない場合、プッシュ操作によりシークレットがパブリックリポジトリにアップされてしまう可能性があります。

そんな状況を防ぎたい場合、個人のGitHubかアカウント設定で「Push Protection for youself」を有効にすることで対処が可能です。

パブリックリポジトリへのプッシュは、GitHub上で認証が完了している前提で実施できる操作です。そのため、この「Push Protection for youself」を有効にしておくことで、間違ってシークレットを含むコードをプッシュしてしまった場合でも、GitHubがブロックしてくれます。」

個人アカウントに紐づく通知受信箱

Githubからの通知を確認できる機能(メールの受信ボックスみたいなもの)

以下のURLからアクセス可能(’Githubログインした後の画面から遷移する方法は不明)

https://github.com/notifications