четверг, 25 марта 2010 г.

Intrusion Detection For PHP Applications With PHPIDS

Эта статья покажет как настроить PHPIDS. PHPIDS (PHP-Intrusion Detection System) - это легко используемая, хорошо структурированная, быстрая прослойка для анализа безопасности ваших приложений. IDS - не является прослойкой для анализа данных, введенных пользователем, он только распознает, когда пытаются атаковать ваш сайт. на основе набора проверенных и оттестированных правил каждой атаке сопоставлен рейтинг ее опасности. Это позволит легко сохранять статистику по атакам или отсылать уведомления для команды разработчиков.

Apache версии 2 и PHP5, IP - мой. Пользователь и группа Apache - apache. Путь к php.ini - etc/php.ini. В качестве document root использовался /var/www/html/

Установка PHPIDS
Из изображений безопасности я установил PHPIDS вне document root, поэтому я создал /var/www/phpids:

Затем я установил PHPIDS (на момент установки последняя версия была 0.5).

cd /tmp
wget http://php-ids.org/files/phpids-0.4.7.ta…
tar xvfz phpids-0.4.7.tar.gz
cd phpids-0.4.7
mv lib/ /var/www/web1/phpids/
cd /var/www/web1/phpids/lib/IDS
chown -R apache:apache tmp/

Далее я переконфигурировал Config.ini:

cd Config/
vi Config.ini


Я использую конфигурацию по умолчанию, и все что надо сделать - это поменять пути

; PHPIDS Config.ini

; General configuration settings

; !!!DO NOT PLACE THIS FILE INSIDE THE WEB-ROOT IF DATABASE CONNECTION DATA WAS ADDED!!!

[General]

filter_type = xml
filter_path = /var/www/phpids/lib/IDS/default_filter.xml
tmp_path = /var/www/phpids/lib/IDS/tmp
scan_keys = false

exceptions[] = __utmz
exceptions[] = __utmc

; If you use the PHPIDS logger you can define specific configuration here

[Logging]

; file logging
path = /var/www/phpids/lib/IDS/tmp/phpids_log.txt

; email logging

; note that enabling safemode you can prevent spam attempts,
; see documentation
recipients[] = test@test.com.invalid
subject = "PHPIDS detected an intrusion attempt!"
header = "From: info@php-ids.org"
safemode = true
allowed_rate = 15

; database logging

wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
user = phpids_user
password = 123456
table = intrusions

; If you would like to use other methods than file caching you can configure them here

[Caching]

; caching: session|file|database|memcached|none
caching = file
expiration_time = 600

; file cache
path = /var/www/phpids/lib/IDS/tmp/default_filter.cache

; database cache
wrapper = "mysql:host=localhost;port=3306;dbname=phpids"
user = phpids_user
password = 123456
table = cache

; memcached
;host = localhost
;port = 11211
;key_prefix = PHPIDS
;tmp_path = /var/www/phpids/lib/IDS/tmp/memcache.timestamp

Использование PHPIDS

Сейчас мы создадим /var/www/html/phpids.php, который будет использовать PHPIDS

set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
echo $result;
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Composite.php';

$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init));
$compositeLog->execute($result);
}

После этого введите в своем браузере http://192.168.0.100/phpids.php, и вы увидите пустую страницу.
Однако если вы добавите различные параметры, например http://192.168.0.100/phpids.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E, PHPIDS определит их и напечатает результат в браузер

otal impact: 54
Affected tags: xss, csrf, id, rfe, lfi, sqli

Variable: REQUEST.test | Value: ">XXX
и т.д.

Сейчас мы сделаем так, чтобы PHPIDS тиспользовался в каждом вашем скрипте. Конечно, вам не придется модифицировать каждый файл php в вашей системе. Мы скажем php, чтобы он запускал PHPIDS при каждом старте скрипта. Мы сделаем это используя auto_prepend_file параметр. Для этого сделаем модификацию в php.ini или .htaccess file

auto_prepend_file = /var/www/html/phpids.php
или для .htaccess
php_value auto_prepend_file /var/www/html/phpids.php

Перепустите ваш Apache (для случая с модификацией php.ini)

Создайте файл info.php с содержимым

phpinfo();

Напишите в браузере http://192.168.0.100/info.php и вы увидите нормальный вывод команды phpinfo()
теперь добавьте параметры, например http://192.168.0.100/info.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E и вы увидите

PHPIDS запишет эти данные в /var/www/phpids/lib/IDS/tmp/phpids_log.txt

"192.168.0.200",2008-06-04T17:36:08+02:00,54,"xss csrf id rfe lfi","REQUEST.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E GET.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E",
"%2Finfo.php%3Ftest%3D%2522%253EXXX%253Cscript%253Ealert%281%29%253C%2Fscript%253E"

Теперь, просмотрев записи. вы увидите, что хакер пытался что-то сделать с вашим приложением.

Для добавления другого уровня безопасности для вашего приложения вы можете остановить скрипт, если PHPIDS обнаружил атаку:
мы можем добавить что-то похожее на это
die('
Go away!
');
в секцию if (!$result->isEmpty()) {} в файле /var/www/html/phpids.php script

set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
echo $result;
require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Composite.php';

$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init));
$compositeLog->execute($result);

die('
Go away!
');
}

Если нет атаки скрипт продолжит выполнение, иначе хакер увидит это

коментарий переводчика
Указанные выше примеры можно использовать и на боевых системах. Однако для этого потребуется некое преобразование

$init = IDS_Init::init('/var/www/phpids/lib/IDS/Config/Config.ini');


так как каждый раз незачем загружать файл настроек из файла, а заменить его написанным заранее классом

источник http://habrahabr.ru/blogs/php/31617/

четверг, 18 марта 2010 г.

пятница, 12 марта 2010 г.

Упрощаем скачку с rapidshare и их клонов

если 1 файл - аддон firefox - SkipScreen (scipscreen.com)
файл разбит на части - JDownloader (jdownloader.org) - если не подхватил ссылку значит сервис не поддерживается
вылажывать лучше на "Народ.Диском" yandex - 5 Gb ограничение

вторник, 9 марта 2010 г.

iptables ньюансы настройки

1). Критерий recent iptables позволяет запомнить не более 100 хостов, для увеличения нужно сделать (критерий служит для защиты от сканирования портов)
в /etc/modrobe.conf
для Debian
/sbin/modprobe ipt_recent ip_list_tot=100000
/sbin/modprobe xt_recent ip_list_tot=100000
RedHat, CentOS
options ipt_recent ip_list_tot=100000
Потом перезагрузка
для ядра Linux redhat 2.6.18-164.9.1.el5 есть баг, где это значение не может превысить 5000
2). ограничение количества одновременных соединений (10 штук в примере)
-m connlimit ! --connlimit-above 10 -j ACCEPT
3). борьба с нестандартными видами сканирования (nmap -sN (пакеты без флагов), -sF (FIN установлен) -sX (FIN, PSH и URG установлены))
запрет FIN-сканирования
iptables -A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -m comment --comment "запрет FIN-сканирования" -j DROP
запрет X-сканирования
iptables -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -m comment --comment "запрет X-сканирования" -j DROP
запрет N-сканирования
iptables -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -m comment --comment "запрет N-сканирования" -j DROP
запрет SYN/ACK- сканирования (nmap -sS - связь разрывается сразу после ответа на запрос открытия соединения) (поддержка только в версии 1.4.6)
iptables -I INPUT -p tcp -m osf --genre NMAP -j DROP
защита от тупого стандартного сканирования (nmap -sT - обычное TCP-сканирование состоящее в открытии соединения на порту и его завершения)
iptables -A INPUT -m recent --rcheck --second 3600 --hitcount 10 --rttl -m comment --comment "проверка на стук в нерабочие порты 10 в час" -j RETURN
iptables -A INPUT -m recent --rcheck --second 60 --hitcount 2 --rttl -m comment --comment "вторая проверка на стук в нерабочие порты 2 в минуту" -j RETURN
# Разрешаем рабочие порты
iptables -A INPUT -m state --state NEW -p tcp -m multiport --dport 21,25,53,80,110 -j ACCEPT
iptables -A INPUT -m state --state NEW -p udp -m multiport --dport 53 -j ACCEPT
iptables -A INPUT -m recent --set -m comment --comment "отбрасываем пакеты всех, кто превысил лимит на количество подключений" /proc/net/ipt_recent/DEFAULT - старые ядра (модуль поддерживает только IPv4) /proc/net/xt_recen/DEFAULT - новые (также IPv6) - если имя списка не задано, если задано тогда вместо дефолтного данное вами имя
Примечания - см. п.1, а также ОБЯЗАТЕЛЬНО УКАЗАТЬ ТОЛЬКО ВНЕШНИЙ ИНТЕРФЕЙС чтобы не попадали тачки из локалки (БУДЕТ ТОРБА ПОСКОЛЬКУ В ЛОКАЛКЕ КУЧА ШИРОКОВЕЩАТЕЛЬНЫХ ЗАПРОСОВ), а только из инета. ТАКЖЕ ДАННЫЕ ПРАВИЛА НУЖНО СТАВИТЬ В КОНЦЕ ЦЕПОЧКИ INPUT ЧТОБЫ ПРИ PING И ДРУГИХ ПОДКЛЮЧЕНИЯХ НЕ ПОПАДАТЬ В ДАННЫЙ ЛИСТ И НЕ БЛОКИРОВАТЬ СЕБЯ САМОГО.
можно установить пакет xtables-addons (содержит наработки проэкта patch-o-matic, получим доступ к модулю PSD (Port Scan Detect)) и 3 строки выше заменить одной
iptables -A INPUT -m psd -j DROP

Безопасность mysql

1). Oтключаем использование команды LOAD DATA LOCAL INFILE. Это предотвратит несанкционированное чтение локальных файлов. Это также подходит против SQL-инъекций в PHP-сценариях.
Листинг 5.2: Отключение LOAD DATA LOCAL INFILE в разделе [mysqld] файла /etc/my.cnf
set-variable=local-infile=0
2). Если вы изменяли пароли в командной строке MySQL, то всегда очищайте ~/.mysql_history и /var/log/mysql/mysql.log, так как они сохраняют список выполненных SQL-команд с открытыми паролями.

Безопасность apache

#Не сообщать информацию о версии сервера
ServerSignature Off
ServerTokens Prod

понедельник, 1 марта 2010 г.

инфа по физике сетевухи (linux)

[root@123 ~]# dmesg | grep -i duplex
bnx2: eth0 NIC Copper Link is Up, 100 Mbps full duplex, receive & transmit flow control ON
e1000e: eth2 NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
e1000e: eth1 NIC Link is Up 100 Mbps Full Duplex, Flow Control: None
e1000e: eth1 NIC Link is Up 100 Mbps Full Duplex, Flow Control: None

Просмотр установленных драйверов

ethtool -i eth0
driver: bnx2
version: 2.1.11
firmware-version: bc 1.9.6
bus-info: 0000:03:00.0

ethtool -i eth3
driver: e1000e
version: 1.4.4-k
firmware-version: 5.11-2
bus-info: 0000:06:00.1

Просмотр статистики, то чего не должно быть выделено жирным

ethtool -S eth0
NIC statistics:
     rx_bytes: 191166177897
     rx_error_bytes: 0
     tx_bytes: 2285524683461
     tx_error_bytes: 0
     rx_ucast_packets: 1376418747
     rx_mcast_packets: 213363
     rx_bcast_packets: 1205607
     tx_ucast_packets: 1897974881
     tx_mcast_packets: 443
     tx_bcast_packets: 318966
     tx_mac_errors: 0
     tx_carrier_errors: 0
     rx_crc_errors: 0
     rx_align_errors: 0
     tx_single_collisions: 0
     tx_multi_collisions: 0
     tx_deferred: 0
     tx_excess_collisions: 0
     tx_late_collisions: 0
     tx_total_collisions: 0
     rx_fragments: 0
     rx_jabbers: 0
     rx_undersize_packets: 0
     rx_oversize_packets: 0
     rx_64_byte_packets: 564349475
     rx_65_to_127_byte_packets: 582392788
     rx_128_to_255_byte_packets: 170241876
     rx_256_to_511_byte_packets: 12601437
     rx_512_to_1023_byte_packets: 13261490
     rx_1024_to_1522_byte_packets: 34991571
     rx_1523_to_9022_byte_packets: 0
     tx_64_byte_packets: 58522065
     tx_65_to_127_byte_packets: 198585366
     tx_128_to_255_byte_packets: 77001638
     tx_256_to_511_byte_packets: 13877856
     tx_512_to_1023_byte_packets: 9683927
     tx_1024_to_1522_byte_packets: 1540623438
     tx_1523_to_9022_byte_packets: 0
     rx_xon_frames: 460
     rx_xoff_frames: 460
     tx_xon_frames: 0
     tx_xoff_frames: 0
     rx_mac_ctrl_frames: 0
     rx_filtered_packets: 922
     rx_ftq_discards: 0
     rx_discards: 0
     rx_fw_discards: 0

