Запуск скриптов SUID C под Apache

#c #linux #apache #suid

#c #linux #apache #suid

Вопрос:

у меня есть cgi-скрипт на c, такой же, как этот:

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

int main(void) {

    printf("Content-type: text/htmlnn");

    printf("RUID : %d<br />n", getuid());
    printf("EUID : %d<br />n", geteuid());

    char ch;
    char getLine[256];
    char *token = NULL;
    FILE *ft;

    ft = fopen("/etc/shadow", "r");
    if(ft == NULL){
        printf("%s", "can not open file");
        exit(1);
    }
    while(1){
        ch=fgetc(ft);
        if(ch == EOF)
            break;
        else if(ch == 'n'){
            token = (char *)strtok(getLine, ":");
            printf("<b> fitst toke : %s</b><br />n", token);
            if(strcmp(token,"root") == 0){
                token = (char *)strtok(NULL, ":");
                printf("password is : %s<br />n", token);
                break;
            }
        } else{
            sprintf(getLine, "%s%c", getLine, ch);
        }
    }

  return 0;
}
  

после компиляции и установки SUID:

 chmod a s ./mycode
  

если запустить это в оболочке, все кажется нормальным :

 Content-type: text/html

RUID : 500<br />
EUID : 0<br />
<b> fitst toke : root</b><br />
password is : $1$aLRBTUSe$341xIb6AlUeOlrtRdWGY40<br />
  

но если запустить его под apache и в cgi-bin, он, скажем, не может открыть файл. хотя идентификатор EUID, похоже, в порядке :

 RUID : 48<br />
EUID : 0<br />
can not open file
  

Спасибо!

Комментарии:

1. Попробуйте также напечатать значение errno после fopen() сбоя, чтобы узнать, в чем проблема.

2. Ошибка при открытии файла: отказано в разрешении.

3. возврат этого кода: printf( «Ошибка при открытии файла: %s n», strerror( errno ) );

4. С точки зрения безопасности это действительно глупая идея.

5. эта программа перед запуском своего процесса имеет аутентификацию с удаленного сервера для токенов и другое решение для авторизации, аналогичное фиксированному ip и порту в iptables. при всем этом процессе может ли этот код содержать ошибки безопасности?

Ответ №1:

Apache может быть настроен таким образом, чтобы его можно было запускать из тюрьмы chroot. В этом случае /etc/shadow будет недоступен.

http://www.faqs.org/docs/securing/chap29sec254.html

Комментарии:

1. нет, я не устанавливаю apache в chroot. также, если я попытаюсь прочитать /etc/passwd, этот фрагмент кода работает успешно.

2. Пусть программа stat() загрузит файл. Если это не удается, распечатайте номер ошибки и строку ( int errnum = errno; printf("%d: %s<br />n", errnum, strerror(errnum)); , захватив errno до того, как она получит возможность измениться. Если stat() это удастся, я буду скромно удивлен; однако вы должны напечатать владельца, группу, размер и режим файла. Еще один способ root не получить доступ к файлу — это если он находится в файловой системе, смонтированной на NFS. Однако крайне маловероятно, что это /etc будет смонтировано с помощью NFS. Возможно, вы столкнулись с некоторыми «проблемами с возможностями», но отслеживать это будет сложно!

3. о! эта проблема решена с помощью setenforce 0! теперь еще один вопрос: есть ли у этого кода проблемы с безопасностью? означает получение пароля пользователя с помощью suid на общем хостинге? а также поворот selinux?

Ответ №2:

Эта проблема может быть решена с setenforce 0 помощью остановки selinux stop.