web-dev-qa-db-ja.com

特権のないApache / PHPにルートタスク(CentOS)の実行を許可する方法

CentOS6.3マシンでお客様向けに一種の個人用ドロップボックスをセットアップしています。サーバーには、SFTPおよびPHPの独自のhttpサービスベースを介してアクセスできます。このマシンは私たちのDMZにあるので、安全でなければなりません。このため、Apacheを非特権ユーザーとして実行し、Apache、OS、PHPのセキュリティを強化し、多くのiptablesでフィルタリングし、いくつかの制限的なTCPラッパーを適用しました。これが来るのではないかと疑ったかもしれませんが、SELinuxも強制するように設定されています。

MySQLを使用するようにPAMを設定しているので、Webアプリケーションのユーザーがログインできます。これらのユーザーはすべて、SFTPにのみSSHを使用できるグループに属し、ユーザーは自分の「ホーム」フォルダーにchrootされます。

このSELinuxを許可するには、フォルダーにuser_home_tタグを付ける必要があります。また、親ディレクトリはルートのみで書き込み可能である必要があります。これらの制限が満たされない場合、SELinuxはSSHパイプをすぐに強制終了します。

HttpとSFTPの両方を介してアクセスできる必要があるファイルなので、Apacheがuser_home_dir_tタグのあるディレクトリを検索/属性/読み取り/書き込みなどできるようにSELinuxモジュールを作成しました。

SftpユーザーはMySQLに保存されているので、ユーザーの作成時にホームディレクトリを設定したいと思います。 Apacheには/ homeディレクトリへの書き込みアクセス権がないため、これは問題です。SELinuxとOpenSSHを満足させるために必要なため、rootによってのみ書き込み可能です。

基本的に、Apacheにrootとして、/ home内でのみいくつかのタスクを実行させる必要があります。したがって、何らかの方法で一時的に特権を上げるか、代わりにrootにApacheのこれらのタスクを実行させる必要があります。

Apacheにroot権限で実行させる必要があるのは次のとおりです。

mkdir /home/userdir/
mkdir /home/userdir/userdir
chmod -R 0755 /home/userdir
umask 011 /home/userdir/userdir
chcon -R -t user_home_t /home/userdir
chown -R user:sftp_admin /home/userdir/userdir
chmod 2770 /home/userdir/userdir

これはユーザーのための家を作成するでしょう、今私はうまくいくかもしれないという考えを持っています、cron。つまり、サーバーは毎分ホームを持たないユーザーをチェックする必要があり、ユーザーを作成するときに、アカウントの作成を確認する前にインターフェイスが平均30秒間フリーズしますが、これは好ましくありません。 sudoersで何かできるかどうか誰か知っていますか?または他のアイデアは大歓迎です...

御時間ありがとうございます!

2
Chris

説明したコマンドを実装するスクリプトを作成し、そのスクリプトでsetuidを実行して、誰かがスクリプトを呼び出したときにrootとして実行できるようにします。 setuidの詳細については、 http://en.wikipedia.org/wiki/Setuid を参照してください。

PHPからは、通常どおりsystem('/bin/setupNewUser');を呼び出すだけで、スクリプトがrootとして実行されます。


インジェクションの機会を制限し、スクリプトでのsetuid実行が無効になっているシステムで機能する代替ソリューション:

Setuidを持つ小さなプログラムを作成します。以下にリストされている例:

#include <stdlib.h>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        cout << "Invalid arguments";
        return 1;
    }

    //make sure the argument passed to the script has only [a-z]
    for (char* i = argv[1]; *i != '\0'; i++)
    {
       //check if the current character falls outside an allowed range
       if (!(
           //Allowed ranges:
           // between a and z
           ('a' <= *i && *i <= 'z') 
           // between 0 and 9
           || ('0' <= *i && *i <= '9')
           // '_' or '-'
           || ('_' == *i)
           || ('-' == *i)
       ))
       {
           cout << "Illegal character in username: " << *i << endl;
           return 2;
       }
    }

    //append the username
    string command = string("/test/setupUser.sh ");
    command += string(argv[1]);

    //execute the command and return the result transparently
    // return system(command.c_str());
    // * OR *
    // call mkdir directly
}

Phpからsetuidプログラムを呼び出す

system('/test/setupUser '.escapeshellarg($username));
1
Mitch

これをしないでください!

少なくともあなたが提案する方法ではありません-Apacheが行う正当な理由はありません[〜#〜]何か[〜#〜] rootとして。
あなたが提案していることのひどいレベルは、Apacheがrootとして実行することを拒否するという事実によって明らかになるはずです(ポート80にバインドするマザープロセスを除く)。

また、信頼できないユーザー入力を使用してrootとして何かを行うことは、ひどい考えであり、ハッカーがボックスに入力できるすべての興味深いことを発見する確実な方法は、システムに予期しないことをさせます。


あなたが本当にこれをしたいのなら:

  • ユーザーディレクトリを手動で作成します。
    人間による検証を伴うこの1つの手動ステップにより、システムが節約されます。ルートシェルから1マイル以内で信頼できないユーザー入力を許可することは、問題を引き起こしているだけです。
    • ディレクトリの所有者はユーザーである必要があります。
    • ディレクトリグループは、Apacheが実行されるグループである必要があります。
    • ディレクトリのアクセス許可は、おそらく4770rwsrwx---

これにより、ユーザーは読み取り/書き込みなどを行うことができます。ディレクトリの内容、およびディレクトリのSetUIDビットにより、ユーザーはすべてのファイルの所有者になります(したがって、SCP/SFTPを使用してログインしたときにファイルを操作できます)。

3
voretaq7