
Исчерпывающий список всех возможных способов объединить вашу Blind SSRF-уязвимость в цепочку
Server Side Request Forgery происходит, когда вы можете заставить сервер выполнять произвольные запросы от вашего имени. Поскольку запросы выполняются сервером, возможно получение доступа к внутренним ресурсам из-за положения сервера в сети. В облачных средах SSRF представляет более серьёзный риск из-за наличия metadata endpoints, которые могут содержать чувствительные учётные данные или секреты.
При эксплуатации server-side request forgery мы часто можем оказаться в ситуации, когда ответ прочитать невозможно. В индустрии такое поведение часто называют «Слепой SSRF» (Blind SSRF). В таких ситуациях как доказать значимость уязвимости? Это интересное обсуждение было начато Джастином Гарднером в Twitter:
I've been finding a large amount of Blind SSRFs recently. What kind of one-shot RCE's have you guys used as pivots for these in the past? I've got access to some Kafka and a bunch of other things. @nnwakelam @thedawgyg
— Justin Gardner (@Rhynorater) January 13, 2021
Если вы можете получить доступ к внутренним ресурсам, существует ряд потенциальных цепочек эксплойтов, которые можно выполнить для доказательства воздействия. В этом посте блога мы постараемся подробно рассмотреть каждую известную цепочку эксплойтов при использовании слепого SSRF, и он будет обновляться по мере обнаружения и распространения новых техник.
Если мы пропустили какие-либо техники, пожалуйста, отправьте нам твит или личное сообщение: @assetnote, и мы добавим их в этот блог.
I tend to call them SSRF canaries, when chaining a blind SSRF to another SSRF internally which makes an additional call externally, or by an app-specific open redir or blind XXE. Confluence, Artifactory, Jenkins and JAMF have some that works well.
— Frans Rosén (@fransrosen) January 13, 2021
Чтобы подтвердить, что вы можете взаимодействовать с внутренними сервисами или приложениями, вы можете использовать «SSRF-канарейки».
Это когда мы можем запросить внутренний URL, который выполняет другой SSRF и отправляет запрос на ваш хост-канарейку. Если вы получите запрос на ваш хост-канарейку, это означает, что вы успешно достигли внутреннего сервиса, который также способен совершать исходящие запросы.
Это эффективный способ проверить, имеет ли SSRF-уязвимость доступ к внутренним сетям или приложениям, а также подтвердить наличие определённого программного обеспечения во внутренней сети. Вы также можете потенциально переместиться в более чувствительные части внутренней сети с помощью SSRF-канарейки, в зависимости от того, где она находится.
С целью поиска как можно большего числа внутренних хостов можно использовать DNS-источники данных, чтобы найти все записи, указывающие на внутренние хосты.
В облачных средах мы часто видим ELB, которые указывают на хосты внутри внутреннего VPC. В зависимости от того, в каком VPC находится целевой ресурс, возможно получение доступа к другим хостам в том же VPC.
Например, рассмотрим следующий хост, обнаруженный с помощью DNS-источников данных:```bash livestats.target.com -> internal-es-livestats-298228113.us-west-2.elb.amazonaws.com -> 10.0.0.82
Можно предположить, что `es` означает Elasticsearch, и затем выполнить дальнейшие атаки на этот хост. Также можно распылить все эти слепые SSRF-пейлоады по всем «внутренним» хостам, которые были обнаружены этим методом. Это часто эффективно.
Чтобы найти больше внутренних хостов, я рекомендую взять все ваши DNS-данные и затем использовать что-то вроде [AltDNS](https://github.com/infosec-au/altdns) для генерации перестановок, а затем разрешать их с помощью [быстрого DNS-брутфорсера](https://github.com/blechschmidt/massdns).
После этого определите все вновь обнаруженные внутренние хосты и используйте их как часть вашей цепочки слепого SSRF.
## Утечки по побочным каналам
При эксплуатации уязвимостей слепого SSRF вы можете получить утечку некоторой информации об ответе. Например, предположим, что у вас есть слепой SSRF через XXE — сообщения об ошибках могут указывать, был ли:
- Ответ был возвращён
`Error parsing request: System.Xml.XmlException: Expected DTD markup was not found. Line 1, position 1.`
в отличие от
- Хост и порт недоступны
`Error parsing request: System.Net.WebException: Unable to connect to the remote server`
Аналогично, помимо XXE, веб-приложение также может иметь утечку по побочному каналу, которую можно обнаружить, изучив различия в:
- **Код состояния ответа**:
Онлайн внутренний ресурс:порт отвечает `200 OK`, а офлайн внутренний ресурс:порт — `500 Internal Server Error`
- **Содержимое ответа**:
Размер ответа в байтах меньше или больше в зависимости от того, доступен ли URL, который вы пытаетесь запросить.
- **Время ответа**:
Время ответа больше или меньше в зависимости от того, доступен ли URL, который вы пытаетесь запросить.
---------------
# Техники
**Возможно через HTTP(s)**
- [Elasticsearch](#elasticsearch)
- [Weblogic](#weblogic)
- [Hashicorp Consul](#consul)
- [Shellshock](#shellshock)
- [Apache Druid](#druid)
- [Apache Solr](#solr)
- [PeopleSoft](#peoplesoft)
- [Apache Struts](#struts)
- [JBoss](#jboss)
- [Confluence](#confluence)
- [Jira](#jira)
- [Другие продукты Atlassian](#atlassian-products)
- [OpenTSDB](#opentsdb)
- [Jenkins](#jenkins)
- [Hystrix Dashboard](#hystrix)
- [W3 Total Cache](#w3)
- [Docker](#docker)
- [Gitlab Prometheus Redis Exporter](#redisexporter)
**Возможно через Gopher**
- [Redis](#redis)
- [Memcache](#memcache)
- [Apache Tomcat](#tomcat)
- [FastCGI](#fastcgi)
- [Java RMI](#java-rmi)
**Инструменты**
- [Gopherus](#gopherus)
- [remote-method-guesser](#remote-method-guesser)
- [SSRF Proxy](#ssrfproxy)
----------------------------------
**Возможно через HTTP(s)**
<div id="elasticsearch"></div>
## Elasticsearch
**Обычно используемый порт: 9200**
При внутреннем развертывании Elasticsearch обычно не требует аутентификации.
Если у вас есть частично слепой SSRF, при котором вы можете определить код состояния, проверьте, возвращают ли следующие конечные точки код 200:```http
/_cluster/health
/_cat/indices
/_cat/health
Если у вас есть слепой SSRF, при котором можно отправлять POST-запросы, вы можете остановить экземпляр Elasticsearch, отправив POST-запрос на следующий путь:
Примечание: API _shutdown был удалён в Elasticsearch версии 2.x и выше. Это работает только в Elasticsearch 1.6 и ниже:```http
/_shutdown
/_cluster/nodes/_master/_shutdown
/_cluster/nodes/_shutdown
/_cluster/nodes/_all/_shutdown
<div id="weblogic"></div>
## Weblogic
**Часто используемые порты: 80, 443 (SSL), 7001, 8888**
**SSRF-канарейка: UDDI Explorer (CVE-2014-4210)**```http
POST /uddiexplorer/SearchPublicRegistries.jsp HTTP/1.1
Host: target.com
Content-Length: 137
Content-Type: application/x-www-form-urlencoded