2013-07-30 16 views
10

szyny 3:Dlaczego to_json automatycznie ucieka Unicode w Railsach 4?

{"a" => "<br/>"}.to_json 
=> "{\"a\":\"<br/>\"}" 

szyn 4:

{"a" => "<br/>"}.to_json 
=> "{\"a\":\"\\u003Cbr/\\u003E\"}" 

dlaczego ???

Wydaje się być przyczyną błędu

Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8 

Kiedy moi Rails 3 aplikacja próbuje analizować JSON generowane przez moich szynach 4 aplikacji.

+0

Spróbuj tego: JSON.generate ({ "a" => "
"}: ascii_only => true) – user2503775

Odpowiedz

9

DLACZEGO ???

Do obrony przed powszechną słabością aplikacji internetowych. Jeśli powiesz na stronie HTML, np:

<script type="text/javascript"> 
    var something = <%= @something.to_json.html_safe %>; 
</script> 

czym myślisz, że jesteś w porządku, bo już JSON-uniknął danych jesteś wstrzykiwanie do JavaScript. Ale w rzeczywistości nie jesteś bezpieczny: oprócz składni JSON masz również otaczającą składnię HTML, aw bloku skryptu HTML </ jest sygnalizacja wewnątrzpasmowa. Praktycznie, jeśli @something zawiera ciąg </script> masz usterkę cross-site scripting, jak to wychodzi:

<script type="text/javascript"> 
    var something = {"attack": "abc</script><script>alert('XSS');//"}; 
</script> 

Pierwszy blok skryptu kończy się w połowie łańcucha (wyjazd o unclosed ciąg dosłownego błąd składni) i drugi <script> jest traktowany jako nowy blok skryptu i wykonywana treść potencjalnie przez niego wysłana.

Ucieczka ze znaku < do \u003C nie jest wymagana przez JSON, ale jest to całkowicie poprawna alternatywa i automatycznie unika tej klasy problemów. Jeśli parser JSON go odrzuca, jest to poważny błąd w czytniku.

Co to jest kod, który generuje ten błąd? Nie jestem przekonany, czy ten błąd ma coś wspólnego z wykrywaniem <, ponieważ mówi o bajcie 0xC3 zamiast 0x3C. Może to wskazywać na ciąg znaków z zakodowaną w UTF-8 treścią nie oznaczoną jako UTF-8 ... może potrzebujesz force_encoding("UTF-8") na wejściu?

+5

Jeśli naprawdę trzeba wyłączyć ucieczki JSON (zakładając, że sytuacja jest bezpieczna od wstrzyknięcia) można zrobić z: 'ActiveSupport.escape_html_entities_in_json = FALSE – elkelk

+0

w przykładzie, dlaczego nie dzwoni' .html_safe' podmiot-uciec „” na „</script >” ? Co robi ta metoda? – qntm

+1

'html_safe' faktycznie robi coś przeciwnego, oznacza to, że ciąg znaków zawierający surowy znacznik, który dzwoniący już zagwarantował, jest bezpieczny, więc nie potrzebuje dalszego ucieczki. Jeśli nie * zaznaczysz łańcucha 'html_safe', to Railsy automatycznie go wyminą (od Rails 3). – bobince

5

można zachować oryginalny łańcuch z JSON::dump:

JSON::dump "a" => "<br/>" 
=> "{\"a\":\"<br/>\"}" 

JSON::dump "a" => "x&y" 
=> {\"a\":\"x&y\"}" # instead of x\u0026y 

Używaj go ostrożnie z powodów bobince wspomina i szczególnie unikać go z dowolnego wejścia generowane przez użytkowników (lub przynajmniej upewnić się, że jest santized).

Oto przykład, który napotkałem, gdy jest to uzasadnione użycie. Generowanie JavaScript hash argumentu w funkcji pomocnika:

# application_helper.rb 

def widget_js(post) 
    options = { 
    color: ColorCalculator(post.color).to_rgb_hex, 
    ... 
    } 
    "third_party_widget(#{JSON::dump options});" 
end 
Powiązane problemy