# CSRF(Cross Site Request Forgery)

CSRF ๊ณต๊ฒฉ(Cross Site Request Forgery)์€ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ทจ์•ฝ์  ์ค‘ ํ•˜๋‚˜๋กœ ์ธํ„ฐ๋„ท ์‚ฌ์šฉ์ž(ํฌ์ƒ์ž)๊ฐ€ ์ž์‹ ์˜ ์˜์ง€์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ ํ–‰์œ„(์ˆ˜์ •, ์‚ญ์ œ, ๋“ฑ๋ก ๋“ฑ)๋ฅผ ํŠน์ • ์›น์‚ฌ์ดํŠธ์— ์š”์ฒญํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ณต๊ฒฉ์ž…๋‹ˆ๋‹ค.

CSRF๋ฅผ ํ†ตํ•ด ํ•ด์ปค๋Š” ํฌ์ƒ์ž์˜ ๊ถŒํ•œ์„ ๋„์šฉํ•˜์—ฌ ์ค‘์š” ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด, ํŽ˜์ด์Šค๋ถ์— ํฌ์ƒ์ž์˜ ๊ณ„์ •์œผ๋กœ ๊ด‘๊ณ ์„ฑ ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด ์ง‘๋‹ˆ๋‹ค. (๋ฌผ๋ก  ํŽ˜์ด์Šค๋ถ์€ CSRF ๊ณต๊ฒฉ์— ๋Œ€ํ•ด ์ž˜ ๋Œ€์‘์„ ํ•˜์˜€๊ฒ ์ง€๋งŒ, ์ด๋ฒˆ ๊ธ€์—์„œ ํ”ผํ•ด ์„œ๋น„์Šค = ํŽ˜์ด์Šค๋ถ์œผ๋กœ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.)

์กฐ๊ธˆ ๋” ์„ค๋ช…ํ•˜์ž๋ฉด, CSRF๋Š” ํ•ด์ปค๊ฐ€ ์‚ฌ์šฉ์ž์˜ ์ปดํ“จํ„ฐ๋ฅผ ๊ฐ์—ผ์‹œํ‚ค๊ฑฐ๋‚˜ ํŽ˜์ด์Šค๋ถ ์„œ๋ฒ„๋ฅผ ํ•ดํ‚น์„ ํ•ด์„œ ์ด๋ค„์ง€๋Š” ๊ณต๊ฒฉ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ CSRF ๊ณต๊ฒฉ์ด ์ด๋ค„์ง€๋ ค๋ฉด ๋‹ค์Œ ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์œ„์กฐ ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ์„œ๋น„์Šค(ํŽ˜์ด์Šค๋ถ)์— ํฌ์ƒ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์ƒํƒœ
  • ํฌ์ƒ์ž๊ฐ€ ํ•ด์ปค๊ฐ€ ๋งŒ๋“  ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ์— ์ ‘์†

์–ธ๋œป ๋ณด๋ฉด ์ด ๋‘ ์กฐ๊ฑด์„ ๋‹ค ๋งŒ์กฑํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™์ง€๋งŒ ์ƒ๊ฐ์ฒ˜๋Ÿผ ๋“œ๋ฌธ ์ผ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ํŽ˜์ด์Šค๋ถ, ๋„ค์ด๋ฒ„, ๊ตฌ๊ธ€ ๋“ฑ์˜ ์œ ๋ช… ์‚ฌ์ดํŠธ๋Š” ๋ณดํ†ต PC์—์„œ ์ž๋™ ๋กœ๊ทธ์ธ์„ ํ•ด๋†“์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ณ  ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ๋Š” ํ”ผ์‹ฑ ๋ฉ”์ผ, ์Œ๋ž€ ์‚ฌ์ดํŠธ(?) ๋“ฑ์„ ํ†ตํ•ด ์ ‘์†๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํฌ์ƒ์ž๊ฐ€ ํ•ด์ปค๊ฐ€ ๋งŒ๋“  ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ๋ฅผ ํ•˜์ง€ ์•Š๋”๋ผ๋„ ํ•ด์ปค๊ฐ€ XSS ๊ณต๊ฒฉ์„ ์„ฑ๊ณตํ•œ ์ •์ƒ ์‚ฌ์ดํŠธ๋ฅผ ํ†ตํ•ด CSRF ๊ณต๊ฒฉ์ด ์ˆ˜ํ–‰๋  ์ˆ˜ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

