5

潜在的に危険な実行可能コードを(PROT_EXECを使用して)mmapprctl(PR_SET_SECCOMP, 1)し、このmmapされたコードを呼び出して実行する小さなプログラムがあります。これはすべて問題なく、mmapされた領域をディスクに同期して評価の状態を「保存」し、後で再ロードすることを可能にします(ほとんどの場合、負荷分散のために別のマシンに)。ただし、この手法は常に機能するとは限りません。このコードは、mmapされた領域にないプログラムに変更を加えた可能性があり、この情報は失われるためです。

したがって、私がやりたいのは、コードを呼び出す前に、(このmmapされた領域を除く)すべてを読み取り専用にすることです。このようにして、実行可能コードが、自由にシリアル化/逆シリアル化できるmmapされた領域以外の状態を変更できないことが保証されます。

ところで、これはx86_64上のLinuxです

ありがとう

4

1 に答える 1

4

mmap()まず、観察:マシン命令をメモリに入れたり、ファイルに保存したりする必要があるということは何もありません。read()これもwrite()可能ですが、この目的のために書き込み可能で実行可能なプライベートマッピングを作成する必要があることに注意してください。

同じプロセス内で実行される場合、スタックが使用できなくなるため、ロードする実行可能コードへの呼び出しを行うスタックの領域への書き込みを確実に無効にすることはできません。これを回避するには、変数にアノテーションを付けるか、アセンブリを使用します。

次のオプションはfork()です。子を特別なラッパー実行可能execファイルに入れて、悪意のある実行可能コードによる損傷と内省を最小限に抑えることができます(単にロード/ダンプを提供します)。または、子に同じ効果をもたらすように変更させることで同じことを行うことができます。これはまだ100%安全ではありません。

提案0

  • 最小限のライブラリに対してリンクされているスタンドアロンのバイナリを作成します(-nodefaultlibs)。
  • の後にforkptrace(PTRACE_TRACEME)子で(メモリの内容を確実に読み取り、他の介入を実行できるように)、パイプ以外のすべてのハンドルを閉じます(stdin簡単にするために)。exec()前述のラッパーバイナリに。

ラッパーバイナリの場合:

  • mmap書き込みおよび実行権限を持つ既知の場所のプライベートリージョン。または、サイズが固定されている場合は、この領域を静的に割り当てることができます。
  • パイプの内容をリージョンに読み込みます。
  • パイプを閉じます。現在、プロセスには開いているハンドルがありません。
  • prctl(PR_SET_SECCOMP, 1)。現在、有効なシステムコールは_exitとだけですsigreturn。プロセスはできないので、raise有用sigreturnな効果はないはずです。
  • メインスタックから書き込み権限を削除します(唯一のスタックである必要があります)。戻るつもりはなく、すぐにジャンプするので、スタックに再度触れる必要はありません。
  • リージョン内の開始位置にジャンプします。アセンブリを使用してこれを行うか、関数ポインターを作成して呼び出します(スタックにプッシュせずに機能させることができる場合)。これで、使用可能な唯一の書き込み可能な領域であるメモリ領域を実行する必要があります。メインスタックは保護されており、ライブラリがサポートされていないため、ヒープを使用しないでください。

親の場合:

  • ptraceまたはを使用しwaitて、誤った完了または正常な完了をキャッチします。
  • /proc/<pid>/memファイルを介して、またはファイルと同等の既知の場所にあるマップされた領域を読み取ります。
于 2011-11-13T14:03:35.853 に答える