Curso MIT "Segurança de sistemas de computadores". Aula 11: Linguagem de Programação Ur / Web, Parte 2

Instituto de Tecnologia de Massachusetts. Curso de Aula nº 6.858. "Segurança de sistemas de computador". Nikolai Zeldovich, James Mickens. 2014 ano


Computer Systems Security é um curso sobre o desenvolvimento e implementação de sistemas de computador seguros. As palestras abrangem modelos de ameaças, ataques que comprometem a segurança e técnicas de segurança baseadas em trabalhos científicos recentes. Os tópicos incluem segurança do sistema operacional (SO), recursos, gerenciamento de fluxo de informações, segurança de idiomas, protocolos de rede, segurança de hardware e segurança de aplicativos da web.

Palestra 1: “Introdução: modelos de ameaças” Parte 1 / Parte 2 / Parte 3
Palestra 2: “Controle de ataques de hackers” Parte 1 / Parte 2 / Parte 3
Aula 3: “Estouros de Buffer: Explorações e Proteção” Parte 1 / Parte 2 / Parte 3
Palestra 4: “Separação de Privilégios” Parte 1 / Parte 2 / Parte 3
Palestra 5: “De onde vêm os sistemas de segurança?” Parte 1 / Parte 2
Palestra 6: “Oportunidades” Parte 1 / Parte 2 / Parte 3
Palestra 7: “Sandbox do Cliente Nativo” Parte 1 / Parte 2 / Parte 3
Aula 8: “Modelo de Segurança de Rede” Parte 1 / Parte 2 / Parte 3
Aula 9: “Segurança de aplicativos da Web” Parte 1 / Parte 2 / Parte 3
Palestra 10: “Execução Simbólica” Parte 1 / Parte 2 / Parte 3
Aula 11: “Linguagem de Programação Ur / Web” Parte 1 / Parte 2 / Parte 3

Um pouco mais tarde, falarei sobre solicitações falsas entre sites. Acho que as notas da aula explicam por que o script crossite não funciona no nosso caso. O motivo é que, sempre que você cria uma "peça" de sintaxe, esse objeto, árvore e diferentes partes dessa árvore não são apenas cadeias de caracteres.



Você não pode acidentalmente transformar uma string de usuário em uma árvore de estrutura, isso não acontece automaticamente, porque é difícil escrever um tradutor desse tipo. Mas você pode tentar escrever um tradutor para Ur / Web. Em breve, darei um exemplo que ajudará a reduzir sua preocupação com isso. Quero mostrar o que essa sintaxe realmente se transforma no compilador.

Pode parecer que podemos apenas adicionar aspas duplas ao HTML para que possamos retornar ao mundo normal. Alguém pode se perguntar por que é tão importante pular aspas duplas, colocando XML em vez disso?

Você pode acreditar que este é o código equivalente para o que faz. Aqui está uma tag de função embutida que cria o nó da árvore de um documento HTML. Em seguida, coloco os argumentos que expressam o estilo CSS neste nó. Na verdade, nada acontece aqui; portanto, existem muitas maneiras diferentes de dizer "Nenhum"; ele não requer atributos.

Em seguida, coloquei a tag body, isso é outra coisa da biblioteca padrão. Todas as tags padrão são funções de primeira classe na biblioteca.



Em seguida, precisamos colocar o texto "Hello World" no corpo, por isso chamamos a função cdata, em que cdata é a palavra XML para dados de caracteres ou apenas uma constante de string, e podemos colocar o texto aqui. Isso deve nos dar o mesmo resultado de antes. Vamos ver se isso funciona.

Agora voltarei à página. Vemos a mesma coisa que antes, então é a mesma que a função fazia no começo.



Isto não é apenas construção de linhas. Isso causa uma série de operações projetadas para que somente elas permitam a criação de HTML válido e nunca serão capazes de interpretar implicitamente a linha como código, em vez de apenas colocar o conteúdo na página que deveria estar lá.



Agora vou tentar fazer algo menos complicado, o que pode ser uma preocupação. Vamos decidir que estamos realmente felizes em ver o mundo, para destacar a palavra "olá" em negrito e compilá-la novamente.



Você vê o que aconteceu na página - a palavra não ficou em negrito porque o compilador mostra como o texto é interpretado em vez da marcação. Esta é uma representação da sintaxe HTML como uma função que constrói a sintaxe sem as convenções de codificação usuais incorporadas a ela. Essa função interpreta tudo da maneira que você deseja escrever, sem pensar em nada de si mesmo.

