Linuxのサンドボックスで信頼できないCプログラムを実行して、ファイルを開いたり、フォークしたりできないようにしますか?


110

Linuxのサンドボックスで信頼できないCプログラムを実行する方法があるかどうか疑問に思っていました。プログラムがファイルを開いたり、ネットワーク接続したり、フォークしたり、実行したりするのを妨げる何か?

サーバーにアップロードされ、ユニットテストが実行される小さなプログラム、宿題です。したがって、プログラムは短命です。


これは、5分間に1回実行する必要がある単一のCプログラムのようなものですか、それとも常に実行する必要があるものですか?
bwawok

これは、アップロードされてユニットテストが実行される小さなプログラムです。したがって、プログラムは短命です。
フランク

システムはどのディストリビューションを使用していますか?一部のディストリビューションには、サンドボックス用の既製のツールがあります。システムでSELinuxやAppArmorなどのセキュリティモデルが有効になっていますか?
thkala

私はFedora 13を使用しています。SELinuxサンドボックスポリシーを調べています。他にどんなオプションがあるのか​​しら。
フランク

回答:


47

Systraceを使用して、信頼できないプログラムを対話型モードと自動モードの両方でサンドボックス化しました。ptrace()Linuxベースのシステムで特別な権限なしで使用できるようにする- ベースのバックエンドと、カーネルにパッチを当てる必要があるはるかに高速で強力なバックエンドがあります。

を使用してUnixライクなシステムでサンドボックスを作成することもできますが、chroot(1)これはそれほど簡単でも安全でもありません。LinuxコンテナーFreeBSDの刑務所は、chrootのより良い代替手段です。Linuxのもう1つの代替手段は、SELinuxAppArmorなどのセキュリティフレームワークを使用することです。これは、私が本番システムに提案するものです。

やりたいことを具体的に教えていただければ、もっとお手伝いできます。

編集:

Systraceはあなたのケースで機能しますが、ディストリビューションによっては、AppArmorやSELinuxなどのLinuxセキュリティモデルに基づくものがより標準的であり、したがって、推奨される代替手段であると思います。

編集2:

一方でchroot(1)(?すべて)Unixライクなシステムほとんどで利用可能ですが、それはかなりの数の問題があります。

  • 壊れる可能性があります。システムで信頼できないCプログラムを実際にコンパイルまたは実行する場合は、この問題に対して特に脆弱です。そして、あなたの生徒が私のようなものであるなら、誰かが刑務所から抜け出そうとします。

  • タスクに必要なすべてのもので完全に独立したファイルシステム階層を作成する必要があります。chrootにコンパイラーを置く必要はありませんが、コンパイルされたプログラムを実行するために必要なものはすべて含める必要があります。これを助けるユーティリティはありますが、それはまだ簡単ではありません。

  • chrootを保守する必要があります。独立しているため、chrootファイルはディストリビューションとともに更新されません。chrootを定期的に再作成するか、必要な更新ツールをその中に含める必要があります。これには、本格的なLinuxディストリビューションである必要があります。また、システムデータとユーザーデータ(パスワード、入力ファイルなど)をホストシステムと同期させておく必要があります。

  • chroot()ファイルシステムのみを保護します。悪意のあるプログラムがネットワークソケットを開いたり、悪質なプログラムが利用可能なすべてのリソースを吸い上げたりするのを防ぐことはできません。

リソース使用量の問題は、すべての選択肢で共通です。ファイルシステムクォータは、プログラムがディスクをいっぱいにするのを防ぎます。適切なulimitsetrlimit()Cでの)設定は、メモリの過剰使用やフォーク爆弾から保護するだけでなく、CPUの負荷を抑えることができます。nice(1)これらのプログラムの優先度を下げることができるので、コンピュータは問題なくより重要と思われるタスクに使用できます。


systraceは単純なプログラムでは機能しましたが、GNU as(1)がGCCで実行されていると、いつまでもスタックしました。だから私はあきらめました。これはsystraceの未修正のバグです。forum.soft32.com
pts

共有メモリ、メッセージキュー、セマフォがサンドボックスプロセス間で共有されないようにする方法はありますか?
daveagp 2014

1
systraceリンクが壊れています。
Collin

2
Firejailはどうですか?これを使用してfsを保守する必要はもうありません。
m3nda 2016

18

