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.

Zmiana wielkości ikon pulpitu w Windows 7

Pojawiające się tutaj wpisy zazwyczaj zawierają wiedzę, do której wracam ja, będą przydatne innym osobom w firmie albo też poza nią. Na prawdę od dawna szukałem tej opcji. Przepraszam za ten post.

Mam nadzieję, że tym razem trafię do osób z małymi ekranami, z dużą ilością ikon, albo po prostu szukające tej opcji w opcjach wyglądu – tylko tyle mam na swoje usprawiedliwienie.

  1. Pulpit.
    \"\"
  2. Prawy przycisk myszy, widok, małe ikony…
    \"\"
  3. Voilà!
    \"\"

Katalog stron Easydir na hostingu Aboo

Katalog stron Easydir oparty jest na frameworku Kohana i bazach SQLite.

Podstawowym wymaganiem Kohany jest choć-trochę-obsługująca programowanie obiektowe wersja interpretera PHP: co najmniej 5.2.
I na tym kompatybilność się kończy – ze względu na wiek skryptu / kunszt programisty, modele aplikacji zawierają odwołania do przestarzałych w domyślnie włączonej wersji PHP (5.3) funkcji z rodziny eregi.
Fakt ten nie objawia się: katalog silently fails, w porywach wyświetla Unknown PHP Error.

Biorąc pod uwagę podstawowe zastosowanie opisywanego kodu – pozycjonowanie stron WWW, nie namawiam nikogo na zastąpienie ich wyrażeniami regularnymi i funkcjami z rodziny preg, a zaproponowane rozwiązanie jest najprostszym z możliwych:

Zgodnie z bazą wiedzy, w pliku .htaccess używamy gotowego makra, zmieniając wersję interpretera:

Use php 52

Katalog znów żyje!

Instalacja certyfikatu SSL w DirectAdmin

Domyślnie DirectAdmin nie korzysta z SSL przy połączeniach do panelu administracyjnego.

Aby włączyć obsługę SSL oraz wygenerować certificate signing request, zastąpić samopodpisane certyfikaty wystawionymi np. przez StartSSL.com. Na serwerze s5.aboo.pl użyty został certyfikat Comodo Essential SSL:

  1. Tworzymy nowy klucz prywatny oraz CSR:

    openssl req -nodes -newkey rsa:2048 -keyout s5.aboo.pl.key -out s5.aboo.pl.csr

  2. Używając CSR generujemy certyfikat na stronie wystawcy. Jeżeli jesteśmy pytani o typ serwera, wybieramy Apache + mod_ssl, dzięki czemu otrzymamy w formacie PEM
  3. Otrzymane od wystawcy pliki umieszczamy w /usr/local/directadmin/conf wraz z wcześniej wygenerowanym kluczem (-keyout …)
  4. Edytujemy plik directadmin.conf, dodając lub modyfikując linie:

    SSL=1 <- włączamy SSL ssl_redirect_host=s5.aboo.pl <- ważne! ustawiamy adres na który klient jest odsyłany, jeżeli połączy się z http:// zamiast https:// cacert=/usr/local/directadmin/conf/cacert.pem <- certyfikat (\"nasz\") cakey=/usr/local/directadmin/conf/cakey.pem <- klucz prywatny carootcert=/usr/local/directadmin/conf/caroot.pem <- certyfikaty pośrednie (CA)

  5. Bardzo, bardzo ważne – ustawiamy odpowiednie uprawnienia na plik z kluczem:

    chown diradmin:diradmin cakey.pem
    chmod 400 cakey.pem

  6. Restartujemy usługę DirectAdmin:

    service directadmin restart

Konfiguracja trunku Sipgate w Trixbox (Asterisk)

Trixbox i Sipgate

Sipgate udostępnia darmowe numery DID (direct inward dialing) z USA, UK oraz DE z których korzystać można za pośrednictwem trunków SIP.

W roli PBX wybrany został Trixbox ze względu na szybką i łatwą konfigurację oraz doświadczenia związane z obecną już w firmie centralną telefoniczną opartą na tej dystrybucji. Doświadczenia zebrane z jej podstawowym zabezpieczeniem zostały już wcześniej zebrane we wpisie bezpieczny Trixbox.

