Белый Тигр
Новичок
Так как раздела специально для статей на форуме не нашёл, то публикую тут
Мне главное чтоб было обсуждение, советы и обоснованная критика. Автор я, так что за отсутствие копирайтов можно не ругать.
Доброго времени суток. Я занимаюсь аудитом защищённости веб-приложений. По простому — тестами на проникновение в отношении веб-сайтов. Иногда в моей практике встречаются интересные и познавательные случаи, которые я бы хотел описывать в виде таких вот статей, но редко (для меня это первый случай) бывают ситуации когда клиент разрешает публикацию подобного материала с подробным описанием всех имевшихся проблем и предпринятых действий. Естественно, тут вы не встретите никаких конкретных имён, названия фирмы-заказчика и т. д. Упоминания таких данных мне, наверное, никто никогда не разрешит. Надеюсь что для вас, уважаемые читатели, данная статья окажется интересной и полезной.
Предисловие
Изначальная ситуация была следующая. Жила и развивалась одна браузерная игра со сравнительно высоким он-лайном. Проект монетизировался за счёт покупок игроками виртуальных вещей за реальные деньги. В один прекрасный день среди игроков появился взломщик, который найдя несколько уязвимостей в движке игры стал нарушать игровой баланс различными способами. Он увеличивал количество денег, как у себя, так и у других игроков, повышал всем желающим игровой опыт, генерировал редкие игровые предметы. Естественно платежи от пользователей почти сразу сошли на нет. Зачем платить за что-то если это что-то бесплатно раздают? Разработчики пробовали бороться с этим, даже нанимали человека, который за 200$ брался устранить «все уязвимости» в коде, но результата не было. Их терпение окончательно лопнуло когда злоумышленник слил дамп БД + все исходные коды игры и разместил их на одном публичном форуме, с предложением использовать игру кто где хочет совершенно свободно. И если раньше, в процессе борьбы с хакером, игра хоть как-то развивалась, то теперь делать это было просто нельзя — любые доработки или новые модули сразу же могли утечь в сеть.
Первичный осмотр
Игра базировалась на VPS под управлением Debian с администрированием силами хостера. От последнего, кроме самого сервера, давалась ещё панель управления и PhpMyAdmin.
Конфигурация внутреннего ПО очень располагала ко взлому. Настройка PHP позволяла и открывать и подключать внешние файлы (allow_url_fopen/include), хотя для работы игры ни того, ни другого не требовалось. Безопасный режим (safe_mode) был выключен, опция open_basedir не установлена. Функции типа system(), exec(), и других, обеспечивающих выполнение системных команд, запрещены с помощью disable_functions не были. Вывод ошибок был включен, а об их логировании не шло и речи.
Что касается веб-сервера (Apache), то под его управлением крутилось несколько поддоменов имеющих отношение к игре — форум, тестовая площадка и прочее. Работа веб-сервера с PHP велась в режиме FastCGI, но главный козырь в плане безопасности — запуск скриптов с правами их владельцев — был сведён на нет простым фактором — владельцем содержимого всех поддоменов был один и тот же пользователь. На этом моменте стало ясно что уязвимости не обязательно должны быть в движке самой игры, они могут находиться и на периферийных доменах.
В MySQL ситуация была аналогичная. Для каждого из поддоменов имелась своя БД, а работа из скриптов с ними шла через одного и того же пользователя.
Доступ к серверу из вне осуществлялся с помощью SSH и FTP. И если в адрес первого ничего плохого сказать не могу, то с FTP ситуация была совершенно иная. Попав на FTP, пользователь сразу получал доступ к содержимому всех поддоменов. Кроме того, здесь же, в корне FTP, лежала папка с бэкапами базы данных. В них было всё вплоть до паролей пользователей. Тут же находились и архивы с логами FTP. Апогеем всего этого, как наверное уже многие догадались, являлось то, что логин и пароль были одни и те же на SSH, FTP и MySQL.
После более тесного ознакомления всплыл ещё один не хороший момент. Движок игры разрабатывался без использования системы контроля версий. Всё правилось «по живому», а если нужно было создать резервную копию файла, её прямо на FTP называли чем-то типа script_name111111111.php, после чего загружали свежий script_name.php. Работа над движком велась уже достаточно долгое время, и таких «откатных» файлов были десятки. Своим присутствием они сильно осложняли поиск веб-шеллов и прочих бэкдоров, которые мог загрузить нападающий. А анализ исходного кода, на предмет наличия в нём уязвимостей, становился просто не возможен. Вообщем, нужно было срочно исправлять ситуацию.
Попытка номер раз
Нужно упомянуть об одной форе, если так можно выразиться, которая работала на нас. К тому времени как разработчики обратились ко мне, развитие игры практически встало, количество игроков упало и взломщику самому наскучило в ней сидеть. Он заходил раз в день, примерно час занимался всякими переписками и уходил. Активно себя вести он начинал только когда начинали действовать разработчики — вводили какие-то дополнения, блокировали его аккаунт и т. д. То есть можно было с уверенностью говорить о том, что пока мы не начнём вносить заметные, для него, изменения в ПО сервера и игры, взломщик сам шевелиться не начнёт.
Исходя из этого нужно было действовать так, чтоб злоумышленник после осознания изменений касающихся защиты, никак на них повлиять уже не смог. Поэтому в первую очередь мы занялись максимальным уменьшением площади его влияния.
Сперва было решено ограничить доступ из вне на все жизненно-важные сервисы (панель управления VPS, PMA, SSH, FTP, MySQL) по IP-адресам. Далее в системе были созданы пользователи для каждого поддомена, и всё их содержимое было перемещено в соответствующие домашние директории. Аналогичным образом поступили с базой данных. Теперь злоумышленник не мог имея контроль над одним сайтом, как-то воздействовать на другие.
Чуть не забыл. Права 777 мы сняли со всех директорий, которые их имели. Сайты полностью стали отделены друг от друга.
Затем поправили конфигурацию PHP. Функции запуска команд ОС, а также возможность подключения и чтения файлов по URL стали запрещены. Вывод ошибок отключили, попутно включив их запись в файл (error_log). К сожалению, по причинам связанным с особенностями работы движка, сразу не получилось включить безопасный режим (safe_mode), или хотя бы установить open_basedir. Поэтому далее пришлось работать без их помощи.
Как ни странно, все наши действия ни коим образом не привлекли внимания злоумышленника.
Видимо ему в конец наскучило лазанье по серверу и кроме самой игры он никуда не заходил. Это давало ещё некоторое количество времени. Как раз к этому моменту разработчики удалили все резервные скрипты и можно было приступать к анализу используемых веб-приложений.
Сразу была обнаружена одна очень популярная проблема — к содержимому директорий с библиотеками, конфигурационными файлами и пр. доступ из вне был открыт. Конечно, критичной брешью это не является (те же конфигурационные файлы представляли из себя php-скрипты и прямое обращение к ним ничего не давало), но если их содержимое доступно из вне, они представляют собой хорошее место для хранения вредоносного кода. Когда в такие папки доступ закрывают, количество мест для поиска «подарков» от злоумышленника резко снижается. В случае с движком игры, возможность обращения из вне мы оставили в одну директорию со скриптами и в несколько с JS-файлами, стилями и изображениями. В последних просто запретили выполнение скриптов. Таким образом осталась одна папка где вообще внешним пользователем могло быть вызвано выполнение PHP-кода. В принципе, злоумышленник мог внести опасные изменения в какой-нибудь внутренний скрипт, и попытаться обращаться к своему коду уже из общедоступных скриптов. Но и эту проблему мы решили, правда не сразу (об этом чуть ниже).
Сам исходный код игры оказался просто нашпигован слепыми SQL-инъекциями. За всё время нашего сотрудничества их было обнаружено несколько десятков. Нанятый для их устранения человек, о котором я уже упоминал в начале статьи, банально приписал к каждым попадающим в запрос переменным использование функции mysql_real_escape_string(). Но по каким-то причинам он не учёл того, что в этих переменных разработчиками ожидалось наличие числовых значений, поэтому в SQL-запросах места их включения кавычками обрамлены не были. Следовательно, не смотря на экранирование средствами mysql_real_escape_string() инъекции можно было использовать, главное не включать в опасные запросы спец. символы.
Что интересно, различных вредоносных скриптов ни на одном домене на тот момент обнаружено не было, хотя мы ожидали наличие как минимум одного. Позже удалось выяснить что все свои действия хакер совершал через PMA.
В качестве последнего штриха мы решили подключить к PHP логгер информации обо всех входящих запросах (запись сериализованных GET/POST/SERVER/COOKIE/SESSION-массивов) с помощью опции auto_prepend_file, и спровоцировать атакующего очередным баном. С логгером сразу же возникли проблемы. Хоть и средний онлайн к тому времени был не велик, запросов игроки совершали столько, что логгер съедал место на жёстком диске не по дням, а по часам. Как решение пробовали использовать сжатие записываемых данных gzip`ом. Помогло. С учётом свободного места на винчестере + 1Гб про запас, логгер мог работать примерно 17 часов. В связи с этим было решено писать лог для каждого часа отдельно, а в середине дня сливать все имеющиеся лог-файлы на локальный компьютер, попутно затирая их оригиналы. Так как злоумышленник после бана начал бы действовать максимум через 24 часа (он появлялся в игре каждый день), то нужно было бы выкачивать логи всего 2-3 раза. Так и получилось.
![Smile :) :)](/talk/styles/default/xenforo/smilies/smile.png)
Доброго времени суток. Я занимаюсь аудитом защищённости веб-приложений. По простому — тестами на проникновение в отношении веб-сайтов. Иногда в моей практике встречаются интересные и познавательные случаи, которые я бы хотел описывать в виде таких вот статей, но редко (для меня это первый случай) бывают ситуации когда клиент разрешает публикацию подобного материала с подробным описанием всех имевшихся проблем и предпринятых действий. Естественно, тут вы не встретите никаких конкретных имён, названия фирмы-заказчика и т. д. Упоминания таких данных мне, наверное, никто никогда не разрешит. Надеюсь что для вас, уважаемые читатели, данная статья окажется интересной и полезной.
Предисловие
Изначальная ситуация была следующая. Жила и развивалась одна браузерная игра со сравнительно высоким он-лайном. Проект монетизировался за счёт покупок игроками виртуальных вещей за реальные деньги. В один прекрасный день среди игроков появился взломщик, который найдя несколько уязвимостей в движке игры стал нарушать игровой баланс различными способами. Он увеличивал количество денег, как у себя, так и у других игроков, повышал всем желающим игровой опыт, генерировал редкие игровые предметы. Естественно платежи от пользователей почти сразу сошли на нет. Зачем платить за что-то если это что-то бесплатно раздают? Разработчики пробовали бороться с этим, даже нанимали человека, который за 200$ брался устранить «все уязвимости» в коде, но результата не было. Их терпение окончательно лопнуло когда злоумышленник слил дамп БД + все исходные коды игры и разместил их на одном публичном форуме, с предложением использовать игру кто где хочет совершенно свободно. И если раньше, в процессе борьбы с хакером, игра хоть как-то развивалась, то теперь делать это было просто нельзя — любые доработки или новые модули сразу же могли утечь в сеть.
Первичный осмотр
Игра базировалась на VPS под управлением Debian с администрированием силами хостера. От последнего, кроме самого сервера, давалась ещё панель управления и PhpMyAdmin.
Конфигурация внутреннего ПО очень располагала ко взлому. Настройка PHP позволяла и открывать и подключать внешние файлы (allow_url_fopen/include), хотя для работы игры ни того, ни другого не требовалось. Безопасный режим (safe_mode) был выключен, опция open_basedir не установлена. Функции типа system(), exec(), и других, обеспечивающих выполнение системных команд, запрещены с помощью disable_functions не были. Вывод ошибок был включен, а об их логировании не шло и речи.
Что касается веб-сервера (Apache), то под его управлением крутилось несколько поддоменов имеющих отношение к игре — форум, тестовая площадка и прочее. Работа веб-сервера с PHP велась в режиме FastCGI, но главный козырь в плане безопасности — запуск скриптов с правами их владельцев — был сведён на нет простым фактором — владельцем содержимого всех поддоменов был один и тот же пользователь. На этом моменте стало ясно что уязвимости не обязательно должны быть в движке самой игры, они могут находиться и на периферийных доменах.
В MySQL ситуация была аналогичная. Для каждого из поддоменов имелась своя БД, а работа из скриптов с ними шла через одного и того же пользователя.
Доступ к серверу из вне осуществлялся с помощью SSH и FTP. И если в адрес первого ничего плохого сказать не могу, то с FTP ситуация была совершенно иная. Попав на FTP, пользователь сразу получал доступ к содержимому всех поддоменов. Кроме того, здесь же, в корне FTP, лежала папка с бэкапами базы данных. В них было всё вплоть до паролей пользователей. Тут же находились и архивы с логами FTP. Апогеем всего этого, как наверное уже многие догадались, являлось то, что логин и пароль были одни и те же на SSH, FTP и MySQL.
После более тесного ознакомления всплыл ещё один не хороший момент. Движок игры разрабатывался без использования системы контроля версий. Всё правилось «по живому», а если нужно было создать резервную копию файла, её прямо на FTP называли чем-то типа script_name111111111.php, после чего загружали свежий script_name.php. Работа над движком велась уже достаточно долгое время, и таких «откатных» файлов были десятки. Своим присутствием они сильно осложняли поиск веб-шеллов и прочих бэкдоров, которые мог загрузить нападающий. А анализ исходного кода, на предмет наличия в нём уязвимостей, становился просто не возможен. Вообщем, нужно было срочно исправлять ситуацию.
Попытка номер раз
Нужно упомянуть об одной форе, если так можно выразиться, которая работала на нас. К тому времени как разработчики обратились ко мне, развитие игры практически встало, количество игроков упало и взломщику самому наскучило в ней сидеть. Он заходил раз в день, примерно час занимался всякими переписками и уходил. Активно себя вести он начинал только когда начинали действовать разработчики — вводили какие-то дополнения, блокировали его аккаунт и т. д. То есть можно было с уверенностью говорить о том, что пока мы не начнём вносить заметные, для него, изменения в ПО сервера и игры, взломщик сам шевелиться не начнёт.
Исходя из этого нужно было действовать так, чтоб злоумышленник после осознания изменений касающихся защиты, никак на них повлиять уже не смог. Поэтому в первую очередь мы занялись максимальным уменьшением площади его влияния.
Сперва было решено ограничить доступ из вне на все жизненно-важные сервисы (панель управления VPS, PMA, SSH, FTP, MySQL) по IP-адресам. Далее в системе были созданы пользователи для каждого поддомена, и всё их содержимое было перемещено в соответствующие домашние директории. Аналогичным образом поступили с базой данных. Теперь злоумышленник не мог имея контроль над одним сайтом, как-то воздействовать на другие.
Чуть не забыл. Права 777 мы сняли со всех директорий, которые их имели. Сайты полностью стали отделены друг от друга.
Затем поправили конфигурацию PHP. Функции запуска команд ОС, а также возможность подключения и чтения файлов по URL стали запрещены. Вывод ошибок отключили, попутно включив их запись в файл (error_log). К сожалению, по причинам связанным с особенностями работы движка, сразу не получилось включить безопасный режим (safe_mode), или хотя бы установить open_basedir. Поэтому далее пришлось работать без их помощи.
Как ни странно, все наши действия ни коим образом не привлекли внимания злоумышленника.
Видимо ему в конец наскучило лазанье по серверу и кроме самой игры он никуда не заходил. Это давало ещё некоторое количество времени. Как раз к этому моменту разработчики удалили все резервные скрипты и можно было приступать к анализу используемых веб-приложений.
Сразу была обнаружена одна очень популярная проблема — к содержимому директорий с библиотеками, конфигурационными файлами и пр. доступ из вне был открыт. Конечно, критичной брешью это не является (те же конфигурационные файлы представляли из себя php-скрипты и прямое обращение к ним ничего не давало), но если их содержимое доступно из вне, они представляют собой хорошее место для хранения вредоносного кода. Когда в такие папки доступ закрывают, количество мест для поиска «подарков» от злоумышленника резко снижается. В случае с движком игры, возможность обращения из вне мы оставили в одну директорию со скриптами и в несколько с JS-файлами, стилями и изображениями. В последних просто запретили выполнение скриптов. Таким образом осталась одна папка где вообще внешним пользователем могло быть вызвано выполнение PHP-кода. В принципе, злоумышленник мог внести опасные изменения в какой-нибудь внутренний скрипт, и попытаться обращаться к своему коду уже из общедоступных скриптов. Но и эту проблему мы решили, правда не сразу (об этом чуть ниже).
Сам исходный код игры оказался просто нашпигован слепыми SQL-инъекциями. За всё время нашего сотрудничества их было обнаружено несколько десятков. Нанятый для их устранения человек, о котором я уже упоминал в начале статьи, банально приписал к каждым попадающим в запрос переменным использование функции mysql_real_escape_string(). Но по каким-то причинам он не учёл того, что в этих переменных разработчиками ожидалось наличие числовых значений, поэтому в SQL-запросах места их включения кавычками обрамлены не были. Следовательно, не смотря на экранирование средствами mysql_real_escape_string() инъекции можно было использовать, главное не включать в опасные запросы спец. символы.
Что интересно, различных вредоносных скриптов ни на одном домене на тот момент обнаружено не было, хотя мы ожидали наличие как минимум одного. Позже удалось выяснить что все свои действия хакер совершал через PMA.
В качестве последнего штриха мы решили подключить к PHP логгер информации обо всех входящих запросах (запись сериализованных GET/POST/SERVER/COOKIE/SESSION-массивов) с помощью опции auto_prepend_file, и спровоцировать атакующего очередным баном. С логгером сразу же возникли проблемы. Хоть и средний онлайн к тому времени был не велик, запросов игроки совершали столько, что логгер съедал место на жёстком диске не по дням, а по часам. Как решение пробовали использовать сжатие записываемых данных gzip`ом. Помогло. С учётом свободного места на винчестере + 1Гб про запас, логгер мог работать примерно 17 часов. В связи с этим было решено писать лог для каждого часа отдельно, а в середине дня сливать все имеющиеся лог-файлы на локальный компьютер, попутно затирая их оригиналы. Так как злоумышленник после бана начал бы действовать максимум через 24 часа (он появлялся в игре каждый день), то нужно было бы выкачивать логи всего 2-3 раза. Так и получилось.