I would be +1 to what Adam wrote from me i.e. just allow the value to
accept floats.
However, I don't think it will work due to the way that we round the
precision of timestamps to days
<https://github.com/django/django/blob/master/django/contrib/auth/tokens.py#L21>.
This was done partly to reduce the number of characters needed to
express the timestamp, to keep URLs as short as possible. We would have
to change the mechanism to store more precision into the timestamp. This
would result in an upgrade 'bump' for users (i.e. links generated before
the upgrade would become invalid after upgrade).
However, I really question whether we need any change here, and whether
it would be a good idea.
Having a short expiration time (less than 1 hour) could cause major
problems for some people - plenty of systems introduce 5 or 10 minute
delays in mail delivery, and with some people's internet connection it
can take several minutes to open a web page. This also means that some
people end up finishing the process of whatever they were doing the next
day (I know I've done this several times on various sites), so a timeout
of at least 1 or 2 days is a good default. If you want to come back
after the weekend and carry on, 3 days makes more sense as a minimum.
In terms of security, I don't think there is really any need for anyone
to reduce below the default at all (see below). So I'm very unconvinced
about the need for changing to PASSWORD_RESET_TIMEOUT - it is just
unnecessary upgrade work for some existing projects (this is the biggest
consideration for me), and it could encourage people to set the value to
something low that would decrease usability.
*Security:*
The security of the password reset feature is almost entirely
independent of the value of the timeout setting. There are 3 attack
vectors I can see:
1) Someone's email account is compromised, and they then do a password
reset on a Django site.
We simply can't protect against this AFAICS.
2) Someone's email account is compromised, and they find/use a password
reset email in the person's inbox.
This is the only scenario for which having a shorter timeout makes a
difference. It is somewhat unlikely, because in 99% of cases the
attacker would be able to generate a password reset email themselves
after compromising the account. For this narrow case where the attacker
is unwilling/unable to trigger/receive a new password reset email, it is
worth having some protection against them being able to use old tokens,
but 3 days seems plenty short enough for this situation, especially
given the fact that a *used* password reset token immediately becomes
invalid due to the way we hash on internal state of the user record.
3) A brute force attack.
To do this, the attacker has to:
1. Supply a user ID (let's assume this is easy)
2. ***Choose*** a timestamp (very easy, just choose the current time)
3. Create a 20 character hexadecimal hmac that matches both the
timestamp and the internal state of the user (see
https://github.com/django/django/blob/master/django/contrib/auth/tokens.py
).
Since the attacker can choose the timestamp, the probability of guessing
correctly depends **only** on:
1. The number of bits in the hash (20*4 = 80)
2. The number of attempts (or, the number of requests per second
possible and the time available)
It does **not** depend on the value of the reset timeout **at all**.
If we assume they can make 100 req/s, and they try continuously for 10
years, they've got a chance of around 1 in 10^13.
In other words, I reject the premise of the ticket, which is that to
improve security some people need to reduce the timeout. It makes
virtually no difference to the security of this feature, and in fact you
would be protected against almost all realistic attacks if there was no
timeout. I imagine that the requirement of "meeting security
requirements" mentioned on the ticket is due to people who think this
works like a short, 6 digit OTP, for which 3 days would be far too long
( see https://sakurity.com/blog/2015/07/18/2fa.html ). We could put a
note in the docs about this, I don't know how to do that in a succinct
way apart from to link to a copy of this email or something.
However, if we really do 'need' this change, we should at least keep the
default to what it is now, and put a notice in the docs saying that
reducing it hurts usability and makes no practical difference to
security. Since we would be causing an upgrade bump and breaking
existing links, we may as well also switch to TimestampSigner (the
password reset code was originally written before that existed), which
would also mean changing urlconfs I imagine. This would also require a
significant section in the upgrade notes. (In my book, this is a further
argument against doing this change at all).
Regards,
Luke
On 21/09/17 12:25, Adam Johnson wrote:
Why not just keep PASSWORD_RESET_TIMEOUT_DAYSand allow floats? Then
you can just do 1/24 for an hour.
On 21 September 2017 at 09:50, Eddy C <[email protected]
<mailto:[email protected]>> wrote:
I think Minute, with default value 30 or 60, is the best unit for
this setting.
3 minutes (even 1) is short enough for edge case and 720 (12
hours) also looks good.
On Thursday, September 21, 2017 at 6:22:20 PM UTC+10, Tom Forbes
wrote:
I think we shouldn't shoe-horn a timedelta into the existing
setting, so my vote is with the second option, but I think a
timedelta is much more readable than just an integer.
Also, the existing 3 day timeout for password links is quite
surprising from a security point of view. The consultants I
work with would flag up a token that lasts longer than 12
hours as an issue during a pentest.
IMO a new, far shorter default should be added to this setting.
On 21 Sep 2017 03:56, "Zhiqiang Liu" <[email protected]> wrote:
I need general consensus on how to proceed with supporting
password expire time to be under a day. Currently it is
not possible because we use PASSWORD_RESET_TIMEOUT_DAYS.
In ticket 28622
<https://code.djangoproject.com/ticket/28622> we have two
options.
One is to continue to use the same setting
PASSWORD_RESET_TIMEOUT_DAYS, but change the value to
non-integer (such as timedelta) so we can send hours,
minutes, etc to it.
The other one is to create a new setting like
PASSWORD_RESET_TIMEOUT which takes seconds.To support
backward compatibility, I think we should keep
PASSWORD_RESET_TIMEOUT_DAYS and its default value of 3.
Only use PASSWORD_RESET_TIMEOUT when provided.
I'm unsure which one is better, so inputs are welcome.
--
You received this message because you are subscribed to
the Google Groups "Django developers (Contributions to
Django itself)" group.
To unsubscribe from this group and stop receiving emails
from it, send an email to [email protected].
To post to this group, send email to
[email protected].
Visit this group at
https://groups.google.com/group/django-developers
<https://groups.google.com/group/django-developers>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/c8e96008-eb95-4924-8e5e-9b02d6b90c99%40googlegroups.com
<https://groups.google.com/d/msgid/django-developers/c8e96008-eb95-4924-8e5e-9b02d6b90c99%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.
--
You received this message because you are subscribed to the Google
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to [email protected]
<mailto:[email protected]>.
To post to this group, send email to
[email protected]
<mailto:[email protected]>.
Visit this group at
https://groups.google.com/group/django-developers
<https://groups.google.com/group/django-developers>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/6d0d4251-64bc-40a0-b191-9cf3dfe8c91b%40googlegroups.com
<https://groups.google.com/d/msgid/django-developers/6d0d4251-64bc-40a0-b191-9cf3dfe8c91b%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.
--
Adam
--
You received this message because you are subscribed to the Google
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to [email protected]
<mailto:[email protected]>.
To post to this group, send email to
[email protected]
<mailto:[email protected]>.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/CAMyDDM2Y-krvLkKwxvNp%3DEuLa-oMDhuB%2BkxABwE5Ae76LOPPdw%40mail.gmail.com
<https://groups.google.com/d/msgid/django-developers/CAMyDDM2Y-krvLkKwxvNp%3DEuLa-oMDhuB%2BkxABwE5Ae76LOPPdw%40mail.gmail.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Django
developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/f0529113-95f6-8383-fc18-f590985b1582%40cantab.net.
For more options, visit https://groups.google.com/d/optout.