ããã«ã¡ã¯ @zaru ã§ããä»åã¯æãããã CSRF (ã¯ãã¹ãµã¤ãã»ãªã¯ã¨ã¹ãã»ãã©ã¼ã¸ã§ãª) ã®ä»æã®å¯¾çã«ã¤ãã¦ã¾ã¨ãã¦ã¿ã¾ããããããè¨äºä¸ã«ééããããã° @zaru ã¾ã§ DM ãããã¯ã¡ã³ã·ã§ã³ããã ãã (ã»ãã¥ãªãã£ã®ç´°ããé¨åã«ã¤ãã¦ã®çè§£ãä¹ããâ¦) ã
- 2022/08/29 : 徳丸ãããããã£ã¼ãããã¯é ããå
容ãåæ ãã¾ããã徳丸ããããããã¨ããããã¾ãï¼
- èªè¨¼ããã»ãªãã§å¯¾çæ¹æ³ãéãç¹
- ãã¼ã¯ã³ç¢ºèªæ¹å¼ã®ãã¡ãªããã®ã¯ãã¹ãã¡ã¤ã³ã«ã¤ãã¦ã®è¨åãåé¤ã代ããã« Cookie æ¹å¤ãªã¹ã¯ã追è¨
- Cookie æ¹ããå¯è½æ§ã«ã¤ãã¦å¾³ä¸¸ããã®åç»ãªã³ã¯ã追è¨
- SameSite 屿§ã§é²ããªãå ·ä½çãªã±ã¼ã¹ã追è¨
- nginx 説æãé¢ä¿ãªãã£ãã®ã§åé¤
ãããã CSRF ã£ã¦ãªã«ï¼
æããã¤ã³ã¿ã¼ãããããã£ã¦ããæ¹ã§ããã°ãã¼ãã¯ã¾ã¡ã¡ããã é¨åã¨è¨ãã°åããããããã¾ããã2005å¹´é ã« mixi ã§ãã¼ãã¯ã¾ã¡ã¡ããï¼ ããã«ã¡ã¯ããã«ã¡ã¯!!ãã¨ããå®åã®æç¨¿ããæç¨¿è ãæå³ããæ¸ãè¾¼ã¾ãã¦ãã¾ã£ãã¨ããäºä»¶ã§ããCSRF ã¯ã¾ãã«ãã®ãæç¨¿è ãæå³ãããã¨ããã¨ããããã¤ã³ãã§ãã
CSRF ã¯ãæ»æè ã仿ãããã¼ã¸ã«è¢«å®³è A ãããèªå°ããã¨ããããå§ã¾ãã¾ããA ããã¯ä¸è¦ãªã«ããªããã¼ã¸ãé²è¦§ããã ãã§ãããè£ã§ã¯ JavaScript ã使ã£ã¦å¥ãµã¼ãã¹ (å³ã§è¨ã BBS) ã«æ¸ãè¾¼ã¿ãªã¯ã¨ã¹ããéä¿¡ããããã«ãªã£ã¦ãã¾ããçµæãBBS ã®ãµã¼ãããè¦ãã¨ãA ããã®é²è¦§ç°å¢ããã®ãªã¯ã¨ã¹ãã¨ãã¦å¦çããã¦ãã¾ãã¾ãã

