Se você pode decodificar o JWT, como eles são seguros?


302

Se eu receber um JWT e puder decodificar a carga, como isso é seguro? Eu não poderia simplesmente pegar o token do cabeçalho, decodificar e alterar as informações do usuário na carga útil e enviá-lo de volta com o mesmo segredo codificado correto?

Eu sei que eles devem ser seguros, mas eu realmente gostaria de entender as tecnologias. o que estou perdendo?


2
md5('original messaged' + secret) != md5('changed message' + secret)portanto, se alguém alterar a mensagem, você poderá detectá-la #
Pithikos

verdadeiro para um caso ideal, no entanto, o md5 tem colisões. @Pithikos
Yash Kumar Verma

@YashKumarVerma sim, é apenas para demonstrar a essência disso, já que todo mundo conhece o MD5.
Pithikos

1
@ user1955934 é codificado em base64, NÃO criptografado. Você pode simplesmente decodificá-lo com qualquer decodificador base64.
Pithikos

1
então o cliente precisará enviar o hash e o token jwt? e, mais tarde, no lado do servidor, eles tentarão fazer o hash do token jwt usando segredo e comparar com o hash?
user1955934

Respostas:


387

Os JWTs podem ser assinados, criptografados ou ambos. Se um token é assinado, mas não criptografado, todos podem ler seu conteúdo, mas quando você não conhece a chave privada, não pode alterá-lo. Caso contrário, o destinatário notará que a assinatura não corresponderá mais.

Resposta ao seu comentário: Não tenho certeza se entendi o seu comentário da maneira certa. Só para ter certeza: você conhece e entende assinaturas digitais? Vou explicar brevemente uma variante (HMAC, que é simétrica, mas existem muitas outras).

Vamos supor que Alice queira enviar um JWT para Bob. Ambos sabem algum segredo compartilhado. Mallory não conhece esse segredo, mas quer interferir e mudar o JWT. Para evitar isso, Alice calcula Hash(payload + secret)e acrescenta isso como assinatura.

Ao receber a mensagem, Bob também pode calcular Hash(payload + secret)para verificar se a assinatura corresponde. Se, no entanto, Mallory alterar algo no conteúdo, ela não poderá calcular a assinatura correspondente (o que seria Hash(newContent + secret)). Ela não conhece o segredo e não tem como descobrir. Isso significa que, se ela mudar alguma coisa, a assinatura não corresponderá mais e Bob simplesmente não aceitará mais o JWT.

Suponhamos que eu envie a mensagem a outra pessoa {"id":1}e assine-a Hash(content + secret). (+ é apenas concatenação aqui). Eu uso a função SHA256 Hash, ea assinatura que recebo é: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c. Agora é sua vez: faça o papel de Mallory e tente assinar a mensagem {"id":2}. Você não pode porque não sabe qual segredo eu usei. Se eu suponho que o destinatário conhece o segredo, ele PODE calcular a assinatura de qualquer mensagem e verificar se está correto.


8
Então a assinatura é alterada quando a carga útil é alterada? Fiquei com a impressão de que o token estava no formato [cabeçalho]. [Carga]. [Assinatura] a assinatura é calculada pela combinação da carga e do segredo? Se fosse esse o caso, uma carga útil com um ID diferente não seria a mesma para esse segredo? Como se os dados fossem {id: 1} e fossem usados ​​para calcular a parte da assinatura do token com o segredo, isso não significaria que {id: 2} seria válido para o usuário 2 e, portanto, o usuário 1 poderia mudar id para 2 e o token seria o mesmo?
precisa saber é o seguinte

7
Dei a você um exemplo para tornar as coisas ainda mais claras, mas não explicarei todo o conceito de assinaturas digitais e HMACs para você. Por favor, leia sobre essas coisas, há muito material explicando isso.
Misch

11
Oh, eu entendo agora. Não sei por que estava perdendo a ideia de que o hash secreto não estaria correto quando você alterou a carga, porque o hash secreto precisaria ser recalculado. Por alguma razão, eu ainda estava pensando que era independente. Aquele último pedaço realmente perfurou tudo para mim. Obrigado por me orientar.
PixMach 5/12/14