CSRF๊ฐ€ ํ–‰ํ•ด์ง€๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ทธ๋ฆผ์œผ๋กœ ๊ทธ๋ ค๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€๋Š” ์ง์ ‘ ๋งŒ๋“ค๊ธฐ ๊ท€์ฐฎ์€ ๊ด€๊ณ„๋กœ OWASP์— ๋ฆฌ๋”๋กœ ๊ทผ๋ฌดํ•˜์‹œ๋Š” ๋ถ„์˜ ๋ธ”๋กœ๊ทธ์—์„œ ๋ฐœ์ทŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. (์นœ์ ˆํ•˜์ง„ ์•Š์ง€๋งŒ ๊ทธ๋‚˜๋งˆ ์ œ์ผ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์ด๋ฏธ์ง€์ธ ๊ฒƒ ๊ฐ™๋„ค์š”.)

img

[์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : http://www.bluekaizen.org]

์ข€ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์˜ˆ์ œ CSRF ๊ณต๊ฒฉ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ง๋„ ์•ˆ๋˜๋Š” ์ด์•ผ๊ธฐ์ง€๋งŒ, ํŽ˜์ด์Šค๋ถ์— ๊ธ€์„ ์“ธ ๋•Œ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์€ ํผ์ด ์ „์†ก๋œ๋‹ค๊ณ  ์˜ˆ๋ฅผ ๋“ญ์‹œ๋‹ค. ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ์— ๋˜‘๊ฐ™์ด ํŽ˜์ด์Šค๋ถ์— ๊ธ€์“ฐ๊ธฐ๋ฅผ ์š”์ฒญํ•˜๋Š” ํผ์ด ์ˆจ๊ฒจ์ ธ ์žˆ๊ณ , ๊ทธ ๋‚ด์šฉ์œผ๋กœ ๊ฐ€์ž…ํ•˜๋ฉด 10๋งŒ์›์„ ์ค€๋‹ค๋Š” ์‚ฌ๊ธฐ์„ฑ ๊ด‘๊ณ ๋ฅผ ๋ณธ๋ฌธ์œผ๋กœ ์ ํ˜€์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ํฌ์ƒ์ž๋Š” ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•จ์œผ๋กœ์จ ๋ณธ์ธ์˜ ํŽ˜์ด์Šค๋ถ ๊ณ„์ •์œผ๋กœ ํ•ด๋‹น ๊ธ€์ด ๋“ฑ๋ก๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ์— ํฌํ•จ๋œ ์ฝ”๋“œ

<form action="http://facebook.com/api/content" method="post">
    <input type="hidden" name="body" value="์—ฌ๊ธฐ ๊ฐ€์ž…ํ•˜๋ฉด ๋ˆ 10๋งŒ์› ๋“œ๋ฆฝ๋‹ˆ๋‹ค." />
    <input type="submit" value="Click Me"/>
</form>

์œ„์˜ ๊ณต๊ฒฉ์„ ํ†ตํ•ด ํฌ์ƒ์ž์˜ ํŽ˜์นœ๋“ค์€ ์นœ๊ตฌ๊ฐ€ ์˜ฌ๋ฆฐ ๊ธ€์ด๋‹ˆ ์˜์‹ฌ์—†์ด ์†์•„ ๋„˜์–ด๊ฐˆ ์ˆ˜๋„ ์žˆ๊ฒ ์ฃ . ์ด๋Ÿฐ ๋”์ฐํ•œ ์ผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ๋Œ€ํ‘œ์ ์ธ CSRF ๊ณต๊ฒฉ ๋ฐฉ์–ด ๋ฐฉ๋ฒ•๋“ค์„ ๋ช‡ ๊ฐ€์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ๋‹ค์Œ 2๊ฐ€์ง€ ๋ฐฉ์–ด๊ธฐ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • Referrer ๊ฒ€์ฆ
  • Security Token ์‚ฌ์šฉ (A.K.A CSRF Token)

์ผ๋ฐ˜์ ์œผ๋กœ CSRF ๊ณต๊ฒฉ ๋ฐฉ์–ด๋Š” ์กฐํšŒ์„ฑ(HTTP GET Method) ๋ฐ์ดํ„ฐ์—๋Š” ๋ฐฉ์–ด ๋Œ€์ƒ์— ๋‘์ง€ ์•Š๊ณ , ์“ฐ๊ธฐ/๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•œ POST, PATCH, DELETE Method์—๋งŒ ์ ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ •๋ง ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ GET์„ ํ†ตํ•ด ์“ฐ๊ธฐ/๋ณ€๊ฒฝ ๋“ฑ์˜ ๋™์ž‘์„ ํ•œ๋‹ค๋ฉด GET Method์—๋„ ๋ฐฉ์–ด๋ฅผ ํ•ด์•ผํ•  ์ˆ˜ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

# Referrer ๊ฒ€์ฆ

Back-end ๋‹จ์—์„œ request์˜ referrer๋ฅผ ํ™•์ธํ•˜์—ฌ domain (ex. *.facebook.com) ์ด ์ผ์น˜ํ•˜๋Š” ์ง€ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ referrer ๊ฒ€์ฆ๋งŒ์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ CSRF ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ™์€ ๋„๋ฉ”์ธ ๋‚ด์˜ ํŽ˜์ด์ง€์— XSS ์ทจ์•ฝ์ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ CSRF ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. domain ๋‹จ์œ„ ๊ฒ€์ฆ์—์„œ ์ข€ ๋” ์„ธ๋ฐ€ํ•˜๊ฒŒ ํŽ˜์ด์ง€ ๋‹จ์œ„๊นŒ์ง€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์ฆ์„ ํ•˜๋ฉด ๋„๋ฉ”์ธ ๋‚ด์˜ ํƒ€ ํŽ˜์ด์ง€์—์„œ์˜ XSS ์ทจ์•ฝ์ ์— ์˜ํ•œ CSRF ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# Security Token ์‚ฌ์šฉ (A.K.A CSRF Token)

Referrer ๊ฒ€์ฆ์ด ๋ถˆ๊ฐ€ํ•œ ํ™˜๊ฒฝ์ด๋ผ๋ฉด, Security Token๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜์— ์ž„์˜์˜ ๋‚œ์ˆ˜ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ ๋งˆ๋‹ค ํ•ด๋‹น ๋‚œ์ˆ˜ ๊ฐ’์„ ํฌํ•จ ์‹œ์ผœ ์ „์†ก์‹œํ‚ต๋‹ˆ๋‹ค. ์ดํ›„ Back-end ๋‹จ์—์„œ ์š”์ฒญ์„ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค ์„ธ์…˜์— ์ €์žฅ๋œ ํ† ํฐ ๊ฐ’๊ณผ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ „๋‹ฌ๋˜๋Š” ํ† ํฐ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ์ง€ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•๋„ ๊ฒฐ๊ตญ ๊ฐ™์€ ๋„๋ฉ”์ธ ๋‚ด์— XSS ์ทจ์•ฝ์ ์ด ์žˆ๋‹ค๋ฉด CSRF ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด์ง‘๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๊ฐ„๋žตํ•œ ์ƒ˜ํ”Œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

// ๋กœ๊ทธ์ธ์‹œ, ๋˜๋Š” ์ž‘์—…ํ™”๋ฉด ์š”์ฒญ์‹œ CSRF ํ† ํฐ์„ ์ƒ์„ฑํ•˜์—ฌ ์„ธ์…˜์— ์ €์žฅํ•œ๋‹ค.
session.setAttribute("CSRF_TOKEN",UUID.randomUUID().toString());

// ์š”์ฒญ ํŽ˜์ด์ง€์— CSRF ํ† ํฐ์„ ์…‹ํŒ…ํ•˜์—ฌ ์ „์†กํ•œ๋‹ค
<input type="hidden" name="_csrf" value="${CSRF_TOKEN}" />
// ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋œ csrf ํ† ํฐ ๊ฐ’
String param = request.getParameter("_csrf");

// ์„ธ์…˜์— ์ €์žฅ๋œ ํ† ํฐ ๊ฐ’๊ณผ ์ผ์น˜ ์—ฌ๋ถ€ ๊ฒ€์ฆ
if (request.getSession().getAttribute("CSRF_TOKEN").equals(param)) {
    return true;
} else {
    response.sendRedirect("/");
    return false;
}

Double Submit Cookie ๊ฒ€์ฆ์€ Security Token ๊ฒ€์ฆ์˜ ํ•œ ์ข…๋ฅ˜๋กœ ์„ธ์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์›น๋ธŒ๋ผ์šฐ์ €์˜ Same Origin ์ •์ฑ…์œผ๋กœ ์ธํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํƒ€ ๋„๋ฉ”์ธ์˜ ์ฟ ํ‚ค ๊ฐ’์„ ํ™•์ธ/์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ด์šฉํ•œ ๋ฐฉ์–ด ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ ๋‹จ์—์„œ ์š”์ฒญ ์‹œ ๋‚œ์ˆ˜ ๊ฐ’์„ ์ƒ์„ฑํ•˜์—ฌ ์ฟ ํ‚ค์— ์ €์žฅํ•˜๊ณ  ๋™์ผํ•œ ๋‚œ์ˆ˜ ๊ฐ’์„ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ(ํ˜น์€ ํ—ค๋”)์—๋„ ์ €์žฅํ•˜์—ฌ ์„œ๋ฒ„๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋‹จ์—์„œ๋Š” ์ฟ ํ‚ค์˜ ํ† ํฐ ๊ฐ’์™€ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํ† ํฐ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ์ง€๋งŒ ๊ฒ€์‚ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„์— ๋”ฐ๋กœ ํ† ํฐ ๊ฐ’์„ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์—†์–ด ์œ„์—์„œ ์‚ดํŽด๋ณธ ์„ธ์…˜์„ ์ด์šฉํ•œ ๊ฒ€์ฆ๋ณด๋‹ค ๊ฐœ๋ฐœ ๊ณต์ˆ˜๊ฐ€ ์ ์€ ํŽธ์ž…๋‹ˆ๋‹ค. ํ”ผ์‹ฑ ์‚ฌ์ดํŠธ์—์„œ๋Š” ๋„๋ฉ”์ธ์ด ๋‹ฌ๋ผ facebook.com ์ฟ ํ‚ค์— ๊ฐ’์„ ์ €์žฅํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ (์กฐ๊ธˆ ์ „์— ์–ธ๊ธ‰ํ•œ Same Origin ์ •์ฑ…) ๊ฐ€๋Šฅํ•œ ๋ฐฉ์–ด ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ƒ˜ํ”Œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

/**
 * Generate 256-bit BASE64 encoded hashes
 *
 * @see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Synchronizer_.28CSRF.29_Tokens
 * @return {string}
 */
var generateCsrfToken = function() {
    function generateRandomString(length) {
        var text = "";
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        for(var i = 0; i < length; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }
        return text;
    };

    return btoa(generateRandomString(32));
}

// ์ฟ ํ‚ค ์…‹ํŒ…
var setCookie = function (cname, cvalue) {
    document.cookie = cname + "=" + cvalue + ";path=/";
}

// ๋ชจ๋“  ajax ์š”์ฒญ ์‹œ ์ฟ ํ‚ค ๋ฐ header์— ํ† ํฐ ๊ฐ’์„ ๊ฐ™์ด ์ „๋‹ฌ
jQuery.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            var csrfToken = generateCsrfToken();

            setCookie('CSRF_TOKEN', encodeURIComponent(csrfToken));
            xhr.setRequestHeader("_csrf", csrfToken);
        }
    }
});
// ํ—ค๋”๋กœ ์ „๋‹ฌ๋œ csrf ํ† ํฐ ๊ฐ’
String paramToken = request.getHeader("_csrf");

// ์ฟ ํ‚ค๋กœ ์ „๋‹ฌ๋˜ csrf ํ† ํฐ ๊ฐ’
String cookieToken = null;

for (Cookie cookie : request.getCookies()) {
    if ("CSRF_TOKEN".equals(cookie.getName())) {
        cookieToken = URLDecoder.decode(cookie.getValue(), "UTF-8");

        // ์žฌ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ์ฟ ํ‚ค ๋งŒ๋ฃŒ
        cookie.setPath("/");
        cookie.setValue("");
        cookie.setMaxAge(0);
        response.addCookie(cookie);

        break;
    }
}

// ๋‘ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ์ง€ ๊ฒ€์ฆ
if (cookieToke.equals(paramToken)) {
    return true;
} else {
    return false;
}

Reference

  • https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
  • https://itstory.tk/entry/CSRF-๊ณต๊ฒฉ์ด๋ž€-๊ทธ๋ฆฌ๊ณ -CSRF-๋ฐฉ์–ด-๋ฐฉ๋ฒ• [๋•'s IT Story]
Last Updated: 6/18/2023, 2:13:15 PM