Codificação do lado do cliente: como evitar o uso malicioso?

59

Nos últimos anos, a tendência para aplicativos do lado do cliente (navegador) realmente decolou.

Para meu último projeto, decidi tentar me movimentar com os tempos e escrever um aplicativo do lado do cliente.

Parte deste aplicativo envolve o envio de emails de transações para os usuários (por exemplo, validação de inscrição, e-mails de redefinição de senha etc.). Estou usando uma API de terceiros para enviar os e-mails.

Normalmente, eu teria meu aplicativo em execução em um servidor. Eu chamaria a API de terceiros do código no meu servidor.

A execução de um aplicativo do lado do cliente significa que isso agora precisa acontecer no navegador de um usuário. A API de terceiros fornece os arquivos JavaScript necessários para isso.

O primeiro problema evidente que vejo é que preciso usar uma chave de API. Isso normalmente seria armazenado com segurança no meu servidor, mas agora presumivelmente precisarei fornecer essa chave ao navegador do cliente.

Supondo que eu possa contornar este problema, o próximo problema é o que impede que um usuário experiente carregue a ferramenta de desenvolvedores JavaScript em um navegador e use a API de e-mail da maneira que preferir, em vez de aderir a qualquer regra definida por mim. na aplicação.

Acho que minha pergunta geral é: como podemos evitar o uso malicioso de um aplicativo do lado do cliente?

    
por Gaz_Edge 30.07.2014 / 15:09
fonte

8 respostas

196

Você não pode, e quanto mais as pessoas entenderem isso, e quanto mais entenderem, melhor para o mundo.

O código que é executado em um dispositivo sob o controle do usuário não pode ser controlado. Os smartphones podem ser desbloqueados. Os decodificadores podem ser quebrados. Os navegadores comuns nem tentam impedir o acesso ao código JavaScript. Se você tem algo que vale a pena roubar ou abusar, um atacante determinado será capaz de fazer isso, a menos que você valide tudo o que você aprecia do lado do servidor.

A ofuscação é de muito pouca ajuda; o tipo de oponente que você atrairá assim que algo remotamente financeiro estiver envolvido, lê linguagem assembly como anúncios classificados. A criptografia não pode ajudá-lo, porque o dispositivo que protegeria a chave é o mesmo dispositivo que você tem que assumir que está quebrado. Existem muitas contramedidas aparentemente óbvias que não funcionam, por razões semelhantes.

Infelizmente, esta é uma verdade muito inconveniente. O mundo está cheio de pequenos operadores que pensam que podem de alguma forma contornar o quebrantamento fundamental da confiança remota, simplesmente porque seria tão bom se pudéssemos supor que o nosso código ser executado da maneira que assumimos. E sim, isso tornaria tudo tão mais fácil que nem é engraçado. Mas desejar não o faz, e esperar que você seja o único biscoito esperto que pode evitar o desconforto só vai queimar você e seus clientes. Portanto, entenda que a Internet é território inimigo, inclua esse custo adicional em suas estimativas e você ficará bem.

Dito isso, é claro que existe uma defesa em profundidade. Ofuscar seu JavaScript não adia um atacante determinado, mas pode adiar alguns invasores menos determinados. Se seus ativos valerem o suficiente para proteger, mas não a qualquer custo, qualquer uma dessas medidas poderá agregar valor comercial ao seu sistema; simplesmente não pode ser perfeito. Contanto que você esteja totalmente ciente do trade-off que está fazendo, essa pode ser uma estratégia razoável.

    
por 30.07.2014 / 15:20
fonte
68

A regra aqui é:

Faça tudo do lado do cliente que não afete mais ninguém se o usuário interferir com isso. Em particular, isso significa efeitos gráficos.

Faça tudo do lado do servidor que precisa ser seguro, e apenas envie eventos de UI do cliente (por exemplo, o cliente apenas diz "o usuário tocou no botão Comprar" enquanto o servidor realmente realiza a transação). Em particular, isso significa transações financeiras.

    
por 30.07.2014 / 19:53
fonte
28

Este é exatamente o caso em que torná-lo um aplicativo completamente do lado do cliente não é apropriado.

Você pode fazer a lógica e validação básica de formulários do lado do cliente (você ainda precisa revalidar no servidor, porque alguém pode tentar falsificar a solicitação) para melhorar a capacidade de resposta, você pode fazer solicitações HTTP de JavaScript transmitindo dados para lá e para trás em JSON para evitar o reenvio de decorações de página e tal, mas se a própria transação precisar ser autenticada e autorizada, ela ainda deverá acontecer em um servidor.

    
por 30.07.2014 / 15:22
fonte
18

Seu parágrafo do meio é o coração do problema:

Running a client side app means this now needs to happen on a users browser. The third party API provides the necessary js files to achieve this.

Por que um aplicativo do lado do cliente significa que você não pode ter um trabalho do lado do servidor? O impulso para a programação do lado do cliente não é apenas eliminar servidores, mas sim alavancar tecnologias mais recentes que os navegadores finalmente suportam para criar melhores interfaces de usuário.

Quanto ao arquivo .js que você recebeu, tem certeza de que se destina a um navegador? Poderia ser uma biblioteca node.js?

    
por 30.07.2014 / 23:43
fonte
11

