Re: Generate JWTs with Django

2020-04-27 Thread Tom Forbes
Thank you for the fantastic summary James. You’re spot on about the various 
implementation issues that plague JWT libraries.

While I think it’s an OK technology if you use a very explicit subset and you 
know what you’re doing (see https://github.com/google/jws) it is indeed a bit 
of a minefield and I’m not sure we should be promoting it.

That being said, are signed cookies really a suitable replacement for JWTs? 
Right off the bat there is a size limit that’s shared with other cookies on 
your domain, and you might not want to (or be able to) encode the data in a 
cookie to begin with.

Maybe we can update the docs to show how you you would might use some of the 
signing primitives instead of JWTs, but this also sounds a bit dangerous 🤷‍♂️ 

>> On 27 Apr 2020, at 03:53, James Bennett  wrote:
> On Sun, Apr 26, 2020 at 8:46 AM Adam Johnson  wrote:
>> 
>> James, I too would like to know your criticisms! I've always understood that 
>> they aren't much different to signed cookies, but I haven't looked too 
>> deeply at them.
> 
> Well, people asked. So.
> 
> The short summary is: JWT is over-complex, puts too much power in the
> attacker's hands, has too many configuration knobs, and makes poor
> cryptographic choices. This is why we see vulnerabilities in JWT
> libraries and JWT-using systems again and again and again.
> 
> And even if you get every single bit of it right, in the ideal perfect
> world with the ideal perfect implementation, the payoff is you've put
> in a ton of work to get something that already existed: signed
> cookies, for the use case of session identification, or any of several
> better token or token-like systems -- everything from PASETO to just
> timestamped HMAC'd values -- for the use case of inter-service
> communication.
> 
> The longer version goes more like this...
> 
> JWT is a more complex thing than many people appreciate. In fact, it's
> at least *five* things, each specified in its own RFC, plus some more
> you have to know about and implement if you want any hope of getting
> the actually-sorta-secure version. And right off the bat, that's
> worrying: the more different things you have to implement, and the
> more places you have to look to find out what and how to implement,
> the more opportunities there are to make mistakes.
> 
> This complexity comes from the sheer number of different options JWT
> tries to support, which in turn is an anti-pattern. JWTs may be
> signed, or they may not. They may be encrypted, or they may not. There
> are multiple different options for how to sign, how to encrypt, how to
> manage and specify keys... in a well-designed system there would be
> far fewer options. Ideally, there'd be only one option, and the
> solution for a vulnerability being found in it would be to increment
> the version of the underlying spec, and change to something
> better.
> 
> Anyway. In JWT, signature and encryption schemes are effectively
> negotiable, which is yet another anti-pattern: you are putting
> enormous power in the hands of attackers to negotiate you down to a
> bad, or nonexistent, cipher/algorithm for encryption or signing. TLS/SSL
> learned this lesson the hard way; JWT has chosen not to learn it at
> all. Worse, JWT embeds the negotiation about how to handle the token
> into the token itself. This is just asking for trouble, and in fact
> trouble has routinely occurred. As a somewhat sarcastic author of my
> acquaintance put it:
> 
>> It is extraordinarily easy to screw up JWT. JWT is a JSON format
>> where you have to parse and interpret a JSON document to figure out
>> how to decrypt and authenticate a JSON document. It has revived bugs
>> we thought long dead, like “repurposing asymmetric public keys as
>> symmetric private keys”.
> 
> (from: https://latacora.micro.blog/a-childs-garden/)
> 
> More succinctly: JWTs inherently and unavoidably violate the
> Cryptographic Doom Principle
> (https://moxie.org/blog/the-cryptographic-doom-principle/). Worse,
> JWTs put full control of the violation in the hands of the attacker,
> who -- thanks to the high level of configurability JWT offers -- is
> free to find the set of options most likely to compromise you, and
> foist them on you.
> 
> That quoted line above about revived long-dead bugs is no joke,
> incidentally. Here's one from a few years back:
> 
> https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
> 
> Five different libraries, written in three different languages, all
> had the same bug. I once had the misfortune of arguing with someone
> who attributed this to the libraries being built by bad programmers,
> or in bad languages. But I personally tend to agree with a line from
> this talk:
> 
> https://www.okta.com/video/oktane19-cryptographic-wrong-answers/
> 
>> Now you can say look those are all implementation vulnerabilities,
>> it's not actually JWTs fault, I disagree. If I can find the same
>> vulnerability in five popular libraries, then maybe the spec d

Re: Generate JWTs with Django

2020-04-27 Thread Steven Mapes
I completely agree with James. I felt dread when I saw a JWT Thread appear 
as, for me synonymous with flaws security and I'd rather Django stay well 
clear of them

On Monday, 27 April 2020 03:53:39 UTC+1, James Bennett wrote:
>
> On Sun, Apr 26, 2020 at 8:46 AM Adam Johnson > 
> wrote: 
> > 
> > James, I too would like to know your criticisms! I've always understood 
> that they aren't much different to signed cookies, but I haven't looked too 
> deeply at them. 
>
> Well, people asked. So. 
>
> The short summary is: JWT is over-complex, puts too much power in the 
> attacker's hands, has too many configuration knobs, and makes poor 
> cryptographic choices. This is why we see vulnerabilities in JWT 
> libraries and JWT-using systems again and again and again. 
>
> And even if you get every single bit of it right, in the ideal perfect 
> world with the ideal perfect implementation, the payoff is you've put 
> in a ton of work to get something that already existed: signed 
> cookies, for the use case of session identification, or any of several 
> better token or token-like systems -- everything from PASETO to just 
> timestamped HMAC'd values -- for the use case of inter-service 
> communication. 
>
> The longer version goes more like this... 
>
> JWT is a more complex thing than many people appreciate. In fact, it's 
> at least *five* things, each specified in its own RFC, plus some more 
> you have to know about and implement if you want any hope of getting 
> the actually-sorta-secure version. And right off the bat, that's 
> worrying: the more different things you have to implement, and the 
> more places you have to look to find out what and how to implement, 
> the more opportunities there are to make mistakes. 
>
> This complexity comes from the sheer number of different options JWT 
> tries to support, which in turn is an anti-pattern. JWTs may be 
> signed, or they may not. They may be encrypted, or they may not. There 
> are multiple different options for how to sign, how to encrypt, how to 
> manage and specify keys... in a well-designed system there would be 
> far fewer options. Ideally, there'd be only one option, and the 
> solution for a vulnerability being found in it would be to increment 
> the version of the underlying spec, and change to something 
> better. 
>
> Anyway. In JWT, signature and encryption schemes are effectively 
> negotiable, which is yet another anti-pattern: you are putting 
> enormous power in the hands of attackers to negotiate you down to a 
> bad, or nonexistent, cipher/algorithm for encryption or signing. TLS/SSL 
> learned this lesson the hard way; JWT has chosen not to learn it at 
> all. Worse, JWT embeds the negotiation about how to handle the token 
> into the token itself. This is just asking for trouble, and in fact 
> trouble has routinely occurred. As a somewhat sarcastic author of my 
> acquaintance put it: 
>
> > It is extraordinarily easy to screw up JWT. JWT is a JSON format 
> > where you have to parse and interpret a JSON document to figure out 
> > how to decrypt and authenticate a JSON document. It has revived bugs 
> > we thought long dead, like “repurposing asymmetric public keys as 
> > symmetric private keys”. 
>
> (from: https://latacora.micro.blog/a-childs-garden/) 
>
> More succinctly: JWTs inherently and unavoidably violate the 
> Cryptographic Doom Principle 
> (https://moxie.org/blog/the-cryptographic-doom-principle/). Worse, 
> JWTs put full control of the violation in the hands of the attacker, 
> who -- thanks to the high level of configurability JWT offers -- is 
> free to find the set of options most likely to compromise you, and 
> foist them on you. 
>
> That quoted line above about revived long-dead bugs is no joke, 
> incidentally. Here's one from a few years back: 
>
>
> https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ 
>
> Five different libraries, written in three different languages, all 
> had the same bug. I once had the misfortune of arguing with someone 
> who attributed this to the libraries being built by bad programmers, 
> or in bad languages. But I personally tend to agree with a line from 
> this talk: 
>
> https://www.okta.com/video/oktane19-cryptographic-wrong-answers/ 
>
> > Now you can say look those are all implementation vulnerabilities, 
> > it's not actually JWTs fault, I disagree. If I can find the same 
> > vulnerability in five popular libraries, then maybe the spec did a 
> > bad job of making sure people avoided that vulnerability. 
>
> So to completely head off the "it's just bad implementations" 
> argument, let's turn to the specs themselves: RFCs 7515, 7516, 7517, 
> 7518, and 7519 are the core specifications that make up with is 
> commonly called "JWT" (and in RFC-land is more properly called "JOSE" 
> -- "JSON Object Signing and Encryption", of which the token format is 
> but one part). 
>
> The JOSE RFCs make a number of choices regarding default sets of 
> stand

Re: Generate JWTs with Django

2020-04-27 Thread Adam Johnson
Thank you very much James. I've learned once again that "everyone is using
it" does not make it good.

(Would love if you pasted your write up on your blog to make it easier to
share)

On Mon, 27 Apr 2020 at 10:37, Steven Mapes  wrote:

> I completely agree with James. I felt dread when I saw a JWT Thread appear
> as, for me synonymous with flaws security and I'd rather Django stay well
> clear of them
>
> On Monday, 27 April 2020 03:53:39 UTC+1, James Bennett wrote:
>>
>> On Sun, Apr 26, 2020 at 8:46 AM Adam Johnson  wrote:
>> >
>> > James, I too would like to know your criticisms! I've always understood
>> that they aren't much different to signed cookies, but I haven't looked too
>> deeply at them.
>>
>> Well, people asked. So.
>>
>> The short summary is: JWT is over-complex, puts too much power in the
>> attacker's hands, has too many configuration knobs, and makes poor
>> cryptographic choices. This is why we see vulnerabilities in JWT
>> libraries and JWT-using systems again and again and again.
>>
>> And even if you get every single bit of it right, in the ideal perfect
>> world with the ideal perfect implementation, the payoff is you've put
>> in a ton of work to get something that already existed: signed
>> cookies, for the use case of session identification, or any of several
>> better token or token-like systems -- everything from PASETO to just
>> timestamped HMAC'd values -- for the use case of inter-service
>> communication.
>>
>> The longer version goes more like this...
>>
>> JWT is a more complex thing than many people appreciate. In fact, it's
>> at least *five* things, each specified in its own RFC, plus some more
>> you have to know about and implement if you want any hope of getting
>> the actually-sorta-secure version. And right off the bat, that's
>> worrying: the more different things you have to implement, and the
>> more places you have to look to find out what and how to implement,
>> the more opportunities there are to make mistakes.
>>
>> This complexity comes from the sheer number of different options JWT
>> tries to support, which in turn is an anti-pattern. JWTs may be
>> signed, or they may not. They may be encrypted, or they may not. There
>> are multiple different options for how to sign, how to encrypt, how to
>> manage and specify keys... in a well-designed system there would be
>> far fewer options. Ideally, there'd be only one option, and the
>> solution for a vulnerability being found in it would be to increment
>> the version of the underlying spec, and change to something
>> better.
>>
>> Anyway. In JWT, signature and encryption schemes are effectively
>> negotiable, which is yet another anti-pattern: you are putting
>> enormous power in the hands of attackers to negotiate you down to a
>> bad, or nonexistent, cipher/algorithm for encryption or signing. TLS/SSL
>> learned this lesson the hard way; JWT has chosen not to learn it at
>> all. Worse, JWT embeds the negotiation about how to handle the token
>> into the token itself. This is just asking for trouble, and in fact
>> trouble has routinely occurred. As a somewhat sarcastic author of my
>> acquaintance put it:
>>
>> > It is extraordinarily easy to screw up JWT. JWT is a JSON format
>> > where you have to parse and interpret a JSON document to figure out
>> > how to decrypt and authenticate a JSON document. It has revived bugs
>> > we thought long dead, like “repurposing asymmetric public keys as
>> > symmetric private keys”.
>>
>> (from: https://latacora.micro.blog/a-childs-garden/)
>>
>> More succinctly: JWTs inherently and unavoidably violate the
>> Cryptographic Doom Principle
>> (https://moxie.org/blog/the-cryptographic-doom-principle/). Worse,
>> JWTs put full control of the violation in the hands of the attacker,
>> who -- thanks to the high level of configurability JWT offers -- is
>> free to find the set of options most likely to compromise you, and
>> foist them on you.
>>
>> That quoted line above about revived long-dead bugs is no joke,
>> incidentally. Here's one from a few years back:
>>
>>
>> https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
>>
>> Five different libraries, written in three different languages, all
>> had the same bug. I once had the misfortune of arguing with someone
>> who attributed this to the libraries being built by bad programmers,
>> or in bad languages. But I personally tend to agree with a line from
>> this talk:
>>
>> https://www.okta.com/video/oktane19-cryptographic-wrong-answers/
>>
>> > Now you can say look those are all implementation vulnerabilities,
>> > it's not actually JWTs fault, I disagree. If I can find the same
>> > vulnerability in five popular libraries, then maybe the spec did a
>> > bad job of making sure people avoided that vulnerability.
>>
>> So to completely head off the "it's just bad implementations"
>> argument, let's turn to the specs themselves: RFCs 7515, 7516, 7517,
>> 7518, and 7519 are the core specifications that

Re: Fellow Reports - April 2020

2020-04-27 Thread Mariusz Felisiak
Week ending April 26, 2020.

*Triaged:*
https://code.djangoproject.com/ticket/31480 - Accessing admin panel doesn't 
work. (worksforme)
https://code.djangoproject.com/ticket/31481 - Admin crash when using 
functions in model meta ordering of o2o primary key. (fixed)
https://code.djangoproject.com/ticket/31483 - Remove admin change_form.js 
dependency on jQuery. (accepted)
https://code.djangoproject.com/ticket/31484 - Possibility to provide 
additional Context to Render a FlatPage. (wontfix)
https://code.djangoproject.com/ticket/31478 - Template.get_exception_info() 
relies on internal state which isn't correct for sub-templates. (duplicate)
https://code.djangoproject.com/ticket/31485 - Update admin's jQuery to 
3.5.X. (created)
https://code.djangoproject.com/ticket/31489 - Django Admin showing "Date 
input" for Time Field in Mobile Safari. (duplicate)
https://code.djangoproject.com/ticket/31492 - Changing field type can cause 
unrelated nullability change in field on Oracle. (created)
https://code.djangoproject.com/ticket/31491 - dbshell command for MySQL 
backend uses "passwd" instead of "password". (accepted)
https://code.djangoproject.com/ticket/31496 - Combined queryset crash when 
chaining `values()` after `order_by()` with annotated constantants. 
(accepted)
https://code.djangoproject.com/ticket/31499 - Store ModeState.fields into a 
dict. (accepted)
https://code.djangoproject.com/ticket/31497 - get_static_prefix() as 
variable in a template doesn't work. (worksforme)
https://code.djangoproject.com/ticket/31498 - GenericRelation's 
get_internal_type() incorrectly reports "ManyToManyField". (wontfix)
https://code.djangoproject.com/ticket/31500 - Allow QuerySet.in_bulk() for 
fields with total UniqueConstraints. (accepted)
https://code.djangoproject.com/ticket/24691 - Document model._state.adding 
(since UUIDField sets value before save) (duplicate)
https://code.djangoproject.com/ticket/31502 - Document Model._state.db and 
Model._state.adding. (accepted)
https://code.djangoproject.com/ticket/31506 - ExpressionWrapper() doesn't 
respect output_field when combining DateField and timedelta on PostgreSQL 
and MySQL. (accepted)
https://code.djangoproject.com/ticket/31507 - Augment QuerySet.exists() 
optimizations to .union().exists(). (accepted)
https://code.djangoproject.com/ticket/31505 - Document possible email 
address enumeration in PasswordResetView. (accepted)
https://code.djangoproject.com/ticket/31510 - server is not working 
properly for admin panel. (duplicate)
https://code.djangoproject.com/ticket/31511 - Allow stopwords in slugs 
generated by ModelAdmin.prepopulated_fields (duplicate)
https://code.djangoproject.com/ticket/31512 - Django TextChoices cannot 
utilize `is` or `==` isn't explicitly stated. (invalid)
https://code.djangoproject.com/ticket/31514 - Correct default forms fields 
in model fields docs. (accepted)

*Reviewed/committed:*
https://github.com/django/django/pull/12751 - Refs #29069 -- Added test for 
calling request_finished signal by static file responses.
https://github.com/django/django/pull/12756 - Fixed #24559 -- Made 
MigrationLoader.load_disk() catch more specific ModuleNotFoundError.
https://github.com/django/django/pull/12741 - Fixed #31477 -- Removed 
"using" argument from DatabaseOperations.execute_sql_flush().
https://github.com/django/django/pull/12742 - Disabled management commands 
output with verbosity 0 in various tests.
https://github.com/django/django/pull/12747 - Fixed #31474 -- Made 
QuerySet.delete() not return the number of deleted objects if it's zero.
https://github.com/django/django/pull/12746 - Refs #22463 -- Replaced 
JSHint with ESLint in contributing docs.
https://github.com/django/django/pull/12734 - Fixed #31064 -- Recreated 
auto-created relationships on type change on SQLite.
https://github.com/django/django/pull/12748 - Fixed #31479 -- Added support 
to reset sequences on SQLite.
https://github.com/django/django/pull/12771 - Fixed #31499 -- Stored 
ModelState.fields into a dict.
https://github.com/django/django/pull/12774 - Fixed #31500 -- Fixed 
detecting of unique fields in QuerySet.in_bulk() when using 
Meta.constraints.
https://github.com/django/django/pull/12708 - Fixed #29224 -- Fixed 
removing index_together indexes if exists unique_together constraint on the 
same fields.
https://github.com/django/django/pull/12788 - Refs #31369 -- Deprecated 
models.NullBooleanField in favor of BooleanField(null=True).
https://github.com/django/django/pull/12790 - Fixed #31514 -- Fixed default 
form widgets in model fields docs.

*Authored:*
https://github.com/django/django/pull/12758 - Fixed #31485 -- Updated 
admin's jQuery to 3.5.0.
https://github.com/django/django/pull/12762 - Updated admin's XRegExp to 
3.2.0.
https://github.com/django/django/pull/12780 - Fixed #31505 -- Doc'd 
possible email addresses enumeration in PasswordResetView.

Best regards,
Mariusz

-- 
You received this message because you are subscribed to the Google Groups 
"Django d