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

60

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

Para o meu projeto mais recente, decidi tentar avançar com os tempos e escrever um aplicativo do lado do cliente.

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

Normalmente, meu aplicativo seria executado 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 agora isso precisa acontecer no navegador do usuário. A API de terceiros fornece os arquivos JavaScript necessários para isso.

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

Supondo que eu possa contornar esse problema, o próximo problema é o que impede um usuário com experiência em tecnologia de carregar a ferramenta de desenvolvedores JavaScript em um navegador e usar a API de e-mail da maneira que preferir, em vez de dizer que cumpre as regras que defini no aplicativo .

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

Gaz_Edge
fonte
24
Algum motivo pelo qual você não tem esse aplicativo se comunica com seu próprio servidor e o servidor encaminha essas solicitações para qualquer serviço externo que você precise usar? (Muitos desses serviços proibiria a usá-los desta forma qualquer maneira)
müller thorsten
11
É por isso que as chaves da API são inúteis. O servidor não deve estar tentando confiar no aplicativo que está enviando comandos; deve confiar apenas no usuário.
22814 Kevin Kevin Panko
42
Eu nunca vi nenhuma pessoa sã definir "aplicativo do lado do cliente" como " nunca se comunica com um servidor" - isso parece mais um palhaço do que um argumento razoável. É evidente que existem algumas coisas que você tem que lidar no lado do servidor, mas a grande maioria das ações pode ser feito localmente, sem problemas, que por sua vez irá melhorar substancialmente a capacidade de resposta e escalabilidade ..
Voo
4
Onde você vê um empurrão para "Aplicativos somente para navegador?" Eu nunca vi nada parecido com o que você está descrevendo, mantendo segredos no código do cliente em uma idéia insanamente ruim, até mesmo os caras mais obstinados do front end que conheço que nunca fariam isso.
Wheeyls
2
Qualquer tentativa de proteger recursos seguros no lado do cliente está condenada porque viola várias leis imutáveis ​​de segurança. # 2/3 - se o seu software está sendo executado no computador do adversário, não é por definição e você já perdeu. A tentativa nº 7 de proteger um recurso por criptografia está condenada, pois você também precisa fornecer ao cliente a chave de descriptografia. # 10 nenhuma tecnologia pode corrigir o que precede. blogs.technet.com/b/rhalbheer/archive/2011/06/16/…
Dan Neely

Respostas:

200

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

O código executado em um dispositivo sob o controle do usuário não pode ser controlado. Os smartphones podem ser jailbroken. Os decodificadores podem ser rachados. Navegadores comuns nem tentam impedir o acesso ao código JavaScript. Se você tem algo de valor para roubar ou abusar, um determinado atacante vai ser capaz de fazer isso a menos que você validar tudo o que prezamos server-side.

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

Infelizmente, essa é uma verdade muito inconveniente. O mundo está cheio de operadores pequenos e grandes que pensam que podem, de alguma forma, contornar o rompimento fundamental da confiança remota, simplesmente porque seria muito bom se pudéssemos assumir que nosso código será executado da maneira que assumimos. E sim, isso tornaria tudo muito mais fácil, nem mesmo engraçado. Mas desejar não é assim, e esperar contra a esperança de que você é o único cookie inteligente que pode evitar o desagradável apenas 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 isto, é claro que existe uma defesa profunda. Ofuscar seu JavaScript não adia um invasor determinado, mas pode adiar alguns atacantes 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. Desde que você esteja totalmente ciente do compromisso que está fazendo, essa pode ser uma estratégia razoável.

Kilian Foth
fonte
6
Mas, para colocar isso em perspectiva: isso é verdade para TODOS os softwares, seja um sistema operacional ou um processo de transação. No final, existem alguns ofuscadores de código muito bons por aí e você pode elevar a fasquia provavelmente alto o suficiente, se não houver incentivo financeiro imediato para invadir seu software!
Falco
5
Hoje em dia, as empresas adotam medidas legais contra pessoas que cortam o conteúdo recebido antes do processamento (por exemplo, através de bloqueadores de anúncios). Isso mostra apenas como é impossível uma ação técnica .
precisa
62
Se eu puder elaborar as duas primeiras frases, a sutileza que as pessoas geralmente sentem falta é que o ponto dos aplicativos de navegador do lado do cliente é descarregar o trabalho pesado. Seu servidor ainda é responsável por operações confiáveis, como enviar e-mails ou acessar os dados. Entretanto, fazer o cliente renderizar um gráfico com esses dados economiza tempo (e dinheiro) da CPU sem alterar o modelo de segurança.
ssube
11
@Gaz_Edge É importante observar que o problema aqui não é que os aplicativos do lado do cliente sejam inerentemente inseguros. O problema é escrever esses aplicativos do lado do cliente de uma maneira que exija confiar ao cliente com informações que você não deseja que sejam públicas. É totalmente possível escrever um aplicativo pesado para o cliente que seja tão seguro quanto um aplicativo em que a maior parte do processamento ocorre no servidor. (Para saber mais sobre isso, veja a resposta de jhocking )
Ajedi32
7
@ Ajedi32 Os aplicativos do lado do cliente são inseguros. É impossível projetar um aplicativo seguro se qualquer lógica feita no lado do cliente não for verificada no lado do servidor. Nesse ponto, a lógica do lado do cliente se torna uma interface do usuário ou uma maneira de descarregar verificações básicas, mas tudo deve sempre ser verificado no servidor !! .
69