Vamos dar um passo para trás e dar uma olhada em um nível mais alto. O Eudora ou Outlook (um aplicativo do lado do cliente, nem mesmo precisando de um navegador) causou uma perda financeira para qualquer empresa? Não. Qualquer um poderia escrever para a API do POP / SMTP e ser o cliente. Mas sem perda para o servidor. O servidor não limitava as ações do cliente, cálculos, armazenamento, temperatura, tamanho do disco, tamanho da memória RAM, monitor de DPI, GPU, FPU, yada yada do cliente, mas especificava exatamente o que responderia e não mais. Você já ouviu falar de quicken ou MS-Money sendo usado para invadir um banco?

Seu aplicativo do navegador (ou seja, do lado do cliente) pode usar a mesma arquitetura.

  1. Você constrói seu servidor com uma API (que BTW, sempre se resume a derivativos de GET POST HEAD etc.).
  2. No servidor, verifique se a API fala apenas com um cliente autenticado e verificado por identidade para cada chamada.
  3. Então você não se importa com quem é o cliente.
  4. E você não se importa se é um navegador, dispositivo desbloqueado, vidro do Google, DOS 3.1 ou um novíssimo Nexus nas mãos de um tecnofóbico tataravó que viajou para 2014 e perdeu toda a tecnologia que tem inundado nossas vidas nas últimas 15 décadas.
  5. Agora você pode começar a descarregar todo o resto para o lado do cliente.

SoapBoxBegin

@KilianFoth levanta um importante ponto de conscientização para os ingênuos e imprudentes, principalmente aqueles que lêem as manchetes o tempo todo, mas nunca acham que acontecerá com o aplicativo, o código, o empregador, o cliente, a conta bancária deles. Ainda mais imprudentes são os empregadores (especialmente os CTOs) que permitem que os aplicativos saiam e expõem os sistemas à exposição não gerenciada / descontrolada. No entanto, estou sempre intrigado com a forma como parece "nunca aprendemos".

SoapBoxEnd

Então, para resumir. Crie uma API sólida e compacta no servidor. Descarregue todo o resto para o cliente com base no que o cliente puder suportar.

    
por 31.07.2014 / 06:57
fonte
6

Eu diria que você realmente não pode. Se você está disposto a enviar os dados para o cliente, você deve esperar que ele será abusado - no entanto, possível. Seu exemplo sobre a chave da API é ilustrativo do ponto, e eu não incluiria isso no JS do seu lado cliente - ele será roubado e abusado.

Você definitivamente ainda precisará de uma certa quantidade de código do servidor para manter as coisas seguras. Mesmo algo tão simples quanto recuperar apenas os dados relacionados ao usuário logado. Essa autenticação não pode ser feita do lado do cliente ou, novamente, você será aproveitado e seus dados não estarão seguros.

Eu sempre veria a experiência do lado do cliente JS como uma adição ao código do servidor. A validação no cliente fornece uma boa experiência ao usuário, mas se você não verificar os dados do POST no servidor de recebimento também, estará se abrindo para o ataque. Qualquer coisa do cliente deve ser considerada suspeita.

    
por 30.07.2014 / 15:20
fonte
4

É bem simples, na verdade. Suponha que o computador cliente e todos os softwares executados nele estejam sob o controle total de um hacker mal-intencionado inteligente.

Isso significa que qualquer informação que você enviar do servidor para o cliente será conhecida pelo hacker mal-intencionado, portanto, você deve enviar nenhuma informação ao cliente que possa ser usada para atacar seu servidor ou sua empresa.

Isso também significa que qualquer coisa enviada do cliente para o servidor foi produzida pelo hacker mal-intencionado, portanto, o código do servidor deve certificar-se de que nada que o cliente possa enviar seja capaz de atacar com êxito seu servidor.

É verdade que a implementação é um problema, mas o importante é a atitude mental, a suposição de que o "cliente" que você acha que seu servidor está falando não é um cliente, mas um invasor ativo.

(Você também precisa assumir que o usuário é um inteligente defensor que tentará atacar seus métodos de negócios, mas isso não tem nada a ver com a programação do lado do cliente).

    
por 03.08.2014 / 01:49
fonte
0

A aplicação do lado do cliente, na minha opinião, é principalmente sobre a interface do usuário. Por exemplo, todo o seu sistema de interface do usuário será enviado uma vez para o cliente e, em seguida, o cliente fará o que quiser com ele.

Normally I would have my application running on a server. I would call the third-party API from code on my server.

Running a client-side application means this now needs to happen on a user's browser. The third-party API provides the necessary JavaScript files to achieve this.

Se você tiver uma chave de API, ela não funcionará no lado do cliente. Se você der a API Key no lado do cliente, qualquer um terá acesso a ela e poderá usá-la para seu próprio propósito. Armazene-o e use-o no lado do servidor quando o cliente precisar dele e, em seguida, envie o resultado usando o Ajax / WebSockets.

É como se o seu banco estivesse dizendo: "Bem, vou colocar a senha do cliente principal do banco de dados para que o cliente possa solicitá-la e ele não incomodará mais nossos servidores".

    
por 01.08.2014 / 16:40
fonte