CSRF

CSRF

in

Cross-site request forgery (CSRF)

πŸ”Ž What is CSRF?

CSRFλŠ” μž„μ˜ 이용자의 κΆŒν•œμœΌλ‘œ μž„μ˜ μ£Όμ†Œμ— HTTP μš”μ²­μ„ 보낼 수 μžˆλŠ” 취약점 μž…λ‹ˆλ‹€.
CSRF 곡격의 ν”Όν•΄μžλŠ” μžμ‹ μ˜ μ˜μ§€μ™€λŠ” λ¬΄κ΄€ν•˜κ²Œ κ³΅κ²©μžκ°€ μ˜λ„ν•œ ν–‰μœ„λ₯Ό νŠΉμ • μ›Ή μ‚¬μ΄νŠΈμ— μš”μ²­ν•˜κ²Œ λ©λ‹ˆλ‹€. CSRF 곡격의 ν”Όν•΄μžλŠ” μ˜λ„μΉ˜ μ•Šμ€ μš”μ²­μ„ 톡해 μž„μ˜ λΉ„λ°€λ²ˆν˜Έ λ³€κ²½, κ²Œμ‹œκΈ€ 등둝 및 μ‚­μ œ, μž„μ˜ λ©”μ‹œμ§€ 전솑 λ“± HTTP μš”μ²­μœΌλ‘œ μ΄λ£¨μ–΄μ§€λŠ” ν–‰μœ„μ— λŒ€ν•΄ μΈμ§€ν•˜μ§€ λͺ»ν•œ 채 ν”Όν•΄λ₯Ό λ‹Ήν•  수 μžˆμŠ΅λ‹ˆλ‹€.
일반적으둜 CSRF 취약점을 λ°©μ–΄ν•˜κΈ° μœ„ν•΄ CSRF Token 을 μ‚¬μš©ν•©λ‹ˆλ‹€.

CSRF Token은 같은 μ˜€λ¦¬μ§„μ—μ„œλ§Œ μ ‘κ·Ό κ°€λŠ₯ν•œ ν˜•νƒœλ‘œ νŠΉμ • Token을 μ €μž₯해두고, HTTP μš”μ²­μ„ 전솑할 λ•Œ ν•¨κ»˜ μ „μ†‘ν•©λ‹ˆλ‹€.
μ›Ή μ„œλ²„λŠ” μ „μ†‘λœ Token을 μ΄μš©ν•˜μ—¬ 제 3μžκ°€ μ•„λ‹Œ μ΄μš©μžλ‘œλΆ€ν„° μš”μ²­μ΄ μ™”λ‹€λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
CSRF Token값은 보톡 HTML form νƒœκ·Έμ˜ hidden 속성에 μž…λ ₯λ˜κ±°λ‚˜, 동적 μš”μ²­μ—μ„œλ„ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€.

이미지 1

CSRF 곡격이 κ°€λŠ₯ν•˜λ €λ©΄ 3κ°€μ§€ μ£Όμš” 쑰건이 μΆ©μ‘±λ˜μ–΄μ•Όν•©λ‹ˆλ‹€.

1. A relevant action : κ³΅κ²©μžκ°€ μ‚¬μš©μžλ₯Ό μœ λ„ν•  수 μžˆλŠ” μš”μ²­μ΄ μžˆμ–΄ν•©λ‹ˆλ‹€(μ‚¬μš©μž κΆŒν•œμˆ˜μ •, μžμ‹ μ˜ νŒ¨μŠ€μ›Œλ“œ λ³€κ²½ λ“±)
2. Cookie-based session handling : μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ€ μ„Έμ…˜ μΏ ν‚€μ—λ§Œ μ˜μ‘΄ν•˜μ—¬ μš”μ²­ν•œ μ‚¬μš©μžλ₯Ό μ‹λ³„ν•˜μ—¬μ•Ό ν•©λ‹ˆλ‹€.
3. No unpredictable request parameters : μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” μš”μ²­ νŒŒλΌλ―Έν„°μ—μ„œ κ³΅κ²©μžκ°€ μΆ”μΈ‘ν•  수 μ—†λŠ” 값을 κ°€μ§„ λ§€κ°œλ³€μˆ˜κ°€ ν¬ν•¨λ˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€. (νŒ¨μŠ€μ›Œλ“œ λ³€κ²½ μ‹œ 기쑴의 μ•”ν˜Έκ°’μ„ μ•Œμ•„μ•Ό ν•  경우 μ·¨μ•½ν•˜μ§€ μ•ŠμŒ)

이메일 μ£Όμ†Œ λ³€κ²½ μ‹œ μ·¨μ•½ν•œ HTTP μš”μ²­μž…λ‹ˆλ‹€.

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

email=wiener@normal-user.com

ν•΄λ‹Ή μš”μ²­μ‹œ 곡격이 κ°€λŠ₯ν•œ CSRF POC μ½”λ“œμž…λ‹ˆλ‹€.(SameSite μΏ ν‚€κ°€ μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€κ³  κ°€μ •)

<html>
  <body>
    <form action="https://vulnerable-website.com/email/change" method="POST">
      <input type="hidden" name="email" value="pwned@evil-user.net" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>
CSRF vulnerability with no defenses

이메일 λ³€κ²½ μ‹œ CSRF에 λŒ€ν•œ μ•„λ¬΄λŸ° λŒ€μ‘μ΄ μ—†μ–΄ 곡격이 κ°€λŠ₯ν•œ μ·¨μ•½μ μž…λ‹ˆλ‹€.

