Я настраиваю своего рода личный 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 с ненадежным пользовательским вводом - ужасная идея, и верный способ обнаружить все интересные вещи, которые хакер может ввести в поле, заставит вашу систему делать то, чего вы не ожидали.
Если вы действительно хотите это сделать:
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));