9

root ユーザーとしてターミナルにログインしました。

次にPythonで:

os.setuid(471)サブルートに切り替えることはできますが、使用してルート ユーザーに戻そうとするとos.setuid(0)、次のエラーが発生します。Operation not permitted

サブルートからルートユーザーに戻す方法を教えてください。

4

3 に答える 3

10

子プロセスで root 以外のユーザーを呼び出しos.fork()て切り替えます。子で終了し、子が親で終了するのを待つだけで、「スイッチバック」します。例えば:

pid = os.fork()
if pid == 0:
    # child - do the work and exit
    try:
        os.setuid(471)
        ... do the work here
    finally:
        os._exit(0)

# parent - wait for the child to do its work and keep going as root
os.waitpid(pid, 0)
于 2013-01-09T07:57:40.533 に答える
8

それはsetuidがどのように機能するかではありません。ルートがそれ自体を降格する場合、ルートを再取得できないのは仕様によるものです。(このコンテキストで)rootをあきらめると、それはなくなります。

rootとしてsetuidを使用すると、戻ることはできません。

os.setuidは、経営幹部レベルの呼び出しまでのシンプロキシであると想定しています。マニュアルページから:

ユーザーがrootであるか、プログラムがset-user-ID-rootである場合は、特別な注意が必要です。setuid()関数は、呼び出し元の有効なユーザーIDをチェックし、それがスーパーユーザーである場合、すべてのプロセス関連のユーザーIDはuidに設定されます。これが発生した後、プログラムがroot権限を取り戻すことはできません。


ルートを再取得できない理由については、一般的な使用法を検討してください。実際のリクエストを処理するためにドロップダウンするApacheサーバーwww(またはある種の非特権ユーザー)を想像してみてください。ルートを取り戻すことができれば、Pythonスクリプト(またはPHP / Perl / CGI / etc)がルートを取り戻し、絶対的な大混乱をもたらす可能性があります。


解決策としては、代わりにseteuidを使用できます(os.seteuid-もう一度、Cレベルのseteuidへの単純なプロキシ)。setuidとseteuidに関するPythonのドキュメントはかなり悪いように見えますが、システムコールに関するドキュメントはたくさんあります。

ルートを一時的に削除して回復するセキュリティについては...非常に注意する必要があります。悪意のあるコードがルートを取得する機会がある場合、あなたは困惑しています。このため、子プロセスにフォークすることをお勧めします(user4815162342が提案したように)。子プロセスはルートを変更できなくなります。懸念事項の詳細については、こちらをご覧ください。setuidの一般的な奇妙さについての詳細は、ここにあります。

アイデアは、有効なユーザーIDをseteuidで設定し、新しいプロセスを生成することです。execの動作方法により、有効なユーザーIDが新しいプロセスの保存されたuidにコピーされます。保存されたuidはrootではなくなったため、rootをに戻すことはできません。さらに楽しいドキュメントはここにあります。

最も関連性の高い部分:

ファイル名が指すプログラムファイルにset-user-IDビットが設定されていて、基になるファイルシステムがnosuid(mount(2)のMS_NOSUIDフラグ)にマウントされておらず、呼び出しプロセスがptraceされていない場合、呼び出しプロセスの実効ユーザーIDは、プログラムファイルの所有者のIDに変更されます。同様に、プログラムファイルのset-group-IDビットが設定されると、呼び出しプロセスの実効グループIDがプログラムファイルのグループに設定されます。

プロセスの実効ユーザーIDは、保存されたset-user-IDにコピーされます。同様に、有効なグループIDが保存されたset-group-IDにコピーされます。このコピーは、set-user-IDおよびset-group-ID許可ビットが原因で発生した有効なID変更の後に行われます。

于 2013-01-09T07:47:31.663 に答える
5

Use seteuid() instead to set the effective ID but maintain the privilege:

import os
os.seteuid(471)
...
os.seteuid(os.getuid())
于 2013-01-23T09:09:29.670 に答える