Assim, a implementação do cdata faz o que é comumente chamado de escape ou "escape". Mas o programador não precisa saber que existe algo como escapar. Você pode pensar nisso como um conjunto de funções convenientes para criar uma árvore de objetos que descreve a página.

Ouvi dizer que você deseja ver o HTML que é gerado aqui. Ok, isso não será a coisa mais emocionante. Vou tentar aumentá-lo na tela, mas não cabe em uma linha.



Aluno: Como você está usando XHTML, poderia usar o caminho para dados de caracteres de cdata em vez de fazê-lo manualmente?

Professor: Eu acho, mas isso exigiria mais XML de mim do que os que tenho. Havia outra boa pergunta sobre URLs JavaScript. Se permitirmos URLs JavaScript, criaremos um backdoor para interpretar automaticamente as strings como programas em tempo de execução. E isso causa todos os tipos de problemas.

Vamos tentar evitá-lo. Voltarei, primeiro, à versão abreviada e farei algumas linhas dentro do corpo. E vamos colocar um link que tentará fazer algo apropriado. Aqui deixamos espaço para mensagens de erro.



Em seguida, execute o compilador e veja como ele funciona.



URL inválido, entrada de JavaScript e a frase "passado para abençoar" ou "passado para abençoar". O Bless é incorporado à função, que é o gatekeeper que resolve o URL. Por padrão, URLs não são permitidos; portanto, é claro que essa opção não é permitida. Em geral, é uma péssima idéia escrever sua própria política de URL para poder criar valores que representam URLs JavaScript. Porque, então, todos os tipos de garantias serão necessários, devido ao fato de que esses endereços podem ser inválidos.

Para deixar um pouco mais claro como isso funciona, deixe-me decompor esse código em uma função separada que chama o vinculador que aceita o URL. Assim, uma URL é um tipo, não uma string. Esse é o tipo que indica a URL, que é explicitamente permitida pela política do seu aplicativo.

Eu uso chaves, como em algumas estruturas de modelo HTML populares, para indicar a inserção de algum código da linguagem host dentro do HTML que criamos. E tudo isso é feito de forma que o tipo seja verificado estaticamente. Portanto, o sistema verificará: "Sim, este é o local ao qual o URL pertence e ele diz que é realmente um URL, então está tudo bem."



E então eu posso organizar explicitamente a chamada de bênção dizendo: "vamos chamar a função vinculador aqui com base nos resultados da" bênção "deste URL". Depois disso, devemos receber a mesma mensagem de erro de antes.



Infelizmente, não posso executar isso para você e esperar até que ele falhe, mas posso dizer que definitivamente falhará, porque intencionalmente cometi um erro do compilador. Este URL não será aceito pela política de URL.

Se eu perdesse essa chamada de benção, seria um erro mais sério no momento da compilação, porque você tem a string e o URL certo, e eles são de tipos diferentes.



Vamos torná-lo mais interessante. Vou abrir um arquivo de configuração para esta demonstração. É bem curto, pelo menos se você olhar para qualquer estrutura de aplicativo da web Java. Eles têm esses arquivos XML gigantes para configuração, então tudo está muito melhor conosco.



Podemos adicionar uma regra que declara que tudo é permitido na Wikipedia e depois colocar o URL da Wikipedia no corpo.



Agora vá para a página e clique em Please Click.



Aqui está o que temos: Endereço da Wikipedia não encontrado.



Portanto, a idéia principal é ter um tipo abstrato de URL, como se você pudesse ter um tipo abstrato de tabela hash que codifique variações da aparência da tabela hash e evite que o código entre na matriz da tabela hash. Nós podemos fazer o mesmo pela URL. Usando essa função de abençoar, o sistema garante que todo valor desse tipo seja aprovado em algum momento.

Por exemplo, com essa política, sabemos que nunca teremos um URL JavaScript, para que você possa pegar com segurança o valor do URL e usá-lo como um link. Isso não interromperá as abstrações básicas do idioma.

Aluno: é possível usar JavaScript "puro" inserindo-o na string do corpo?

Professor: sim e não. Em vez de JavaScript, você incorpora o código de Ur / Web que executa algum tipo de tarefa. Agora vou digitar o comando:

return <xml><body onload = {alertLOADED”}> 

E você verá o que aconteceu - o intérprete colocou uma janela na tela com a inscrição “Loaded” - “Loaded”.



Tentar interpretar o código JavaScript na forma de string como um programa seria um desastre. Veja bem, podemos colocar o código na mesma linguagem de programação com a qual você está trabalhando, já limitado por essas chaves. E então é compilado automaticamente em JavaScript para ser executado no lado do cliente.

