Skip to content

passengers 2

Dmitry Zubarev edited this page Mar 15, 2018 · 2 revisions

Система регистрации Spacebury Craft, возможно, содержит уязвимости

Условие

После публикации новости об открытии набора экипажа на космический корабль корпорации Spacebury Craft сразу несколько исследователей в области информационной безопасности предостерегли желающих поучаствовать в программе. Они напомнили, что, несмотря на революционность изобретений компании, разработчики программного обеспечения Spacebury регулярно допускали ошибки, которые впоследствии приводили ко взломам.

Эксперты недвусмысленно намекают на то, что новая система с открытым кодом, используемая компанией для регистрации заявок, тоже может содержать уязвимости, ставящие под угрозу безопасность всего предприятия. «Это давно стало традицией Spacebury: если есть одна уязвимость, то обязательно найдётся и вторая», — заявил Эгнинг Маркуссон, известный хакер и программист.

Представители компании, однако, считают, что у желающих принять участие в экспедиции нет поводов для беспокойства. «Это всё пустые слова. Пусть покажут мне хотя бы одну уязвимость», — парирует основатель корпорации Иван Ланн, — «тогда я поверю, что, может быть, есть и вторая».

Примечание: для доступа к системе следует использовать программу nc: nc passengers.contest.qctf.ru 50001. При заполнении заявки нужно воспользоваться токеном Your_Token_Right_Here

Решение

Краткий обзор исходного кода системы приведён в предыдущем райтапе. Теперь мы хотим найти второй флаг. Довольно быстро можно заметить следующую функцию:

void print_flag2() {
    print_file_content("./flag2");
}

Но нигде в коде она не используется. Нам нужно каким-то образом заставить поток исполнения зайти в эту функцию.

Уязвимость

Посмотрим на функцию update_info, которая используется для изменения данных в анкете:

........
........
........
switch (choice) {
    case 1:
        printf("\nNew first name: ");
        input_string(buf, 111);
        strcpy(applier->first_name, buf);
        break;
    case 2:
        printf("\nNew last name: ");
        input_string(buf, 111);
        strcpy(applier->last_name, buf);
        break;
    case 3:
        printf("\nNew country: ");
        input_string(buf, 111);
        strcpy(applier->country, buf);
        break;
........
........
........

Мы вводим 111 байтов в поле last_name, хотя в определении структуры это поле занимает только 100 байт. То есть 11 байт запишутся после структуры last_name, а именно в поле указателя на функцию on_unfreeze_ptr. Как вы уже знаете, указатели хранят адрес, на который ссылаются. В данном случае, при создании пассажира, можно увидеть, что on_unfreeze_ptr ссылается на функцию on_unfreeze. Если мы перезапишем этот указатель на какой-либо свой адрес, например, 0x00414141, то при вызове passngr->on_unfreeze_ptr() вызовется код по адресу 0x00414141. Таким образом мы можем контролировать поток исполнения программы

Эксплуатация

Мы можем перезаписать адрес указателя on_unfreeze_ptr на функцию print_flag2, тем самым стриггерив вывод флага при вызове passngr->on_unfreeze_ptr(). Эта функция используется, когда происходит разморозка члена экипажа. Значит, мы можем перезаписать адрес, заморозить какого-либо члена экипажа, а затем его разморозить. После этого выведется флаг.

Код эксплойта, который выводит флаги сразу для первой и второй уязвимостей доступен здесь.