2015. augusztus 9., vasárnap

Webszerver biztonsági kérdései



Ebben a bejegyzésben néhány általános hibát mutatok be, ami egy webszerver elleni támadásban megkönnyíti a támadó dolgát, de egyszerűen orvosolható lenne.

Sok cég egyszerűen nem fordít figyelmet a webszervere biztonságossá tételére, hiszen "webszervert mindenki tud üzemeltetni".

Lehet úgy csinálni, hogy működjön és lehet úgy is, hogy biztonságosan működjön, jellemzően a "csak működjön" a cél.

Íme a problémák:

Szükségtelen header paraméterek 

Az első szabályok között van a szerver biztonsági szabályok oktatása során, hogy ne áruljuk el, hogy milyen kiszolgáló melyik verziója végzi a szolgáltatást.

Server

Szinte minden webszerver automatikusan hozzáadja a nevét és a verziószámát a HTTP válaszhoz. Ez jó nekik, hiszen jobban szerepelnek az ilyen jellegű felméréseken, viszont egy támadót is kényelmes helyzetbe hoz, mivel kéretlenül átadja a nevét és verziószámát.
Egy nem frissített rendszernél ennél többre nincs is szükség, hiszen a kiszolgáló típusa és verziószáma alapján egyszerűen ki lehet keresni a sérülékenységeit (pl https://www.exploit-db.com/)  és már mehet is a támadás. Ahány webszerver, annyi módja a kikapcsolásnak.

NginX 
Javasolt az nginx-extras csomag használata, mivel ki tudja venni a Server headert:
        more_clear_headers 'Server';
Ettől függetlenül a /etc/nginx/nginx.conf-ban a server_tokens paramétert érdemes off- ra állítani.

Apache

/etc/apache2/conf.d/security fájlban két módosítás javasolt:
 ServerTokens Prod
ServerSignature Off
Ezzel csak a verziót takarjuk el, de a header megmarad, ezért a domain-hez tartozó konfigot érdemes kiegészíteni a következővel:
Header always unset "Server

HAproxy
A HAproxy ugyan nem erre való, de terheléselosztáson kívül is rengeteg dologban tud segíteni. A header-ek manipulálása is hozzátartozik.
A server header eltávolítható vele, a vonatkozó backend szakasz következő sorral való kiegészítésével:
 rspidel ^Server:.*
Érdemes ezt a webszervereknél konfigurálni, ne foglaljuk a loadbalanszert ilyen dolgokkal.

X-Powered-By

Az előzőhöz hasonló céllal jöhetett létre, arról ad információt, hogy a webalkalmazás miben készült, melyik verzió futtatja.

PHP-ban a megfelelő php.ini  expose_php sorát off-ra állítva kapcsolható ki:

expose_php = Off

Amennyiben erre nincs lehetőség, akkor a webszerverre érdemes bízni.

Session ID

Az előzőhöz kapcsolódik. Ha lehet,  azt sem kell a felhasználók orrára kötni, hogy az alkalmazás miben íródott. 

PHP-ben a php.ini session.name paraméter határozza meg, hogy a session cookie milyen névvel jelenjen meg a klienseknél. Ez alapesetben PHPSESSID, érdemes kihagyni a PHP-t a karakterláncból.

Természetesen az URL-ből is kiderülhet, hogy miben írodott az alkalmazás, SEO barát URL-t feltételezünk ebben az esetben...

Hibaoldalak

Webszervertől függően a 404,403, stb státuszokhoz tartozó statikus HTML fájlok is tartalmazzák a webszerver típusát.
A barátságosabb felhasználó értesítésen kívül mégegy ok saját hiba oldalak (Error page) használatára

Szükségtelen modulok

A webszerverek általában előre definiált modul csomaggal érkeznek, amelyek az általános igényeket és a minnél kevesebb konfigurációt tartják  szem előtt. Ennek azonban van hátulütője is, hiszen egy bekapcsolt Apache autoindex modul olyan információkhoz is hozzáférést enged, amihez nem feltétlenül szeretnénk hozzáférést engedni. Pl CMS-ek modules, templates, egyéb könyvtárának listája.
Amennyiben nincs rá szükség, érdemes kikapcsolni.
Apache esetén a2dismod autoindex


PHPmodulok

Nem csak  a webszerverekre érvényesek az előző gondolatok, amire nincs feltétlenül szükség, azt érdemes kikapcsolni.
Egy egyszerű és kényelmes eszköz erre: LAMPSecurityToolkit

Védekezés a feltérképezések ellen

Érdemes belenézni a webszerver logba időnként, hogy lássuk milyen kérések érkeznek, amire a kiszolgálónk 404 - nem található vagy 403 - forbidden üzenettel válaszol.
Pl:
[09/Aug/2015:12:11:35 +0200] "GET /MyAdmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:36 +0200] "GET /scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:37 +0200] "GET /db/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:38 +0200] "GET /dbadmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:39 +0200] "GET /myadmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:39 +0200] "GET /mysql/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:40 +0200] "GET /mysqladmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:41 +0200] "GET /phpadmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu"
[09/Aug/2015:12:11:42 +0200] "GET /phpMyAdmin/scripts/setup.php HTTP/1.1" 404 56 "-" "ZmEu


 Az ilyen jellegű kéretlen próbálkozások ellen célszerű felokosítani a fail2ban-t, ami az ilyen próbálkozóktól távol tart bennünket. Íme pléda: Apache 404 
Ezzel azért körültekintően kell bánni, hiszen, ha a weboldalunkból hiányzik valamilyen fájl, az tud felesleges kitiltást eredményezni...


Ellenőrzés fájl kiterjesztés szerint

Előfordul, amikor egy webalkalmazáson valamilyen code injection sérülést találnak, de a javításig a szolgáltatást fenn kell tartani.
Pl: Egy sérülékenység eredményeként php fájlokat hoztak létre a támadók egy cache könyvtárban:
# ls -1 cache/*.php
cache/blog27.php
cache/dirs2.php
cache/start65.php
cache/template39.php


Nem kényelmes helyzet, de az alábbi konfigurációval átmenetileg megmenekülünk a spam áradattól (amit feltehetőleg ezek a php fájlok generálnak):

NginX:
location ~ /cache/(.+)\.php$ {
        deny all;
 }

Remélem hasznosnak bizonyulnak a fenti javaslatok, a véleményeket szívesen fogadom.