Observo que as versões mais recentes dos navegadores são capazes de evitar erros de interpretação de caracteres, mas alguns navegadores mais antigos são capazes de confundir alguma coisa. De qualquer forma, todos os elementos de caractere serão interpretados como UTF-8 se eles entrarem no documento. Se houver algum problema com uma codificação diferente, essa codificação não deve ser aplicada aqui.

Aluno: O compilador verifica se a sequência contém um URL válido. Mas, se você calcular uma string no tempo de execução, o bless verificará no tempo de execução se uma determinada string é válida ou não?

Professor: vamos criar um formulário para testar esta afirmação e colocá-la aqui. Nós inserimos nosso URL na caixa de texto e depois inserimos o botão enviar envio.



Quando você clica nela, a função vinculador será chamada com a gravação de um valor para cada campo no formulário. Nesse caso, existe apenas um campo chamado "URL", portanto o vinculador processará a entrada que contém o URL como um tipo de string. E então tentamos aplicar a função abençoar e ver se funciona.



Você vê um exemplo de mensagens de erro ao digitar o tipo errado de URL, uma daquelas coisas que não fará sentido se você não estiver familiarizado com Haskell. Esqueci de inserir a função de retorno aqui. Pelo menos agora é mais como um programa Java. E também esqueci de dizer que agora é uma página inteira. Portanto, não podemos usar a tag a até estarmos dentro da tag body.



Agora execute o compilador, vá para a nossa página, clique no botão Please Click, digite um endereço inexistente abstruso.



Em seguida, clicamos em Enviar consulta - "Enviar uma solicitação" e recebemos uma mensagem de erro - o endereço desse tipo não é resolvido.



Se inserirmos o URL correto, como mostrado na próxima tela, e clicar em Enviar consulta, nenhuma mensagem de erro será exibida.



Acho que a resposta para sua pergunta foi longa e não muito emocionante.

Aluno: existem condições mais rigorosas para os URLs além da proibição de usar JavaScript?
Professor: Atualmente, restrições mais rigorosas são simplesmente constantes e prefixos. Mas você também pode criar suas próprias regras de proibição, e elas funcionarão na ordem em que você as escrever.

Aluno: acontece que, se você seguir a proibição de JavaScript, mas colocar uma quebra de linha no meio da palavra "JavaScript", o compilador poderá interpretar isso ...

Professor: sim, isso seria muito ruim. É por isso que é bom seguir a abordagem da lista de permissões, em vez de usar a abordagem da lista negra. Você provavelmente deseja que todas as regras iniciem com um protocolo específico, como HTTP, e permita apenas o que se encaixa no seu conjunto de protocolos aprovado. Eu recomendo fazer exatamente isso.

Aluno: em muitos sites, você pode permitir que os usuários troquem links. Nesse caso, é necessário permitir links em qualquer lugar.

Professor: você pode permitir links se quiser que seus usuários compartilhem links JavaScript ou, não sei, links em flash ou o que for permitido lá. Veja bem, você pode criar uma "lista branca" de todos os HTTP, HTTPS, URLs e, assim, garantir a operação segura da maioria dos sites. Essa abordagem é apenas um pouco mais fraca do que permitir apenas URLs específicos. Mas pelo menos você pode eliminar completamente a possibilidade de execução automática de uma string como um programa.

Deixe-me dar um exemplo de resumo, que é um exemplo de um sistema simples de sala de bate-papo apresentado no banco de dados. O usuário pode clicar no link para ir para a sala e enviar uma mensagem. Esta é a primeira de várias opções para o esquema.



Em primeiro lugar, observarei que vou recompilar isso. E, magicamente, todas as tabelas declaradas do banco de dados serão adicionadas ao banco de dados, e podemos começar a usar o aplicativo. Mas primeiro precisamos adicionar algumas salas de bate-papo. Então, vamos abrir nossa interface para o banco de dados demo e inserir os valores "um" e "dois" na sala de tabelas.



Agora eles apareceram aqui.



Agora entramos na primeira sala de bate-papo e podemos nos divertir o dia inteiro enviando linhas de texto, por exemplo, uma primeira linha. Será mais interessante tentar enviar HTML, e ele é imediatamente processado. Este é um exemplo da principal funcionalidade do programa.



Mais uma vez, veremos rapidamente como isso funciona, por isso temos essas duas tabelas SQL - sala de tabela e mensagem de tabela, que são simplesmente declaradas nesta primeira classe dentro da linguagem de programação. E nós damos um diagrama de cada tabela. E então, quando tentamos acessar essas tabelas, o compilador garante que elas sejam acessadas de acordo com um esquema de digitação promissor.



