понедельник, 16 июня 2014 г.

Полумарафон Лось-2014

Замечательный забег прошел вчера 15 июня в национальном парке "Лосиный остров".

Последнее время я готовлюсь к марафону "Белые ночи" в Питере, который стартует через 2 недели. При подготовке я почувствовал, что мне нужна довольно длинная тренировка, причем желательно быстрая. Ничего лучше чем поучаствовать в полумарафонском забеге придумать нельзя.
В эти выходные мы три дня были на Волге - катались на парусных катамаранах с 12го по 14ое, и как раз 15го я успевал на полумарафон.

Старт был запланирован на 11 часов утра, что мне показалось довольно поздно, уже должно было быть довольно жарко. Но, когда мы подъезжали к старту прошел настоящий ливень, и я уже начал жалеть, что не взял одежды потеплее.
До старта полумарафона, как раз под проливным дождем стартовали дети и юниоры на дистанциях 1км и 6км и как следует промокли =). Впрочем, настоящих бегунов дождь никогда не останавливал.
На будущее - надо на всякий случай на забеги брать непромокайку какую нибудь, которую можно скинуть перед стартом.
В стартовой зоне встретил Мишу Святловского - сильного игрока в Го. Да и бегуна не слабого. В том году я его еще обгонял, а в этом на "Весеннем громе" он сделал меня больше чем на 10 минут.
Особой цели на забег не ставил - решил для себя, что это тренировочный забег. Если получится выбежать из 1:35, то будет здорово. Миша целил на 1:26.

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

Старт.
Я зацепился за Мишей. Со старта мы бежали не очень быстро. Я провел в голове калькуляции еще раз - чтобы пробежать за 1:35 мне нужно было держать темп 4:30 мин/км. Мы стартовали чуть быстрее где то 4:20, что меня вполне устраивало. До первого разворота на 7км мы так и держались примерно. На развороте - 7км - время было примерно 31:00.
После разворота Миша выпил стаканчик воды и попер. Пару секунд я думал и решился за ним.
Темп стал примерно 4:00 мин/км. Следующие 5км мы прошли за 20 минут. 12км - чуть больше 51:00. Я полностью понял что значит, когда тебя тащат. Это действительно намного легче, чем бежать самому.
После 12км был пункт питания, на котором Миша остановился, а я пробежал мимо. Лично мне пить совсем не хотелось. Погода позволяла.
Как только Миша перестал меня тащить, бежать стало тяжелее. Ноги тут же заявили, что они болят и т.д. Однако я пытался поддерживать темп. Тем не менее он начал скатываться к 4:15. Миша был секундах в 20ти сзади. 14 км чуть быстрее чем 1:00:00. И силы еще были. 14км - две трети полумарафона, а значит можно было уже задуматься о выходе из 1:30. Ближе к отсечке 15км я очень удачно смог догнать бегуна, который тащил меня до 18 км. На 18 км время было где то 1:16:40, надо было пробежать оставшиеся 3 км за 13 минут - задача выполнимая, но не самая простая когда за спиной уже 18 км.  Тащивший меня бегун ушел на финишное ускорение, у меня сил уже не было на это, я отвалился. Но держать темп силы были. 20км = 1:25. Через 500м меня обходит Миша показывая большой палец - "молодец". Я пытаюсь уже "по привычке" зацепиться за ним, но он мне этого не позволяет - ускоряется и скидывает меня. Ну и ладно.
Финиш и фантастические для меня 1:29:18. Я и не знал, что могу так бегать. Личный рекорд улучшен почти на 10 минут. После финиша чувствовал себя на удивление хорошо, обычно после полумарафонов я несколько минут "умираю", а в этот раз все великолепно.
У Миши - 1:29:01.

Всю дистанцию я пытался применять различные психологические техники - во-первых я с самого начала убеждал себя в том, что я бегу не полумарафон, а полноценный - 42 км. Я думаю, это позволяет избежать подобия "стенки" в конце забега.  Во-вторых я пытался "разговаривать с подсознательным" по технике BSFF, чтобы избавиться от проблем с пищеварением, которые ощущались на первой половине дистанции. Вообще техника BSFF предназначена для другого, но я других техник не знаю =). Это помогло или что-то другое, но после середины забега проблем в животе я уже не ощущал.

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

Upd: А вот и отчет Миши.

среда, 12 марта 2014 г.

О самоконтроле