ãã£ããè¨ãã¨ãããã CSRF ã§ããæ»ææ¹æ³ã¯ãã¾ãã¾ããã¾ãããèå¼±æ§ããããã°ãä¼å¡ã¨ãã¦ãã°ã¤ã³æ¸ã¿ã®ãµã¼ãã¹ã§åæã«éä¼å¦çãå¼·å¶ãããããªã©æ§ã ãªå½±é¿ãåºã¦ãã¾ãã¾ããæãã§ããã
CSRF 対çã£ã¦ã©ãããã°è¯ãã®ï¼
çµè«ããè¨ãã¨ä»¥ä¸ã®2ç¹ã§ãã
- ç¾ä»£çãªãã¬ã¼ã ã¯ã¼ã¯ã»ã©ã¤ãã©ãªã使ã
- ä¸è¨ãã¼ã«ã® CSRF å¯¾çæ©è½ããªãã«ããªã
CSRF ã¨ããã®ã¯æããããæ»æã§ç¾ä»£çãªãã¬ã¼ã ã¯ã¼ã¯ããã©ã¼ã ã©ã¤ãã©ãªãªã©ã§ããã°æ¨æºã§å¯¾çãããã¦ãã¾ããã¤ã¾ãã¢ããªã±ã¼ã·ã§ã³ã®éçºè ã¯èªåã§å¯¾çãããªãã¦ãããã¼ã«ã®ã«ã¼ã«ã«å¾ã£ã¦ã³ã¼ããæ¸ãã¦ããã°å¿ è¦ååãªå¯¾çã¯ã§ãã¦ãããã¨ã«ãªãã¾ã (å½ç¶ã100ï¼ ããã§é²ããã¨ããä¿è¨¼ããããã®ã§ã¯ãªãã§ãã)ã
èªãèå¼±æ§ãä½ã£ã¦ãã¾ãè¡çº
CSRF 対çãæ©è½ã¨ãã¦ã¯æã£ã¦ãã¦ãä½ããã®äºæ
ã§æ©è½ããªãã«ãã¦ãã¾ãã¨æå³ãããã¾ãããä¾ãã° Rails ã§ããªãã ActionController::InvalidAuthenticityToken ä¾å¤ãåºã¦åããªã⦠skip_forgery_protection ãæå®ãããåããããã¿ãããªè¨äºãããè¦ã¾ãã
ãããçè§£ãã skip_forgery_protection ãæå®ããã¨èªãèå¼±æ§ãä½ã£ã¦ãã¾ãå±éºãªè¡çºã§ããä¸è¬ç㪠Web ã¢ããªã±ã¼ã·ã§ã³ã§ããã° CSRF 対çããªãã«ããå¿
è¦ã¯ãã¾ããªãã®ã§ããããã£ãæã«ã¯ä¸åº¦ç«ã¡æ¢ã¾ã£ã¦ä»ã«ééã£ã¦ããã¨ããããªãããèããããã«ããæ¹ãè¯ãã§ãããã
ã¾ããæ©è½ããªãã«ã¯ãã¦ããªãã CSRF 対çããå¤ããã³ã¼ããæ¸ããã¨ãããå¾ã¾ããä¾ãã° GET ãªã¯ã¨ã¹ãã§ ç¶æ ã夿´ãããã㪠API ãä½ã£ã¦ãã¾ãçã§ããWeb ã¢ããªã±ã¼ã·ã§ã³ã®ä½æ³ã¨ãã¦ç¶æ 夿´ããã API 㯠POST ã¡ã½ããã«ããã¨ãããã®ãããããã¬ã¼ã ã¯ã¼ã¯ã® CSRF 対çã POST æã«ããæå¹ã«ãªããªãã£ãããã¾ãããã®ããã使ã£ã¦ãããã¬ã¼ã ã¯ã¼ã¯ãã©ã¤ãã©ãªã® CSRF å¯¾çæ©è½ã調ã¹ã¦ä¿è·ãããã±ã¼ã¹ãçè§£ãããã¨ãéè¦ã§ãã
ä»ã«ããã¬ã¼ã ã¯ã¼ã¯ããã©ã¦ã¶èªä½ã®èå¼±æ§ãããã㯠CSRF 以å¤ã« XSS ãªã©ã®èå¼±æ§ããã㨠CSRF 対çããã¦ããã¨ãã¦ãæãéãã§ãã¦ãã¾ãã®ã§å ¨ä½ã®ã»ãã¥ãªãã£å¯¾çã¯å¿ è¦ã«ãªãã¾ãã
代表ç㪠CSRF å¯¾çææ³
代表ç㪠CSRF 対çã®ææ³ãããã¤ãç´¹ä»ãã¾ãã
- ãã¼ã¯ã³ã®ç¢ºèª
- ã«ã¹ã¿ã ãªã¯ã¨ã¹ããããã®ç¢ºèª
- SameSite Cookie Lax/Strict è¨å®
- Double Submit Cookie
- Origin ãªã¯ã¨ã¹ããããã®ç¢ºèª
- Sec-Fetch ãªã¯ã¨ã¹ããããã®ç¢ºèª
ãã¬ã¼ã ã¯ã¼ã¯ã§ã¯åç¬ã®ææ³ã ãã§ã¯ãªããè¤æ°çµã¿åããã¦ãããã¨ãããã¾ããRails ã§ã¯ãã¼ã¯ã³ã®ç¢ºèªã¨ Origin ãããã®ç¢ºèªãä½µç¨ãã¦ãã¾ãã以ä¸ã§ã¯ããããã®ç¹å¾´ãç°¡åã«è§£èª¬ãã¾ããããééã£ã¦ãããæãã¦ãã ããã
ã¾ããèªè¨¼ãå¿ è¦ã¨ããã±ã¼ã¹ã¨å¿ è¦ã¨ããªãã±ã¼ã¹ã§ CSRF 対çãç°ãªãç¹ã«ã注æã§ããèªè¨¼ãå¿ è¦ã¨ããã¨ããã®ã¯ä¾ãã° SNS ãä¼å¡ãã¼ã¸ãªã©ã®ãã°ã¤ã³ãå¿ è¦ã¨ããã±ã¼ã¹ã§ããèªè¨¼ã«ã¯ Cookie ã§ã»ãã·ã§ã³ç®¡çãããåæã§è©±ãé²ãã¾ãã
ãã¼ã¯ã³ã®ç¢ºèª
æããããããããããã£ã¨ã使ããã¦ãã対çã§ããç´°ããå®è£
æ¹æ³ã¯ãã¬ã¼ã ã¯ã¼ã¯ãã©ã¤ãã©ãªã«ãã£ã¦ç°ãªãã¾ãããéã«è¨ãã¨ä¸æçãªã©ã³ãã ãã¼ã¯ã³ããµã¼ãã§çºè¡ããã»ãã·ã§ã³ã¨ãã¦ä¿æããã©ã¦ã¶ã«ã¯ã»ãã·ã§ã³ Cookie ã¨ããã¼ã¯ã³ã <input type="hidden" value="token-xxx"> ã¨ãã©ã¼ã ãã¼ãã¨ãã¦å«ãã HTML ãè¿ãã¾ãã
POST ãããéã«ããã©ã¼ã ã®éä¿¡ãã¼ã¿ã®ãã¼ã¯ã³ã¨ãã»ãã·ã§ã³ã§ä¿æãã¦ãããã¼ã¯ã³ãä¸è´ãããã§æ£è¦ãªãªã¯ã¨ã¹ããã©ããã夿ãã¾ãã

