ホームページ >バックエンド開発 >Golang >Go のコマンド インジェクションの脆弱性を理解する

Go のコマンド インジェクションの脆弱性を理解する

DDD
DDDオリジナル
2024-11-26 00:49:14644ブラウズ

Go 開発者は、画像の処理やサイズ変更、リソースの管理やメトリクスやログの収集のためのシステム コマンドの実行が必要な画像操作など、さまざまなシナリオでシステム コマンドを使用する必要がある場合があります。

また、既存のレガシー システムとインターフェースする必要がある新しいシステムを Go で構築している場合もあります。このインターフェイスは、システム コマンドの実行とその出力の処理に依存しています。

いずれの場合も、システム コマンドを生成する際には、コマンド インジェクションとして知られるセキュリティ上の脆弱性を引き起こす可能性があるため、安全なコーディング規約に従うことが不可欠です。

コマンドインジェクションとは何ですか?

コマンド インジェクションは、アプリケーションがユーザーが指定した安全でないデータ (Web フォームからの入力など) をシステム シェルに渡すときに発生するセキュリティ上の脆弱性です。この脆弱性により、攻撃者は同じアプリケーション ユーザーのホスト オペレーティング システム上で任意のコマンドを実行することができます。

Go では、コマンド インジェクションでは、os/exec パッケージを使用してシステム コマンドを生成することがよくあります。

次の Go コード例を考えてみましょう:

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

このコード スニペットでは、cmdName がリクエスト クエリ パラメーターから直接抽出され、サーバー上で実行されるコマンドの構築に使用されます。これは、コマンド インジェクションの脆弱性の典型的な例です。攻撃者が cmd クエリ文字列の値を操作して、選択したコマンドを実行できるため、サーバーが侵害される可能性があります。

攻撃者は、次のような悪意のあるコマンドを使用してリクエストを作成する可能性があります。

http://example.com/execute?cmd=rm%20-rf%20/

コマンドインジェクションが危険なのはなぜですか?コマンド インジェクションは、攻撃者がサーバー上で任意のコマンドを実行できるため危険であり、次のような重大な結果につながる可能性があります。

  • データ侵害: 攻撃者はサーバーに保存されている機密データにアクセスできます。彼らが config.toml などのリソースや資格情報をリストした構成ファイルにアクセスしているところを想像してください。
  • システムの侵害: 攻撃者がサーバーを制御し、さらなる悪用につながる可能性があります。これは多くの場合、侵害されたシステム内での横方向の移動と、侵害される可能性のある他のサーバーの検出アクションの形で行われます。
  • サービスの中断: 攻撃者はサービスを中断し、ダウンタイムを引き起こすコマンドを実行する可能性があります。事実上、これはサービス拒否攻撃による経済的損失やビジネスリスクに直接つながる可能性があります。

コマンド インジェクション攻撃が成功すると、その影響は壊滅的なものになる可能性があり、侵害されたシステムだけでなく、組織の評判や顧客の信頼にも影響を及ぼします。

Go における脆弱なプロセス実行とコマンド インジェクション

シンプルさとパフォーマンスを好むことで知られる Go 開発者は、これらのユーティリティの機能を利用するためにシステム コマンドを統合することを選択する場合があります。このアプローチにより、車輪を再発明することなく、堅牢なアプリケーションの構築に集中できるようになります。ただし、この統合には、特にセキュリティの面で、独自の一連の課題が伴います。

より現実的なシナリオを説明するために、convert などのコマンドライン ユーティリティを使用して画像ファイルを処理する Go アプリケーションを考えてみましょう。

画像のサイズ変更リクエストを処理するように設計された Go アプリケーションを調査します。このアプリケーションは、Gin Web フレームワークを使用して、ユーザー入力に基づいて画像のサイズ変更を処理する POST エンドポイント /cloudpawnery/image を定義します。このエンドポイントは、クエリ文字列から tenantID、fileID、fileSize などのパラメーターを受け入れます。 fileSize パラメータはオプションであり、指定しない場合はデフォルトの「200」になります。

次のコード スニペットは、Go での脆弱な実装を示しています。

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

downloadAndResize 関数は、convert を使用して画像のサイズを変更するコマンド文字列を構築し、exec.CommandContext を使用してそれを実行します。

downloadAndResize 関数はどのようにコマンド文字列を構築しますか?ユーザーが指定した fileSize を使用してこの入力を受け取ります。その後、この文字列が実行され、攻撃者が悪意のあるコマンドを挿入できる可能性があります。このリスクを軽減するには、Go 開発者はすべてのユーザー入力を検証してサニタイズし、パラメーター化されたコマンドを使用し、コマンドの実行を安全に処理するセキュリティ手法を活用する必要があります。

コマンドインジェクションの脆弱性を軽減する

Go 開発では、他の言語と同様に、コードがコマンド インジェクションの脆弱性に対して安全であることを確認することが最も重要です。コマンド インジェクションは、攻撃者がホスト上で任意のコマンドを実行できる場合に発生し、不正アクセス、データ侵害、その他の重大なセキュリティ問題を引き起こす可能性があります。

これらのリスクを軽減するためのベスト プラクティスをいくつか見てみましょう。

入力の検証とサニテーション

コマンドインジェクションを防ぐための基本的な手順の 1 つは、厳密な入力検証とサニテーションです。提供された例では、downloadAndResize 関数は、fileSize などのユーザー指定の入力を使用してコマンド文字列を構築します。これらの入力が適切に検証されない場合、攻撃者は悪意のあるコマンドを挿入する可能性があります。