ethtool eth3
Settings for eth3:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Advertised auto-negotiation: Yes
        Speed: 100Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: d
        Wake-on: d
        Current message level: 0x00000001 (1)
        Link detected: yes

Скорость важна как и duplex режим. Если хотим вырубить avtonegotiation и форсировать режим для сетевухи

mii-tool -F 100baseTx-HD

Прописав

ethtool -s eth0 speed 100 duplex full
в /etc/rc.d/rc.local добьемся того же самого

[root@123 ~]# mii-tool
eth0: negotiated 100baseTx-FD flow-control, link ok
SIOCGMIIREG on eth1 failed: Input/output error
eth1: negotiated 100baseTx-FD, link ok
SIOCGMIIREG on eth2 failed: Input/output error
eth2: negotiated 100baseTx-FD flow-control, link ok

flow-control важен поскольку если его нет то скорость на интерфейсе может быть не ахти

Тестирование (при удаленном доступе лучше не делать)

ethtool -t ethX [offline|online]

offline - вырубает карточку из сетевого обмена

для дебиана тогда прописываем в постапе

sleep 3
ethtool -s eth1 speed 100 duplex full advertise 0x008
ethtool -A eth1 autoneg off rx on tx on


Webalizer + geoip

1. Установка Webalizer со статистикой по странам
Хочется статистику по странам - заодно и установим Webalizer ->
apt-get install webalizer
ln -s /var/www/webalizer /home/sites/plusminus1.com/www/webal
обновляем GeoIP для корректного отображения стран:
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
копируем ее в папку /usr/share/GeoIP
раскомментируем в /etc/webalizer 2 строки, связанные с GeoIP
если нужно, настраиваем формат лог apache - "combined" дает например детальную статистику, но плодит километров логов.
Потом пишем скрипт (например webstat):
====
webalizer /home/sites/plusminus1.com/logs/custom_log
======
запускаем наш webstat
по адресу http://plusminus1.com/webal видим нашу статистику
2. Использование GeoIP в Apache
apt-get install libapache2-mod-geoip
/etc/init.d/apache2 restart
скриптик для проверки:
=====

$ip= getenv("REMOTE_ADDR");
$country_code = apache_note("GEOIP_COUNTRY_CODE");
$region = apache_note("GEOIP_REGION");
$country_name = apache_note("GEOIP_COUNTRY_NAME");
$city = apache_note("GEOIP_CITY");
echo "Откуда припёрся: " . $ip . "\n";
echo "Код страны: " . $country_code . "\n";
echo "Регион: " . $region . "\n";
echo "Имя страны: " . $country_name . "\n";
echo "Город: " . $city . "\n";
?>

======
Откуда припёрся: 86.57.220.209
Код страны: BY
Регион:
Имя страны: Belarus
Город:
$region и $city не показывает - для этого нужны другие базы (кроме умолчательной /usr/share/GeoIP/GeoIP.dat)
скачаем базу GeoLiteCity:
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
и разархивируем ее в /usr/share/GeoIP.
настройки для apache2 находятся в файле /etc/apache2/mods-available/geoip.conf
напишем там:
GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat
GeoIPDBFile /usr/local/share/GeoIP/GeoLiteCity.dat
после перезагрузки apache2 видим, что город определился, но он - Новолукомль, а не Витебск (база бесплатная, поэтому такие накладочки)
Откуда припёрся: 86.57.220.209
Код страны: BY
Регион: 07 Имя страны: Belarus
Город: Novolukoml
3. PHP и GeoIP
А если уже есть 10000 IP в моей базе юзеров и нужно узнать, откуда они ходили. Для PHP есть extension с аналогичным названием. Для debian-lenny можно установить пакет php5-geoip. Для более ранних версий - компилировать. Но повторимся - используя lite-базу - будем иметь погрешность в определении города.
Можно попользоваться плагином с geoplugin.net - но там вроде-бы есть ограничения на количество запросов - в общем, как тулзину для своих целей, если php-скрипт нужно запускать изредка, то можно, но нет гарантии что будет доступно/ не сделают платным.

источник: http://www.cooldrinking.com/index.php?option=com_content&view=article&id=18:webalizer&catid=5:linux-&Itemid=10