Gostaria de saber se é possível sandbox JavaScript em execução no navegador para impedir o acesso a recursos que normalmente estão disponíveis para o código JavaScript em execução em uma página HTML.
Por exemplo, digamos que desejo fornecer uma API JavaScript para os usuários finais, para que eles definam manipuladores de eventos a serem executados quando "eventos interessantes" acontecerem, mas não quero que esses usuários acessem as propriedades e funções do window
objeto. Eu sou capaz de fazer isso?
No caso mais simples, digamos que eu queira impedir que os usuários liguem alert
. Algumas abordagens em que consigo pensar são:
- Redefina
window.alert
globalmente. Eu não acho que isso seria uma abordagem válida, porque outro código em execução na página (ou seja, coisas não criadas pelos usuários em seus manipuladores de eventos) pode querer usaralert
. - Envie o código do manipulador de eventos ao servidor para processar. Não tenho certeza de que enviar o código ao servidor para processar seja a abordagem correta, porque os manipuladores de eventos precisam ser executados no contexto da página.
Talvez uma solução em que o servidor processe a função definida pelo usuário e gere um retorno de chamada a ser executado no cliente funcionaria? Mesmo que essa abordagem funcione, existem maneiras melhores de resolver esse problema?
fonte
while (1) {}
--- simplesmente trava. Da mesma formaa=[]; while (1) { a=[a,a]; }
.Dê uma olhada no ADsafe de Douglas Crockford :
Você pode ver um exemplo de como usar o ADsafe observando os arquivos
template.html
etemplate.js
no repositório GitHub do projeto .fonte
this
, o que é totalmente inaceitável. Você não pode escrever um bom javascript sem usarthis
.this
. Não é difícil evitar o parâmetro com nomes inadequados.this
, existe uma maneira igual e equivalentethis
de fazê-lo (afinal, é apenas um parâmetro).Criei uma biblioteca de sandbox chamada jsandbox que usa web workers para sandbox o código avaliado. Ele também possui um método de entrada para fornecer explicitamente dados de código em área restrita que de outra forma não seria possível obter.
A seguir, um exemplo da API:
fonte
Eu acho que vale a pena mencionar o js.js aqui. É um intérprete de JavaScript escrito em JavaScript.
É cerca de 200 vezes mais lento que o JS nativo, mas sua natureza o torna um ambiente de sandbox perfeito. Outra desvantagem é seu tamanho - quase 600 kb, o que pode ser aceitável para desktops em alguns casos, mas não para dispositivos móveis.
fonte
Conforme mencionado em outras respostas, basta prender o código no iframe em área restrita (sem enviá-lo para o servidor) e se comunicar com as mensagens. Sugiro dar uma olhada em uma pequena biblioteca que criei principalmente devido à necessidade de fornecer alguma API para o código não confiável, assim como descrito na pergunta: há uma oportunidade de exportar o conjunto específico de funções diretamente para a sandbox onde o código não confiável é executado. E também há uma demonstração que executa o código enviado por um usuário em uma sandbox:
http://asvd.github.io/jailed/demos/web/console/
fonte
Todos os fornecedores de navegadores e a especificação HTML5 estão trabalhando em direção a uma propriedade de área restrita real para permitir iframes em área restrita - mas ainda é limitado à granularidade de iframe.
Em geral, nenhum grau de expressões regulares etc. pode limpar com segurança o usuário arbitrário, desde que o JavaScript se degenere no problema de interrupção: - /
fonte
Uma versão aprimorada do código da caixa de areia dos trabalhadores da Web do @ RyanOHara, em um único arquivo (nenhum
eval.js
arquivo extra é necessário).Teste-o:
https://jsfiddle.net/kp0cq6yw/
Deve sair
6
(testado no Chrome e Firefox).fonte
De uma maneira feia, mas talvez isso funcione para você, peguei todas as globais e as redefinii no escopo da sandbox e também adicionei o modo estrito para que elas não possam obter o objeto global usando uma função anônima.
https://gist.github.com/alejandrolechuga/9381781
fonte
window
voltar disso.sandboxcode('console.log((0,eval)("this"))')
function sbx(s,p) {e = eval; eval = function(t){console.log("GOT GOOD")}; sandboxcode(s,p); eval =e}
(_=>_).constructor('return this')()
É provável que um intérprete Javascript independente produza uma sandbox robusta do que uma versão em gaiola da implementação do navegador interno. Ryan já mencionou js.js , mas um projeto mais atualizado é o JS-Interpreter . Os documentos abordam como expor várias funções ao intérprete, mas seu escopo é muito limitado.
fonte
A partir de 2019, o vm2 parecerá a solução mais popular e a mais atualizada regularmente para esse problema.
fonte
Com o NISP, você poderá fazer uma avaliação em área restrita. Embora a expressão que você escreve não seja exatamente um JS, você escreverá expressões-s. Ideal para DSLs simples que não exigem programação extensa.
fonte
1) Suponha que você tenha um código para executar:
Agora, suponha que você queira executá-lo em uma sandbox:
Essas duas linhas quando executadas falharão, porque a função "alert" não está disponível na "sandbox"
2) E agora você deseja expor um membro do objeto de janela com a sua funcionalidade:
Na verdade, você pode adicionar aspas escapando e fazer outro polimento, mas acho que a ideia é clara.
fonte
De onde vem esse JavaScript do usuário?
Não há muito o que fazer sobre um usuário incorporar código à sua página e chamá-lo pelo navegador (consulte Greasemonkey, http://www.greasespot.net/ ). É apenas algo que os navegadores fazem.
No entanto, se você armazenar o script em um banco de dados, recuperá-lo e eval (), poderá limpar o script antes de executá-lo.
Exemplos de código que remove todas as janelas. e documento. referências:
Isso tenta impedir que o seguinte seja executado (não testado):
Existem muitas limitações que você teria que aplicar ao script de usuário não seguro. Infelizmente, não há 'container sandbox' disponível para JavaScript.
fonte
Eu tenho trabalhado em uma sandbox js simplista para permitir que os usuários criem applets para o meu site. Embora eu ainda enfrente alguns desafios ao permitir o acesso ao DOM (parentNode simplesmente não me deixa manter as coisas seguras = /), minha abordagem foi apenas redefinir o objeto de janela com alguns de seus membros úteis / inofensivos e depois avaliar () o usuário código com essa janela redefinida como o escopo padrão.
Meu código "principal" é assim ... (não estou mostrando isso totalmente;)
Então, eu posso instalar uma Sandbox e usar sua execute () para executar o código. Além disso, todas as novas variáveis declaradas no código eval'd acabam vinculadas ao escopo execute (), portanto, não haverá nomes conflitantes nem interferindo no código existente.
Embora os objetos globais ainda sejam acessíveis, aqueles que devem permanecer desconhecidos no código da área restrita devem ser definidos como proxies no objeto Sandbox :: scope.
Espero que funcione para voce.
fonte
Você pode agrupar o código do usuário em uma função que redefine objetos proibidos como parâmetros - estes seriam
undefined
chamados quando:Obviamente, invasores inteligentes podem contornar isso inspecionando o DOM Javascript e localizando um objeto não substituído que contém uma referência à janela.
Outra idéia é escanear o código do usuário usando uma ferramenta como jslint . Certifique-se de que ele esteja definido para não ter variáveis predefinidas (ou: apenas variáveis desejadas) e, se quaisquer globais estiverem configurados ou acessados, não permita que o script do usuário seja usado. Novamente, pode ser vulnerável a andar pelo DOM - objetos que o usuário pode construir usando literais podem ter referências implícitas ao objeto de janela que pode ser acessado para escapar da sandbox.
fonte