system() API によるコマンドインジェクションを回避する

system() API によるコマンドインジェクションを回避する

権限の低いユーザーが昇格された権限でカスタム スクリプトを実行できるようにするために使用されるレガシー C コードがあります。これには SUID ビットが設定されています。このコードは、PATH 環境を特定のフォルダーに制限し、system()api を使用して制限されたシェルでスクリプトを実行します。

/bin/bash -r -c "script <arg>"

パスが制限されているため、特定のフォルダーからのスクリプトのみを実行できます。

APIを使用したコマンド インジェクションの落とし穴をすべて理解したところでsystem()、コマンド インジェクションを回避するためにどのような対策を講じることができますか? これはさまざまなスクリプトなどの多くの場所で使用されるため、回帰を回避するために完全に新しい実装を行うことは望ましくありません。

答え1

正しく実行するのは難しいので、コードから SUID を削除することをお勧めします。 を使用するように C コードを変更しますsudo。 sudo を使用すると、安全なシステム プログラミングを実現する難しい側面が実現します。

次に、visudo を使用して、タスクを実行するために必要最小限のことだけを行い、これを必要なユーザー/グループに制限する sudo 構成を慎重に構築します。sudo を構成した後、自分以外の誰かにテストしてもらい、意図した制約を破ってみてください。

答え2

コード インジェクションでは、ユーザーがsystem()呼び出しに任意の文字列をパラメータとして渡す必要があります。これは SQL インジェクションと非常によく似ており、同様の方法で回避する必要があります。ユーザー定義の文字列を呼び出しに直接渡さないでください。

  • 数値パラメータは整数に変換され、呼び出し時に文字列に戻される必要があります。

  • 固定辞書に属するパラメータは、「enum」値または類似の値に変換され、呼び出し時に文字列に戻される必要があります。

  • 自由テキスト入力は、可能な限り、無害な文字セットに制限する必要があります (例[a-zA-Z0-9]*)。問題のある文字 (スペースを含む) が必要な場合は、適切なエスケープを適用する必要があります (つまり、を などa bに置き換える必要がありますa\ b)。

関連情報