С подачи Келли Макгонигал "Сила воли" (http://www.ozon.ru/context/detail/id/8243294/) сегодня всерьез задумался над тем как я принимаю решения. Чем я руководствуюсь.
Когда об этом задумываешься, начинаешь понимать свои истинные мотивы. Почему я пошел направо, а не налево, почему не помог свалившейся девушке? Решения принимаются за один миг. Это практически неуловимый момент. Однако задумываться об этом - очень интересно...
В каком именно состоянии ты находишься когда поддаешься соблазну (для меня сейчас очень актуальна проблема отвлекания. Я постоянно переключаю браузер на сервер для игры Го, либо на баш орг.).
Пока что я не много наблюдений провел, но на этот вопрос уже есть гипотеза - когда появляется какая то "проблема", которую не получается решить сразу, которую не знаешь как решать, или решение которой требует малоприятного труда, мозг дает какой-то "стоп-сигнал" и я выключаюсь и перехожу к "удовольствиям" ("наркотики" - тоже подходящее  слово, зависимость от электронной почты, соц сетей и компьютерных игр - очень известные случаи).

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

Еще опишу свои впечатления от применения данной методики.

вторник, 28 января 2014 г.

stand back, we have PHDays! write-up

PHDays CTF quals.

stand back, we have PHDays! write-up  TRex CTF Team

Отныне буду публиковать райт-апы на блоге. С целью повышения популярности блога. Разумеется не без ссылки на форум.

Итак stand back, we have PHDays!
Задача на две категории - crypto и web.

Когда мы открываем задачу мы видим такое вот окно:




Ни одна ссылка на странице не работает. Ничего вообще хоть сколько нибудь интерактивного.
Единственная зацепка - кука. Сайт каждому зашедшему шлет куку. Если куку изменить - ничего не происходит. Если куку удалить, то сайт шлет нам новую куку, уже другую.
Кука выглядит примерно так:
%2Fbt5GIxaW53eI7rJtbeSoO8TS5B1lc6kqkzTPNXtnHk%3D
Если перевести из base64, получается 32 байта. На взгляд совершенно случайных.
Что делать совершенно не понятно =). Я долго бился в разных попытках, пока не попросил совета у Виктора. Он попросил дать ему несколько кук, чтобы он их рассмотрел повнимательнее.
Я написал скрипт который доставал любое количество кук (для дальнейших исследований у меня был файл с 500 кук)
Куки в хексе выглядят так:
ee8c6d18bf475ca2ba2edfe1e2b993f9a82833d437b5eca8b04e823384cf9e55
e2bb690c930d4f94f232cde8c8bfa7bfad1e38c263e79983c05df545c5cfbc67
bd806679d2706cf4c809caddc68cff9f9b3120ad65a1e797a1758322fccba47d
f8fc7e65b14b5f91ce0bbd95ff84fabdaf2131a567969e839f60d10cc0da8900
d9be0f5d80087081d228e1eae086fb9efa5d2a8e6783c8b5946fda25f2c6874a
fb9470778d526c87de27fcf4e5a6a9bcb61c0db261a6ede6be17f52fe3b9ab5e

