O JSON Hijacking ainda é um problema nos navegadores modernos?


149

Estou usando o Backbone.js e o servidor da web Tornado. O comportamento padrão para receber dados de coleta no Backbone é enviar como uma matriz JSON.

Por outro lado, o comportamento padrão do Tornado é não permitir o JSON Array devido à seguinte vulnerabilidade:

http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx

Um relacionado é: http://haacked.com/archive/2009/06/06/25/json-hijacking.aspx

Parece mais natural para mim não ter que agrupar meu JSON em um objeto quando realmente é uma lista de objetos.

Não consegui reproduzir esses ataques em navegadores modernos (por exemplo, Chrome, Firefox, Safari e IE9 atuais). Ao mesmo tempo, não consegui confirmar em nenhum lugar que os navegadores modernos haviam resolvido esses problemas.

Para garantir que eu não seja enganado por possíveis habilidades de programação ruins ou habilidades de pesquisa no Google:

Esses ataques de seqüestro de JSON ainda são um problema hoje em navegadores modernos?

(Nota: desculpe pela possível duplicação para: É possível executar o 'sequestro de JSON' no navegador moderno? Mas como a resposta aceita não parece responder à pergunta - achei que estava na hora de perguntar novamente e obter algumas explicações mais claras .)


usando eval? então possível de outra maneira Não. Se nada tiver sido alterado ou mudado em parses backbone forma como resposta, então você deve ser seguro
Deeptechtons

10
De um modo geral, você nunca deve abordar a segurança na Web com a suposição de que alguém usará um navegador "moderno".
Lucas

7
@ Lucas - Veja abaixo o comentário de Reid. Ótimo ponto em geral - mas não estou fazendo uma pergunta geral de segurança. (Meus usuários só será capaz de autenticar se eles estão usando um navegador moderno em primeiro lugar.)
Rocketman

4
@ Lucas, às vezes temos que seguir em frente e permitir que desenvolvamos com padrões modernos (como REST neste caso: a obtenção de dados é uma operação GET e não deve ser outra coisa) sem proteção contra ameaças antigas, se agora elas parecem aplicar apenas para uma pequena audiência. Portanto, essa pergunta é realmente valiosa, para permitir avaliar se ele pode ignorar essa ameaça ou não no seu caso de aplicação. Em algum momento, é provável que os usuários com software muito obsoleto tenham outro tipo de ameaça (malware) contra o qual não poderemos protegê-lo.
Frédéric

2
@ jpaugh, onde você vê essas suposições? Suponho apenas que as pessoas com esse software obsoleto sejam "desprotegíveis" de qualquer maneira. (Sobre justificar o custo dos meus patins, eu já estava acostumado a colocar um terço do seu preço em patins de velocidade, desgastados em menos de um terço do tempo que levava para usar meus patins atuais. acho que eles valem a pena, desde que você como montá-los, que é o meu caso).
Frédéric

Respostas:


112

Não, ele não é mais possível é a de valores de captura passados para o []ou {}construtores em Firefox 21, Chrome 27 ou IE 10. Aqui está uma página de teste pequena, com base nos principais ataques descritos em http://www.thespanner.co.uk / 2011/05/30 / sequestro de json / :

( http://jsfiddle.net/ph3Uv/2/ )

var capture = function() {
    var ta = document.querySelector('textarea')
	ta.innerHTML = '';
	ta.appendChild(document.createTextNode("Captured: "+JSON.stringify(arguments)));
	return arguments;
}
var original = Array;

var toggle = document.body.querySelector('input[type="checkbox"]');
var toggleCapture = function() {
    var isOn = toggle.checked;
    window.Array = isOn ? capture : original;
    if (isOn) {
        Object.defineProperty(Object.prototype, 'foo', {set: capture});    
    } else {
        delete Object.prototype.foo;
    }
};
toggle.addEventListener('click', toggleCapture);
toggleCapture();

[].forEach.call(document.body.querySelectorAll('input[type="button"]'), function(el) {
    el.addEventListener('click', function() {
        document.querySelector('textarea').innerHTML = 'Safe.';
        eval(this.value);
    });
});
<div><label><input type="checkbox" checked="checked"> Capture</label></div>
<div><input type="button" value="[1, 2]" /> <input type="button" value="Array(1, 2);" /> <input type="button" value="{foo: 'bar'}" /> <input type="button" value="({}).foo = 'bar';" /></div>
<div><textarea></textarea></div>

Ele substitui window.Arraye adiciona um configurador e Object.prototype.footesta inicializando matrizes e objetos por meio dos formulários curto e longo.

A especificação do ES4 , na seção 1.5, "exige que as ligações padrão globais de Object e Array sejam usadas para construir novos objetos para inicializadores de objeto e matriz" e observa no Precedent de implementação que "Internet Explorer 6, Opera 9.20 e Safari 3 fazem não respeite as religações locais ou globais de Object e Array, mas use os construtores Object and Array originais ". Isso é mantido no ES5, seção 11.1.4 .

Allen Wirfs-Brock explicou que o ES5 também especifica que a inicialização do objeto não deve acionar setters, pois usa DefineOwnProperty. MDN: Working with Objects observa que "A partir do JavaScript 1.8.1, os setters não são mais chamados ao definir propriedades nos inicializadores de objetos e matrizes". Isso foi abordado na edição 1015 da V8 .


28
Em 2009, Brendan Eich sugeriu que os navegadores não avaliassem scripts servidos como application / json ( bugzilla.mozilla.org/show_bug.cgi?id=376957#c75 ), o que ainda me parece uma boa ideia.

2
Observe que o POST CSRF cego ainda é possível usando formulários, principalmente com a codificação de texto / sem formatação, e precisa ser derrotado usando tokens / nonces.

1
Sim para o POST CSRF. Obrigado por todas as suas ótimas informações aqui.
Rocketman

5
Sua declaração está correta quando se refere apenas à substituição do construtor Array. No entanto, os microsofts IE e Edge ainda são vulneráveis ​​ao sequestro de JSON UTF-7. Testei recentemente (e por diversão hoje novamente), e ainda funciona.
user857990

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.