30
Eu tenho uma questão relacionada. O que está impedindo alguém de se passar por Alice com o JWT copiado?
Morrowless 23/08/16

25
Se alguém tem o JWT, pode se passar por Alice. Portanto, você precisa ter cuidado com o armazenamento e o envio. Você também deve definir um prazo para isso na carga útil. Dessa forma, se alguém rouba o JWT, ele tem um prazo limitado para usá-lo. Dê uma olhada em stormpath.com/blog/…
Geraint Anderson

134

Você pode ir para jwt.io, colar seu token e ler o conteúdo. Isso é chocante para muitas pessoas inicialmente.

A resposta curta é que o JWT não se preocupa com criptografia. Ele se preocupa com a validação. Ou seja, ele sempre pode obter a resposta para "O conteúdo desse token foi manipulado"? Isso significa que a manipulação do token JWT pelo usuário é inútil porque o servidor conhecerá e desconsiderará o token. O servidor adiciona uma assinatura com base na carga útil ao emitir um token para o cliente. Posteriormente, verifica a carga útil e a assinatura correspondente.

A questão lógica é: qual é a motivação para não se preocupar com o conteúdo criptografado?

  1. A razão mais simples é porque assume que esse é um problema resolvido na maior parte. Se estiver lidando com um cliente como o navegador da web, por exemplo, você poderá armazenar os tokens JWT em um cookie que é secure(não é transmitido via HTTP, apenas via HTTPS) e httpOnly(não pode ser lido por Javascript) e conversa com o servidor um canal criptografado (HTTPS). Depois de saber que possui um canal seguro entre o servidor e o cliente, você pode trocar com segurança o JWT ou qualquer outra coisa que desejar.

  2. Isso mantém as coisas simples. Uma implementação simples facilita a adoção, mas também permite que cada camada faça o que faz melhor (deixe o HTTPS manipular a criptografia).

  3. O JWT não se destina a armazenar dados confidenciais. Depois que o servidor recebe o token JWT e o valida, é gratuito procurar o ID do usuário em seu próprio banco de dados para obter informações adicionais para esse usuário (como permissões, endereço postal, etc.). Isso mantém o JWT pequeno em tamanho e evita vazamentos inadvertidos de informações, porque todo mundo sabe que não deve manter dados confidenciais no JWT.

Não é muito diferente de como os próprios cookies funcionam. Os cookies geralmente contêm cargas úteis não criptografadas. Se você estiver usando HTTPS, tudo estará bem. Caso contrário, é aconselhável criptografar os cookies confidenciais. Não fazer isso significará a possibilidade de um ataque man-in-the-middle - um servidor proxy ou ISP lê os cookies e os replica mais tarde, fingindo ser você. Por razões semelhantes, o JWT sempre deve ser trocado por uma camada segura como HTTPS.


4
Cuidado! JWT deve sempre ser trocados sobre uma camada seguro como HTTPS
CodeMirror

Mas se o JWT é seguro apenas por HTTPS, por que não enviar a carga útil? POST -> nome de usuário, senha. Ainda está criptografado, certo?
9119 GeekPeek

Para o @GeekPeek, você deve ler os princípios básicos do JWT, mas o Auth de Sessão como você menciona geralmente é tudo o que você precisa. O JWT oferece alguns outros benefícios, mas faz algumas compensações webskeleton.com/webdev/2019/10/22/…
aleemb

17

O conteúdo de um JWT (json web token) não é inerentemente seguro, mas há um recurso interno para verificar a autenticidade do token. Um JWT é composto por três hashes separados por pontos. O terceiro é a assinatura. Em um sistema de chave pública / privada, o emissor assina a assinatura do token com uma chave privada que só pode ser verificada por sua chave pública correspondente.

É importante entender a distinção entre emissor e verificador. O destinatário do token é responsável por verificá-lo.