Poprawne działanie opisanej konfiguracji zostało potwierdzone w praktyce – zarówno w nawiązywaniu jak i odbieraniu połączeń. W dalszej części zakładam, że trixbox został świeżo zainstalowany na maszynie dostępnej pod NAT-owanym adresem IPv4 192.168.0.6, a adres publiczny IPv4 to 12.34.56.789;

Konfiguracja Trixbox

Konfiguracji dokonujemy przez wygodne gui dostępne pod http://trixbox/maint z jako \”maint\” z hasełem \”password\”.

Dodajemy SIP extension dla lokalnego telefonu

  1. W PBX Settings -> Basic -> Extensions wybieramy Add an Extension -> Generic SIP device
  2. Wypełniamy pole \”User extension\” wpisując wewnętrzny numer, np. \”100\”, w \”Display Name\” określającą go nazwę, oraz w \”secret\” przypisujemy doń hasło.

Dodajemy SIP trunk od Sipgate

  1. W PBX Settings -> Basic -> Trunks wybieramy Add SIP Trunk
  2. W Outbound Caller ID wpisujemy otrzymany od Sipgate numer
  3. Ograniczamy ilość wychodzących jednocześnie połączeń wpisując w Outbound Caller ID wartość 1
  4. Wypełniamy Outgoing Settings, wpisując w Trunk Name \”sipgate\” oraz w PEER Details poniższą konfigurację, zamieniając \”ID-UŻYTKOWNIKA\” na ID dostępne szczegółach konta na Sipgate oraz \”HASŁO-SIP-UŻYTKOWNIKA\” na dostępne tam hasło SIP różne od hasła używanego do logowania na stronie

    authuser=ID-UŻYTKOWNIKA
    context=ext-did
    dtmfmode=info
    fromdomain=sipgate.co.uk
    fromuser=ID-UŻYTKOWNIKA
    host=sipgate.co.uk
    insecure=very
    qualify=yes
    secret=HASŁO-SIP-UŻYTKOWNIKA
    type=peer
    username=ID-UŻYTKOWNIKA

  5. W Incoming Settings ustawiamy USER Context na \”ext-did\”, a USER Details identycznie jak PEER Details
  6. W Register String ustawiamy \”ID-UŻYTKOWNIKA:HASŁO-SIP-UŻYTKOWNIKA@sipgate.co.uk/ID-UŻYTKOWNIKA\”

Konfigurujemy inbound i outbound route

  1. W PBX Settings -> Inbound Call Control-> Inbound routes wybieramy Add Incoming Route
  2. W DID Number wpisujemy \”ID-UŻYTKOWNIKA\”
  3. W sekcji Set Destination wybieramy utworzony wcześniej numer (extension)
  4. W PBX Settings -> Basic -> Outbound routes wybieramy Add Route
  5. W Route Name wpisujemy np. \”sipgate_outside\”
  6. Aby skierować wszystkie rozmowy do trunku w Dial Patterns wpisujemy \”.\”
  7. W Trunk Sequence wybieramy utworzony trunk: \”SIP/sipgate\”
Konfiguracja NAT
  1. Przekierowujemy porty 12.34.56.789:5060-5070 TCP i UDP na porty 192.168.0.6:5060-5070
  2. Przekierowujemy porty 12.34.56.789:10000:20000 UDP na porty 192.168.0.6:10000:20000

W Vyatta Core 6.2 realizują to polecenia:

for i in 1 2; do set service nat rule 60${i} type destination; set service nat rule 60${i} inside-address address 192.168.0.6; set service nat rule 60${i} inbound-interface eth0; done
set service nat rule 601 protocol tcp_udp
set service nat rule 601 destination port 5060-5070
set service nat rule 602 protocol udp
set service nat rule 602 destination port 10000:20000

Konfiguracja dla trunków USA i DE przebiega analogicznie z dokładnością co do domeny.

Instalacja Xen Cloud Platform na soft-raid1

Niemożliwe, niewspierane, …

Zgodnie z dokumentacją, instalacja Xen Cloud Platform na macierzy RAID1 może odbyć się tylko w przypadku korzystania z wspieranego sprzętowego kontrolera RAID. Ze względu na ograniczoną przestrzeń na karty rozszerzeń w HP Microserver nie pozwalającą na wykorzystanie tanich kontrolerów Dell PERC, zdecydowałem się na instalację systemu na macierzy stworzonej mdadm.