Можно подметить закономерность. Первый байт всегда больше 0x80. Последний всегда меньше. Мы предположили, что некоторые случайные данные ксорятся на некоторую постоянную последовательность. Причем данные не совсем случайны. Скорее всего это текст.
Получается, что можно попробовать провести атаку на not-one-time-pad и выявить ключ.
Это и было сделано.
После нескольких экспериментов с алфавитом (оказалось что используется алфавит [a-z][A-Z][0-9]!@#$) получился такой вот код, восстанавливающий ключевую последовательность:
file = open('cookies.txt')

arr = [] while True:     st = file.readline()     if st == '':         break     st = st[:-1]     st = st.decode('hex')     arr.append(st)     keys = [] import string print len(string.printable) print string.printable alph = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 +=-[]\'"*%!$/\\.,<>{}()?:;@~^\r\n\t#' alph = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$' for index in range(32):     key = []     for i in range(256):         good = True         for st in arr:             ch = ord(st[index])             res = (ch ^ i) % 256             if chr(res) in alph:                 continue             else:                 good = False                 break         if good:             key.append(i)     keys.append(key)        print keys print keys key = '' for ch in keys:     key+=chr(ch[0])     print key

Теперь была возможность послать что нибудь на сервер. После нескольких попыток послать что то типо admin и administrator, мы попробовали поставить кавычку иии:
Отлично - инъекция. Казалось бы дальше все понятно.
Однако все не так просто. У нас есть только 32 байтовый ключ. Собственно и инъекция могла содержать только 32 символа. И так получается, что стандартные техники типо select table_name from information_schema.tables limit ... не работают, потому что тупо не влезают. Скрипт также не позволял делать инъекцию с -- в конце. Работало что то типо:
aaa' or '1'='1
На такой строке мы получали новый вид страницы:

Дальше мы придумали такую вот слепую инъекцию, которая позволила восстановить id (надо было сначала угадать, что в таблице есть такое поле):
"a' or id LIKE '%s%%' or 7='" % try
, где try - это пробуемая строка.
Так можно было восстановить первые 5 символов id, на больше не хватало длины строки. Но остальные можно было восстановить также через LIKE с использованием двух символов %:
"a' or id LIKE '%%%s%%' or 7='" % try

Ну ок мы получили id. Что дальше? Это id можно установить в куку (разумеется зашифровав) и нам выдает что мы admin без всякой инъекции. Но флага не дает...
Значит флаг где то в БД. таблице key и flag в БД не было. А узнать список таблиц мы не могли из за длины запроса...

Уже на следующий день с утра Миша предложил проверить пароль админа. До этого я и не смотрел его. Он вроде и не нужен на сайте. Тем не менее поле password было в текущей таблице.
 Восстановив его как и id я получил:
 50m37im35_y0u_d0_n07_n33d_a_k3y_70_d3cryp7_aes
Очень похоже на флаг, но сайт его не принимал.
Ну чтож, пришлось копать дальше.

Следующее предположение было, что  мы открыли не весь ключ. 
Если предположить что так то мы можем вычислить остальной ключ следующим образом:
мы шлем запрос с такой строкой
' or '1'= ____
где ___ столько пробелов, сколько надо чтобы дополнить запрос до 32 байтов. И следующим байтом мы шлем по очереди все 256 символов. Только на одном из этих запросов система не даст ошибку. Причем мы точно знаем, что этот символ с той стороны воспринимается как кавычка. Значит если поксорить символ с которым не выдалась ошибка на 0x27 (кавычку), то мы вычислим следующий байт ключа. Здорово. Таким образом я восстановил еще 120 байт ключа.
Теперь можно было делать обычные запросы.
Но... в базе ничего не было. Других таблиц не было. В таблице users, к которой и был уязвимый запрос, был только один кортеж. И только 3 столбца. Все нам было известно.
Я уже начал просматривать системные таблицы БД, думая что что то лежит в них. Потом я все таки решил считать password из таблицы users и нашел вот что:
 50M37IM35_Y0U_D0_N07_N33D_A_K3Y_70_D3CRYP7_AES

ЁПРСТ. Флаг у меня уже был давным давно. Только я не учел что LIKE пофиг на регистр, и поэтому нижний тоже подошел, а он в моем переборщике стоял первым. Можно было и не восстанавливать остаток ключа!!

Часа 3 наверно было потрачено зря... Но какая разница. Флаг был найден.

После CTF я узнал что вебсайт отдавал еще и исходники по запросу /index.php~
Оттуда я узнал что скрипт позволял делать и не слепую - обычную инъекцию. А я все атаки делал через слепую.
Короче можно было решить эту задачу намного проще. Но, значит соображалка у нас работает хорошо, если мы смогли решить задачу в которой предполагалось знание исходников без исходников. =)

Всем спасибо за прочтение.



 

понедельник, 27 января 2014 г.

Как многие знают, я активный участник эвентов по информационной безопасности и хакингу, которые носят обобщенное название CTF. Кто не знает что это - wiki.
Обычный ctf состоит из некоторого количества несвязанных задач.
Задачи конечно бывают разные, но есть такая тенденция. На самых лучших CTF'ах большинство задач требуют творческого подхода, и не решаются шаблонными действиями. Казалось бы что тут придумаешь нового - SQL инъекция. Однако таскмейкеры постоянно умудряются придумать что то новое. Чего еще не было. Что то не обычное. Как у них получается это делать - это отдельный вопрос. Я честно говоря не понимаю этого, но я не об этом.

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

Вот с последнего CTF - phdays CTF Quals. Задача была на веб + крипто. Собственно есть страница. И она шлет тебе какую то рандомную казалось бы куку каждый раз как на неё заходишь. И всё. Больше ничего на странице нету. Ни форм, ни ссылок. Ничего.
Шаблонное мышление не позволяет решить эту задачу. Я долбился в стену долго, пытаясь что то вставить в куку, расхешировать её (она была 32 байта, я думал это sha256), или найти какие то еще страницы типо /robots.txt.
Потом я попросил помощи у Виктора - даже не помощи, а идею скорее. Он мне и говорит - дай несколько этих кук посмотреть. А я даже об этом и не подумал. Я решил что они случайные и не изучил их как следует. А оказалось что в них легко прослеживается закономерность.
Дальше в этом таске было еще много чего интересного и я его в итоге решил.
Главное что я хочу сказать - это то что перестать действовать шаблонами - путь к решению таких задач. В английском, кстати, есть хорошая устойчивая фраза про это - 'to have an open mind'.
Как вот только заставлять себя быть в этом состоянии - open mind? Это я пока что не знаю.






Начало

Попытаюсь вести свой блог. Не уверен пока здесь он будет или в ЖЖ. Но начну отсюда.