入力検証を改善する方法は次のとおりです:

  1. 許可リスト入力: fileSize などの入力に許容される値のセットを定義します。たとえば、妥当な範囲内の数値のみを許可します。
  2. 入力のサニタイズ: ユーザー入力から潜在的に危険な文字を削除またはエスケープします。これには、;、|、& などのシェル メタ文字を含めることができます。コマンドをハードコーディングし、ユーザー入力による制御を許可しないことをお勧めします。
  3. 厳密な型を使用する: 入力をできるだけ早く期待されるデータ型に変換します。たとえば、fileSize を整数に変換し、その範囲を検証します。

これらのプラクティスを実装する方法の例を次に示します。

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

それでも、Go コードをコマンド インジェクションから保護するために、さらに改善できることがあります。読み続けてください!

システムコマンドの代わりに安全な API またはライブラリを使用する

もう 1 つの効果的な戦略は、可能な限りシステム コマンドを直接実行しないことです。代わりに、アプリケーションをコマンドインジェクションのリスクにさらすことなく、必要な機能を提供する安全な API またはライブラリを活用してください。

たとえば、アプリケーションで画像を操作する必要がある場合は、ImageMagick ソフトウェア ライブラリからの Convert などの外部コマンドを呼び出す代わりに、github.com/disintegration/imaging などの Go ライブラリを使用することを検討してください。このアプローチでは、Go のタイプセーフ環境内に機能がカプセル化され、攻撃対象領域が減少します。

http://example.com/execute?cmd=rm%20-rf%20/

Go でイメージングなどのライブラリを使用すると、シェル コマンドを構築して実行する必要がなくなり、コマンド インジェクションのリスクが軽減されます。それでも、一部のライブラリや言語エコシステムでは、サードパーティのパッケージがコマンド実行の単純なラッパーである可能性があるため、そのような機密性の高い操作についてはコードをレビューすることが必須です。

インジェクションを防ぐために脆弱な downloadAndResize 関数をリファクタリングする

前の例では、exec.CommandContext 関数を使用してシェル コマンドを実行する、潜在的に脆弱な Go アプリケーションを示しました。このアプローチは、前述したようにコマンド インジェクションの脆弱性を引き起こす可能性があります。

ユーザー入力によって任意のコマンドが実行されないように、downloadAndResize 関数をリファクタリングしてみましょう。

コマンド インジェクションを防ぐ効果的な方法の 1 つは、ユーザー入力から直接シェル コマンド文字列を構築しないようにすることです。代わりに、個別の引数を指定して exec.Command 関数を使用できます。これにより、シェルを呼び出したり、ユーザーが実際のコマンドを制御したりすることなく、ユーザー入力をパラメーターとしてコマンドに安全に渡すことができます。

コマンド インジェクションの脆弱性に対処する downloadAndResize 関数のリファクタリング バージョンを次に示します。

func handler(req *http.Request) {
  cmdName := req.URL.Query()["cmd"][0]
  cmd := exec.Command(cmdName)
  cmd.Run()
}

このリファクタリングでは、コマンドを引数から分離しました。 exec.CommandContext を別の引数とともに使用することで、シェル コマンド文字列を構築する必要がなくなります。この方法により、ユーザー入力が実行可能コードではなくデータとして扱われるようになり、コマンド インジェクションのリスクが大幅に軽減されます。

また、シェルを呼び出す必要もなくなりました。リファクタリングされたコードは、コマンド インジェクションの一般的なベクトルであるシェル (sh -c) を呼び出しません。代わりに、指定された引数を使用して変換ユーティリティを直接呼び出します。

コードのセキュリティに Snyk を活用

Snyk Code は、開発者がコードベースの脆弱性を特定して修正するのに役立つ強力な静的分析ツールです。 IDE と開発ワークフローにシームレスに統合され、潜在的なセキュリティ問題に関するリアルタイムのフィードバックが提供されます。

Snyk が Go のコマンド インジェクションの脆弱性を特定するのにどのように役立つか

提供されている Go の例では、downloadAndResize 関数はユーザー指定の入力を使用してシェル コマンドを構築します。

http://example.com/execute?cmd=rm%20-rf%20/

このコードはユーザー入力をコマンド文字列に直接組み込むため、コマンドインジェクションに対して脆弱です。

あなたのチームにコマンド インジェクションの脆弱性を知らない開発者がいたらどうなるでしょうか?

このコマンド インジェクションの脆弱性を見つけるために、コード レビューでファイル間の静的分析の呼び出しフローを簡単に特定できますか?

ここで Snyk の出番です。

VS Code エディター内で脆弱なコードをリアルタイムで強調表示する Snyk Code 拡張機能を使用して、アプリケーションのセキュリティがどのように簡単になるかを見てみましょう:

Understanding command injection vulnerabilities in Go
Snyk は、Go コードをスキャンし、ユーザー入力がシェル コマンドで安全に使用されていないインスタンスにフラグを立てることで、そのような脆弱性を特定するのに役立ちます。 Snyk は、この特定の脆弱性を軽減する他のオープンソース プロジェクトによって作成された実際のコミットを示し、「良いもの」の例としていくつかのコード参照を取得します。

さらに、[問題の概要] タブをクリックすると、コマンド インジェクションを防止するための詳細とベスト プラクティスのドリルダウンが表示されます。このタブには、これらのリスクを軽減する方法に関する詳細な洞察と推奨事項が表示されます。このタブは、コーディング中に IDE ビューで直接利用でき、コストのかかるコンテキスト切り替えを行わずにこれらのアクションに従うことができます。

Understanding command injection vulnerabilities in Go
このような脆弱性からコードを保護する方法をさらに学習するには、Snyk Code IDE 拡張機能をインストールし、Git プロジェクトに接続して、Go アプリケーションのセキュリティ問題を特定して修正することを検討してください。サインアップしてコードの脆弱性のスキャンを開始することで、簡単かつ無料で実行できます。

以上がGo のコマンド インジェクションの脆弱性を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。