Нужда от елементарна защита
В днешно време защитата на LAMP сървър става все по трудна. Дали да влизам в теория на конспирациите незнам, но никой не може да ми обясни какво печелят така наречените “скриптъри” съвсем незаслужено наричащи себе си “хакери”, като “дифейснат” някой сайт с шарена картинка отпред или БотНет който “пръска” излишен и абсолютно бесмислен трафик или пък някой Китайски DVR питащ DNS сървъра ми 100 пъти в секунда за никога несъществуващ домейн и много други подобни случаи в които атакуващия няма никаква изгода. Всеки здравомислещ човек усеща, че има нещо “гнило в Дания”, но казахме вече, че съвсем “мижитурски” ще избягаме от темата с конспирациите. Освен всичко друго забравяйки за безмислените атаки има и такива с ясната цел да те превърнат в зомби, като постоянно те сканират за някакъв отворен порт на услуга опитваики се да отгаднат я парола в SSH или да прихванат някое “куки” от сесиията на логнат потребител в HTTP. Системният администратор на подобна машина като тази трябва ясно да се разбере с девелопера ако има такъв кой, какви отговорности ще носи. Класическия случай е когато администратора си отговаря за SSH а девелопера за HTTP(S) например.
Firewall – защитна стена
Винаги Първата ми стъпка е да сканирам с nmap отдалечено сървъра.
nmap 93.155.130.82 |
До тук нещата изглеждат добре, имаме отворени 3 порта като 22, тоест SSH през който имаме достъп отдалечено и ще го филтрираме така, че само IP адресите които опишем ще имат достъп до него. За целта ще се логна в Ubuntu server 16.04 LTS и ще създам файла.
sudo nano firewall.sh |
#!/bin/bash # # Basic iptables rules for sample hosting # Samuil Arsov <support@itservice-bg.net> # iptables -F iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp --dport 22 -s 93.155.130.0/23 -m comment --comment "Local NET" -j ACCEPT iptables -A INPUT -p tcp --dport 22 -s 93.155.162.0/24 -m comment --comment "Local NET" -j ACCEPT iptables -A INPUT -p tcp --dport 22 -s 93.155.169.0/24 -m comment --comment "Local NET" -j ACCEPT iptables -A INPUT -p tcp --dport 22 -s 88.203.250.79 -m comment --comment "My Village" -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j LOG --log-level 7 --log-prefix "ACCEPT HTTP" iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j LOG --log-level 7 --log-prefix "ACCEPT HTTPS" iptables -A INPUT -p tcp --dport 443 -j ACCEPT iptables -A INPUT -p icmp --icmp-type 8/0 -j LOG --log-level 7 --log-prefix "ACCEPT ICMP" iptables -A INPUT -p icmp --icmp-type 8/0 -j ACCEPT iptables -A INPUT -p icmp --icmp-type 11/0 -j LOG --log-level 7 --log-prefix "ACCEPT TIME EXCEEDED" iptables -A INPUT -p icmp --icmp-type 11/0 -j ACCEPT iptables -A INPUT -j LOG --log-level 7 --log-prefix "DEFAULT DROP" iptables -A INPUT -j DROP |
Ще го направя изпълним
sudo chmod 755 firewall.sh |
И ще го стартирам
sudo ./firewall.sh |
Ако не сте си отрязяли достъпа защото сте забравили да си напишете ип адреса в веригата на SSH трябва да проверите минават ли някакви пакети през iptables.
sudo iptables -nvL |
Видимо явно, да ! Което значи, че нашият iptables работи. Още по любопитното в случая обаче е какво логва iptables в sysloga на Линукс сървъра:
sudo tail -f /var/log/syslog |
И веднага се набива на очи още в първите редове на firewall лога как китайски IP адрес SRC=116.31.116.30 проверява дали порт 22 DPT=22 на сървъра DST=93.155.130.82 е отворен SYN. Но тъй като аз съм филтрирал този порт за непознати IP адреси firewall го отхвърля DEFAULT DROPIN=ens3 което ме прави по малко нервен.
Защита на директории
С Firewall защитихме порт 22 SSH, но директория не можем. Достъпа до директориите се управлява от сървъра Apache от така наречените директиви (правила за директории). Когато инсталирахме phpmyadmin ние не защитихме директорията му, въпреки, че той иска потребителско име и парола, един от потребителите е root тоест администратора на MySQL сървъра. Страшничко е някой да ти знае името на потребителя (50% от информацията за акаунта) за да се опита да отгатне паролата му. Затова ние ще защитим директорията по следния начин като редактираме файла:
sudo nano /etc/phpmyadmin/apache.conf |
добавяики третата директива AllowOverride All
<Directory /usr/share/phpmyadmin> Options FollowSymLinks DirectoryIndex index.php AllowOverride All |
След което трябва да създадем htaccess
sudo nano /usr/share/phpmyadmin/.htaccess |
И да му добавим IP адресите които искаме да имат достъп до web директорията на phpmyadmin
deny from all allow from 93.155.130.0/23 allow from 93.155.162.0/24 allow from 93.155.169.0/24 allow from 88.203.250.79 |
След което естествено трябва да рестартираме Apache
sudo systemctl restart apache2.service |
IP адрес който не е в htaccess листата трябва да види това в браузера си Forbidden
Apache логове
Web сървъра Apache има доста сериозна система за записване на събития. Основно има два вида събития access.log записва посещенията на сайтовете и error.log записва евентуални проблеми. Самият error.log разделя събитията по важност, като error – грешка което си е някакъв проблем, warn – внимание и notice – бележка. Не мисля, че е нужно да изпадам в подробности, има ужасно много документация за Apache дори и на Български въпросът тук, че логовете много често се пренебрегват а те са ключа към решаването на бъдещи все още неизникнали проблеми.
sudo tail -f /var/log/apache2/error.log |
По принцип в access.log Apache, записва доста неща които са излишни, затова ще покажа какво филтрирам аз за да извлеча по лесно читаема информация от записаните събития.
awk -F\" '{print $6}' /var/log/apache2/access.log.1 | sort | uniq -c | sort -fr |
Списък на броя на посещенията на сайтовете ни от различни платформи. Google bot ни е посетил само за една нощ 6 пъти.
Броя на кодовете в HTTP протокола за една нощ:
awk '{print $9}' /var/log/apache2/access.log.1 | sort | uniq -c | sort |
Основните кодове са:
200 - OK 206 - Partial Content 301 - Moved Permanently 302 - Found 304 - Not Modified 401 - Unauthorised (password required) 403 - Forbidden 404 - Not Found |
Кой ип адреси, времето на заявка към Apache и пътищата които посещават
cat /var/log/apache2/access.log.1 | awk '{print $1,$4,$5,$6,$9,$11,$19}' |
Няма да се занимаваме повече с логовете на Apache но с риск да стана банален пак ще кажа, че това много често е доста подценяван момент в поддръжката на един LAMP сървър.
Лог на потребителя
Обикновенно една такава машина не се админстрира от един човек или пък девелопера също има достъп до нея през SSH. След като се срине нещо за да се оправи то по най бързия начин е да се разбере историята на потребителя счупил системата. В тези критични моменти обикновенно никой не знае какво се е случило и често звучат репликите:
– Не съм пипал нищо !
– Спря е така без причина !
– Не съм, аз !
Затова първо започваме с последните събития в системата изискващи оторизация
cat /var/log/auth.log |
В личната директори в този файл се съхраняват последните 1000 изпълнени команди в терминала:
cat .bash_history |
Дори и потребителя да си изтрие историята с командите при съмнения, че той е променил точно определен файл може да се провери със stat (кой и кога е модифицирал файла за последно)
stat firewall.sh |
MySQL injection – attacks
MySQL injection е доста често срещана атака към MySQL сървъра, но това още в самото начало трябва да се разберете с разработчика/девелопера на системата, че си е негова работа. Работата на системния администратор е да архивира базите редовно но не и да ги администрира. Казвам това защото има едно често прехвърляне на топката от този на озни отбор.
Sloworis – DdoS TCP attacks
Sloworis е вид DdoS TCP атака в тих режим. Идеята му е да отвори максималните връзки на Apache без нищо да прави с тях като по този начин се явява така нареченото “запушване”. Хитрото в случая е, че системата ви не се товари, трафика е минимален но сайтовете ви се отварят много трудно или въобще не се отварят. Атаката се диагностицира като видите в htop много процеси на Apache и в tcpdump -i $ETH -nn dst host $IP and dst port 80 хиляди SYN пакети от един IP адрес към порт 80. В Apache има такъв модул който помага това да се предотврати.
Инсталираме:
sudo apt-get -y install libapache2-mod-qos |
Редактираме:
sudo nano /etc/apache2/mods-available/qos.conf |
<IfModule qos_module> # minimum request rate (bytes/sec at request reading): # QS_SrvRequestRate 120 # limits the connections for this virtual host: # QS_SrvMaxConn 100 # allows keep-alive support till the server reaches 600 connections: # QS_SrvMaxConnClose 600 # allows max 50 connections from a single ip address: QS_SrvMaxConnPerIP 50 </IfModule> |
Рестартираме Apache
sudo systemctl restart apache2.service |
high–level – По високо ниво на защита
От администраторска гледна точка ако искате да вдигнете летвата още малко нагоре разгледайте това: