03.08.2024

Атака на WEB.

Vortex777

Интересующийся
Регистрация
27.06.2022
Сообщения
98
Реакции
0
Гарант продажи
0
Гарант покупки
0
Депозит
0 р
Публикацию статьи автора NSD о технологии атаки через reverse-ip(lookup-ip) можно считать началом открытого противостояния администраторов хостингов и желающих залезть на смежный сайт соседа.
(Здесь и далее многие аспекты вопросов рассмотрены с точки зрения rever-ip подхода)
Многие начинающие хостинги вообще не занимаются разделением прав доступа.
Через какое-то время( видимо после пары тысяч жалоб\дефейсов ), сисадмин прикручивает suphp ибо suexec и какое-то время все работает.
Инициатива попеременно переходит от одной стороне к другой в ритме выхода нового паблик эксплойта под PHP и выхода патча =)
Прошло довольно прилично времени, чтобы всем наконец стало ясно (кто-то еще сомневается?) - PHP дыряв как друшлаг и доверять ему НЕЛЬЗЯ.
Пусть не сегодня, но завтра выйдет новое адвизори с новым мегабагом и снова все будут ахать и патчится... в который уже раз - и уж точно не в последний.

В настоящий момент идет тенденция в упоре на разделение прав через стандартную файловую систему в купе с suexec и ftp-доступом разделения прав.
Довольно бронебойный прием, поскольку попасть в директорию, тебе не принадлежащую, может разве что только root.

Для надежности дополнительно чмодят все системные директории на -rwx--x--x .
Действительно, кому еще (и, главное, зачем?) может потребоваться листинг корневой директории, /etc, /var, /usr помимо root'a ?
Полезные бинарники вроде id,cwd,uname,find тоже порой имеют права root:wheel -r-xr-x---, так что и не выполнишь команды.

Но есть одна маленькая тонкость чмода.
Дело в том, что наличие байта выполнения --x на директории позволяет пройти в эту директорию...
Прочитать мы её не сможем, но, например, вложенные директории и файлы могут иметь уже более демократичные права доступа.

Рассмотрим пример.
Код:
id
uid=80(www) gid=80(www) groups=80(www)
ls -liaR /home
-rwx--x--x root:root /home/
-rwx--x--x user:user /home/user/
-rwxr-xr-x user:user /home/user/htdocs/
-rwxrwxrwx user:user /home/user/htdocs/tmp/
Таким образом, обратившись по абсолютному пути "/home/user/htdocs/tmp/" мы окажемся в папке, доступную на запись и видимую из веба.

Даже в случае отсутствия листинга папок нам ничто не мешает тупо подобрать вероятное имя по словарю брутфорсом, скрипт которого ищи на диске.
Перебор возможных путей через скрипт брутфорса [a-z] символами на путь длинной в 5-ть символов займет не более минуты на .php и еще меньше через .sh скрипт)
Даже в случае нечитабельных папок не составляет труда прочесть .htaccess\index.php и уже из них повытягивать логины\пароли\инклуды на конфиги и др.

Таким образом, так или иначе определив существование директории\файла, мы скорее всего получим доступ на чтение + возможный бонус листать\писать во вложенные директории и файлы.

Ну, а где же достать этот самый полный путь?
Конфиги Апача httpd.conf, vhosts.conf идеально подходят для этого.
Однако, они практически всегда защищены от любопытных глаз уже правильным чмодом.
Но, несмотря на это, извечный "/etc/passwd" всегда расскажет нам о домашнем каталоге юзеров.
А уж наличие соотвествующих папок можно определить исходя из аналогии имеющегося домашнего каталога, либо незатейлевым брутфорсом.
И даже если включен safe_mode и\или open_basedir, мешающий получить passwd и никто не делится с тобой приватными эксплоитами для обхода этого фашистского изобретения, виновного в геноциде хаксоров, -- даже тут можно вывернуться через фичу в posix_getpwuid(): http://packetstormsecurity.org/0712-exploits/php525-bypass.txt

Защита проста как два байта -- достаточно лишь одной директории в пути быть чмоднутой на "-rwx--x---" или даже "-rwx------" и хэккеры пойдут лесом.
..Хотя вспоминая прошлый номер ][ с описанием багов файловых систем от Криса Касперски, я начинаю задумываться, а что если... =) Но это уже совсем другая история.

PS: уже после написания подтемы chmod, вынашиваемой и проверяемой мной в течении многих месяцев, и руководствуясь исключительно лишь своим насыщенным опытом, было решено, в давно заведенном порядке, посерфить секурити-блоги, в надежде разжиться мало-мальски свежей инфой и новыми идеями.
Как выяснилось, не одну мою голову(ака пытливый моск) затронула вышеописанная бага.
( и это нормально, в истории одинаковые идеи часто посещают двух людей сразу -- чего только стоят открытые законы в физике, математике и др. науках, названные двойными фамилиями соавторов, порой живших в разных точках земного шара и понятия на имевших друг о друге... эк меня понесло =) )
c0nst#secureblog.org в своем блоге также разобрал тему кривого чмода и разработал свой (надо сказать, весьма неплохой) скрипт пентестинга на бажность.
Также в статье немало внимания уделено борьбе с проблемой средствами PHP ака "safe_mode" + "open_basedir" + "disable_functions" , однако, повторяюсь, что имхо это не секурно.
Просто правильно чмодьте.
[ Коммунальный /tmp ]

И только одно остается по прежнему незыблемым - /tmp .
<!-- Темп, сцуко, опасный! =) -->

Казалось бы, что такого примечательного в общей временной папке?
То, что она - ОБЩАЯ. Это самое главное.

Как правило каждому виртуалхосту прописывают индивидуальные настройки вроде сэйфмода, опенбаздира.
Но временную папку ставят одну на всех вместо создания индивидуальной в домашней директории клиента.
(напоминаю, в php.ini это параметр "session.save_path")
Почему? Темп - это по факту мусорка.
Проходит пара месяцев и в одно недоброе утро администратору приходит пара десятков жалоб на многочисленные ошибки с варнигами.
Темп оказывается переполненным, ведь созданные сессии удаляются только при вызове session_destroy(), которой часто брезгуют\забывают\не жмут на Exit\недогружают страницу.
Тем более если сервер имеел долгий аптайм (в некоторых никсовых дистрибутивах встроена очистка темпа при ребуте по дефолту).
Не долго думая, в cron.month админом ставится новая задача, призванная периодически чистить "/tmp" .
Разумеется написать sh-скрипт очистки одной статичной папки проще, чем N юзверских папок.
(хотя можно возложить почетную задачу уборки на юзера, особенно если квоты дискового пространства уже прикручены)

Вобщем, так или иначе, но индивидуальный "session.save_path" необходим для секурности.

Как впрочем и... "upload_tmp_dir" !
Ведь сбои происходят довольно часто при загрузке файлов, ибо аплоад файла - это прежде всего POST-пакет нехилых размеров.
А по моему опыту далеко не каждый провайдер\прокси-сервер\VPN корректно его переваривает особенно в часы пик.
Да и PHP не всегда удаляет недогруженные куски, подвисая баластом в ожидании оконечной части.
Это дает вероятный бонус найти в темпе что-либо либо интересное, например, кусок недогруженного конфига или дампа БД, логи, а иногда какие-либо творческие эксперименты(или экскременты?) администрации\юзеров в процессе программирования с наличием чувствительных данных.

Более того, ЛЮБОЙ php-скрипт при "file_uploads=ON" автоматически принимает файл в POST-пакете.
Это позволяет загрузить на целевой сервер большое кол-во файлов(тем более используя ботнет).
~ колличество загружаемых файлов за раз неограничено!
~ [upload_max_filesize] лимитируется для 1го файла.
~ В PHP 5.1.x [upload_max_filesize] вообще игнорирует [post_max_size].
Значит в PHP 5.1.x можно загрузить за раз неограниченное кол-во файлов! А в свежем PHP - не более [post_max_size].
Что повлечет за собой исчерпание свободного дискового пространства в папке временных файлов.
~ загруженные файлы не удаляются до тех пор, пока php-скрипт не закончит исполняться
~ сервер продолжает поддерживать соединение и не начинает выполнение php-скрипта до тех пор, пока не будет принят весь HTTP-POST-пакет.
Атакующий может намеренно исказить величину HTTP-POST-пакета и удерживать соединение,
а следовательно загруженные файлы будут присутствовать на диске до тех пор, пока не истечет таймаут соединения на стороне сервера.

Схема атаки:
1) Атакующий посылает специально сформированный POST-запрос ("multipart/form-data") , содержащий файл(ы), к любому php-скрипту на сервере
- размер 1-го отсылаемого файла должен быть не больше максимально установленного значения директивы PHP [upload_max_filesize] (Default=32Мб) и не более [post_max_size] (Default=16Мб) по минимальному значению любого из параметров.
- Размер пакета (Http-хидер) "Content-Length" указывается заведомо больше истинного(как минимум на 5 байт).
2) Сервер принимает POST-пакет с файлом
- в незаконченной передаче держим коннект и заставляем сервер слушать соединение максимально возможное время
- все это время загруженный файл будет занимать место на диске сервера, реализуя атаку на исчерпание дискового пространства

Варианты защиты от атаки:
~ запретить [file_uploads]
~ ограничить время установленного соединения клиент-сервер в фаерволе или веб-демоне(apache)
~ http://sysoev.ru/web/upload.html
Данная фича может быть использована для усиления ддоса, хотя несомненным минусом является весьма приличный трафик на каждый загружаемый файл.

Что интересно - в ряде случаев мне встречаются системы, где загружаемые временные файлы имеют не псевдослучайное имя, а именуются строго последовательно.
От версии PHP это не зависит(испытывал на разных). И от чего зависит - мне пока не известно.
Проверить конкретный сервер на предмет предсказуемых имен временных файлов легко - достаточно найти вывод phpinfo().
На это скрипт посылаем пакет с файлом и смотрим в ответе значение [tmp_name]. Посылаем еще раз и сравниваем.
Если имя вполне последовательно прибавило пару чисел - это баг.
Используя вышеописанный алгоритм задержки загруженных файлов на сервере, можно загрузить вебшелл.
И теперь, если где-то на сервере имеется php-include...
;)


Однако, помимо описанного, на мой взгляд, самым интересным здесь является (о, да!) угон чужой сессии(session hijacking), об этом читай чуть ниже.
 

Vortex777

Интересующийся
Регистрация
27.06.2022
Сообщения
98
Реакции
0
Гарант продажи
0
Гарант покупки
0
Депозит
0 р
[ Коварные сессии ]

Немалая часть веб-приложений юзает сессии PHP для разграничения прав доступа между юзерами.
(Важно: здесь и далее рассматриваются уязвимости PHP сессий; определить, что php-скрипт юзает php-сессии можно по вызову session_start() и др. )

Напомню забывчивым, что вызов <?php;session_start();?> создает файл сессии с id из случайных alpha-numeric,
например, /tmp/sess_50d7ed4b37f95f991679fdd92ba894e2
( случайных или определенных в скрипте посредством вызова в скрипте session_id('<alpha-numeric>') перед session_start() )
после чего это имя дублируется в браузер пользователю как значение кукис с дефолтным именем "PHPSESSID"
( можно изменить глобально из php.ini или локально в скрипте, вызвав session_name('<MY_SESSID>') перед session_start() )
Set-Cookie: PHPSESSID=50d7ed4b37f95f991679fdd92ba894e2;

Как минимум, атака на сессии является одним из эффективнейших тестов на раскрытие полного пути в десятке лидеров,
таких как поиск и обращение к левым скриптам, передача массива вместо строки в переменной, ддос на БД, переполнение мусором логфайла и др.
Например, достаточно передать в гете или куках "PHPSESSID=123!@#$%^" и получим еррор уровня варнига, если error_reporting(E_WARNING) :
Код:
Warning: session_start() [function.session-start]: The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in...
Либо передадим "PHPSESSID" длинной более 256 символов. Файл с таким именем не может быть создан, и ответом сервака будет:
Код:
Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct
Сам факт создания файла лишь на основании PHPSESSID в гете или куках, с именем аналогичным id, наводит на мысль о... ддосе.
Точнее сказать - на эффекте его усиления.
Ресурсы системы, затраченные на создание файла сессии, ничтожны. А сам файл сессии зачастую и вовсе пуст.
( это зависит от того, были ли внесены значения в $_SESSION в процессе выполнения скрипта )
Но генерируя мусорный трафик с рэндомным PHPSESSID можно создать кол-во файлов сессий равное числу http-пакетов при ддосе, тоесть уххх как дофига.
А MFT никто не отменял. Совсем недавно Крис писал, что даже совершенно пустой файл занимает 1 кластер.

Да что там раскрытие пути... К сведению, к PHP написаны более 10-ти эксплоитов, с атакой BoF на функции сессий, а это уже кое о чем да говорит.
И те, кто с презреньем утверждает, что BoF для PHP -- полная лажа -- лишь оправдавают свое незнание.
Между прочим - это порой единственный шанс из клетки опен_баздира с сэйф-модом, когда exec-эксплоиты кончились, а выполнения сис. команд так и нет.

Ну а теперь подробно рассмотрим перехват сессий.
Примечательной особенностью пользовательской сессии является уникальность её id.
Знание которого, как ни странно, является достаточным для успешного прохождения авторизации юзверя.
Хранятся сессии либо в базе данных приложения(и это правильно ибо максимально безопасно), либо в созданных средствами PHP файлах в папке.. "/tmp" .
Ну а поскольку "/tmp" как мы уже выяснили часто доступен всем желающим на листинг\чтение\запись, то нетрудно догадаться о выводах.
Здесь в зависимости от условий возможные различные варианты атаки.

Фактически можно обойтись только листингом темпа, ведь как правило достаточно знать лишь id сессии.
Подменив id своей сессии на id чужой сессии в кукисе, мы успешно авторизуемся под другим юзверем.
Зачастую, если возможен лишь листинг темпа, то сессии каждого сайта имеют uid\guid , принадлежащий конкретному сайту.
Это очень удобно, ибо вместо перебора всех сессий из "/tmp" легко отделить нужные.
Защитой может служить хранимый в сессии IP-address и\или User-Agent пользователя, срок действия, и соответствующая их проверка при авторизации.

Если же можно читать файлы чужих сессий, тогда мы уже будем иметь хотя бы представление о её структуре и содержании.
Это важно, если используется какой-либо самописный\неизвестный движок, структура сессий которого не известна заранее, или если стоит секурити проверка на ip, browser, срок действия.
Тогда, пусть мы и не сможем использовать существующие сессии, но исходя из примеров читабельных сессий, становится возможным сгенерировать свою собственную!
Закинуть её в темп, чмоднуть на 0777, чтобы другой пользователь имел доступ к ней(правда, с safemode=on это не прокатит), после чего использовать.
Защитой здесь может служить хранение данных не в открытом виде, а в зашифрованном.
Либо обратимым алгоритмом(AES,blufish,twufish) с ключом, хранящимся в конфиге или БД, либо необратимым алгоритмом(md5,sha1) с рэндомной солью, хранящийся опять же в конфиге,БД или другом недосягаемом месте.
Тогда, даже если хакеру будет известен механизм генерации хеша - он не сможет сгенерировать собственную подложную сессию.

