ReDoSとは
なにこれこわい
検証
ipythonでやってみる
import re
from datetime import datetime
n = 5
while n < 12:
s = "username@host{}.".format(".abcde" * n)
start = datetime.now()
print(re.match(r"\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z", s, flags=re.IGNORECASE))
print('{}: {}'.format(len(s), (datetime.now() - start).total_seconds()))
n += 1
実行結果
None
44: 0.085964
None
50: 0.41799
None
56: 2.106463
None
62: 10.319476
None
68: 57.825968
None
74: 269.451777
None
80: 1400.865988
まじで指数関数的に増えてる。こえー
Django の EmailValidator でもやってみる
from datetime import datetime
from django.core.exceptions import ValidationError
from django.core.validators import EmailValidator
validator = EmailValidator()
n = 5
while n < 12:
s = "username@host{}.".format(".abcde" * n)
start = datetime.now()
try:
validator(s)
print(True)
except ValidationError:
print(False)
print('{}: {}'.format(len(s), (datetime.now() - start).total_seconds()))
n += 1
実行結果
False
44: 0.015296
False
50: 0.000116
False
56: 9.3e-05
False
62: 0.000127
False
68: 0.00016
False
74: 0.000122
False
80: 0.000125
お、大丈夫そう。
ついでに自作のValidatorもやってみる
import re
from datetime import datetime
from django.core.exceptions import ValidationError
from django.core.validators import EmailValidator
class JapaneseEmailValidator(EmailValidator):
user_regex = re.compile(
r"(^[-.!#$%&'*+/=?^_`{}|~0-9A-Z]+$" # dot-atom
r"|^\"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*\"$)", # quoted-string
re.IGNORECASE
)
validator = JapaneseEmailValidator()
n = 5
while n < 12:
s = "username@host{}.".format(".abcde" * n)
start = datetime.now()
try:
validator(s)
print(True)
except ValidationError:
print(False)
print('{}: {}'.format(len(s), (datetime.now() - start).total_seconds()))
n += 1
実行結果
False
44: 0.00613
False
50: 9.8e-05
False
56: 8.6e-05
False
62: 9.9e-05
False
68: 0.000127
False
74: 0.000145
False
80: 0.000105
まとめ
セキュアプログラミングとか気をつけないとね
よくわからないときは、Django公式のvalidatorとかにしておけばいいんじゃね
80文字で1400sec(23min20sec)とかないわー