[Tut]Błędy związane z kodowaniem znaków

hxv

Były Moderator
Dołączył
Sierpień 9, 2006
Posty
797
Opiszę dwa, dość rzadko występujące na stronach, błędy związane z niepoprawną obsługą kodowania znaków:

-wykorzystanie braku ustalonego kodowania strony do XSS:
zadziała to tylko jeśli serwer nie wysyła nagłówków z domyślnym kodowaniem i użytkownik używa IE (ta przeglądarka jako domyślne kodowanie użyje UTF-7 dzięki czemu możliwe będzie przeprowadzenie ataku) lub domyślne kodowanie to UTF-7 .
Skrypt:
Kod:
<?php
$xss = '<script>alert(0);</script>'; //nasz XSS
$xss = mb_convert_encoding($xss, 'UTF-7'); //zmieniamy kodowanie na UTF-7

echo htmlentities($xss); //filtrujemy
?>
Na początek zmieniamy kodowanie naszego XSS'a na UTF-7, gdybyśmy wyświetlili go w UTF-8 będzie to wyglądać tak:
Kod:
+ADw-script+AD4-alert(0)+ADsAPA-/script+AD4-
Potem wyświetlamy go przefiltrowanego funkcją htmlentities(). Jednak ta funkcja działa tylko z UTF-8 więc nie ruszy naszego XSS'a który jest zakodowany w UTF-7.
Jako że serwer ani skrypt nie wysyłają nagłówków z kodowaniem jakie jest na stronie przeglądarka sama musi wybrać jakiego użyć. Jak wspomniałem IE wybierze UTF-7 więc XSS zadziała. W Firefoxie i Operze wyświetli się po prostu (gdy nie będzie ustalonego kodowania)
Kod:
+ADw-script+AD4-alert(0)+ADsAPA-/script+AD4-
Jak się zabezpieczyć? Jeśli możemy zmienić ustawienia serwera to należy ustawić domyślne kodowanie na UTF-8 albo ISO-8859-2, jeśli nie to na początku skryptu wysyłać dodatkowy nagłówek:
Kod:
header('Content-Type: text/html; charset=UTF-8');


-w niektórych przypadkach (gdy baza danych korzysta z kodowania w którym jeden znak może być zapisany w postaci dwóch bajtów) możliwe jest przeprowadzenie ataku SQL Injection na skrypt zabezpieczony przy pomocy funkcji addslashes():

Przykładem takiego kodowania jest GBK (kodowanie używane w chinach).
PHP 'widzi' każdy ciąg znaków tak jakby był kodowany w UTF-8 (jeden bajt = jeden znak), więc gdy baza danych używa GBK można obejść addslashes.
Prosty przykład: PHP ciąg znaków składający się z 2 bajtów 0xBF27 zinterpretuje jako 2 znaki: jeden o kodzie 0xBF a drugi o kodzie 0x27. Natomiast baza danych, w której kodowanie to GBK będzie widzieć jeden znak o kodzie 0xBF27. Jak więc to wykorzystać? Dość prosto, 0x27 to nic innego jak ' który można wykorzystać do SQL Injection. Gdy na naszym ciągu znaków wykonamy funkcję addslashes() PHP doda przed ' (0x27) znak \ (0x5C).
W efekcie otrzymamy #\' (0xBF5C27) //# będzie tu jakimś 'krzaczkiem', nie chcę zbyt motać więc tak będę zaznaczać
PHP wykonał swoją robotę więc przesyła nasz ciąg znaków (0xBF5C27) do bazy danych.
Ta natomiast widzi to tak: #' (0xBF5C27). Jak widać \ który dodał PHP został 'zjedzony', MySQL widzi go jako część zupełnie innego znaku.
Gdybyśmy wstawili to do zapytania wynik będzie np. taki:
Kod:
SELECT * FROM users WHERE login='#'' AND password=''
Teraz wystarczy postępować jak w zwykłym SQL Injection, dodać po ': OR 1=1-- i już możemy się zalogować bez podawania hasła.

Jak się przed tym zabezpieczyć? Jeśli możemy korzystajmy z kodowań w bazie danych które nie są 'podatne' na ten atak (UTF-8, ISO-8859-1, ISO-8859-2, ...). Zamiast funkcji addslashes() użyjmy natomiast mysql_real_escape_string() która przefiltruje poprawnie przekazane dane.

Źródła:
http://shiflett.org/blog/2006/jan/addslash...l-escape-string
http://shiflett.org/blog/2005/dec/google-xss-example
http://shiflett.org/blog/2005/dec/googles-xss-vulnerability

//jeśli to możliwe prosiłbym o przeniesienie do tutoriali [;
 
Do góry Bottom