이메일 λ³€κ²½ μš”μ²­μ—μ„œ Generate CSRF POCλ₯Ό μ‚¬μš©ν•˜μ—¬ κ³΅κ²©μ½”λ“œλ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

csrf1

μ‚¬μš©μžκ°€ κ³΅κ²©μ½”λ“œκ°€ μ‚½μž… 된 νŽ˜μ΄μ§€ μ ‘μ†μ‹œ μžλ™μœΌλ‘œ μ œμΆœμ„ ν•  수 μžˆλŠ” μ½”λ“œλ₯Ό 같이 μƒμ„±ν•˜μ—¬ μ€λ‹ˆλ‹€

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://acd71ffa1ece7aa8c0b41bfe0040007f.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="test&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

csrf2

HTML μ‚½μž…μ΄ κ°€λŠ₯ν•œ νŽ˜μ΄μ§€μ— ν•΄λ‹Ή κ³΅κ²©μ½”λ“œλ₯Ό μ‚½μž… ν›„ μ‚¬μš©μžκ°€ 접속 μ‹œ μžλ™μœΌλ‘œ κ³΅κ²©μžκ°€ μž…λ ₯ν•œ μ΄λ©”μΌλ‘œ 변경이 λ©λ‹ˆλ‹€

csrf3

CSRF where token validation depends on request method

CSRF Token을 μ‚¬μš©ν•΄ CSRFλ₯Ό λŒ€μ‘ν•˜κ³  μžˆμ§€λ§Œ GET λ©”μ†Œλ“œμ—μ„œλŠ” λŒ€μ‘ν•˜μ§€ μ•Šμ•„ μš°νšŒκ°€λŠ₯ν•œ μ·¨μ•½μ μž…λ‹ˆλ‹€.

μž„μ˜μ˜ CSRF Token 값을 λ³€κ²½ν•˜μ—¬ μš”μ²­ μ‹œ CSRF토큰이 λ§žμ§€ μ•Šλ‹€λŠ” μ—λŸ¬λ©”μ‹œμ§€κ°€ λ…ΈμΆœλ©λ‹ˆλ‹€.

csrf1

λ©”μ†Œλ“œλ₯Ό POSTμ—μ„œ GEt으둜 λ³€κ²½ν•˜μ—¬ λ™μΌν•œ λ‚΄μš©μ„ 전솑 μ‹œ μ—λŠ” CSRF 토큰을 μΈμ¦ν•˜μ§€ μ•Šκ³  μš”μ²­μ΄ μ „μ†‘λ©λ‹ˆλ‹€.

csrf2

GET λ°©μ‹μ˜ μš”μ²­μ—μ„œ POC μ½”λ“œλ₯Ό μƒμ„±ν•˜μ—¬ 곡격 μ‹œ μš°νšŒκ°€ λ˜λŠ” μ·¨μ•½μ μž…λ‹ˆλ‹€.

csrf3

CSRF where token validation depends on token being present

CSRF ν† ν°μœΌλ‘œ λŒ€μ‘ν•˜κ³  μžˆμ§€λ§Œ νŒŒλΌλ―Έν„° 전솑 μ‹œ CSRF토큰을 μ‚­μ œν•˜μ—¬ μš°νšŒν•˜λŠ” 취약점 μž…λ‹ˆλ‹€.

νŒŒλΌλ―Έν„° 전솑 μ‹œ csrf 토큰을 μ‚­μ œν•˜κ³  전솑 μ‹œ 인증을 κ±°μΉ˜μ§€ μ•Šκ³  우회 κ°€λŠ₯

csrf1

ν•΄λ‹Ή μš”μ²­μ˜ POCμ½”λ“œ 생성

csrf2

CSRF where token is not tied to user session

μ‹œν¬λ¦Ώμ°½μ„ μ‚¬μš©ν•˜μ—¬ λ‹€λ₯Έκ³„μ •μ—μ„œ CSRF토큰을 λ°œκΈ‰ ν›„ 곡격 μ‹œ λ‹€λ₯Έκ³„μ •μ—μ„œ λ°œκΈ‰λ°›μ€ CSRF토큰을 μ‚¬μš©ν•˜μ—¬ μš°νšŒκ°€ κ°€λŠ₯ν•œ 취약점 μž…λ‹ˆλ‹€.

wiener κ³„μ •μ—μ„œ 이메일 λ³€κ²½ μš”μ²­μ„ ν•˜μ—¬ CSRF 토큰을 λ°œκΈ‰λ°›μ€ ν›„ DROP으둜 νŒ¨ν‚·μ„ μ „μ†‘ν•˜μ§€ μ•Šκ³  λ“œλžμ‹œμΌœ μ€λ‹ˆλ‹€

csrf1

κ·Έ ν›„ carlos κ³„μ •μ—μ„œ 이메일 λ³€κ²½ μ‹œ λ°œκΈ‰λ°›μ€ CSRF토큰이 μ•„λ‹Œ wiener κ³„μ •μ—μ„œ λ°œκΈ‰λ°›μ€ CSRF ν† ν°μœΌλ‘œ λ³€κ²½ ν›„ 값을 전솑 μ‹œ 인증을 κ±°μΉ˜μ§€ μ•Šκ³  ν•΄λ‹Ή CSRF토큰이 μ‚¬μš©λ©λ‹ˆλ‹€

csrf2

μœ„μ™€ λ™μΌν•œ λ°©μ‹μœΌλ‘œ CSRFκ³΅κ²©μ½”λ“œ 생성이 κ°€λŠ₯ν•©λ‹ˆλ‹€

csrf3



🍁 Cheat sheet


🐞 BugBounty Write up


πŸ“ƒ References