HOME    FORUMS    MEMBERS    RECENT POSTS    LOG IN  
Баннер 1   Баннер 2

ANTICHAT — форум по информационной безопасности, OSINT и технологиям

ANTICHAT — русскоязычное сообщество по безопасности, OSINT и программированию. Форум ранее работал на доменах antichat.ru, antichat.com и antichat.club, и теперь снова доступен на новом адресе — forum.antichat.xyz.
Форум восстановлен и продолжает развитие: доступны архивные темы, добавляются новые обсуждения и материалы.
⚠️ Старые аккаунты восстановить невозможно — необходимо зарегистрироваться заново.
Вернуться   Форум АНТИЧАТ > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Песочница
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 22.06.2017, 20:35
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

Всем доброго дня!

В течении последнего полугода играю в одну не очень известную онлайн-игрушку на планшете. Попутно пытаюсь ее ломать то с одного боку, то с другого. Но каких-то успехов достиг только на пакетном уровне. К сожалению большинство переменных там защищены. Взлом в стиле ололо-репитов не канает. Дыры есть, но мало, особо не разгуляешся. А хочется гораздо большего. Поэтому пришел к вам, за советами.

Итак, что уже достигнуто:

1. Обошел SSL-шифрование. Могу слушать трафик между игрой и клиентом.

2. Расковырял игровой клиент, выдрал оттуда алгоритм подписи пакетов. На его основе сделал тулзу чтоб подписывать свои собственные пакеты. Могу вклиниваться в процесс и менять значения переменных на лету. Либо самостоятельно формировать и отправлять на сервер любые пакеты. Сервер их принимает и обрабатывает.

3. Нашел несколько незащищенных переменных, подмена которых дает некоторое игровое преимущество. К сожалению возможности у этих дыр ограничены.

4. Собрал кое-какую информацию об игре. Сервер работает на CentOS, имеет Apache версии 2.2.15, клиент написан на С#. Запросы от клиента обрабатываются на сервере PHP скриптами. Думаю есть БД, но какая - не знаю.

5. Пытался проверить сервер на уязвимость Shellshock (Bashdoor). По моим скромным выводам результат отрицательный.

Какие цели есть на данный момент.

Найти любую уязвимость, которая откроет передо мной более широкие возможности.

Хорошо бы по крайней мере один их пунктов:

1. Найти новые полезные дыры на пакетном уровне. Хотя за полгода я наверное уже все щели обнюхал.

2. Получить частичный или полный доступ к БД. Как минимум читать произвольные таблицы. Как максимум - редактировать их.

3. Получить доступ к исходникам серверной части игры. Как минимум заглянуть во внутренности скриптов. Как максимум - внести в них свои поправки.

4. Было бы хорошо залить шелл. Еще лучше - сделать это не привлекая внимания админов.

5. Получить доступ к админке (CP), FTP или SSH (мечты, мечты...)

6. Получить доступ еще к чему-нибудь полезному, может я о чем-то даже не подозреваю, а вы подскажете. Но оговорюсь что чужие аккаунты меня не интересуют. И гробить сервер или мешать его работе я тоже не собираюсь. Скорее наоборот, предпочитаю быть тише воды ниже травы.

Какие ресурсы и опыт имеются:

1. Понимание самых базовых принципов работы приложений и серверов. На уровне начинающего.

2. Небольшой опыт программирования. Программирую методом топора, подпирая программы костылями со всех сторон.

3. Любительский опыт взлома. На 70% почерпнутый из разнообразных статей в сети, на 30% состоящий из личных шишек, пота и крови. На самом деле опыт не очень большой. Умею делать часть из того, чему учат в мануалах "для чайников" которыми пестрит рунет.

4. Терпение, время. Готовность курить мануалы с уровнем утомительности не превышающим мои психические возможности. "Войну и мир" о принципах работы с ассемблерным кодом читать не готов.

Какие будут идеи?
 
Ответить с цитированием

  #2  
Старый 25.06.2017, 00:20
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

Тема провисела на форуме 2 суток, набрала 500 просмотров и 0 ответов. Куда подевались все гуру-хакеры?

Ладно, попробую задать более конкретный вопрос.

Что имеем:

Последние несколько дней я пытаюсь сделать игре SQL-инъекцию.

Как я уже говорил, клиент обменивается с сервером HTTPS запросами.

На сервер отправляются обыкновенные POST-запросы вида https://www.game.ru/public/api/scrip...ta1&var2=data2...

В ответ приходит целая гора данных в формате JSON, основываясь на которых, клиент выдает картинку игровых действий (передвижение, битвы, игровой инвентарь ит.д.)

Разумеется никаких html-страниц и форм нет и в помине. Но поскольку я могу слушать трафик напрямую, то и вмешиваться в него могу тоже напрямую. Следовательно - изменять переменные отправляемые на сервер так, как если бы я это делал в строке запроса GET.