ã¡ãªããã¯æå ãã¨ããããã¡ãªããã¯èªåã§å®è£ ããéã®ã³ã¹ããé«ãã¨ããã§ãã
ã¾ããèªè¨¼ãå¿ è¦ã¨ããªãã±ã¼ã¹ã§ã¯ãå¾è¿°ãã Double Submit Cookie ã¨åæ§ã« Cookie ãæ¹å¤ããã¦ãã¾ãã¨ãã¼ã¯ã³ãã§ãã¯ããã¹ã§ãã¦ãã¾ãå¯è½æ§ãããã¾ãã
ã«ã¹ã¿ã ãªã¯ã¨ã¹ããããã®ç¢ºèª
POST ãªã¯ã¨ã¹ãããéã«ãç¬èªã®ã«ã¹ã¿ã ããããæå®ãããµã¼ãå´ã§ç¢ºèªããææ³ã§ããAjax ãªã© fetch() ã¡ã½ããã使ã£ããªã¯ã¨ã¹ããããéã«æ¡ç¨ãããããã¾ããfetch() ã§ã«ã¹ã¿ã ããããæå®ããã¨ãããªãã©ã¤ããªã¯ã¹ãã¨ãã OPTIONS ã¡ã½ããã®ãªã¯ã¨ã¹ããèªåã§çºè¡ããã¾ãã
ãµã¼ãå´ã¯ OPTIONS ãªã¯ã¨ã¹ãã®ä¸èº«ãè¦ã¦è¨±å¯ãããã©ããã夿ãã¾ããã¾ã許å¯ãããå¾ã«æ¬æ¥ã® POST ãªã¯ã¨ã¹ããé£ã³ããã®ãªã¯ã¨ã¹ããããã®ä¸èº«ãã¿ã¦ã«ã¹ã¿ã ããããæ£è¦ãªãã®ãã©ããã§è¿½å ã®å¤æããããã¨ãã§ãã¾ãã

