æ£èŠè¡šçŸã¯ã©ãåããŠããïŒãšã³ãžã³ã®ä»çµã¿ã解説
æ£èŠè¡šçŸã£ãŠããèããã©ãããããäœããããã®ãªã®ïŒ
æååã®ãã¿ãŒã³ãæå®ããŠãæ€çŽ¢ã»çœ®æã»æ€èšŒãã§ããä»çµã¿ã ããããšãã°ãã¡ãŒã«ã¢ãã¬ã¹ã£ãœãæååãæ¢ããŠãã¿ãããªææ§ãªèŠæãã`[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-z]+` ãšãããã¿ãŒã³ã§æ£ç¢ºã«è¡šçŸã§ãããã ãããã°ã©ãã³ã°èšèªã®ã»ãšãã©ã«æšæºã§æèŒãããŠãããããã¹ãåŠçã®åºæ¬ããŒã«ã ãã
ãã®èšå·ã®çŸ åã«ãããªæå³ããã£ããã ïŒã§ãäžã§ã¯ã©ããã£ãŠããããèŠã€ããŠãã®ïŒ
æ£èŠè¡šçŸãšã³ãžã³ã®äžæ žã¯ãã¹ããŒããã·ã³ïŒç¶æ æ©æ¢°ïŒãã ãããã¿ãŒã³ãèªã¿èŸŒããšããŸãå éšçã«ç¶æ ã®é·ç§»å³ãäœããã ãããšãã° `abc` ãšãããã¿ãŒã³ãªãããa ãèªãã ãæ¬¡ã®ç¶æ ãžããb ãèªãã ãæ¬¡ãžããc ãèªãã ãäžèŽïŒããšãã3ã¹ãããã®å³ã«ãªãããšã³ãžã³ã¯å ¥åæååã1æåãã€èªã¿ãªããããã®å³ã®äžãç§»åããŠãããã ãã
ç¶æ æ©æ¢°ã«ãçš®é¡ãããã£ãŠèããããšããããã©âŠïŒ
倧ããåããŠNFAïŒéæ±ºå®æ§æéãªãŒãããã³ïŒãšDFAïŒæ±ºå®æ§æéãªãŒãããã³ïŒã®2çš®é¡ãããããDFAã¯åç¶æ ããæ¬¡ã®ç¶æ ã1ã€ã«æ±ºãŸãã®ã§é«éã ãã©ãæ§ç¯ã«ã¡ã¢ãªãšæéãããããNFAã¯1ã€ã®ç¶æ ããè€æ°ã®é·ç§»å ãããããã®ã§ãåå²ã詊ããªããé²ãå¿ èŠããããPythonãJavaScriptãRubyãªã©å€ãã®èšèªã¯NFAããŒã¹ã®ãšã³ãžã³ã䜿ã£ãŠããŠããã®çç±ã¯åŸæ¹åç §ããã£ããã£ã°ã«ãŒããªã©ã®é«æ©èœãå®è£ ãããããããªãã ã
NFAã§åå²ã詊ãã£ãŠãå ·äœçã«ã¯ã©ãããã®ïŒ
ãããã¯ãã©ããã³ã°ïŒåŸæ»ãïŒããšããä»çµã¿ã ããããšãã° `a*b` ãšãããã¿ãŒã³ã§æåå `aaac` ãããããããããšãããšããšã³ãžã³ã¯ãŸã `a*` ã§è²ªæ¬²ã«aãå šéšé£ã¹ãŠããŸããã§ã次㮠`b` ãcãšäžèŽããªããããaã1ã€åãåºããŠåææŠãããããã§ããã¡ãªããã1ã€åãåºããŠâŠãšåŸæ»ãããªããå šãã¿ãŒã³ã詊ããã ããããããªãå Žåã¯å šéšè©ŠããŠãããäžäžèŽããšå€å®ãããã
å šãã¿ãŒã³è©Šãã£ãŠããšã¯ããããé ããªãããšãããã®ïŒ
ããããŸãã«æ£èŠè¡šçŸã®èœãšã穎ã§ãReDoSïŒRegular Expression Denial of ServiceïŒãšåŒã°ããåé¡ã ããããšãã° `(a+)+$` ã®ãããªãã¿ãŒã³ã« `aaaaaaaaaaaaaaaaab` ãäžãããšãããã¯ãã©ããã³ã°ã®çµã¿åãããææ°é¢æ°çã«ççºããŠãCPUãäœåãåºãŸãããšããããããã¯å®éã«æ»æææ³ãšããŠæªçšãããããšããããã ã
ããã£ïŒã¡ãªã¿ã«ã貪欲ããšãæ æ°ãã£ãŠããã®ãããã¯ãã©ããã³ã°ã«é¢ä¿ããã®ïŒ
ãããšããã«æ°ã¥ãããã`*` ã `+` ã¯ããã©ã«ãã§ã貪欲ïŒgreedyïŒããã€ãŸãã§ããã ãå€ãã®æåããããããããšããã`*?` ã `+?` ã®ããã« `?` ãä»ãããšãæ æ°ïŒlazyïŒãã«ãªã£ãŠãã§ããã ãå°ãªããããããããšãããã ãããšãã°HTMLãã `<b>倪å</b>` ãæãåºããšãã`<.*>` ã ãšè²ªæ¬²ã«å šäœãããããããã©ã`<.*?>` ãªãæåã® `<b>` ã ãã«ãããããããã ãæ æ°ã«ããŠãããã¯ãã©ããã³ã°èªäœã¯çºçãããããReDoS察çã«ã¯ãªããªããã
ã¡ãŒã«ã¢ãã¬ã¹ãšãé»è©±çªå·ã®ãã§ãã¯ã«ãæ£èŠè¡šçŸããã䜿ãããïŒããã£ãŠã©ããªã£ãŠãã®ïŒ
ããããäŸãåè§£ããŠã¿ãããé»è©±çªå·ã® `^0\d{1,4}-\d{1,4}-\d{4}$` ã¯ãã0ã§å§ãŸããæ°åã1ã4æ¡ããã€ãã³ãæ°åã1ã4æ¡ããã€ãã³ãæ°å4æ¡ã§çµããããšããæ§é ã ããã¡ãŒã«ã¢ãã¬ã¹ã¯RFCæºæ ã«ãããšæãããè€éã«ãªããããå®åã§ã¯ `^[^@]+@[^@]+\.[^@]+$` ãããã®ããããã§ãã¯ã«ããŠãããšã¯å®éã«ã¡ãŒã«ãéã£ãŠç¢ºèªããã®ããã¹ããã©ã¯ãã£ã¹ã ããæ£èŠè¡šçŸã ãã§å®ç§ãªããªããŒã·ã§ã³ãããããšãããšæ²Œã«ããããã ã
å èªã¿ãšãåŸèªã¿ã£ãŠããæ©èœãããã£ãŠèãããã©ãããã¯äœïŒ
å èªã¿ïŒlookaheadïŒãšåŸèªã¿ïŒlookbehindïŒã¯ããããã¯ãããã©æ¶è²»ããªããç¹æ®ãªæ¡ä»¶ã ããããšãã° `\d+(?=å)` ã¯ãåãã®åã«ããæ°åã«ããããããã©ããããçµæã«ãåãã¯å«ãŸããªãããã¹ã¯ãŒãã®åŒ·åºŠãã§ãã¯ã§ãè±å€§æåã»å°æåã»æ°åããã¹ãŠå«ããã¿ãããªè€åæ¡ä»¶ã1ã€ã®æ£èŠè¡šçŸã§æžããšãã«éå®ãããã ã`(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}` ã®ããã«å èªã¿ã䞊ã¹ããšãANDæ¡ä»¶ãšããŠæ©èœãããã
䟿å©ã ãã©ãæ£èŠè¡šçŸã䜿ããªãã»ããããå Žé¢ã£ãŠããã®ïŒ
ããããããããHTMLãXMLã®ããŒã¹ã¯æ£èŠè¡šçŸã ãã§ã¯æ£ç¢ºã«ã§ããªãããJSONãCSVã«ãå°çšããŒãµãŒã䜿ãã¹ãã ããããšåºå®æååã®æ€çŽ¢ãªã `indexOf` ã `includes` ã®ã»ããå§åçã«éããæ£èŠè¡šçŸãåŸæãªã®ã¯ããã¿ãŒã³ãå¯å€ã§ããã€ããã¹ããæ§é åãããŠããªããã±ãŒã¹ã ãããã°ãã¡ã€ã«ããç¹å®ã®ãšã©ãŒãã¿ãŒã³ãæœåºãããšãããŠãŒã¶ãŒå ¥åã®ç°¡æããªããŒã·ã§ã³ãšããäžèœã«èŠããŠã䜿ãã©ãããéžã¶ããŒã«ãªãã ã
å®éã«æ£èŠè¡šçŸã®ããã§å€§äºæ ã«ãªã£ãã±ãŒã¹ã£ãŠããã®ïŒ
æåãªã®ã¯2019幎ã®Cloudflareã®é害ã ããWAFïŒWebã¢ããªã±ãŒã·ã§ã³ãã¡ã€ã¢ãŠã©ãŒã«ïŒã®ã«ãŒã«ã«è¿œå ãããæ£èŠè¡šçŸã«ã«ã¿ã¹ãããã£ãã¯ã»ããã¯ãã©ããã³ã°ãçºçããŠãäžçäžã®Cloudflareå©çšãµã€ããçŽ27åéããŠã³ãããã ãåå 㯠`(?:(?:\")+)+` ã®ãããªãã¹ãããéæå®åã§ãå ¥åã«ãã£ãŠã¯ææ°é¢æ°çã«CPUãæ¶è²»ãããã¿ãŒã³ã ã£ãããã®äºä»¶ä»¥éãCloudflareã¯ããã¯ãã©ããã³ã°ããªããšã³ãžã³ïŒRustã®regexã¯ã¬ãŒãçïŒãžã®ç§»è¡ãé²ãããã
äžçèŠæš¡ã®éå®³ãæ£èŠè¡šçŸ1ã€ã§âŠïŒå¯ŸçãšããŠã¯ã©ãããã°ããã®ïŒ
ãŸãããã¹ãããéæå®åããé¿ããããšã`(a+)+` ã `(a*)*` ã®ãããªãã¿ãŒã³ã¯å±éºä¿¡å·ã ããæ¬¡ã«ãã¢ãããã¯ã°ã«ãŒã `(?>...)` ãææéæå®å `*+` ã䜿ãããšã³ãžã³ãªãããã¯ãã©ããã³ã°ãå¶åŸ¡ã§ãããããã«æ ¹æ¬çãªå¯ŸçãšããŠã¯ãRE2ãRustã®regexã¯ã¬ãŒãã®ããã«ããã¯ãã©ããã³ã°ããªããšã³ãžã³ãéžã¶æ¹æ³ãããããããã¯NFAã§ã¯ãªãDFAããŒã¹ã§åããããã©ããªå ¥åã§ãç·åœ¢æéã§åŠçãå®äºãããã ãã»ãã¥ãªãã£ãéèŠãªã·ã¹ãã ã§ã¯ããšã³ãžã³éžå®ããèããã®ãçŸä»£ã®ãã¹ããã©ã¯ãã£ã¹ã ãã