最近、Linuxのサンドボックステクニックの概要を書きました。あなたの最も簡単なアプローチは、フォークなどを気にしないのであれば、Linuxコンテナー(lxc)を使用することだと思いますが、この環境ではそれほど重要ではありません。プロセスに読み取り専用のルートファイルシステム、分離されたループバックネットワーク接続を与えることができ、それでも簡単に強制終了してメモリ制限などを設定できます。

Seccompはコードがメモリを割り当てることさえできないので、少し難しいでしょう。

Selinuxはもう1つのオプションですが、コンテナーよりも作業が多いと思います。


6

Qemuを使用して、割り当てをすばやくテストできます。以下のこの手順は、私の5年前のラップトップで5秒未満かかります。

学生が、「-1」の行が到着するまで、それぞれが独自の行にある符号なし整数を受け取るプログラムを開発する必要があると仮定します。次に、プログラムはすべてのintを平均し、「平均:%f」を出力します。完全に分離されたプログラムをテストする方法は次のとおりです。

  1. まず、root.binJslinuxから取得します。これをユーザーランドとして使用します(tcc Cコンパイラーがあります)。

    wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin

  2. 生徒の提出物をに入れたいroot.binので、ループデバイスをセットアップします。

    sudo losetup /dev/loop0 root.bin

    (これにもfuseext2を使用できますが、あまり安定していません。安定したら、rootは必要ありません)

  3. 空のディレクトリを作成します。

    mkdir mountpoint

  4. マウントroot.bin

    sudo mount /dev/loop0 mountpoint

  5. マウントされたファイルシステムを入力してください:

    cd mountpoint

  6. 修正権:

    sudo chown -R `whoami` .

  7. mkdir -p etc/init.d
  8. vi etc/init.d

    #!/bin/sh
    cd /root
    echo READY 2>&1 > /dev/ttyS0
    tcc assignment.c 2>&1 > /dev/ttyS0
    ./a.out 2>&1 > /dev/ttyS0
    
  9. chmod +x etc/init.d/rcS

  10. 提出物をVMにコピーします。

    cp ~/student_assignment.c root/assignment.c

  11. VMのルートFSを終了します。

    cd ..

  12. sudo umount mountpoint
  13. これでイメージの準備ができました。実行するだけです。起動後に提出物をコンパイルして実行します。
  14. mkfifo /tmp/guest_output
  15. 別のターミナルを開いて、ゲスト出力のリスニングを開始します。

    dd if=/tmp/guest_output bs=1

  16. 別のターミナルで:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (ここではUbuntuカーネルを使用しましたが、多くのカーネルが機能します)

  17. ゲストの出力に「READY」と表示されたら、qemuプロンプトからVMにキーを送信できます。たとえば、この割り当てをテストするには、次のようにします

    (qemu) sendkey 1
    (qemu) sendkey 4
    (qemu) sendkey ret
    (qemu) sendkey 1
    (qemu) sendkey 0
    (qemu) sendkey ret
    (qemu) sendkey minus
    (qemu) sendkey 1
    (qemu) sendkey ret
    
  18. これAverage = 12.000000で、ゲスト出力パイプに表示されます。そうでない場合、学生は失敗しました。

  19. qemuを終了します。 quit

テストに合格したプログラムは、https//stackoverflow.com/a/14424295/309483です。のtcclib.h代わりに使用してくださいstdio.h


5

ユーザーモードLinuxをお試しください。CPUを集中的に使用するジョブの場合、パフォーマンスオーバーヘッドは約1%ですが、I / Oを集中的に使用するジョブの場合は6倍遅くなる可能性があります。


4

Firejailは、そのための最も包括的なツールの1つです。seccomp、ファイルシステムコンテナー、機能などをサポートしています。

https://firejail.wordpress.com/features-3/


この回答は素晴らしいです。firejailが優れたドキュメントで積極的に維持され、他のすべての回答ではないにしてもほとんどの回答を網羅し、比較的使いやすいように設計されていることを考えると、より多くの賛成票に値します。
ジェフハイキン

3

仮想マシン内で実行すると、必要なセキュリティと制限がすべて提供されます。

QEMUはこれに適しています。すべての作業(アプリケーションのダウンロード、ディスクイメージの更新、QEMUの起動、内部でのアプリケーションの実行、後で取得するための出力の保存)は、自動テスト実行用にスクリプト化できます。