ã¡ãªããã¯ã·ã³ãã«ãªå®è£
ã«ãªããã¨ããã¡ãªãã㯠<form> ãã¤ãã£ã POST ã¯ä¿è·ã§ããªããã¨ã§ãã
SameSite Cookie Lax/Strict è¨å®
2020 å¹´ãªãªã¼ã¹ããã Chrome 84 ãã Cookie ã® SameSite 屿§ã¯ Lax ãããã©ã«ãå¤ã«ãªãã¾ãããSameSite 屿§ã¨ããã®ã¯ Cookie å¶å¾¡ããã¡ã¼ã¹ããã¼ãã£ã®ã¿ã«ãããã©ãããæå®ãããã¨ã§ãã¾ãã3ã¤ã®å¤ãããã¾ãã
- Lax : ç¾ä»£ãã©ã¦ã¶ã®ããã©ã«ãå¤ãç°ãªã Origin ããã®ãªã¯ã¨ã¹ãã«ããã¦ããããã¬ãã«ããã²ã¼ã·ã§ã³ã㤠GET ãªã¯ã¨ã¹ãæã« Cookie éä¿¡ã許å¯ãã¾ããé常ã®ãªã³ã¯é·ç§»ã§ããã° Cookie éä¿¡ããã¾ããã
iframeã§ã¯ GET ã§ãéä¿¡ããã¾ãã - Strict : ãã¡ã¼ã¹ããã¼ãã£ã®ã¿éä¿¡ãç°ãªã Origin ããã®ãããããªã¯ã¨ã¹ãã«ããã¦éä¿¡ããã¾ãã
- None : ãã¤ã¦ã®ããã©ã«ãå¤ã§ããã©ã®ç¶æ
ã§ã Cookie ãéä¿¡ãã¾ãããã ã
Secure屿§ãåããã¦æå®ãããªãã¨æ©è½ãã¾ãã
ãã®ææ³ã¯ CSRF æ»æãããç¨åº¦ç·©åãããããã®ãã®ãªã®ã§ãåç¬ã§åå㪠CSRF 対çã«ã¯ãªãå¾ã¾ãããååã§ãªãã±ã¼ã¹ã¨ãã¦ã¯ãããèãããã¾ã (徳丸ãããããã£ã¼ãããã¯ããã ãã¾ãã) ã
- GET ãªã¯ã¨ã¹ãã§æ´æ°å¦çã許ãã¦ãã¾ã
- èªè¨¼ãå¿ è¦ã¨ããªãã±ã¼ã¹
- SameSite 屿§ã«å¯¾å¿ãã¦ããªãå¤ããã©ã¦ã¶ã使ã£ã¦ããã±ã¼ã¹
ã«ã¸ã¥ã¢ã«ã«é²ããã±ã¼ã¹ã ã¨ãLax / Strict ã§ããã°ããã°ã¤ã³ (Cookie) ãå¿ è¦ãªã¢ããªã±ã¼ã·ã§ã³ã® API ããå¤é¨ããåæã«ãªã¯ã¨ã¹ããå¼·å¶ãããæ»æã¯é²ããã¨ãã§ãã¾ããCookie ãéä¿¡ããããã°ã¢ã¦ãç¶æ ã®ãªã¯ã¨ã¹ãã«ãªãããã
Double Submit Cookie
ä»çµã¿ã¨ãã¦ã¯æåã«ç´¹ä»ãããã¼ã¯ã³ã®ç¢ºèªã¨ã»ã¼åãã§ããéãã¯åè ã¯ãã¼ã¯ã³ãã»ãã·ã§ã³ãã¼ã¿ã«ä¿æãã¦ãã¾ã (ä¾ãã° Redis ãªã©ã«) ãã¤ã¾ããµã¼ãå´ããã¼ã¯ã³ãä¿æãã¦ãã¾ããããããã® Dobule Submit Cookie ã¯ããã¼ã¯ã³ã Cookie ã¨ãã¦æ¸¡ãã¾ãããã®å¾ãPOST æã« Cookie ã®ãã¼ã¯ã³ã¨ããªã¯ã¨ã¹ãããã£ã«ãã¼ã¯ã³ãåãè¾¼ãã§ãµã¼ãã¸éä¿¡ãã¾ãããµã¼ãã¯éä¿¡ãããäºã¤ã®ãã¼ã¯ã³ãä¸è´ãããã確èªãã¾ãã