Я могу придать переменной любое значение, однако часть символов экранируется.

А именно символы / (слэш), \ (обратный слэш) и "(двойная кавычка).

Все остальные символы поступают на сервер без экранирования. По крайней мере символы ['],[`],[*],[:],[;],[&],[%],[$],[@],[?],[(],[)],[{],[}],[,],[.],[!],[-],[|],[=],[^],[#] можно передать в исходном виде.

Однако SQL-инъекцию затрудняет то, что часть переменных защищена проверками на валидность, а другая часть, по видимому, в SQL-запросах не участвует. Но я таки отыскал одну переменную, через которую инъекция возможна. Как не удивительно, но это переменная uid (id игрока).

Что работает:

Предположим мы работаем с исходной переменной uid=99


Если привести ее к виду uid=99' получим ошибку 500 (Internal Server Error), т.е. ошибочный SQL-запрос который сервер выполнять откажется.

Значение uid=99/* передать к сожалению нельзя из-за экранирования слэша.

Значение uid=99-- будет обработано.

Так же будет обработано: uid=99--+любой текст

Будет обработано: uid=99+and+null--

Будет обработано: 99+and+null

Будет обработано: 99+and+concat('1','2')

Будет обработано: 99+and+version()

Будет обработано: 99+and+@@version

Приведет к небольшому зависанию и ошибке 504 Gateway Time-out: uid=99+or+1--

Ну еще бы, аккаунтов в игре зарегистрировано более 13 млн.

Вот такая переменная затянет выполнение запроса на ~2300мс: uid=99+and+BENCHMARK(10000000,md5(current_date))

Обычно запрос выполняется за 5-15мс.

Скорее всего есть возможность провести DOS атаку, но меня это не интересует.

Что не работает (подводные камни):

Проблема 1.


Первая проблема состоит в том, что значение переменной uid используется не только в запросе к БД, но и каким-то образом связано с проверкой валидности игровой сессии. Всего в проверке сессии их учавствует три - uid (номер игрока), serverid (номер сервера) и sessionToken (ключ сессии).

uid - всегда неизменный для отдельного игрока

serverid - неизменен до тех пор пока мы играем на одном и том же сервере

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

Если поменять хотя бы один символ в любой из этих переменных, получим обрабатываемую игровым движком ошибку "Ключ сессии неверный!". При этом, несмотря на то, что запрос к БД будет выполнен, обычный набор данных в JSON-формате PHP-скрипт нам не отправит. А если он их не отправит, то и результаты SQL-запроса вставлены никуда не будут...

То есть не представляется возможным получить какую-либо пользу даже от успешного внедрения в запрос конструкции UNION SELECT...

Как решить данную проблему я не понимаю и очень рассчитываю на вашу помощь.

Проблема 2.

Собственно, мне не удается узнать число столбцов между SELECT и FROM.

Я пытался это сделать вот так:

uid=99+union+select+null

uid=99+union+select+null,null

uid=99+union+select+null,null,null

...

и т.д.


К сожалению сервер все время возвращает ошибку 500. То есть запрос не выполняется. Предположим это может быть просто результатом неверного числа добавленный мной null. Я утомился после 30-го по счету. Конечно, их может быть 100 или 300. Ну да черт с ним. В случае чего я пару часов своего времени на перебор убить могу. Но что если сервер отказывается принимать саму конструкцию select+null? Или оператор union? Или еще что-нибудь в синтаксисе моего запроса?

У меня есть основания полагать что это так, поскольку переменная uid=99; (добавлена точка с запятой) сервером обрабатывается. В то время как uid=99;+select+null приводит к ошибке 500, хотя после точки с запятой количество нуль-значений в запросе никак не должно влиять на его валидность. Ведь мы не объединяем результат с предыдущим, а делаем новый независимый запрос.

Почему конструкция uid=99;+select+null не работает?

Я не знаю какая именно СУБД там находится. Но поскольку сервер на CentOS думаю я не ошибусь если предположу что это MySQL, причем с версией никак не ниже 4.* Мне точно известно что Apache имеет версию 2.2.15, а PHP версию 5.4.11. По-моему крайне маловероятно, что вместе с ними стали устанавливать бы такую древность как MySQL 3.* А современные версии MySQL поддерживают, как UNION, так и расщепление запросов оператором ; (точка с запятой).

Следовательно, существует какая-то другая причина, по которой uid=99;+select+null не работает. Но какая?

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

Требуется ваша помощь.
 
Ответить с цитированием

  #3  
Старый 25.06.2017, 00:52
crlf
Guest
Сообщений: n/a
Провел на форуме:
169212

Репутация: 441
По умолчанию

Возможно слепая инъекция. Пробуй так:

Код:
Code:
uid=99 and 1=1 -- true
uid=99 and 1=2 -- false
Так же, полистай эту тему https://rdot.org/forum/showthread.php?t=60
 
Ответить с цитированием

  #4  
Старый 25.06.2017, 01:12
artkar
Guest
Сообщений: n/a
Провел на форуме:
131082

Репутация: 6
По умолчанию

Не понял как ты хочеш узнать число стлобцов:

Цитата:
Сообщение от KAPTOHHbIu  
KAPTOHHbIu said:

Собственно, мне не удается узнать число столбцов между SELECT и FROM.
Я пытался это сделать вот так:
uid=99+union+select+null
Если:

Цитата:
Сообщение от KAPTOHHbIu  
KAPTOHHbIu said:

Если поменять хотя бы один символ в любой из этих переменных, получим обрабатываемую игровым движком ошибку
"Ключ сессии неверный!"
. При этом, несмотря на то, что запрос к БД будет выполнен, обычный набор данных в JSON-формате PHP-скрипт нам не отправит. А если он их не отправит, то и результаты SQL-запроса вставлены никуда не будут...
Цитата:
Сообщение от KAPTOHHbIu  
KAPTOHHbIu said:

У меня есть основания полагать что это так, поскольку переменная
uid=99;
(добавлена точка с запятой) сервером обрабатывается. В то время как
uid=99;+select+null
приводит к ошибке 500, хотя после точки с запятой количество нуль-значений в запросе никак не должно влиять на его валидность. Ведь мы не объединяем результат с предыдущим, а делаем новый независимый запрос.
Почему конструкция
uid=99;+select+null
не работает?
Скорее всего точка с запятой просто удаляеться, перед подачей скуль-серверу, ибо иначе ты ею рвешь неизвестный тебе запрос, и должна возвращаться ошибка скуль - ошибка.
 
Ответить с цитированием

  #5  
Старый 25.06.2017, 01:15
artkar
Guest
Сообщений: n/a
Провел на форуме:
131082

Репутация: 6
По умолчанию

Цитата:
Сообщение от KAPTOHHbIu  
KAPTOHHbIu said:

На самом деле опыт не очень большой. Умею делать часть из того, чему учат в мануалах "для чайников" которыми пестрит рунет.
На самом деле очень хорошо, ресёрча продвинутая
 
Ответить с цитированием

  #6  
Старый 25.06.2017, 03:10
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

Цитата:
Сообщение от crlf  
crlf said:

Возможно слепая инъекция.
Так же, полистай эту тему
https://rdot.org/forum/showthread.php?t=60
Спасибо. Про слепые инъекции не знал, весьма любопытная штука оказывается!

Поскольку никаких данных, кроме злосчастной ошибки о неверном ключе сессии, скрипт не выводит - пришлось в качестве критерия угадывания использовать HTTP ошибку 504.

Постепенно по одной цифре узнал версию базы данных: MySQL 5.6.21

Использовал такие запросы:

Код:
Code:
uid=99 or substring(@@version,1,1)=1
uid=99 or substring(@@version,1,1)=2
uid=99 or substring(@@version,1,1)=3
uid=99 or substring(@@version,1,1)=4
...
До тех пор пока не получал ошибку 504, говорящую что цифра была угадана.

После чего переходил к следующей цифре.

Самое интересное, что после каждого такого угадывания сервер переставал отвечать на мои запросы на 10 минут, даже самые безобидные. Через 10 мин все возвращалось на круги своя. Причину такого поведения не понимаю. С одной стороны запрос возвращает 13 миллионов строк, это серьезная нагрузка на сервер. Но с другой сам по себе сервер не уходил в даун. Я проверял это входя в игру обычным способом, через клиент.

Что ж, еще раз спасибо. Ссылка тоже полезная, я пока прочитал не все, так что когда закончу - отпишусь о результатах.
 
Ответить с цитированием

  #7  
Старый 25.06.2017, 03:42
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

Цитата:
Сообщение от artkar  
artkar said:

Не понял как ты хочеш узнать число стлобцов:
Если:
Очень просто.

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

Я бы на месте разработчиков игры сделал с точностью до наоборот - сперва проверял нужно ли вообще делать запрос к БД, и только потом бы его делал. Но они решили иначе

В результате получаем следующую картину:

Когда запрос к БД успешно выполнен - я получаю движковую ошибку "Ключ сессии неверный!", ведь для инъекции мне волей-неволей пришлось изменить значение uid.

Если же запрос к БД завершается ошибкой (например при добавлении символа кавычки), я получаю HTTP ошибку с кодом 500.

Таким образом, постепенно добавляя к запросу uid=99+union+select+null новые и новыеnull через запятую, я буду получать ошибку 500 до тех пор пока количество null не станет равнымм количеству столбцов. В этом случае я должен буду получить сообщение о неверном ключе сессии.

В теории должен, на практике пока ни разу не получил...

Цитата:
Сообщение от artkar  
artkar said:

Скорее всего точка с запятой просто удаляеться, перед подачей скуль-серверу, ибо иначе ты ею рвешь неизвестный тебе запрос, и должна возвращаться ошибка скуль - ошибка.
Хочу уточнить, что SQL-ошибок мне не возвращается в принципе, ни при каких условиях. Ошибок Apache тоже.

У меня бывает всего 4 ситуации:

1. Если переменная uid находится в девственно неприкосновенном виде, я получаю: JSON-текст, содержащий данные из БД.

2. Если переменная uid была изменена и SQL-запрос был выполнен, я получаю: ошибку движка throwException("Ключ сессии неверный!");

3. Если переменная uid была изменена и SQL-запрос НЕ был выполнен (например добавлен символ кавычки), я получаю: HTTP 500 Internal Server Error

4. Если переменная uid была изменена, SQL-запрос был выполнен, при этом он попытался вернуть всю таблицу целиком (в ней 13млн. строк), я получаю: HTTP504 Gateway Time-out

Других ситуаций не бывает.

В идеале я хочу получить 5-тую ситуацию, когда uid была изменена, SQL-запрос был выполнен, и я получаю JSON-текст, с данными из запроса. Но пока не получается...

В этом и заключается Проблема №1, описанная во втором посте данной темы.

А почему символ ; должен удаляться перед подачей в БД?

Ты думаешь разработчики сделали специальную функцию для этого?
 
Ответить с цитированием

  #8  
Старый 25.06.2017, 04:17
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

Версию скуля я узнал просто в виде эксперимента.

Все-таки я впервые в жизни слепую инъекцию делал, хотел понять как она работает.

Юзера я хочу и сам, но никак не могу сообразить, как его выцепить из БД. Я ведь даже имен таблиц не знаю.

Наверно потому что спать пора и соображалка туго работает... Завтра продолжу.
 
Ответить с цитированием

  #9  
Старый 25.06.2017, 06:05
crlf
Guest
Сообщений: n/a
Провел на форуме:
169212

Репутация: 441
По умолчанию

Используй and, а не or.

Для, простого, быстрого перебора:

[CODE]
Code:
id=99 and ascii(substring(version(),1,1)) > 100 -- false
id=99 and ascii(substring(version(),1,1)) > 50 -- true
id=99 and ascii(substring(version(),1,1)) > 55 -- false
id=99 and ascii(substring(version(),1,1))
 
Ответить с цитированием

  #10  
Старый 25.06.2017, 14:34
KAPTOHHbIu
Guest
Сообщений: n/a
Провел на форуме:
3832

Репутация: 0
По умолчанию

2crlf, спасибо, ваши советы бессценны! Попробую применить все, что смогу.

Цитата:
Сообщение от None  
Используй
and
, а не
or
.
К великому сожалению, я вынужден использовать именно orвместоand, поскольку из-за "ошибки сессии" не имею возможности возможности отличить обычный результат запроса от нулевого.

Да, and удобнее. Но если я буду использовать and- я получу throwException("Ключ сессии неверный!"); в не зависимости от результатов запроса. Я писал об этом ранее.

Цитата:
Сообщение от None  
Для, простого, быстрого перебора...
Идея бинарного поиска просто гениальна, спасибо!

К сожалению совсем быстрым он не выйдет, т.к. ошибка 504, на которую я ориентируюсь, помимо прочего приводит еще и к отказу сервера на 10 минут. Угадали символ - ждем 10 минут пока сервер отвиснет, угадали еще один - опять 10 минут ждем.

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

Цитата:
Сообщение от None  
Количество полей, для union based, можно подбирать так:
group by...
union select...
Не знаю почему, но такие инъекции приводят к ошибке:

Код:
Code:
id=99 group by 1 -- а так же group by любое другое число или набор чисел
id=99 order by 1 -- то же самое
id=99; Select 1 -- ошибка
id=99 union select null -- снова ошибка
id=99 LIMIT 0,50 -- опять ошибка
На локалхосте всё вышеперечисленное выполняется на ура! А вот на атакуемом сервере не хочет. Почему-то вообще ничего кроме эндов и оров НЕ ПРОХОДИТ.

Такое может быть, если инъекция производится не в хвост а в середину запроса (я ведь не знаю какой он там). Но это предположение опровергается тем, что запрос id=99; обрабатывается корректно. Кроме того, я, на всякий случай, отбрасываю ввероятный хвост при помощи --, но и это не помогает.

Откуда растут ноги у проблемы понять не могу.
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