Portanto, temos uma tabela de salas, em que cada sala é um registro que consiste em um ID de identificador, que é um número inteiro, e um Título, que é uma string. Este é o tipo de visão em que simplesmente criamos registros. Acabei de criar algumas salas no console do SQL. Também temos uma notificação de que cada mensagem pertence a uma sala específica, a hora em que foi criada e o texto que é o conteúdo da mensagem.
Agora deixe-me pular rapidamente para a função principal.



Executamos uma consulta SQL - você vê um exemplo de sintaxe SQL incorporada ao Ur / Web. Eu não quero entrar em chamadas de função através desta extensão da biblioteca padrão. Será bastante detalhado, basta recordar minhas palavras sobre o fato de que a biblioteca padrão possui métodos para chamar funções que são formas válidas de criar uma consulta SQL.

E essas funções têm tipos que os fazem imprimir solicitações para você, e não apenas garantem que a sintaxe é válida. Esse código simplesmente itera sobre todas as linhas que saíram dessa consulta e gera partes do código HTML para cada uma delas.

Em particular, colocaremos o resultado da consulta no campo Título e o converteremos em HTML com uma notação que inclui chaves. Os colchetes indicam adicionalmente que ainda não é um pedaço real de HTML, mas converta-o para mim de maneira padrão. Assim, podemos fazer com strings e inteiros e todos os dados de outros tipos.

Aluno: se contivesse HTML malicioso ou algo mais, seria filtrado?

Professor: sim, seria. Em Ur / Web, você pode pensar nisso como construir uma árvore. Este é um nó que representa algum texto. Obviamente, o texto não pode fazer nada.

Aluno: se este cabeçalho estivesse sob o controle do usuário e alguém tivesse conversado com o cabeçalho Alerta, não seria JavaScript?

Professor: não será automaticamente interpretado como JavaScript, HTML ou qualquer outra coisa. Será percebido pelo programa como texto simples.

Então, voltando à nossa imagem na tela. Temos este título Título, vamos enquadrá-lo com tags. E, em vez de href, a maneira usual de vincular em HTML, usamos o atributo link, que é um tipo de pseudo-atributo ur / web que usa como argumento não a URL, mas principalmente expressões Ur / Web. O ponto é que, quando você clica nesse link, essa expressão é iniciada para criar uma nova página que deve ser exibida.
Nesse caso, fazemos uma chamada para a função de bate-papo, que é definida aqui na próxima tela, é isso que é.



Não vou entrar em detalhes. Mas temos mais algumas consultas SQL usando várias funções de biblioteca padrão para várias maneiras de usar os resultados solicitados.

Geramos essa página HTML e dizemos que você está em um bate-papo com esse título, temos um formulário no qual o usuário pode inserir texto. Este é o formulário que eu usei para demonstrar como o programa funcionou alguns minutos atrás. O botão enviar formulário possui este atributo Adicionar contendo say, que é o nome da função Ur / Web. Portanto, quando enviamos o formulário, chamamos essa função.

A execução de mais algumas SQL insere novas linhas na tabela. Saltamos automaticamente do ID da sala de bate-papo para os campos de texto que vieram aqui do formulário e eles são ocultados automaticamente conforme necessário. Mas, novamente, em Ur / Web, você não precisa pensar em "escapar" da função dessa maneira. Porque é apenas a sintaxe para construir uma árvore, não para uma string. Portanto, não há como estranhar a análise de coisas estranhas que você não espera da maneira escolhida de interpretar a sintaxe.

Portanto, como temos um widget neste formulário na forma de uma GUI gráfica e este é um campo de texto, o compilador conclui que o registro resultante do preenchimento do formulário da caixa de texto deve ter um elemento chamado "texto" do tipo string . Essa codificação do formulário e as regras para digitação não são incorporadas ao idioma, mas são obtidas da biblioteca do Ur express, que na verdade controla esses formulários, determinando os tipos de funções válidas.
Se você não tiver mais perguntas sobre essa parte do programa, passarei à próxima etapa. Vou usar uma maneira de forçar o encapsulamento de várias partes de um aplicativo que suporta Ur / Web e que raramente suporta outros idiomas. Eu vou pegar este quarto. Vou pegar algumas definições e colocá-las em um módulo que encapsula algumas delas como privadas. Em particular, as tabelas do banco de dados serão privadas, portanto ninguém poderá acessá-las diretamente.