Самый редкий, но благоприятный случай, если Апач работает на правах www-data\nobody для всех.
А значит все файлы(в том числе и сессионные) создаются с одинаковыми правами и доступны всем не только на чтение, но и на запись.
Права на запись хороши тем, что становится возможным обойти простую(не зашифрованную) привязку к пользователю, изменив в существующей сессии параметры под себя.
Алгоритмы защиты аналогичны предыдущему пункту.

Проблем взломщику заметно прибавит вызов session_regenerate_id(), меняющий session_id() при каждом вызове.
<!--хотя больше ему проблем прибавит вызов братков на хату =))-->

Говоря о сессиях следует упомянуть еще об одном баге PHP от Stefan Esser
http://www.php-security.org/MOPB/PMOPB-46-2007.html - "EXT/Session HTTP Response Header Injection Vulnerability PHP4<=4.4.7,PHP5<=5.2.3"
Однако, так и быть, я сэкономлю несколько часов твоего времени, в ином случае будучи гарантировано тобой убитыми(ибо время для хэккеров бесценно, ты не забыл наш манифест?).
Если мы обратимся к сайту так: "/session.php?PHPSESSID=123" -- мы просто заюзаем сессию sess_123, если она есть или создадим её, если её нет.
Но так будет ТОЛЬКО В ТОМ СЛУЧАЕ, если в браузере еще нет куки "PHPSESSID", поскольку она имеет более высокий приоритет в сравнении с гетом.
Дело обстоит совсем по другому при обращении к линку вида "/session.php/PHPSESSID=123456;INJECTED=ATTRIBUTE;/"
В ответ браузеру отправится пакет с хидером "Set-cookie: PHPSESSID=123456;INJECTED=ATTRIBUTE;;path=/"
Для успешной эксплуатации уязвимости необходим error_reporting(0) !
PoC урл немного вводит в заблуждение словом "INJECTED" - сразу чудится CSRF и прочее.
К сожалению внедрить какой-либо символ в urlencode вроде %0D,%0A нельзя - urlencode просто не обрабытывается.
Тоесть ни "Location" , ни дополнительный "Set-cookie" добавить не выйдет, а только expired, domain и path для текущей куки.
Если заблаговременно создать свой файл сессии, чмоднуть его на 0777, заманить админа по линку и тем фактически вынудить его браузер юзать сессию с нашим id!
Тогда мы получим его файл сессии с правами на запись.

Также стоит затронуть тему перехвата cессии через REFERER.
С одной стороны звучит даже как-то неправдоподобно, но это лишь кажется.
Во первых главное условие - атака становится возможной, если приложение так или иначе добавляет сессию пользователя в GET(урл).
Причем это может быть отнюдь не глюком, а документированной поддержкой. Зачем это нужно?
Подобный механизм авторизации через GET активируется в двигах в случаях:
- отключенных куков в браузере ( аля так безопаснее
;)
)
- отключенной явой( тотже [NoScript] )
И в итоге вместо повышения безопасности - вы получаете бонусную течь.
Так какже это использовать?? Да оч просто. Второе главное условие - поддержка чатом\форумом\блогом\коментами тэга
Код:
<img>\[img], <a>\[url]
Ну или поддержка удаленного аватара. Краааайне редко разрешают закачивать файлы, а на удаленные -- ссылайся пожалуйста!
Вот тут и дырка - мы можем сослаться на изображение на своем сервере и снифать поступающие рефереры его просмотра через access_log или через php подобно капча-скриптам.
В реферере помимо урл предыдущей страницы будет содержаться сессия юзера.

Ярким примером служат ПРАКТИЧЕСКИ ВСЕ WAP порталы. 0-day
;)

Даже в профайле часто бывает личная ссылка для входа без пароля, видели?
Я не специалист по такому софту, но (видимо) некоторые сотики\PDA\КПК не держат cookie, и это компенсируется передачей сессии в гете.
 
Сверху