Limitowanie zasobów użytkowników przy suPHP z wykorzystaniem stosu PAM

Nowy pracownik naszej firmy, administrator Linux Mateusz Małek, w ramach prowadzonych testów podatności przeprowadził udany, a zarazem trywialny atak mający wpływ na stabilność pracy jednego z naszych serwerów hostingowych.

Poniżej prezentujemy sposób częściowy zabezpieczenia serwera przed lokalnymi atakami DoS wykonywanymi przy pomocy funkcji shell_exec() w PHP, jeżeli wykorzystywany jest suPHP.

W przypadku wykorzystywania suPHP, uruchamiane z UID+GID użytkownika procesy nie przechodzą przez stos PAM, tym samym nie dotyczą ich limity pam_limits.so z /etc/security/limits.conf. Opisane poniżej kroki zmieniają to zachowanie.

Patchowanie, rekompilacja i rekonfiguracja suPHP

  1. Nakładamy przygotowany patch na suPHP:

    cd /usr/local/directadmin/custombuild
    cp $(find -type d -name \’suphp-0*\’) suphp-patched;
    cd suphp-patched;
    wget http://mkwm.zielonki.info/suphp_patch.diff -O – | patch -p1

  2. Tworzymy nową usługę PAM – np. \”suphp\”, uwzględniającą moduł pam_limits z dedykowaną konfiguracją – wykorzystanie globalnego pliku konfiguracyjnego stwarza pewne problemy (o czym za chwilę):

    cat << EOF > /etc/pam.d/suphp
    auth sufficient pam_permit.so
    session required pam_limits.so conf=/usr/local/suphp/etc/security/limits.conf
    session required pam_permit.so
    EOF

  3. Konfigurujemy limity dotyczące liczby procesów (tak, serwer uległ \”trzynastu znakom\”). Dedykowany plik konfiguracyjny rozwiązuje problem z sytuacją, w której konta użytkowników nie posiadają żadnej wspólnej grupy – w przypadku ustawienia limitów dla wszystkich (*), nie ma możliwości podniesienia ich dla konkretnego użytkownika/grupy (co powoduje problemy z działaniem usług czy administrowaniem serwerem):

    cat << EOF > /usr/local/suphp/etc/security/limits.conf
    * soft nproc 20
    * hard nproc 20
    EOF

  4. Rekompilujemy suPHP i dodajemy \”pam_service=suphp\” do sekcji global w jego pliku konfiguracyjnym.

Wiele wersji PHP w DirectAdmin używając mod_suphp i mod_macro

Integracja z Directadmin

Od strony DirectAdmina użyliśmy modułu phpsv specjalnie zaadaptowanego dla potrzeb używanej konfiguracji.
Pozwala on na ustawianie osobno wersji PHP dla każdej domeny.

Jeżeli taka możliwość okaże się dla klienta niewystarczająca, możliwe jest ustawienie dla każdej subdomeny, a nawet katalogu osobnej wersji używając opisanego poniżej makra.

 Instalacja wielu wersji PHP

Poszczególne wersje PHP zostały ręcznie skompilowane z różnymi prefiksami, np.:

\”–prefix=/usr/local/php52\”
\”–with-config-file-path=/usr/local/etc/php52/cgi\”

oraz podlinkowane z wygodnymi nazwami w celu uproszczenia używania zadań cron

/usr/local/bin/php-5.2 -> /usr/local/php52/bin/php

Dostępne są php-4.4.9, php-5.2.17, php-5.3.14, php-5.4.4, php-6.0.0.

Każda z nich została zlinkowana z bibliotekami libmysql dla Percona Server oraz w miarę możliwości wyposażona w Zend Optimizer albo Zend Guard Loader oraz ionCube Loader.

Instalacja mod_macro

Dla Apache/2.2.22 używamy modułu w wersji 1.1.11.
Instalacja ogranicza się do pobrania pliku ze strony mod_macro Fabiena Coelho i kompilacji przez apxs zgodnie z plikiem INSTALL.

Dla potrzeb konfiguracji wersji PHP udostępniamy dla użytkowników globalnie następujące macro.

/home/.htaccess:

<Macro php $version>
<FilesMatch \”\\.(inc|php|php3|php4|php5|php6|phtml|phps)$\”>
AddHandler x-httpd-php$version .inc .php .php3 .php4 .php5 .phtml
</FilesMatch>
</Macro>

Którego można użyć w pliku .htaccess wybierając stosowną wersję PHP:

Use php 4
Use php 52
Use php 53
Use php 54
Use php 6

 Konfiguracja mod_suphp

Po standardowej instalacji mod_suphp z custombuild dodajemy stosowne handlery.
W pliku /usr/local/suphp/etc/suphp.conf:

[handlers]
;Handler for php-scripts
x-httpd-php4=\”php:/usr/local/php4/bin/php\”
x-httpd-php52=\”php:/usr/local/php52/bin/php-cgi\”
x-httpd-php53=\”php:/usr/local/php53/bin/php-cgi\”
x-httpd-php54=\”php:/usr/local/php54/bin/php-cgi\”
x-httpd-php6=\”php:/usr/local/php6/bin/php-cgi\”

/etc/httpd/conf/extra/httpd-suphp.conf:

<IfModule mod_suphp.c>
Use php 53
<Location />
suPHP_Engine on
#suPHP_ConfigPath /usr/local/etc/php5/cgi/
suPHP_AddHandler x-httpd-php4
suPHP_AddHandler x-httpd-php52
suPHP_AddHandler x-httpd-php53
suPHP_AddHandler x-httpd-php54
suPHP_AddHandler x-httpd-php6
</Location>
</IfModule>