Há duas etapas críticas no uso seguro do JWT em um aplicativo Web: 1) envie-os por um canal criptografado e 2) verifique a assinatura imediatamente após recebê-la. A natureza assimétrica da criptografia de chave pública torna possível a verificação da assinatura JWT. Uma chave pública verifica se um JWT foi assinado por sua chave privada correspondente. Nenhuma outra combinação de chaves pode fazer essa verificação, evitando assim tentativas de representação. Siga estes dois passos e podemos garantir com certeza matemática a autenticidade de um JWT.

Mais informações: Como uma chave pública verifica uma assinatura?


2

Vamos discernir desde o início:

O JWT é uma abordagem muito moderna, simples e segura, que se estende aos Json Web Tokens. Os Json Web Tokens são uma solução sem estado para autenticação. Portanto, não há necessidade de armazenar nenhum estado de sessão no servidor, o que obviamente é perfeito para APIs repousantes. APIs repousantes sempre devem ser sem estado, e a alternativa mais amplamente usada para autenticação com JWTs é apenas armazenar o estado de logon do usuário no servidor usando sessões. Mas, é claro, não segue o princípio que diz que APIs repousantes devem ser apátridas e é por isso que soluções como a JWT se tornaram populares e eficazes.

Então agora vamos saber como a autenticação realmente funciona com os Json Web Tokens. Supondo que já tenhamos um usuário registrado em nosso banco de dados. Assim, o cliente do usuário inicia fazendo uma solicitação de postagem com o nome de usuário e a senha, o aplicativo verifica se o usuário existe e se a senha está correta, o aplicativo irá gerar um Json Web Token exclusivo para esse usuário.

O token é criado usando uma cadeia secreta que é armazenada em um servidor . Em seguida, o servidor envia esse JWT de volta ao cliente, que o armazena em um cookie ou no armazenamento local. insira a descrição da imagem aqui

Assim, o usuário é autenticado e basicamente está conectado ao nosso aplicativo sem deixar nenhum estado no servidor.

Portanto, o servidor de fato não sabe qual usuário está realmente logado, mas é claro que o usuário sabe que está logado porque possui um Json Web Token válido, que é um pouco como um passaporte para acessar partes protegidas do aplicativo.

Então, novamente, apenas para ter certeza de que você entendeu a idéia. Um usuário é logado assim que recebe de volta seu Json Web Token válido exclusivo, que não é salvo em nenhum lugar do servidor. E, portanto, esse processo é, portanto, completamente sem estado.

Então, sempre que um usuário deseja acessar uma rota protegida, como seus dados de perfil de usuário, por exemplo. Ele envia seu Json Web Token junto com uma solicitação, então é um pouco como mostrar seu passaporte para ter acesso a essa rota.

Depois que a solicitação chegar ao servidor, nosso aplicativo verificará se o Json Web Token é realmente válido e se o usuário realmente é quem ele diz ser. Bem, os dados solicitados serão enviados ao cliente e, caso contrário, haverá um erro ao dizer ao usuário que ele não tem permissão para acessar esse recurso. insira a descrição da imagem aqui

Toda essa comunicação deve ocorrer por https, portanto, Http criptografado com segurança, a fim de impedir que qualquer pessoa possa ter acesso a senhas ou tokens da Web Json. Só então temos um sistema realmente seguro.

insira a descrição da imagem aqui

Portanto, um Json Web Token parece com a parte esquerda desta captura de tela que foi tirada do depurador JWT no jwt.io. Portanto, essencialmente, é uma sequência de codificação composta de três partes. O cabeçalho, a carga útil e a assinatura Agora, o cabeçalho são apenas alguns metadados sobre o próprio token e a carga útil são os dados que podemos codificar no token, quaisquer dados realmente desejados. Portanto, quanto mais dados queremos codificar aqui, maior o JWT. De qualquer forma, essas duas partes são apenas texto simples que serão codificadas, mas não criptografadas.