2
OPについてはわかりませんが、多くの場合、テストプログラムごとにVMを起動することは受け入れられません。私の環境(私はTAです)では、2時間以内に200人もの学生がそれぞれ10〜12のプログラムを提出できます。10秒を超えるCPU時間で実行されるプログラムはありませんが、提出物が山積みになると、15分以上のターンアラウンドタイムが得られます。プログラムごとにVMを導入すると、プログラムごとにCPU時間を60秒以上に押し上げることになり、ターンアラウンドタイムについてまったく考えたくありません。セッションごとのVMかもしれませんが、プログラムごとに実行する方法はありません...
thkala

@thkalaこれは良い点です。QEMUのアイデアは気に入っていますが、送信ごとにVMを起動するのはよくありません。
フランク

その場合は、同じVMを常に実行し続けてください。
Laurent Parenteau、2011年

すべて起動し、コードをコンパイルして実行する準備ができているVMのスナップショットを使用して何かできますか?参考までに、VMは必ずしもピアシングの影響を受けません。このハードウェアバージョンを構築することもできます-読み取り専用メディアまたはネットワークを介して再開イメージを起動し、ネットワークまたはシリアル経由で出力を提供し、次に再起動する小さなシステム。Linuxを数秒で起動する、いくつかの迅速な起動の進歩がありました。
Chris Stratton

@thkala:つまり、連続して実行した場合、1回の送信で必要な時間は3秒未満です。私が投稿したアプローチは、おそらく現代のマシンでは(シリアルで)約3秒かかります。あなたが並列化するなら(あなたもそうかもしれません)、それは十分に速いでしょう。
Janus Troelsen 2013年

3

ptrace(strace)チェックアウトに基づいてサンボクシングを行う場合:

" sydbox " sandboxおよび " pinktrace "プログラミングライブラリ(C99ですが、PythonとRubyへのバインディングは私の知る限りです)。

トピックに関連する収集されたリンク:

http://www.diigo.com/user/wierzowiecki/sydbox

(申し訳ありませんが、直接のリンクではありませんが、まだ十分な評判ポイントがありません)


3

seccompおよびseccomp-bpfは、最小限の労力でこれを実現します。https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt


1

このライブラリはあなたの目標にうまく役立つはずです

http://sandbox.sourceforge.net

幸運を!


8
これは積極的に維持されていないようです。また、その最新バージョンの日付は2003年にバックアップすることを考えると、それはほとんど役に立たないになるだろう、Linuxカーネルのパッチ、必要としているようだ
thkala


-1

彼らが私を助けてくれたすべての答えに感謝します。しかし、私は元の質問をした人のための解決策としてそれらのどれも提案しません。言及されたすべてのツールは、教師、家庭教師、教授として生徒のコードをテストするために多くの作業を必要とします。この場合の最良の方法は、私の意見のvirtualboxです。OK、それは完全なx68システムをエミュレートし、このようにサンドボックス化の意味とは何の関係もありませんが、私のプログラミングの先生を想像すれば、彼にとっては最高でしょう。したがって、Debianベースのシステムで「apt-get install virtualbox」を実行すると、他のすべてのユーザーはhttp://virtualbox.org/にアクセスしVMを作成し、ISOを追加して、[インストール]をクリックし、しばらく待ってから幸運です。user-mode-linuxをセットアップしたり、重いstraceを実行したりする方がはるかに簡単です...

そして、あなたがあなたの生徒をハッキングするのを恐れているなら、私はあなたが権威の問題を抱えていると思います、そしてそれに対する解決策は、彼らが与える仕事で男性器の一口だけを証明できるなら、あなたが彼らから生きている日光を訴えることになると彼らを脅かすでしょう君は...

また、クラスがあり、その1%が彼がそのようなことをするのと同じくらい良い場合、そのような単純なタスクでそれらを退屈させないでください。統合学習は誰にとっても最適なので、古いデッドロック構造を中継しないでください...

そして当然のことながら、ウェブの閲覧やソフトウェアのテストなどに使用しているのと同じコンピュータを、証明や試験の作成などの重要なものに使用しないでください。

重要なことにはオフラインコンピュータを使用し、その他すべてにはオンラインコンピュータを使用します。

しかし、偏執的な教師ではない他のすべての人にとって(誰も気分を害したくない、プログラマーの教師になる前にセキュリティと私たちの社会についての基本を学ぶべきだという意見です...)

...私はどこにいましたか...他の皆のために:

ハッピーハッキング!!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.