2011-12-14 9 views
32

これは、セットルートのuidプログラムは、ソースコードRealUID、保存されたUID、有効なUID。どうしたの?

$ls -l 
-rwsr-sr-x 1 root root 7406 2011-12-13 22:37 ./x* 

次のとおりです。

int main(void) { 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

seteuid(600); 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

setuid(1000); 

    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

setuid(0); // HOW DOES THIS SUCCEED IN SETTING THE EUID BACK TO 0 
    printf(
     "   UID   GID \n" 
     "Real  %d Real  %d \n" 
     "Effective %d Effective %d \n", 
      getuid(),  getgid(), 
      geteuid(),  getegid() 
    ); 

    return 0 ;  
} 

OUTPUT

  UID   GID 
Real  1000 Real  1000 
Effective 0 Effective 0 
     UID   GID 
Real  1000 Real  1000 
Effective 600 Effective 0 
     UID   GID 
Real  1000 Real  1000 
Effective 1000 Effective 1000 
     UID   GID 
Real  1000 Real  1000 
Effective 0 Effective 1000 

私の質問

のsetuid意志manページ状態本当の、保存された、効果的なuidを変更してください。 したがって、setuid(1000)を呼び出すと、3つとも1000に変更されます。 どうすればsetuid(0)euid0に変更しますか?

答えて

24

2例、

  1. は、あなたがsetuidの実行中に一時的にroot権限をドロップしますがありますプログラム
  2. setuidプログラムの実行中にroot権限を永久に削除したい場合...
  • あなたは本当のユーザーIDにEUIDを設定し、その後、あなたがrootにsetuidをすることができ、効果的なユーザーIDが変更されますroot権限をバック必要とするとき、あなたが後でwant.And何にUIDを変更することで、それを一時的に行うことができますrootに戻ってください。これは、保存されたユーザーIDが変更されていないためです。
  • 権限を永久に削除するには、権限をより低い特権のユーザーIDに直接変更します。その後、root特権を得ることができません。

ケース1:

のsetuidプログラムは、このような場合のために

1.seteuid(600); 
2.setuid(1000); 
3.setuid(0); 

の実行を開始した後、root権限を再び獲得することができます。

   +----+------+------------+ 
       | uid|euid |saved-uid | 
       |----|------|------------| 
      1.|1000| 0 | 0   | 
      2.|1000| 600 | 0   | 
      3.|1000| 1000 | 0   | 
      4.|1000| 0 | 0   | 
       | |  |   | 
       +------------------------+ 

ケース2:

のsetuidプログラムがの実行を開始した後、この場合、

1.setuid(1000); 
2.setuid(0); 



       +----+------+------------+ 
       | uid|euid |saved-uid | 
       |----|------|------------| 
      1.|1000|0  | 0   | 
      2.|1000|1000 | 1000  | 
       | |  |   | 
       +------------------------+ 

あなたがroot権限を取り戻すことはできません。 これは、次のコマンドで確認できます。

cat/proc/PROCID/task/PROCID/status |このコマンド

Uid: 1000 0  0  0 
Gid: 1000 0  0  0 

以下は、UIDとGIDが表示され、それが(最初の3つのフィールドは、我々はと懸念している一つです)の4つのフィールドを持つことになります。上記のようなもの

3つのフィールドは、uid、euid、およびsaved-user-idを表します。 setuidプログラムで一時停止(ユーザーからの入力)を導入し、cat /proc/PROCID/task/PROCID/status | lessコマンドの各ステップを確認できます。各ステップで、保存されたuidが変更されたことを確認できます。

あなたがeuidがrootで、あなたがuidを変更した場合、権限は永久に削除されます。有効なユーザIDがrootでない場合、保存されたユーザIDは決して変更されません。あなたのプログラムで。

+0

Uidの最後の列は何ですか:1000 0 0 0は –

+0

を表します。サンプルコードでテストしようとしたとき、4番目の値は有効なユーザーIDと同じに表示されました。有効なユーザーIDである必要がありますが、実際のユーザーIDを2回印刷する理由はわかりません。 – Ajai

+1

最後の列は、groovyなしで(例えば、bashシェルで)続行しようとする人のためのFSUID – user368507

8

のsetuid DESCRIPTION()呼び出しプロセスの実効ユーザIDを設定します。呼び出し元の実効UIDが rootの場合、実UIDと保存されたset-user-IDも設定されます。

Linuxでは、setuid()はPOSIXバージョンの_POSIX_SAVED_IDS機能と同様に実装されています。この は、root権限を持たないset-user-IDプログラムがすべてのユーザー権限を削除し、権限のない作業を行った後、元の有効なユーザーIDを安全に再エンゲージできます。

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

したがって、root権限を一時的に削除したい場合は、 権限のないユーザーのアイデンティティを前提にしてから、root権限を再度取得してもsetuid()を使用できません。これはseteuid(2)で を実行することができます。

(Linuxのプログラマのマニュアルから、2014年9月21日、ページ setuid.2

+0

あなたが言ったことによると、出力の最後のセグメントは 'Effective' = '1000'と表示されます。しかし、それは「0」に戻ることができる。それはまさに私の質問です。 –

+0

私はあなたが作っている 'seteuid'への呼び出しのためだと信じています。カーネルは将来的に 'root'を取り戻す能力を '保護'します。その呼び出しを削除すると、 "バックドア"効果がなくなります。 – BRFennPocock

+0

うん、@アジャイの答えはあまりにも証拠を提供します。とにかく答えてくれてありがとうございます –

2

O!これらの機能は正しく使用するのが難しいです。

マニュアルページには、setuidが実際の、保存された、有効なuidを変更することが記載されています。だから、(1000)を呼び出すのsetuidした後、あなたはあなたがsetuid(0)を呼び出す時0 EUIDである場合にのみ、しかし、あなたはEUID 1000および保存であればそうである1000

に3つのすべての変更 uid 0(たとえば、getresuid(2)をチェック)。だからあなたは特権を取り戻すことができます。

+0

あなたは正しいですか? getresuid()は正常に動作しているようです。しかし、POSIX準拠ではありません。しかし、この場合は問題ではありません。ありがとう.. –

関連する問題