Como matar os processos quando nenhuma permissão raiz e limite nproc são excedidos?

1

Assim, um usuário ultrapassou seu limite nproc . Devido a isso, tanto o SSH quanto o su não conseguem efetuar login como o usuário de destino. No entanto, não há shell acessível que seja de propriedade do usuário. Como isso pode ser resolvido sem permissão de root?

Obrigado

    
por Hellow Hi 20.03.2017 / 08:33

3 respostas

1

Como vejo a tag nproc e "ulimit", adicionarei 2 pontos a este mecanismo ulimit:

Eu esperaria que o seu sysadmin tenha colocado um limite soft um pouco abaixo do hard-limit, exatamente para evitar o caso em que você está. Dessa forma, você pode aumentar seu valor para lançar su de outra conta e usar isso para matar.

Além disso, tenha em mente que os ulimits são definidos pelo PAM ( grep -r pam_limits.so /etc/pam.d/ ), portanto, se você tiver um método / programa de autenticação que não use este módulo PAM, você pode evitar esse ulimit e gerar um kill. / p>

Além dessas duas soluções que exigem uma ação antes do problema, não há como enviar um sinal para um programa existente sem o acesso correto (mesmo usuário, root, setuid ou capacidade CAP_KILL ).

    
por 20.03.2017 / 23:25
0

Se você tiver credenciais de outros usuários e a credencial do usuário de destino puder ser usada para alterar o sistema de arquivos de alguma forma, você poderá compilar o programa a seguir, definir o bit s e usar a credencial de outro usuário para executá-lo.

OBSERVAÇÃO: o executável deve pertencer ao usuário de destino para poder seteuid do usuário alvo uid .

O primeiro argumento do programa é o usuário alvo uid .

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

int main(int argc, char**argv) {
    if(seteuid(atoi(argv[1])) != 0) {
        printf("seteuid failed... %d", errno);
    }
    if(kill(-1, SIGTERM) != 0) {
    printf("kill failed...%d", errno);
    }

    return 0;
}
    
por 20.03.2017 / 10:18
0

Se nproc for atingido, o kernel não permitirá que nenhum outro processo seja executado com as credenciais desse usuário, como você aprendeu. Isso significa que nenhuma sessão remota por SSH, sem su ou sudo , nem mesmo um programa definido para a conta deles.

Isso deixa você com raiz ou com o usuário se eles ainda tiverem uma sessão interativa em funcionamento. Como você excluiu o root, espere que seu usuário ainda tenha um shell em execução. Em caso afirmativo, deve haver funcionalidade suficiente incorporada em seu shell para eliminar alguns dos processos ofensivos. Você precisará aproveitar os recursos internos do shell para percorrer /proc .

Por exemplo, se eu quisesse matar todos os meus bash shells, eu poderia fazer algo assim, que só usa builtins do shell Bash:

pushd /proc && for pid in *; do
    test "$pid" = "self" && continue        # skip /proc/self
    test -d "$pid" || continue              # skip if not a directory
    test -O "$pid" || continue              # skip if we don't own it
    read cmd < "${pid}/cmdline"
    case "$cmd" in
        *bash*) kill -9 $pid ;;             # or whatever you want to do to it
    esac
done && popd

Isso sofre algumas limitações, por isso não é infalível, mas deve ser útil na maioria dos casos.

  1. Se houver um lote de processamento em execução, a expansão * na parte superior do loop poderá resultar em sequências que excedam o comprimento máximo do comando . Se você se deparar com isso, poderá reduzir a expansão de curingas com várias execuções usando 1* , 2* , {1..3}* ou algo assim.

  2. /proc/${pid}/cmdline contém uma lista delimitada por NULL, da qual o comando real é apenas um item. Eu não estou ciente de uma maneira de analisar corretamente essa string usando apenas Bash builtins. Como as strings são normalmente terminadas com um NULL, read somente obterá o primeiro item, que pode ou não ser o nome do comando. Uma abordagem alternativa seria iterar sobre /proc/${pid}/stat ou /proc/${pid}/status .

por 22.03.2017 / 18:00