Execute o shell script do php, como usuário root?

5

Precisa executar a seguinte linha do PHP:

$res = shell_exec('sudo sh /home/nicklas/cronjobs/make_account.sh username password');

O problema é que nada acontece na execução. Se eu tentar ecoar $ res, ele fica em branco. Eu tentei usar system () também, mesmo resultado. Eu estou supondo que não funciona porque eu preciso executar o script com acesso root, e o usuário www-data não tem isso por padrão. Eu adicionei a seguinte linha ao / etc / sudoers na esperança de obter acesso:

www-data ALL=(ALL:ALL) NOPASSWD: /home/nicklas/cronjobs/make_account.sh

Mas sem sucesso. Eu tentei reiniciar o apache no meio, não muda nada.

Estou sentindo falta de algo?

    
por qwerty 04.09.2012 / 17:55

2 respostas

2

Por razões de segurança, você nunca deve tentar executar algo com o usuário www-data com mais privilégios do que naturalmente. Houve uma razão pela qual, algumas vezes, o acesso ao Apache foi movido para www-data. Se você precisa fazer algo em sua máquina como root - e alterar senhas ou criar contas é esse 'algo' - você deve criar uma interface. Deixe o script php colocar algo em algum lugar e escaneie isso via scripts executados a partir do root e manipule-o lá. Você poderia f.e. crie um arquivo contendo os usuários para adicionar em um diretório onde www-data tenha acesso, e então faça isso via root-cronjob a cada 5 minutos (ou menos) e mova o arquivo para uma pasta com timestamp para ter controle sobre o que é acontecendo.

    
por 04.09.2012 / 23:01
5

Eu discordo totalmente que executar algo com privs mais altos em um servidor da web é sempre uma má ideia.

Os problemas de segurança de um aplicativo da web vêm da confiança nos dados fornecidos pelo usuário, não do processo exato que está usando esses dados.

Em outras palavras, se você não validar e limpar seus dados, não é mais seguro transmiti-los a um processo de propriedade da raiz por meio do named-pipe do que escrever um script wrapper para processar esses dados e permitir que o usuário do www-data o execute via sudo.

Na verdade, a maior parte do processamento / validação / limpeza dos dados deve ser feita antes dos dados serem passados para o script sudo, o que deve a) fazer uma verificação final dos dados eb) executar apenas as operações que precisam de privs mais altos.

Na verdade, eu diria que é possivelmente mais seguro fazer o último, porque é uma solução mais simples que é mais fácil de entender ... quanto mais complicado você faz algo, maior a probabilidade de cometer um erro.

Qualquer que seja o método que você usa (named-pipe, sudo wrapper, ou qualquer outro), a coisa crucial é que você examina os dados fornecidos pelo usuário e garante que ele se encaixa em critérios definidos estreitamente antes de fazer qualquer coisa com isso.

Existem inúmeros artigos e howtos sobre segurança CGI na web, incluindo vários aqui nos sites da stackexchange, mas alguns dos temas comuns são:

  • considere os dados como "contaminados" e indignos de confiança até que você os tenha verificado e / ou modificado para torná-los seguros.
  • verifique os dados - por exemplo, teste se corresponde a um regexp de caracteres permitidos ou proibidos. A opção mais segura é abortar se houver algo estranho, caso contrário, transformá-lo com um regexp ou algo do tipo para remover elementos potencialmente inseguros.
  • sempre cite os dados se você passar os dados para um script de shell externo. por exemplo. o script de shell deve usar aspas duplas em torno das variáveis.
  • da mesma forma, ao inserir dados no banco de dados, você deve usar uma biblioteca de banco de dados que ofereça suporte a valores de espaço reservado em vez de confiar em escape ou cotação. Aqui é uma ilustração humorística do porquê.

Eu poderia continuar, mas há muito para resumir em uma resposta aqui - a Segurança da CGI é um tópico amplo. Experimente uma pesquisa no google para Segurança da CGI ou Validando Entrada CGI

Com a sua atitude 'Eu não ligo porque é só eu usá-la' para a segurança, Eu meio que sinto que estou te dando uma espingarda carregada para explodir seus pés, mas atirar no próprio pé é uma valiosa experiência de aprendizado. Aqui está um script simples para criar uma conta de usuário. Requer privs de raiz.

O script se baseia no adduser, que está disponível nos sistemas debian e debian e talvez em outros. modificar para usar useradd em vez disso, se não estiver no seu sistema.

#! /bin/bash 

# make the script abort on any error
set -e

U="$1"
P="$2"

[ -z "$U" ] && echo "Error: No username provided" >&2 && exit 1
[ -z "$P" ] && echo "Error: No password provided" >&2 && exit 1

# simple check - only allow lower-case letters and digits in usernames.
[ "$U" !~ '^[a-z0-9]*$' ] && echo "Error: Invalid Username" >&2 && exit 1

# create user if they don't already exist
if ! getent passwd "$U" > /dev/null ; then

   # create the user using adduser, must provide the gecos field 
   # and disable the password so adduser doesn't ask for them. 
   adduser --gecos "$U" --disabled-password "$U"

   # now change the password
   echo "$U:$P" | chpasswd
else
    echo "Error: Username already exists" >&2
    exit 1
fi

Salve o script em algum lugar e torne-o executável com chmod.

Para permitir que o www-data execute-o como root sem uma senha, edite / etc / sudoers com visudo e adicione o seguinte:

Cmnd_Alias APACHEADDUSER = /path/to/makeaccount.sh

www-data ALL = NOPASSWD: APACHEADDUSER
    
por 08.09.2012 / 04:19