Você pode acessá-los apenas usando o conjunto de métodos que fornecemos. Um método é executado dentro de uma transação e cria uma lista de registros com os campos ID e título das salas de bate-papo disponíveis.

Em seguida, apenas expandimos essa operação de bate-papo. E a única coisa que fiz aqui foi inserir um nome para o conceito ID - tipo ID. Portanto, não estou dizendo apenas que o ID é um número inteiro, estou dizendo que esse é um novo tipo.



A única maneira pela qual o mundo externo pode entrar em contato com o bate-papo é obter uma lista de todas as salas, e a única maneira que o mundo externo pode usá-lo é chamar a função de bate-papo. Digamos que este seja algum tipo abstrato de tabela de hash dentro da classe de tabelas de hash, onde são armazenados detalhes que explicam quais IDs são e como são produzidos internamente, sendo privados para este módulo, e o código do cliente que chama esse módulo não deve usá-los.

Agora vou transferir toda essa sintaxe para baixo e colocá-la dentro do módulo, para que, por padrão, não seja exposta ao restante do código. Em seguida, implemento esse método de salas. Já temos a oportunidade de organizar um bate-papo. Mas podemos implementar as salas de uma maneira mais simples, usando outra função de biblioteca padrão para interpretar a solicitação no formulário atual.
Vamos apenas selecionar tudo da lista de quartos, classificados por nome. Como sempre, essa consulta é um tipo de dados validado para nós. E o sistema determina: “OK, essa expressão irá gerar uma lista de registros que correspondem ao tipo declarado na assinatura deste módulo.” Portanto, agora, fora deste módulo, nenhum outro código pode mencionar uma tabela de sala ou tabela de mensagens.



Assim, pelo menos do ponto de vista desta aplicação, podemos aplicar a invariância necessária a partir dela. Podemos até ocultar segredos dentro do módulo para que não haja problemas de segurança se qualquer outra parte do código puder obtê-los.

Aluno: algum outro código também poderia implementar esse método de sala?

Professor: Essa seria uma tabela completamente diferente. Na verdade, podemos fazer isso inserindo um fragmento de 4 linhas em outro módulo.



Então podemos fazer o que quisermos com esta tabela. Vou compilar, talvez em 30 segundos, e vamos ver o que acontece. Mas, na verdade, esta é uma tabela diferente, como se você tivesse o mesmo nome privado, mas para duas classes Java diferentes.

Portanto, você assume que dentro deste módulo existe um tipo abstrato chamado room, que contém o identificador de identificação e o título. Isto não está correto. O bate-papo aceita os parâmetros da sala como entrada. Quando chamamos a função de bate-papo, ela será chamada via URL. O ID e o Título são passados ​​para fora da representação da URL que chama a função. Nós precisamos apenas do ID para implementar esta função. Então, quando chamamos a função, na verdade chamamos o URL.
Seria um desperdício em termos de uso de espaço e pareceria rude com o usuário se o cabeçalho fosse passado como um argumento adicional ao invocar o bate-papo por meio da URL. Isso faz sentido? Vamos olhar para a barra de URL neste slide.



O identificador do canal que estamos seguindo é serializado automaticamente para o URL no final da linha. E se transmitíssemos um registro que contenha o ID e o título Title, esse título também seria serializado, o que é pelo menos um pouco ilógico.

54:10

Curso MIT "Segurança de sistemas de computadores". Aula 11: Linguagem de Programação Ur / Web, Parte 3


A versão completa do curso está disponível aqui .

Obrigado por ficar conosco. Você gosta dos nossos artigos? Deseja ver materiais mais interessantes? Ajude-nos fazendo um pedido ou recomendando a seus amigos, um desconto de 30% para os usuários da Habr em um análogo exclusivo de servidores básicos que inventamos para você: Toda a verdade sobre o VPS (KVM) E5-2650 v4 (6 núcleos) 10GB DDR4 240GB SSD 1Gbps da US $ 20 ou como dividir o servidor? (as opções estão disponíveis com RAID1 e RAID10, até 24 núcleos e até 40GB DDR4).

VPS (KVM) E5-2650 v4 (6 núcleos) 10GB DDR4 240GB SSD de 1Gbps até dezembro de graça quando pagar por um período de seis meses, você pode fazer o pedido aqui .

Dell R730xd 2 vezes mais barato? Somente nós temos 2 TVs Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 a partir de US $ 249 na Holanda e nos EUA! Leia sobre Como criar um prédio de infraestrutura. classe usando servidores Dell R730xd E5-2650 v4 custando 9.000 euros por um centavo?

Source: https://habr.com/ru/post/pt425999/


All Articles