web-dev-qa-db-ja.com

Node.js REST rootとして実行されているサーバー

私はNode.jsとExpressを使用してREST APIサーバーを構築しています。これにより、任意のLinuxサーバーをNASに変えることができます。基本的にシェルを生成するいくつかのfileExecがありますそして、BASHコマンドを実行します(pvspvcreatelvsvgsなど)。これらのコマンドのほとんどは、正しく実行するためにrootアクセスを必要とします。そのためには、Node.jsをSudoを使用してrootユーザーとして実行する必要があります。

Root以外のユーザーがサーバーを実行し、その特定のコマンドを実行するSudoが含まれる別の関数を使用できる可能性があることはわかっています。ただし、正しい資格情報を取得するには、サーバーアプリケーションにSudoパスワードを配置して管理する必要があります。それがはるかに良いかどうかはわかりません。また、アプリケーションがさらに複雑になります...

だから私の質問は、私のサーバーアプリケーションを保護するより良い方法はありますか?

4
InitEnabler

標準化されたREST APIを介して通信する複数のコンポーネントにアプリを分割することをお勧めします。

この場合、LVMボリュームを管理するのに十分な権限を持つユーザーとして(または、不可能であれば、rootとして)実行するストレージマネージャーアプリがあり、REST APIを通じてそのサービスを公開しますメインアプリ(権限のないアプリ)が消費する可能性があります。この小さなアプリは、TCP 1ではなく、UNIXソケットをリッスンする必要があります。パフォーマンスとセキュリティの両方の理由から(UNIXソケットは、 TCPはどこからでもアクセスできます)。

このアプローチでは、メインアプリを変更せずに、低レベルのコンポーネントを他のものと交換することもできます。

3
André Borie

アンドレの答えを拡張します。これは、あなたが受け入れるべきだと思います。

特権の削減

最初のステップは、アプリのワークフローに必要な最小限の特権を識別することです。私が理解していることから、仮想ボリュームを操作する必要があります。ログインシェルや他のroot機能なしで、新しいUIDを構成できますか?ほとんどのLinuxインターフェースには、権限を付与するための構成ファイルがあるため、使用する必要があるコマンドの開発者に確認してください。

次に作ります。アプリをそのように実行します。そのUIDのbashとホームが存在しないようにしてください。そのため、アプリが悪用された場合、ハードドライブの永続的な書き込み権限を持つ領域は、可能な限り存在しないはずです。また、そのUIDにリモートログインする機会もありません。このアカウントIDでアプリを実行するためのランチャースクリプト(Upstart、Systemd、Initなど、これらの論争に巻き込まれないもの)を使用できます。

次に、rootには見た目以上のものがあることを理解してください。まず、rootとして実行されるプロセスは、保持するのが危険と見なされる特権を放棄する可能性があります。それらは Linux機能 と呼ばれます。したがって、すべての無関係な機能を削除するアプリのラッパーを記述します。いくつかの機能を残す必要がある場合は、それらを悪用できないように調査してください!たとえば、 Linuxの機能を活用する は、特定の機能のみで始まる完全な機能セットを取り戻す方法について説明しています。

区画化

アンドレの答えを見てください。基本的に、小さなアプリですべての特権操作を実行して、(1)簡単に確認できるようにします。APIを検証して適切な入力ドメイン検証を実行するだけで済みます。 (2)出荷されるコードが少ないため、アプリの制御を完全に委ねる悪用可能なバグが発生する可能性が低くなります。

硬化

この種のシナリオであなたを保護するように設計されたもう1つの武器は、必須アクセスコントロールLinuxセキュリティモジュールです。デフォルトでは、Linuxはrootがシステムコールに対して行ったほとんどの随意アクセス制御チェックを上書きすることを許可します。ただし、LSMは独自の必須ロジックを呼び出しに適用できます。これにより、LSMはrootの特権を減らすことができます。

