Назад | Перейти на главную страницу

Как разрешить непривилегированным apache / PHP выполнять корневую задачу (CentOS)

Я настраиваю своего рода личный Dropbox для наших клиентов на машине CentOS 6.3. Сервер будет доступен через SFTP и проприетарную сервисную базу http на PHP. Этот компьютер будет в нашей демилитаризованной зоне, поэтому он должен быть безопасным. Из-за этого у меня apache работает как непривилегированный пользователь, усилена безопасность apache, ОС, PHP, применена большая фильтрация в iptables и применены некоторые ограничительные TCP Wrappers. Теперь вы могли подозревать, что это произойдет, SELinux также настроен на принудительное исполнение.

Я настраиваю PAM для использования MySQL, чтобы мои пользователи в веб-приложении могли входить в систему. Все эти пользователи будут в группе, которая может использовать SSH только для SFTP, и пользователи будут перемещены в свою собственную «домашнюю» папку.

Чтобы разрешить это, SELinux хочет, чтобы папки имели тег user_home_t. Также родительский каталог должен быть доступен для записи только root. Если эти ограничения не соблюдены, SELinux немедленно отключит канал SSH.

Файлы, которые должны быть доступны через http и SFTP, поэтому я создал модуль SELinux, чтобы позволить Apache искать / attr / читать / писать и т. Д. В каталогах с тегом user_home_dir_t.

Поскольку пользователи sftp хранятся в MySQL, я хочу настроить их домашние каталоги при создании пользователя. Это проблема, поскольку Apache не имеет доступа на запись в каталог / home, он доступен для записи только пользователю root, так как это необходимо для поддержки SELinux и OpenSSH.

В основном мне нужно, чтобы 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? Или любые другие идеи приветствуются ...

Спасибо за ваше время!

ПОЖАЛУЙСТА, не делайте этого!

По крайней мере, не так, как вы предлагаете - у Apache нет разумных причин делать ЧТО-НИБУДЬ как корень.
Уровень вопиющего того, что вы предлагаете, должен быть очевиден из того факта, что Apache откажется запускаться от имени пользователя root (за исключением привязки материнского процесса к порту 80).

Также делать что-либо от имени root с ненадежным пользовательским вводом - ужасная идея, и верный способ обнаружить все интересные вещи, которые хакер может ввести в поле, заставит вашу систему делать то, чего вы не ожидали.


Если вы действительно хотите это сделать:

  • Создайте каталоги пользователей вручную.
    Этот единственный ручной шаг с проверкой человеком спасет вашу систему. Разрешение любого ненадежного пользовательского ввода в пределах мили от корневой оболочки просто вызывает проблемы.
    • Владельцем каталога должен быть пользователь.
    • Группа каталогов должна быть группой, под которой работает Apache.
    • Разрешения каталога, вероятно, должны быть либо 4770 (rwsrwx---)

Это позволит вашему пользователю читать / писать / и т. Д. содержимое каталога и бит SetUID в каталоге заставят пользователя стать владельцем всех файлов (чтобы они могли манипулировать ими при входе в систему с использованием SCP / SFTP).

Создайте сценарий, реализующий описанные вами команды, и запустите setuid на нем, чтобы он мог запускаться от имени root, когда кто-либо его вызывает. Видеть http://en.wikipedia.org/wiki/Setuid для получения дополнительной информации о 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
}

Вызов программы setuid с php

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