noexec, nosuid на директории свалок (/tmp, /var/tmp)

К сожалению, в предустановленном варианте /tmp раздел не всегда идет отдельным разделом, что открывает атакующемудополнительные возможности. Мы прикроем это следующим образом:
— директории-свалки сделаем отдельными файлами и будем присоединять их через mount -o loop,noexec,nosuid;
— будем проверять все директории-свалки и что-то делать с файлами с опастными правами (x, s). Этот пункт противодействия важен, так-как noexec ограничение на раздел возможно обойти;

Разобьем первый пункт на подпункты:

1.1 Определение директорий для контроля
1.2 Создание файл-разделов.
1.3 Проверка работы noexec,nosuid.
1.4 Обход ограничения noexec
1.5 Скрипт для дополнительной защиты.



1.1 Определение директорий для контроля
Определяем, для каких директорий будут создаваться файл-разделы. Обычно это /tmp, /var/tmp.  
Для поиска директорий имеющих права запись/выполнение/чтение для всех + sticky bit (1**7). можно использовать следующуюкоманду:

            [root@redhat root]# find / -perm -1007 -type d -print
Тоже но без sticky bit:
            [root@redhat root]# find / -perm -007 -type d -print

Пример вывода:
/tmp
/tmp/.font-unix
/var/tmp
/var/spool/samba

Так как обычно на Shared hosting не поддерживается работа samba (которая входит в установку по умолчанию), рекомендуетсяудалить пакет samba*.  Вывести все пакеты, имеющие отношение к samba, может следующая команда:

       [root@redhat root]# rpm -qa|grep samba

Пример вывода:
       samba-3.0.9-1.3E.2
         samba-common-3.0.9-1.3E.2
         samba-client-3.0.9-1.3E.2
         redhat-config-samba-1.0.16-2
         samba-swat-3.0.9-1.3E.2

Удаляем пакеты:
       [root@redhat root]# rpm -e samba samba-common samba-client  redhat-config-samba samba-swat

Если не желаете удалять пакеты, тогда уберите права с директории /var/spool/samba:

       [root@redhat root]# chmod 0000 /var/spool/samba

Если Вы таки используете samba, тогда с этой директорией поступайте так же, как дальше по статье работаем с /tmp.

1.2 Создание файл-разделов.
Мы определили директории, для которых необходимо создать раздел-файлы. Это /tmp, /var/tmp.
Создаем директорию, где будут лежать файлы-разделы:

       mkdir /filesystems

Создаем файл-разделы:

         [root@redhat root]# dd if=/dev/zero of=/filesystems/tmp_fs seek=100 count=1 bs=1M
         [root@redhat root]# dd if=/dev/zero of=/filesystems/var_tmp_fs seek=100 count=1 bs=1M
        
Я решил выделить под /tmp и /var/tmp по 100 M. Вы можете выделить больше — по Вашим потребностям.
Следующим шагом создаем в файлах ФС:

[root@redhat root]# mkfs.ext3 /filesystems/tmp_fs
[root@redhat root]# mkfs.ext3 /filesystems/var_tmp_fs

Добавляем в /etc/fstab строки автоматического присоединения файл-разделов при старте сервера:

/filesystems/tmp_fs /tmp ext3 defaults, noexec, nosuid, loop 1 1 
/filesystems/var_tmp_fs /var/tmp ext3 defaults, noexec, nosuid, loop 1 1      

Присоединяем и проверяем присоединились ли новые файл-разделы (не забыв удалить данные из папок /tmp /var/tmp или, если таместь нужные данные, — временно перенести в другое место, а потом положить в новые файл-разделы):

[root@redhat root]# mount /tmp
[root@redhat root]# mount /var/tmp
[root@redhat root]# df 

Пример вывода:

Filesystem            Size  Used Avail Use% Mounted on 
/dev/hda1              2.0G  988M  926M  52% /
/filesystems/tmp_fs    98M  4.1M   89M   5% /tmp
/filesystems/var_tmp_fs
                       98M  4.1M   89M   5% /var/tmp

1.3 Проверка работы noexec,nosuid.

Пробуем запустить suid файл из под nobody. Вот код С программы:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main (int argc, const char * argv[],char * envp[])
        {
           uid_t uid;
           uid = getuid ();
           printf ( «My id is %d\n»,uid);
           if (0! = setuid (0)) printf ( «\nError suid to root\n»);
           uid = getuid ();
           printf ( «After suid My id is %d\n»,uid);
        }         
        

Собираем:

       [root@redhat root]# gcc suid.c -o suid

Ставим SUID на suid:

       [root@redhat root]# chmod 4775 suid

Копируем для проверки в /:

       [root@redhat root]# cp suid /

проверяем:

         [root@redhat root]# sudo -u nobody /suid

My id is 99 
After suid My id is 0 

Копируем в защищенные директории /tmp /var/tmp:
      
       [root@redhat root]# cp suid /tmp/
         [root@redhat root]# cp suid /var/tmp/

Проверяем:
      
       [root@redhat root]# sudo -u nobody /tmp/suid
         sudo: unable to exec /tmp/suid: Permission denied
         [root@redhat root]# sudo -u nobody /var/tmp/suid
         sudo: unable to exec /var/tmp/suid: Permission denied                                                
      
Сделаем аналогичную проверку для SheLL, Perl, PHP скриптов.
      