ãµã¼ãã¯çºè¡ãããã¼ã¯ã³ãä¿æããªã代ããã«ã¦ã¼ã¶ã« Cookie ã§ä¿æãã¦ãããã¨ããç¹ãç¹å¾´ã§ãããã㯠Cookie ãæ¹å¤ãããªãã¨ããåæã«ç«ã£ãææ³ã«ãªãã¾ããCookie ãæ¹å¤ããã«ããããã«ããããã«ã¯ããã¤ãæ¹æ³ãããã¾ãã
- HTTPS ã§ Secure 屿§ã使ç¨
- HTTP Strict Transport Security ã使ç¨
- Cookie åã«
__Host-ãã¬ãã£ãã¯ã使ç¨
__Host- ãã¬ãã£ãã¯ã¹
__Host- ã§å§ã¾ãã¯ããã¼åã¯ã secure ãã©ã°ãè¨å®ããå®å ¨ãªãã¼ã¸ (HTTPS) ããèªã¿è¾¼ãå¿ è¦ãããããã¡ã¤ã³ãæå®ãããã¨ãã§ãã (å¾ã£ã¦ããµããã¡ã¤ã³ã«ãéããã¾ãã)ããã¹ã / ã§ããå¿ è¦ãããã¾ãã
ã¾ããCookie ã®æ¹ããã«ã¤ãã¦ã¯å¾³ä¸¸ããã® YouTube åç»ã§è©³ãã解説ããã¦ãã¾ãã®ã§ãæ¯éåç §ããã¦è¦ã¦ãã ããã
Origin ãªã¯ã¨ã¹ããããã®ç¢ºèª
ä»çµã¿ã¨ãã¦ã¯ä»ã¾ã§ç´¹ä»ããææ³ã®ä¸ã§ãæãã·ã³ãã«ã§ãããã©ã¦ã¶ãä»ä¸ãã Origin ãªã¯ã¨ã¹ãããã ã¨ããµã¼ããåãã¦ãããã¹ããæ¯è¼ãã¦ä¸è´ããå ´åã«æ£è¦ãªãªã¯ã¨ã¹ãã¨ãã¦å¦çããä¸ä¸è´ã®å ´åã¯æ³å®ãã¦ããªããµã¤ãããã®ãªã¯ã¨ã¹ãã¨ãã¦æå¦ãã¾ãã