Instalacja XCP 1.5

Instalator XCP nie pozwala nam ani na instalację na macierzy fake-raid ani nawet na modyfikację układu partycji.
Jako, że wykorzystałem dyski 1TB, nie miałem konieczności korzystania GUID Partition Table. Pozwoliło to na uproszczenie procedury i w tej też formie przedstawiam ją tutaj.

W przypadku instalacji z płyty CD wybieramy przy rozruchu opcję \”shell\”, w przypadku instalacji z sieci (PXE) przełączamy konsolę na 3 (ALT+F3) i dokonujemy poniższych modyfikacji, następnie restartując program instalatora (kill).

  1. Wyłączamy GPT – nie wspierane przez dmraid:

    sed \’s/GPT_SUPPORT = True/GPT_SUPPORT = False/\’ -i /opt/xensource/installer/constants.py

  2. Wychodzimy z shell komendą exit
  3. Prowadzeni przez instalator Anaconda dokonujemy instalacji na pierwszym z dysków nie tworząc local storage
Przeniesienie systemu na RAID1
  1. Tworzymy docelową struktury partycji
    Najprościej:

    sfdisk -d /dev/sda | sed \’s/Id=83/Id=fd/g\’ | sed \’s/Id=8e/Id=fd/g\’ | sfdisk –force /dev/sdb

    Lepiej: tworzymy analogiczną strukturę jak na pierwszym dysku, wypełniając go partycjami typu Linux RAID autodetect (w fdisk – typ \”fd\”), przeliczając odpowiednio wielkości w przypadku korzystania z dysków Advanced Format (4kb sektor).

  2. Tworzymy macierze RAID1, zapisujemy konfigurację…

    mdadm –create /dev/md0 –level=1 -n 2 missing /dev/sdb1
    mdadm –create /dev/md1 –level=1 -n 2 missing /dev/sdb2
    mdadm –create /dev/md2 –level=1 -n 2 /dev/sda3 /dev/sdb3
    mdadm –detail –scan | sed -r \’s\\$\\ auto=yes\’ > /etc/mdadm.conf

  3. …systemy plików…

    mkfs.ext3 /dev/md0
    mkfs.ext3 /dev/md1

  4. …oraz local storage.

    xe sr-create content-type=user type=ext device-config:device=/dev/md2 shared=false name-label=\”Local storage\”

  5. Zmieniamy wpis dla / w /etc/fstab, ustawiając urządzenie na /dev/md0
  6. Modyfikujemy initrd:

    mkinitrd -v -f –fstab=/etc/fstab –with=raid1 –preload=raid1 /boot/raid-initrd $(uname -r)
    mkdir /tmp/initrd; cd /tmp/initrd; cat /boot/raid-initrd | gzip -d – | cpio -id
    sed \’s/Scanning and configuring dmraid supported devices/raidautorun \\/dev\\/md0/\’ -i init
    sed \’s/sda1/md0/\’ -i init
    find . -print0 | cpio –null -ov –format=newc | gzip -9 > /boot/raid-initrd

  7. Dodajemy wpisy w /boot/extlinux.conf z opcją z root=/dev/md0 i na końcu /boot/raid-initrd, zmieniamy opcję domyślną
  8. Kopiujemy system na dysk docelowy, instalujemy bootloader i restartujemy system:

    mkdir /mnt/md0; mount /dev/md0 /mnt/md0; rsync -xav / /mnt/md0/
    dd if=/usr/share/syslinux/mbr.bin of=/dev/sdb
    extlinux –install –raid /mnt/md0/boot

  9. Po wyłączeniu komputera uruchamiamy go jedynie z drugim dyskiem.
  10. Jeżeli procedura powiodła się, dodajemy pierwotny dysk jako drugi, ponownie kopiujemy nań tablicę partycji i dołączamy go do macierzy

    sfdisk -d /dev/sda | sfdisk –force /dev/sdb
    mdadm –manage /dev/md0 –add /dev/sdb1
    mdadm –manage /dev/md1 –add /dev/sdb2
    mdadm –manage /dev/md2 –add /dev/sdb3