A regra aqui é:

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

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

jhocking
fonte
28

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

Você pode fazer a validação lógica e básica dos formulários do lado do cliente (ainda é necessário revalidar no servidor, porque alguém pode tentar falsificar a solicitação) para melhorar a capacidade de resposta, é possível fazer solicitações HTTP do JavaScript passando dados lá e de volta no JSON para evite reenviar decorações da página e tal, mas se a transação em si precisar ser autenticada e autorizada, ela ainda deverá ocorrer em um servidor.

Jan Hudec
fonte
11
Nota: Embora seja ótimo validar formulários no lado do cliente, nunca se esqueça de validá-los também no lado do servidor! Quando você envia o código do seu cliente para o navegador, ele deixa de ser o seu código! Você precisa validar cada bit enviado novamente!
Josef
17

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

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

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 é eliminar servidores, mas aproveitar as tecnologias mais recentes que os navegadores finalmente suportam para criar melhores interfaces com o usuário.

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

Brandon
fonte
4
+1 para a boa sugestão de que o arquivo JS destina-se a um servidor NodeJS
Machinarius
11

Vamos dar um passo atrás e dar uma olhada em um nível mais alto .. devemos ... O Eudora ou o Outlook (um aplicativo do lado do cliente, que nem precisa de um navegador) causou uma perda financeira para qualquer empresa? Não. Qualquer um pode escrever nas APIs POP / SMTP e ser o cliente. Mas nenhuma perda para o servidor. O servidor não limitou as ações do cliente, cálculos, armazenamento, temperatura, tamanho do disco, tamanho da ram, DPI do monitor, GPU, FPU e yada yada do cliente, mas especificou exatamente o que responderia e nada mais. Você já ouviu falar de quicken ou MS-Money sendo usado para invadir um banco?

O aplicativo do seu navegador (por exemplo, do lado do cliente) pode usar a mesma arquitetura.

  1. Você constrói seu servidor com uma API (que BTW, sempre se resume a derivados 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, um dispositivo jailbroken, o Google glass, DOS 3.1 ou um Nexus novinho em folha nas mãos de um tataravô tecnofóbico que já viajou até 2014 e perdeu tudo a tecnologia que vem inundando nossas vidas nas últimas 15 décadas.
  5. Agora você pode começar a carregar todo o resto para o lado do cliente.

SoapBoxBegin

O @KilianFoth levanta um ponto importante de conscientização para os ingênuos e os imprudentes, principalmente aqueles que leem as manchetes o tempo todo, mas nunca pensam que isso acontecerá com seu aplicativo, código, empregador, cliente e conta bancária. Ainda mais imprudentes são seus empregadores (especialmente os CTOs) que permitiriam que aplicativos saíssem que expusessem qualquer sistema a exposição não gerenciada / não controlada. No entanto, estou sempre intrigado com o que parece "nunca aprendemos".

SoapBoxEnd

Então, para resumir. Crie uma API sólida e rígida do lado do servidor. Descarregue tudo o mais para o cliente com base em tudo o que o cliente possa manipular.

LMSingh
fonte
6

Eu diria que você realmente não pode. Se você deseja enviar os dados para o cliente, deve esperar que eles sejam abusados ​​- da maneira que for possível. Seu exemplo em relação à chave da API é ilustrativo e não incluiria isso no JS do seu cliente - ele será roubado e abusado.

Definitivamente, você 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 conectado. Essa autenticação não pode ser feita no lado do cliente ou novamente, você será beneficiado e seus dados não serã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 experiência agradável ao usuário, mas se você não verificar os dados do POST no servidor receptor, estará se abrindo para o ataque. Qualquer coisa do cliente deve ser considerada suspeita.

Matt Klinker
fonte
4

É bem simples, realmente. Suponha que o computador cliente e todo o software executado nele estejam sob controle total de um hacker malicioso inteligente.

Isso significa que qualquer informação que você enviar do servidor para o cliente será conhecida pelo hacker mal-intencionado, portanto, certifique-se de não enviar nenhuma informação ao cliente que possa ser usada para atacar o servidor ou a 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 garantir que nada que o cliente possa enviar seja capaz de atacar com êxito o servidor.

É certo que a implementação é um problema, mas o importante é a atitude mental, a suposição de que o "cliente" com o qual o servidor está falando não é um cliente, mas um invasor ativo.

(Você também precisa assumir que o usuário é um vigarista inteligente 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).

gnasher729
fonte
0

O aplicativo 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 ao cliente e, em seguida, o cliente faria o que quisesse com ele.

Normalmente, meu aplicativo seria executado 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 agora isso precisa acontecer no navegador do usuário. A API de terceiros fornece os arquivos JavaScript necessários para isso.

Se você possui uma chave de API, ela não deve funcionar no lado do cliente. Se você der a chave da API no lado do cliente, qualquer pessoa terá acesso a ela e poderá usá-la para seu próprio objetivo. Armazene-o e use-o no servidor quando o cliente precisar, depois envie o resultado usando Ajax / WebSockets.

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

Depado
fonte