AppArmorやTOMOY Linuxについて話すことはできますが、小学校のおもちゃは幼児にまかせましょう。 SELinuxを調べて、実際にそれを理解する必要があります(くそ。はい、それは難しい)。プロセスに適用するSELinuxロールを作成する必要があります。ロールは、SELinuxのIDに加えて、すべてのシステムコールにポリシーを適用します。役割とは、システム上で事実上何もすることを禁止されているrootユーザーを持つことができることを意味します。ここでは、必要なシステムコールを特定する必要があります(audit2allow to this end)そして、これらのシステムコールへのアクセス権をロールに付与します。

特権のリストを取得したら、必ず特権を確認し、可能であれば、適切なリソースでのみ許可するようにしてください。たとえば、ロールは/ var/wwwにファイルを書き込むことを許可されますが、/ var/logには許可されません。つまり、システム上のいくつかのファイルに特定のタイプのラベルを付け、独自のスクリプトを作成してラベルを維持する必要があるでしょう。また、アプリの新しいドメインを作成する必要があります。これにより、ドメインおよびタイプ施行ポリシーと呼ばれるものを記述できます。ポリシーは、ドメイン内のアプリが他の特定のタイプおよびドメインとのみ対話する方法を決定します。

要約すると、ドメインタイプのポリシーはプロセスが抑制されることを保証し、役割のポリシーはUIDが抑制されることを保証します。いくつかのオーバーラップがありますが、間違いを犯した(または正当なニーズがある)ためにアプリが別の制限の少ないドメインに移行する可能性があるため、両方が必要です。アプリに課すSELinuxの役割により、遷移は選択したドメインにのみ発生することが保証されます。

役割に許可されたすべてのドメインに、システムを永続的に危険にさらすことのない十分な特権を確実に与えることは、依然としてあなたの責任です。これは、( 1)「悪用可能な」Linux機能を阻止する。 (2)制限付きアプリと他のアプリの間でリソースを共有していない。 (および(3)すべての形式の永続ストレージを拒否する( [制限問題に関するメモ のメモリレスプロパティを参照)。これにより、侵害されたアプリが存続しなくなります)。

それを達成できない場合、アプリが必要とする特権が多すぎるため、システムを保護できない可能性があります。エキスパートを雇って、あなたが何かを見逃していないことを確認できるようにするときです。

1

プログラムに欠陥がないと仮定すると、root資格情報で安全に実行できます。残念ながら、これは常に当てはまるとは限らないため、ルート資格情報を使用して、公的にアクセス可能なサービスをneverで実行する必要があります。

サービスがパブリックにアクセスできない場合(つまり、LANのみ、またはIPアドレスアクセスリストを使用して訪問者を制限している場合)、誰かがこれらの方法でサービスにアクセスできる可能性を判断して、セキュリティが低いかどうかを判断する必要があります。 rootサービスは利用できます。

それ以外の場合は、リスナーを非rootとして実行する必要があります。ハッカー、およびroot以外のアカウント設定に応じて、これは簡単にダメージのないハックと完全な+秘密の乗っ取りの違いです。

1つのオプションは、親プロセスをrootとして実行し、次に子プロセスにHTTPリスナーやopensslベースのHTTPSリスナーを含む主要なアプリケーション機能を実行させることです。 setuidを呼び出して、自身の資格情報をnoaccessnobodywebservd、またはこの目的に適した、作成/見なしたアカウントに下げます。使用する stdin/stdout親プロセスと通信します。

しかし、実際には、sudoersファイルで[パスワードなし]オプションを設定するのが最も簡単な解決策だと思います。これは、サービスが実行されている1つのユーザーアカウント(つまり、webservd)に対してのみ行う必要があり、コマンドの特定のホワイトリストが必要です。 「any」コマンドに対してSudoアクセスが許可されている場合、非rootとして実行する目的が無効になっています。

0
Bryan Field

通常、外部からアクセス可能なアプリケーションをrootとして実行することは悪い考えとされています

これを行う正しい方法は、次のいずれかです。

  • node-dataのような新しいユーザーを作成し、必要な権限のみを付与します(NASファイルシステムのルートへの権限)NOT / =必要な実行可能ファイルへの特定の権限と同様に)

および/または

  • 2つのノードサーバーを作成します。1つは低レベルのユーザーアクセスで外部に面し、もう1つはルートアクセスコマンドを実行するためにZMQのようなものを介して内部のみのapiで作成します。
0