1731560383
2024-11-13 09:09:00
Go コードを書くときにセキュリティを念頭に置くとはどういう意味ですか?この質問に 1 つの短い記事で答えるのは不可能に思えます。このため、いくつかの具体的な実践方法に絞り込んでいきます。
これらを継続的に適用すると、堅牢で安全かつパフォーマンスの高いコードを作成できるようになります。
- Go のセキュリティに関する発表について常に最新情報を入手するにはどうすればよいですか?
- Go コードにパッチを当てて最新の状態に保つにはどうすればよいでしょうか?
- セキュリティと堅牢性に重点を置いて Go コードをテストするにはどうすればよいでしょうか?
- CVE とは何ですか?最も一般的なソフトウェアの脆弱性についてはどこで学べますか?
メーリングリスト
最もわかりやすい場所である Go メーリング リストから始めましょう。すべての重要なセキュリティ情報をソースから直接取得するには、サブスクライブする必要があります。セキュリティ修正を含むすべてのリリースは、 [email protected] リスト。リストに登録すると、重要なお知らせを見逃すことがなくなります。
Go のバージョンを最新の状態に保つ
2 番目のステップは、プロジェクト内の Go バージョンを最新の状態に保つことです。最新かつ最高の言語機能を使用していなくても、Go のバージョンを上げれば、発見された脆弱性に対するすべてのセキュリティ パッチが提供されます。また、新しい Go バージョンでは、新しい依存関係との互換性が保証されています。これにより、潜在的な統合の問題からアプリケーションが保護されます。
3 番目のステップは、どの Go リリースでどのセキュリティ問題と CVE が対処されているかを知ることです。 Go リリース履歴 Web サイトでそれを確認し、次の Web サイトで最新バージョンに更新できます。 go.mod プロジェクト内のファイル。
Go の新しいバージョンにアップグレードした後は、特にサードパーティのパッケージとの操作によって互換性や依存関係の問題が発生しないことを確認する必要があります。数十、場合によっては数百もの直接的および間接的なパッケージ依存関係を伴う大規模なプロジェクトに取り組む場合、より危険になる可能性があります。
重要なのは、潜在的な依存関係の問題を排除してリスクを維持することです。この問題には、既存のコードを新しい依存関係で動作させるために緊急にリファクタリングする必要があることが含まれる場合があります。このような問題の例には、変更されたパッケージ、API、または関数のシグネチャが含まれます。
セキュリティ上の問題なく Go バージョンを使用できることがわかったら、プロジェクトのソース コードに集中できます。静的コード アナライザーを採用することで、コードの品質とセキュリティの評価を開始できます。
獣医
サードパーティのアナライザーをインストールして使用する前に、Go の「ネイティブ」を使用することをお勧めします。 go vet 指示。
使用できます go vet Go コードを分析するコマンド。の go vet 引数を指定しないコマンドは、デフォルトで許可されているすべてのオプションを使用してツールを実行します。このツールはソース コードをスキャンし、潜在的な問題を報告します。この問題には、コード構文エラーや、プログラムの実行中に問題を引き起こす可能性のある特定のプログラミング構造が含まれます。
最も一般的な問題には、ゴルーチンの間違い、未使用の変数、コードベースの到達不能領域などがあります。を使用する主な利点は、 go vet コマンドは Go ツールボックスの一部であるということです。
別の記事でさらに詳しく説明します vet 詳細。広範なドキュメントと例は、 go vet Webサイト。
静的チェック
Staticcheck は、別の静的コード アナライザーです。これは、バグを発見し、潜在的なパフォーマンスの問題を検出するのに役立つサードパーティのリンターです。また、Go 言語のスタイル設定も強制されます。コードを簡略化し、発見された問題を説明し、例を示して修正を提案します。
CI パイプラインで staticcheck を実行する以外に、次のものをインストールできます。 staticcheck ラップトップ上でスタンドアロン バイナリとして実行し、コードをローカルでスキャンします。最新バージョンをインストールしましょう。
go install honnef.co/go/tools/cmd/staticcheck@latest
端末にエラーはありませんか?そうであれば、スキャンを実行する準備ができています。ただし、最初に、インストールされているバージョンをチェックして、すべてが正常であることを確認しましょう。
staticcheck --version
staticcheck 2024.1.1 (0.5.1)
同様に、 go vet、走っています staticcheck 引数を指定しないと、デフォルトですべてのコード アナライザーが起動されます。このアプローチは、賢明なデフォルトを使用し、ユーザーに不必要な事務処理を強制しないという UNIX プログラミングの哲学とうまく調和しています。
ツールが何を見つけることができるか見てみましょう NGINX エージェント GitHub リポジトリ。まず、クローンを作成する必要があります。
次に、プロジェクトのルート ディレクトリから実行できます。
➜ agent git:(main) ✗ staticcheck ./...
しばらくすると、スキャン結果を確認する準備が整います。リストされた例は 3 つのグループに分類できます。
- 非推奨となったパッケージ、メソッド、または関数。例:
...
src/core/metrics/sources/cpu.go:111:9: times.Total is deprecated: Total returns the total number of seconds in a CPUTimesStat Please do not use this internal function. (SA1019)
...
test/component/nginx-app-protect/monitoring/monitoring_test.go:15:8: "github.com/golang/protobuf/jsonpb" is deprecated: Use the "google.golang.org/protobuf/encoding/protojson" package instead. (SA1019)
- 未使用の変数とフィールド、例:
src/core/metrics/sources/nginx_plus.go:74:2: field endpoints is unused (U1000)
src/core/metrics/sources/nginx_plus.go:75:2: field streamEndpoints is unused (U1000)
src/core/metrics/sources/nginx_plus_test.go:94:2: var availableZones is unused (U1000)
- コードの品質に関連して考えられる問題。例:
src/core/nginx.go:791:4: ineffective break statement. Did you mean to break out of the outer loop? (SA4011)
これで、強調された問題の分析を開始する準備が整いました。コードベースの詳細については、この入門記事の範囲外です。今後の記事では、より詳細なコード分析を行い、例を示し、セキュリティとパフォーマンスの問題を修正する予定です。
現時点では、後で調査できるように、リストされた弱点に関する大量の情報が含まれている CWE Web サイトに注目してみましょう。
ゴランシリント
使用する 3 番目のコード アナライザーは次のとおりです。 golangci-lint。すべての Go ツールと同様、さまざまな方法でインストールできます。 go install 指示:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
インストールが正常に完了したかどうかを確認し、バージョンを確認してみましょう。
golangci-lint --version
golangci-lint has version v1.61.0 built with go1.23.2
...
完璧!すべてが良さそうです。
驚きを最小限にするという同じ原則に従って、 golangci-lint 引数なしで呼び出すと、すべてのリンターが実行されます。
最小の驚きのルール: インターフェイスのデザインでは、常に最小の驚きを行うようにしてください。
以前にクローンを確認するとどうなるか agent リポジトリ?意思 golangci-lint 同じ警告や提案を私たちに示してくれるでしょうか?調べてみましょう。
前と同様に、ルート ディレクトリからプロジェクトのスキャンを開始します。
➜ agent git:(main) ✗ golangci-lint run ./...
ほぼすぐに、コードを改善するための提案のリストに気づきました。例えば:
src/extensions/nginx-app-protect/monitoring/processor/nap_test.go:60:14: S1025: the argument is already a string, there's no need to use fmt.Sprintf (gosimple)
logEntry: fmt.Sprintf(`%s`, func() string {
^
src/plugins/common.go:85:5: S1009: should omit nil check; len() for []string is defined as zero (gosimple)
if loadedConfig.Extensions != nil && len(loadedConfig.Extensions) > 0 {
^
リンターは、注意が必要な正確なファイルと行を指します。私たちの現在の仕事は、コードを評価し、変更を加え、ライナーを 2 回目に実行し、すべての単体テストを実行することです。テストが緑色の場合は、更新されたコードをコミットできます。仕事は終わりました! OK、まだリモートにプッシュする必要があります。
競合状態の検出
複数のゴルーチンがリソースに同時にアクセスしようとすると、プログラムやライブラリで競合状態が発生する可能性があります。これらの条件は、少なくとも 1 つのゴルーチンがリソースに書き込み (変更) を試みたときに検出されます。たとえば、リソースは、カウンターとして機能するグローバルなパッケージ レベルの変数にすることができます。プログラム内のこの状況は、診断と検出が非常に難しい微妙なバグにつながる可能性があります。
Go は、そのような条件をテストするためのネイティブ サポートを備えています。 Go を使用してテストを実行します test 引数を指定したツール -race。このメソッドは競合検出機能を実行し、同時実行プログラムの問題を特定するのに役立ちます。
覚えておく必要がある警告が 1 つあります。検出器は実行されたコードを評価でき、実行されないコード パスは無視されます。したがって、最初に静的コード アナライザーを実行し、プロジェクト内にいわゆるデッド コードがないことを確認することが重要です。
Go に次のように指示すると、「ねえ、 -race 引数」を指定すると、Go コンパイラは競合検出機能を有効にしてコードをコンパイルします。次に、テストが実行され、実行時に競合状態の可能性がチェックされます。人種が検出されると、ツールは詳細なレポートを出力します。どのゴルーチンがどのリソースにアクセスしようとしているのかが表示されます。
同時実行の問題を検出する可能性を高めるもう 1 つの方法は、テストを並行して実行することです。そのためには、以下を追加してランナーに明示的に通知する必要があります。 t.Parallel() 私たちのテストに。
2 つのテストを並行して実行
func TestParseDiskSpace(t *testing.T) {
t.Parallel()
...
func TestParseMemoryUsage(t *testing.T) {
t.Parallel()
...
競合状態の検出と同時実行コードの設計は、将来的に説明する広大でエキサイティングなトピックです。
ソースコードの脆弱性をスキャンする
ゴヴルンチェック
コードベースをスキャンして、次のリストにある既知の脆弱性を見つけるツールを幅広く選択できます。 CVE データベース。
安全なコードの開発とリリースを保証するためのデフォルトのツールは次のとおりです。 govulncheck。コードをリモート Git リポジトリにコミットしてプッシュする前に、開発者のマシンにローカルにインストールし、ローカルでスキャンを実行できます。
オプションで、スキャン手順を GitHub または GitLab の CI パイプラインと統合できます。その後、マージ リクエストごとにスキャンを実行して、プロジェクトに脆弱性が生じないようにすることができます。
govulncheck Go チームによって開発されました。 Go 脆弱性の専用データベースは、スキャナーに情報を提供します。インストールしましょう govulncheck ローカルで基本的な機能を試してください。
最新バージョンをインストールするには、次のコマンドを実行する必要があります。
go install golang.org/x/vuln/cmd/govulncheck@latest
インストール プロセスが正常に完了したかどうかを確認します。
govulncheck -version
Go: go1.23.2
Scanner: [email protected]
DB: https://vuln.go.dev
DB updated: 2024-10-17 15:37:30 +0000 UTC
...
最初のスキャンを実行する準備ができました。クローンを作成しましょう 癖 gitリポジトリ。次に、ルート ディレクトリに移動してツールを実行します。
➜ habit git:(main) ✗ govulncheck
No vulnerabilities found.
期待できそうですね!ソースコードに脆弱性は見つかりませんでした。もう終わりですか?あまり!私たちが習慣バイナリを構築したのは、 go.mod ファイルは Go 1.18 のバージョンを定義しました。現在のバージョンは v1.23.2 です。
ソースコードではなく、習慣バイナリをスキャンしましょう。
➜ habit git:(main) ✗ govulncheck -mode binary -show verbose habit
私たちは走ります govulncheck バイナリモードで。これは、アクセスできるすべての Go バイナリをスキャンできることを意味します。ソースコードは必要ありません。次に、冗長モードでスキャンを実行します。複数のセクションに分かれた完全なレポートが表示されます。最後の引数は、スキャンするバイナリの名前です。
うーん!このレポートは見た目が違います!一体何が起こったのでしょうか?
Scanning your binary for known vulnerabilities...
Fetching vulnerabilities from the database...
Checking the binary against the vulnerabilities...
=== Symbol Results ===
No vulnerabilities found.
=== Package Results ===
Vulnerability #1: GO-2023-2186
Incorrect detection of reserved device names on Windows in path/filepath
More info: https://pkg.go.dev/vuln/GO-2023-2186
Standard library
Found in: path/[email protected]
Fixed in: path/[email protected]
=== Module Results ===
Vulnerability #1: GO-2024-3107
Stack exhaustion in Parse in go/build/constraint
More info: https://pkg.go.dev/vuln/GO-2024-3107
Standard library
Found in: [email protected]
Fixed in: [email protected]
...
Vulnerability #18: GO-2023-1878
Insufficient sanitisation of Host header in net/http
More info: https://pkg.go.dev/vuln/GO-2023-1878
Standard library
Found in: [email protected]
Fixed in: [email protected]
Your code is affected by 0 vulnerabilities.
This scan also found 1 vulnerability in packages you import and 18
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
最初のセクションには最も重要なメッセージが含まれています。 脆弱性は見つかりませんでした。
残りのセクションには、標準 Go ライブラリで発見された他の脆弱性に関する情報が含まれています。わかりましたが、私たちも影響を受けていますか?私たちのプログラムは安全ではありませんか?
最終スキャンレポートを見ると、心配する必要はないことがわかります。私たちのプログラム これらの脆弱性を呼び出すものではないようです!幸せな日々を!
Your code is affected by 0 vulnerabilities.
This scan also found 1 vulnerability in packages you import and 18
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
更新しましょう go.mod ファイルを編集し、Go バージョンを最新のものに変更します 1.23。次に、実行する必要があります go mod tidy すべての依存関係を最新の状態にします。この時点で、バイナリを再度ビルドする準備が整いました。
➜ habit git:(main) ✗ go build -o habit cmd/main.go
スキャンを再実行してみましょう。
➜ habit git:(main) ✗ govulncheck -mode binary -show verbose habit
Scanning your binary for known vulnerabilities...
Fetching vulnerabilities from the database...
Checking the binary against the vulnerabilities...
No vulnerabilities found.
それが私たちが望んでいたものです! Go のバージョンをアップグレードし、依存関係を取得し、ソフトウェアと依存関係に CVE がないことを確認しました。
ゴセック
gosec 静的コードアナライザーです。安全でないコード構造を見つけるのに役立ちます。これをラップトップにローカルにインストールすることも、CI パイプラインで GitHub アクションとして実行することもできます。前に説明したように、 golangci-lint が含まれます gosec プラグインとして使用し、コードスキャンごとにデフォルトとして実行します。
スキャナをローカルにインストールして試してみましょう。
go install github.com/securego/gosec/v2/cmd/gosec@latest
エラーが見つからない場合は、 gosec 行動の準備ができています。最初のスキャンを実行する前に、メニューを見てみましょう。
gosec -h
gosec - Golang security checker
gosec analyses Go source code to look for common programming mistakes that
can lead to security problems.
...
オプションとルールの長いリストを使用して、スキャナーの動作を構成できます。特定のオプションの詳細については、この記事の範囲外です。この SAST ツールの構成、実行、メリットに関する詳細なチュートリアルが近日公開されます。乞うご期待!
gosec を試すには、スキャンしたい Go コードを含む GitHub リポジトリのクローンを作成する必要があります。
クローンを作成しましょう ブルータス リポジトリ。オープンソースの実験版です OSINT Webサーバーの構成をテストするためのアプリ。
次に、現在のディレクトリをプロジェクトのルート ディレクトリに変更し、スキャンを開始します。
数秒後、 gosec スキャンレポートを提示します。すぐに学べることは何でしょうか?重大度と信頼度によって分類された潜在的な問題のリストが表示されます。私たちは、コードのどの部分に注意が必要か、そして問題がどのような弱点の分類に当てはまるのかを知っています。完璧!次は何でしょうか?
...
[/.../bruter/pkg/fuzzer/randomua.go:69] - G404 (CWE-338): Use of weak random number generator (math/rand or math/rand/v2 instead of crypto/rand) (Confidence: MEDIUM, Severity: HIGH)
68:
> 69: randomIndex := rand.Intn(len(userAgents))
70: return userAgents[randomIndex]
...
[/.../bruter/pkg/server/config.go:40] - G402 (CWE-295): TLS InsecureSkipVerify set true. (Confidence: HIGH, Severity: HIGH)
39: customTransport := &http.Transport{
> 40: TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
41: }
...
調査のこの段階では、報告された CWE を確認し、リストされた弱点の詳細を知ることができます。たとえば、2 番目にリストされている問題は、次のような問題をもたらします。 CWE-295 脆弱性について詳しく知ることができるウェブサイト。
ファジング
コードの品質をチェックして脆弱性を発見する最後の方法は、ファズ テストです。ファジングは特別な種類の自動テストです。コード テスト カバレッジを使用して、ランダムに生成された入力データを操作します。
バッファ オーバーフローなどの潜在的なセキュリティ上の欠陥を見つけるのに非常に役立ちます。 SQLインジェクション、 DoS攻撃 そして XSS 攻撃。ファジングの最も重要な特性は、多くの入力の組み合わせが自動的に生成されることです。開発者は、数千とは言わないまでも、数百もの入力データの組み合わせを理解しようとして頭を悩ませる必要はありません。なんという安心でしょう!
今後のチュートリアルでは、ファジングについてさらに詳しく説明します。
今日説明した方法とテスト手法のほとんどは、以下によって奨励されています。 OpenSSF 財団。ベスト プラクティス バッジの取得を希望するオープンソース プロジェクトは、次の条件を満たす必要があります。 FLOSS 基準 ライセンス、変更管理、脆弱性レポート、品質、セキュリティ、静的および動的セキュリティ コード分析などの分野です。
安全を確保し、CVE から解放され、プログラミングを楽しんでください。
として ジョン・アランデル 言います:
「プログラミングは楽しい、楽しんでやるべきだ!」
次回まで!
#安全な #コードの作成 #ヤクブヤロシュ