ã¡ãªããã¯å®è£ ãé常ã«ã·ã³ãã«ã§ç°¡åãªãã¨ããã¡ãªããã¯ãµã¼ããèªèº«ã®ãã¹ãåã確å®ã§ãããã¨ãæ¡ä»¶ã§ãããã¨ãã¨ã¯ããä¸è¬ç㪠Web ã¢ããªã±ã¼ã·ã§ã³ã§ããã°ãã¹ãåã¯ç¢ºå®ã§ããã®ã§åé¡ã«ã¯ãªããªãã¨æãã¾ãã
ç¹°ãè¿ãã«ãªãã¾ãããGET ãªã¯ã¨ã¹ãã§ç¶æ ã夿´ãããã㪠API ããªããã¨ãåæã§ããOrigin ãªã¯ã¨ã¹ãããã㯠CORS ã POST ãªã¯ã¨ã¹ãæã«ããä»ä¸ãã¾ãããã¤ã¾ã GET ã§ã¯ Origin ãªã¯ã¨ã¹ããããã®ç¢ºèªã¯ã§ããªãç¹ã«æ³¨æãã¦ãã ããã
Sec-Fetch ãªã¯ã¨ã¹ããããã®ç¢ºèª
ããã¯åè¿°ã® Origin ãªã¯ã¨ã¹ããããã¨åãä»çµã¿ã§ããã¤ã¤ãããã«æ¥½ãªææ³ã«ãªãã¾ããSec-Fetch ãªã¯ã¨ã¹ããããã¨ã¯ãã©ã¦ã¶ãèªåã§ä»ä¸ãã¦ãããæ å ±ã§ãã以ä¸ã®4ã¤ãããã¾ãã
- Sec-Fetch-Dest : ãªã¯ã¨ã¹ãå ã fetch ãããã½ã¼ã¹ã使ãå½¢æ e.g. document / iframe
- Sec-Fetch-Mode : ãªã¯ã¨ã¹ãã®å½¢æ ã表ã e.g. cors / navigate
- Sec-Fetch-Site : ãªã¯ã¨ã¹ãå ãªãªã¸ã³ã¨ãªã¯ã¨ã¹ãããããªãªã¸ã³ã®é¢ä¿ e.g. same-origin / cross-site
- Sec-Fetch-User : ã¦ã¼ã¶èªèº«ããªã¯ã¨ã¹ããçºè¡ãããã©ããããã®å ´åã«ããã¦å¤ã¯å¿
ã
?1
ãã®ä¸ã§ã CSRF 対çã¨ãã¦ã¯ Sec-Fetch-Site ãªã¯ã¨ã¹ããããã使ãã¾ããSec-Fetch-Site ã same-origin ã®å ´åã¯åä¸ãªãªã¸ã³ã§ãããã¨ãä¿éããã¾ããã¤ã¾ãåè¿°ã® Origin ãªã¯ã¨ã¹ããããã§ã¯å®éã«ãã¹ãåãåå¾ãã¦æ¯è¼ãã¦ããã®ããäºåã«ãã©ã¦ã¶èªèº«ãå䏿§ãæ¯è¼ããçµæã ããåãåããã¨ãã§ãã¾ãã大å¤ä¾¿å©ã§ããã
ãããããã®æ¹æ³ã«ã¯å¯ä¸ã®æ¬ ç¹ãããã¾ãããã㯠2022-08-27 æç¹ã§ Safari ãã¾ããµãã¼ããã¦ããªãç¹ã§ãã

Safari ããµãã¼ãããã¦ãããã°ãSec-Fetch-Site ãªã¯ã¨ã¹ããããã確èªããã®ãæãæè»½ãª CSRF 対çã«ãªãããã§ãã
ã¾ã¨ã
CSRF 対çã¯ããã¤ãããã¾ãããæåã«æ¸ããããã«ç¾ä»£çãªãã¬ã¼ã ã¯ã¼ã¯ã使ãããã¬ã¼ã ã¯ã¼ã¯ã®æµåã«ã®ã£ãã³ã¼ãã§å®è£ ãããã¨ãä¸çªã®å¯¾çã«ãªãããªã¨æãã¾ããã¾ãããªã«ãããã¨æµåããå¤ãé²å¾¡ãããªããªãã®ããç¥ãããã«ãCSRF å¯¾çææ³ãã®ãã®ãçè§£ãããã¨ã大äºã ã¨æ¹ãã¦æãã¾ããã
ã»ãã¥ãªãã£å¯¾çã¯æä»£ã®æµãã¨ã¨ãã«å¤ãã£ã¦ããã®ã§ããããããæ å ±ã追ãã¤ã¤å®é¨ãã¦ããããã¨æãã¾ãã
æå¾ã«ãããè¨äºä¸ã«ééããããã° @zaru ã¾ã§ DM ãããã¯ã¡ã³ã·ã§ã³ããã ããã