Para que alguém seja capaz de decodificá-los e lê-los , não podemos armazenar dados confidenciais aqui. Mas isso não é um problema, porque na terceira parte, na assinatura, é onde as coisas realmente ficam interessantes. A assinatura é criada usando o cabeçalho, a carga útil e o segredo que é salvo no servidor.

E todo esse processo é chamado de assinatura do Json Web Token . O algoritmo de assinatura pega o cabeçalho, a carga útil e o segredo para criar uma assinatura exclusiva. Portanto, apenas esses dados e o segredo podem criar essa assinatura, certo? Em seguida, juntamente com o cabeçalho e a carga útil, essas assinaturas formam o JWT, que é enviado ao cliente. insira a descrição da imagem aqui

Depois que o servidor recebe um JWT para conceder acesso a uma rota protegida, ele precisa verificá-lo para determinar se o usuário realmente é quem ele afirma ser. Em outras palavras, ele verificará se ninguém alterou o cabeçalho e os dados da carga útil do token. Então, novamente, esta etapa de verificação verificará se nenhum terceiro realmente alterou o cabeçalho ou a carga útil do Json Web Token.

Então, como essa verificação realmente funciona? Bem, é realmente bem direto. Depois que o JWT é recebido, a verificação pega seu cabeçalho e carga e, juntamente com o segredo que ainda é salvo no servidor, basicamente cria uma assinatura de teste.

Mas a assinatura original que foi gerada quando o JWT foi criado pela primeira vez ainda está no token, certo? E essa é a chave para esta verificação. Porque agora tudo o que precisamos fazer é comparar a assinatura de teste com a assinatura original. E se a assinatura de teste for igual à assinatura original, significa que a carga útil e o cabeçalho não foram modificados. insira a descrição da imagem aqui

Porque se eles tivessem sido modificados, a assinatura do teste teria que ser diferente. Portanto, neste caso em que não houve alteração dos dados, podemos autenticar o usuário. E, claro, se as duas assinaturas são realmente diferentes, bem, isso significa que alguém violou os dados. Geralmente, tentando alterar a carga útil. Mas o fato de terceiros manipularem a carga útil obviamente não têm acesso ao segredo, portanto não podem assinar o JWT. Portanto, a assinatura original nunca corresponderá aos dados manipulados. E, portanto, a verificação sempre falhará neste caso. E essa é a chave para fazer todo esse sistema funcionar. É a mágica que torna o JWT tão simples, mas também extremamente poderoso.


1

Somente o privateKey do JWT, que está no seu servidor, descriptografará o JWT criptografado. Quem conhece o privateKey poderá descriptografar o JWT criptografado.

Oculte o privateKey em um local seguro no seu servidor e nunca conte a ninguém o privateKey.


1
Os JWTs nem sempre são criptografados. Eles podem ser assinados, criptografados, assinados e depois criptografados ou criptografados e assinados.
Csauve

0

Para as pessoas que não podem pagar consultas caras ao banco de dados como eu, uma opção para manter dados confidenciais (privilégios de usuário etc.) é que, ao gerar o JWT, você pode criptografar esses dados e anexá-lo ao token JWT. (Mantenha a chave de criptografia no back-end)

Quando você deseja ler as informações confidenciais, pode enviar o token JWT para o back-end, descriptografá-lo e recuperá-lo. Dessa forma, você não precisa fazer pesquisas de banco de dados ou ter as informações confidenciais nuas no front-end via token JWT


-1

Eu sugeriria examinar o JWE usando algoritmos especiais que não estão presentes no jwt.io para descriptografar

Link de referência: https://www.npmjs.com/package/node-webtokens

jwt.generate('PBES2-HS512+A256KW', 'A256GCM', payload, pwd, (error, token) => {
  jwt.parse(token).verify(pwd, (error, parsedToken) => {
    // other statements
  });
});

Essa resposta pode ser tarde demais ou você já deve ter descoberto o caminho, mas, mesmo assim, achei que seria útil para você e outras pessoas também.

Um exemplo simples que eu criei: https://github.com/hansiemithun/jwe-example

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.