Меню
Наши новости
Учебник CSS

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

Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3

Надо знать обо всем понемножку, но все о немногом.

Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы

Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)

Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода

Самоучитель CSS

Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5

Новости

Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости

Справочник CSS

Справочник от А до Я
HTML, CSS, JavaScript

Афоризмы

Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы

Видео Уроки


Видео уроки
Популярные статьи
Наш опрос



РЕКЛАМА


ВАША РЕКЛАМА
20-08-2021, 00:00
HTB CrossfitTwo. Применяем на практике UNION SQL Injection, DNS rebinding и NPM Planting - «Новости»
Рейтинг:
Категория: Новости

Hack The Box уров­ня слож­ности Insane.

info


Чи­тай так­же: «HTB CrossFit. Рас­кру­чива­ем слож­ную XSS, что­бы зах­ватить хост».



 

Разведка


Ад­рес машины — 10.10.10.232, добав­ляем его в /etc/hosts как crossfit2.htb и прис­тупа­ем к ска­ниро­ванию пор­тов.



Справка: сканирование портов


Ска­ниро­вание пор­тов — стан­дар­тный пер­вый шаг при любой ата­ке. В его резуль­тате ата­кующий узна­ет, какие служ­бы на хос­те при­нима­ют соеди­нение. Эта информа­ция поз­воля­ет выб­рать даль­нейший путь к получе­нию точ­ки вхо­да.


На­ибо­лее извес­тный инс­тру­мент для ска­ниро­вания — это Nmap. Улуч­шить резуль­таты его работы ты можешь при помощи сле­дующе­го скрип­та.