Пример скриптов:

test.php:
#!/usr/bin/php -q
<? echo «running\n»;? >   


test.pl:
#!/usr/bin/perl
print «running\n»   


test.sh:
#!/bin/sh
echo «running»   

Результатты проверок:
PHP:

         [root@redhat root]# chmod 755 test.php
         [root@redhat root]#. /test.php
         running
         [root@redhat root]# cp test.php /tmp
         [root@redhat root]# /tmp/test.php
         -bash: /tmp/test.php: /usr/bin/php: bad interpreter: Permission denied


Perl:

         [root@redhat root]# chmod 755 test.pl
         [root@redhat root]#. /test.pl
         running
         [root@redhat root]# cp test.pl /tmp/
         [root@redhat root]# /tmp/test.pl
         -bash: /tmp/test.pl: /usr/bin/perl: bad interpreter: Permission denied


Shell:

         root@redhat root]# chmod 755 test.sh
         [root@redhat root]#. /test.sh
         running
         [root@redhat root]# cp test.sh /tmp/
         [root@redhat root]# /tmp/test.sh
         -bash: /tmp/test.sh: /bin/sh: bad interpreter: Permission denied

На первый взгляд все хорошо. Ничего из директорий-свалок запустить нельзя.

1.4 Обход ограничения noexec.
         Обход noexec при запуске исполняемого файла:

         root@redhat root]# sudo -u nobody  /lib/ld-linux.so.2 /tmp/suid
         My id is 99 
         error suid to root
         After suid My id is 99  

       Как видите, ограничение noexec было обойдено, ограничение на nosuid обойти не удалось (мне не известны способы обхода nosuid надиректорию…).
Данный способ обхода был действителен для всех доступных мне ОС Linux RHE (≤2.4.21-27.0.4.EL  -  последний kernel, доступныйдля обновление через up2date, в момент написания статьи). В случае использование 2.6.x kernel, собранного с исходников, данный способуже недействителен.

         root@redhat root]# sudo -u nobody  /lib/ld-linux.so.2 /tmp/suid
         /tmp/suid: error while loading shared libraries: /tmp/suid: failed to map segment from shared object: Operation not permitted

Вот пример обхода ограничения на запуск скриптов PHP/Perl/Shell:

PHP:

[root@redhat root]# /usr/bin/php -q /tmp/test.php
running

Perl:

[root@redhat root]# /usr/bin/perl /tmp/test.pl
running

Shell:

[root@redhat root]# /bin/sh /tmp/test.sh
running        



1.5 Скрипт для дополнительной защиты.
      
Как видим, одно ограничение noexec, nosuid не способно остановить вторжение, но является дополнительным сдерживающимсредством. Расширим его скриптом, который будет проходить по директориям-свалкам и изменять/удалять неугодные нам файлы. Я лишьприведу пример написанный на shell. Вы можете реализовать данную методику любым удобным Вам способом.
Вот код:

#!/bin/sh
DIR4PROTECT= «/root/dir4protect»
for dir in `cat $DIR4PROTECT`;do
FILE2DELETE=`find $dir -perm +1111 -print`
for file in `echo $FILE2DELETE`;do
        if [ -f $file ];then
                chmod 0000 $file
                chown root.root $file
        fi 
done
done  

Проверяем его работу:


         [root@redhat root]#. /tmpprotect.sh
            [root@redhat root]# ls -la /tmp
            total 45 
            drwxr-xr-x    3 root     root         1024 Apr 29 18:32.
            drwxr-xr-x   20 root     root         4096 Apr 28 23:45. .
            ----------    1 root     root            0 Apr 29 18:32 1 
            drwx------    2 root     root        12288 Apr 27 21:31             lost+found
            ----------    1 root     root        11841 Apr 29 00:36 s2 
            ----------    1 root     root           34 Apr 29 00:10 shell.sh
            ----------    1 root     root        11841 Apr 29 00:00 suid
            ----------    1 root     root           40 Apr 29 16:30 test.php
            ----------    1 root     root           38 Apr 29 16:35 test.pl
            ----------    1 root     root           26 Apr 29 16:40 test.sh
            [root@redhat root]# ls -la /var/tmp
            total 29 
            drwxr-xr-x    3 root     root         1024 Apr 29 00:00.
            drwxr-xr-x   19 root     root         4096 Mar  4 23:29. .
            drwx------    2 root     root        12288 Apr 27 21:32             lost+found
            ----------    1 root     root        11841 Apr 29 00:00 suid                                         

Проверяем возможно ли запустить скрипты:
        
            [root@redhat root]# sudo -u nobody /usr/bin/php -q /tmp/test.php
            [root@redhat root]# sudo -u nobody  /usr/bin/perl /tmp/test.pl
            Can't open perl script «/tmp/test.pl»: Permission denied
            [root@redhat root]# sudo -u nobody /bin/sh /tmp/test.sh
            /tmp/test.sh: /tmp/test.sh: Permission denied

Написанный скрипт помогает блокировать файлы, которые могут быть backdoor, exploits, trojanhorse в директориях свалках. Егоможно расширить автоматическим отправлением письма администратору, любыми другими пришедшими вам на ум идеями. Самый простойспособ — это установить данный скрипт для автозапуска в  crontab на запуск раз в минуту.
Пример содержимого файла крон службы:
         * * * * * /root/tmpprotect.sh