ports=$(nmap -p- --min-rate=500 $1 | grep^[0-9] | cut -d '/' -f 1 | tr 'n' ',' | sed s/,$//)nmap -p$ports -A $1

Он дей­ству­ет в два эта­па. На пер­вом про­изво­дит­ся обыч­ное быс­трое ска­ниро­вание, на вто­ром — более тща­тель­ное ска­ниро­вание, с исполь­зовани­ем име­ющих­ся скрип­тов для Nmap (опция -A).



По­луча­ем сле­дующие резуль­таты.


Ре­зуль­тат работы скрип­та

Итак, мы име­ем три откры­тых пор­та:



  • 22 — служ­ба OpenSSH 8.4;

  • 80 — веб‑сер­вер OpenBSD httpd PHP/7.4.12;

  • 8953 — служ­ба Unbound.


Пер­вым делом сто­ит заг­лянуть на дос­тупный сайт.


Стар­товая стра­ница сай­та 

Сканирование веб-контента


Что­бы ничего не оста­лось незаме­чен­ным, информа­цию на сай­те будем собирать через Proxy. В шап­ке сай­та находим навига­цию, а так­же опре­деля­ем, что пос­ледняя ссыл­ка ведет на дру­гой под­домен: employees.crossfit.htb. Добавим его в файл /etc/hosts, так­же изме­ним име­ющуюся у нас запись с crossfit2.htb на crossfit.htb.


10.10.10.232 crossfit.htb employees.crossfit.htb

На самом сай­те нас встре­чает фор­ма авто­риза­ции, боль­ше ничего мы там не получим. Так как все наши дей­ствия фик­сирова­ны в Burp, заг­лянем в Burp History. Там мы обна­ружим, что при обра­щении к глав­ной стра­нице дела­ется зап­рос на еще один под­домен.


Вклад­ка Burp History

До­бавим этот под­домен в файл /etc/hosts и пов­торим зап­рос к глав­ной стра­нице. Затем отпра­вим­ся в Burp и про­верим ответ, который вер­нул сер­вер при зап­росе к новому под­домену.


10.10.10.232 crossfit.htb employees.crossfit.htb gym.crossfit.htb
Вклад­ка Burp History

В отве­те видим опо­веще­ние о сме­не про­токо­ла на WebSocket.


 

Точка входа


 

WebSocket


WebSocket — это про­токол свя­зи поверх TCP-соеди­нения, пред­назна­чен­ный для обме­на сооб­щени­ями меж­ду бра­узе­ром и веб‑сер­вером в режиме реаль­ного вре­мени. WebSocket осо­бен­но хорош для сер­висов, которые нуж­дают­ся в пос­тоян­ном обме­не дан­ными, нап­ример для онлай­новых игр, тор­говых пло­щадок, чатов.


Пос­ле уста­нов­ления соеди­нения уже нет деления на кли­ент и сер­вер, а есть два рав­ноправ­ных учас­тни­ка обме­на дан­ными. Каж­дый работа­ет сам по себе и, ког­да надо, отправ­ляет дан­ные дру­гому.


Для прос­мотра сооб­щений по про­токо­лу WebSocket перей­дем к Burp WebSocket History. Там находим единс­твен­ное сооб­щение, в содер­жимом которо­го будет при­ветс­твие, информа­ция о коман­де help и какой‑то токен.


Вклад­ка Burp WebSocket History

Ра­ботать с WebSocket будет удоб­но с помощью инте­рак­тивной кон­соли. Ее нес­ложно орга­низо­вать при помощи Python 3 и модуля websockets.


python3 -mwebsockets ws://gym.crossfit.htb/ws/
Ус­танов­ление соеди­нения WebSockets

Пос­ле под­клю­чения нам сра­зу приш­ло зна­комое сооб­щение. Давай поп­робу­ем получить справ­ку. Сооб­щение с коман­дой нуж­но будет отпра­вить тоже в JSON.


{"command":"help"}
Зап­рос справ­ки

В отве­те нам сооб­щают о невер­ном токене, поэто­му пов­торя­ем отправ­ку, но вклю­чаем новый параметр.


{"command":"help","token":"29a20a82768c1531e28fe18a519a59fbe986801ebdcd543920dbe3bdaa8c20d9"}
Пов­торный зап­рос справ­ки

На­ше сооб­щение оста­ется без отве­та, а пос­ле пов­торной отправ­ки нам вооб­ще сооб­щают, что токен боль­ше не дей­стви­телен и дают новый токен. Инте­рес­но! Давай поищем фраг­мент кода, который отве­чает за отправ­ку сооб­щений. В панели бра­узе­ра перехо­дим к вклад­ке Debug и находим файл ws.min.js.


Пов­торный зап­рос справ­ки

В коде находим отправ­ку сооб­щения в парамет­ре message и токена — в парамет­ре token. Отправ­ляем свое сооб­щение в ана­логич­ном фор­мате.


{"message":"help","token":"cdfc745eb97670fb768678a2fbe3d37eabd307dac630720392892e5525ad87f8"}
Пов­торный зап­рос справ­ки

На­конец нам при­шел ответ, отку­да мы узна­ем о трех дос­тупных коман­дах: coaches, classes и memberships.


От­пра­вим все три коман­ды и вни­матель­но пос­мотрим на ответ сер­вера.


Ко­ман­да coaches
Ко­ман­да classes
Ко­ман­да memberships

Во всех слу­чаях нам вер­нули HTML-код стра­ницы. В пер­вом вари­анте мы получа­ем прос­то информа­цию о тре­нерах, во вто­ром — спи­сок занятий, а вот в ответ на коман­ду memberships заод­но со спис­ком при­езжа­ет выбор опций. Реали­зован он как фун­кция check_availability, в которую переда­ется чис­ло от 1 до 4. Пос­мотрим код этой фун­кции в уже зна­комом фай­ле ws.min.js.


HTB CrossfitTwo. Применяем на практике UNION SQL Injection, DNS rebinding и NPM Planting - «Новости»
Код фун­кции check_availability

Фун­кция отправ­ляет три парамет­ра:




  • message — содер­жит стро­ку available;


  • params — чис­ло, передан­ное в фун­кцию;


  • token.


{"message":"available","params":"1","token":"6775bfe48d278f7a5bc90dcb6c0e9b47e8cfcfa266446ef8345f9e01e83e6233"}
От­прав­ка сооб­щения available

В этом сооб­щении я отпра­вил четыре парамет­ра и получил два раз­ных вари­анта отве­та: успешный и нет. При этом мы еще получа­ем пояс­нение в парамет­ре debug. То есть мы отправ­ляем параметр, который сис­тема обра­баты­вает и дает резуль­тат, а зна­чит, это мес­то для тес­тирова­ния!


Даль­ше я написал скрипт на Python 3, который в цик­ле зап­рашива­ет параметр.


#!/usr/bin/python3
import json
from websocket import create_connection
def send_command(ws, token):
inp = input("> ")
ws.send('{"message":"available","params":"' + inp + '","token":"' + token + '"}')
req = ws.recv()
token = json.loads(req)['token']
print(req)
return token
ws = create_connection("ws://gym.crossfit.htb/ws/")
req = ws.recv()
token = json.loads(req)['token']
for _ in range(100):
token = send_command(ws, token)
Ре­зуль­тат работы скрип­та

Все работа­ет, идем даль­ше.


 

SQL Injection


Так как ответ выбира­ется в зависи­мос­ти от отправ­ленно­го парамет­ра, пер­вым делом я решил про­верить SQL-инъ­екцию. Бла­го я регуляр­но сос­тавляю сло­вари для тес­тов и нуж­ный как раз имел­ся под рукой. Что­бы исполь­зовать его, нем­ного под­пра­вим код.


import jsonimport timefrom websocket import create_connectiondef send_command(ws, token):
inp = input("> ")
ws.send('{"message":"available","params":"' + inp + '","token":"' + token + '"}')
req = ws.recv()
token = json.loads(req)['token']
print(req)
return tokendef send_command2(ws, token, inp):
print("input: <" + inp + ">")
ws.send('{"message":"available","params":"' + inp + '","token":"' + token + '"}')
req = ws.recv()
token = json.loads(req)['token']
print(req)
return tokenws = create_connection("ws://gym.crossfit.htb/ws/")req = ws.recv()token = json.loads(req)['token']with open('/home/ralf/tmp/wordlists/SQL/1.check_sqli.txt', 'r') as f:
wordlist = f.read().split('n')[:-1]for w in wordlist:
token = send_command2(ws, token, w)
Ре­зуль­тат работы скрип­та

При отправ­ке любого сооб­щения, содер­жащего двой­ную кавыч­ку ("), отве­та мы не получа­ем. По этой при­чине исклю­чим из сло­варя любую наг­рузку, содер­жащую этот сим­вол. И пов­торим выпол­нение.


Ре­зуль­тат работы скрип­та
Ре­зуль­тат работы скрип­та (про­дол­жение)

Прос­матри­вая вывод, обна­ружим реак­цию сер­вера на четыре наг­рузки. Смот­рим ком­мента­рий SQL:




  • 1 and 1 и 1 and true вер­нет дей­стви­тель­ный ответ;


  • 1 and 0 и 1 and false вер­нет наш ввод;


  • 1 -- - вер­нет дей­стви­тель­ный ответ.


Я нашел уяз­вимость, и теперь ее нуж­но экс­плу­ати­ровать. Пер­вым делом най­дем наг­рузки для экс­плу­ата­ции, поэто­му сме­ним сло­варь и пов­торим выпол­нение скрип­та.


Ре­зуль­тат работы скрип­та
Ре­зуль­тат работы скрип­та (про­дол­жение)

В резуль­тате есть реак­ция на UNION-наг­рузки. А имен­но при отправ­ке -1 UNION ALL SELECT 1,2# получим ответ, параметр name которо­го содер­жит 2, а при отправ­ке -1 UNION ALL SELECT USER(),SLEEP(5)--, в парамет­ре id отве­та при­сутс­тву­ет имя поль­зовате­ля базы дан­ных. Такая уяз­вимость называ­ется UNION SQL Injection и поз­воля­ет добавить к выбор­ке стол­бцы таб­лицы, которые ранее были нам не вид­ны.


Вер­нем пос­ледние две стро­ки нашего пер­воначаль­ного скрип­та для руч­ной работы и прис­тупим к экс­плу­ата­ции.


for _ in range(100):
token = send_command(ws, token)

Пер­вым делом получим вер­сию базы дан­ных.


-1UNION ALL SELECT 1,@@version #
Вер­сия базы дан­ных

На хос­те работа­ет MySQL, поэто­му даль­ше мы будем исполь­зовать ее син­таксис. Получим име­на всех име­ющих­ся баз. Мы можем выводить все­го одну стро­ку, поэто­му исполь­зуем фун­кцию GROUP_CONCAT для объ­еди­нения нес­коль­ких строк в одну, а раз­делите­лем будет про­бел.


-1UNION ALL SELECT 1,GROUP_CONCAT(schema_name,' ')FROM information_schema.schemata #
Спи­сок имен баз

Ба­за information_schema слу­жеб­ная, поэто­му нас не инте­ресу­ет. Давай узна­ем при­виле­гии нашего поль­зовате­ля в дру­гих базах.


При­виле­гии поль­зовате­ля для баз

Мы можем работать как с базой crossfit, так и с базой employees. Для начала получим наз­вания таб­лиц.


Таб­лицы в базах crossfit и employees

В базе crossfit ничего инте­рес­ного не наш­лось — надеж­ду подава­ла таб­лица password_reset, но она ока­залась пус­той.


По­лучим наз­вания стол­бцов в таб­лице employees.


Стол­бцы в таб­лице employees

Мы можем получить учет­ные дан­ные для сай­та. Зап­росим име­на, пароли и адре­са элек­трон­ной поч­ты.


Со­дер­жимое таб­лицы employees

У нас есть четыре поль­зовате­ля и хеши от их паролей. С помощью ути­литы hashid опре­делим тип хешей.


Ре­зуль­тат работы hashid

На­ибо­лее веро­ятным будет хеш SHA-256 из‑за его популяр­ности, одна­ко с нас­кока сло­мать хеши и авто­ризо­вать­ся на сай­те не выш­ло. Ни в онлай­новых базах, ни с помощью локаль­ного перебо­ра узнать хоть один из про­обра­зов хеша не уда­лось. Поэто­му пос­мотрим, какие еще у нашего поль­зовате­ля базы дан­ных есть при­виле­гии.


При­виле­гии поль­зовате­ля базы дан­ных

Мы можем читать фай­лы на хос­те! Пер­вым делом, конеч­но же, про­чита­ем /etc/passwd.


-1UNION ALL SELECT 1,LOAD_FILE('/etc/passwd') #

На­ходим поль­зовате­лей node, david и john, у которых есть воз­можность логинить­ся в сис­тему. А пос­коль­ку мы име­ем дело с OpenBSD, абсо­лют­но все служ­бы тоже отра­жены в этом фай­ле. Прос­мотрев этот спи­сок, отме­тим демон relayd, который может дать нам новые адре­са, и unbound, так как у него есть дос­туп на внеш­ний порт 8953. Сна­чала пос­мотрим нас­трой­ки релея, про­читав файл /etc/relayd.conf.


-1UNION ALL SELECT 1,LOAD_FILE('/etc/relayd.conf') #
Со­дер­жимое фай­ла /etc/relayd.conf

Так мы находим еще один домен crossfit-club.htb, который добавим в файл /etc/hosts. Сра­зу прос­мотрим одно­имен­ный сайт, который нас встре­чает фор­мой авто­риза­ции.


Фор­ма авто­риза­ции

Так как зап­росы мы по‑преж­нему дела­ем через Burp Proxy, нам это помога­ет опре­делить под­клю­чение неко­его API, о чем говорит обра­щение к /api/auth.


Вклад­ка Burp History

При попыт­ке авто­риза­ции с тес­товыми учет­ными дан­ными обна­ружи­ваем еще одну стра­ницу, которая работа­ет с фор­матом JSON.


Вы­пол­нение зап­роса на авто­риза­цию

К тому же на сай­те име­ется фор­ма регис­тра­ции. Кноп­ка в ней может быть и отклю­чена, но мы можем поп­робовать все рав­но авто­ризо­вать­ся — при помощи Burp Repeater. Получим име­на перемен­ных из исходно­го кода стра­ницы и отпра­вим тес­товые дан­ные на /api/signup. Но в отве­те нам ска­жут, что эта фун­кция дос­тупна толь­ко адми­нис­тра­тору.


Фор­ма регис­тра­ции
Вы­пол­нение зап­роса на регис­тра­цию

Тут пока боль­ше ничего не сде­лать, поэто­му идем даль­ше.


Теги: CSS

Просмотров: 63
Комментариев: 0:   20-08-2021, 00:00
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

 
Еще новости по теме:



Другие новости по теме:
Комментарии для сайта Cackle