Czy bezpieczne jest przesyłanie nieprzetworzonych łańcuchów base64 za pomocą parametrów GET?
Czy bezpieczne jest przesyłanie nieprzetworzonych łańcuchów base64 za pomocą parametrów GET?
Odpowiedzi:
Nie, musisz go zakodować, ponieważ ciągi base64 mogą zawierać znaki „+”, „=” i „/”, które mogą zmieniać znaczenie twoich danych - wyglądają jak podfolder.
Prawidłowe znaki base64 są poniżej.
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
Istnieją dodatkowe specyfikacje base64. (Szczegóły podano w tabeli tutaj ). Ale zasadniczo potrzebujesz 65 znaków do zakodowania: 26 małych liter + 26 wielkich liter + 10 cyfr = 62.
Potrzebujesz jeszcze dwóch ['+', '/'] i padding char '='. Ale żaden z nich nie jest przyjazny dla adresów URL, więc po prostu użyj dla nich różnych znaków i gotowe. Standardowe z powyższej tabeli to ['-', '_'], ale możesz używać innych znaków, o ile dekodujesz je tak samo i nie musisz dzielić się z innymi.
Polecam po prostu napisać własnych pomocników. Podobnie jak w komentarzach na stronie podręcznika php dla base64_encode :
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '._-');
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '._-', '+/='));
}
urlencode
jak sugeruje odpowiedź rodrigo-silveira. Utworzenie dwóch nowych funkcji w celu zaoszczędzenia kilku znaków w adresie URL to jak wejście do domu przez okno zamiast po prostu korzystania z drzwi.
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
,
należy to zaadresować %2C
, sugeruję użycie ._-
zamiast -_,
jak jedynego wariantu w en.wikipedia.org/wiki/Base64#Variants_summary_table, który utrzymuje końcowy =
@joeshmo Lub zamiast pisać funkcję pomocnika, możesz po prostu urlencode kodowany ciąg base64. To zrobiłoby dokładnie to samo, co funkcja pomocnika, ale bez potrzeby dwóch dodatkowych funkcji.
$str = 'Some String';
$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );
/
znak, jeśli przekazujesz go nie jako parametr GET, ale jako ścieżkę w adresie URL. Zmieni to twoją ścieżkę, jeśli nie zastąpisz /
czegoś innego po obu stronach.
Uwaga wstępna Skłaniam się do opublikowania kilku wyjaśnień, ponieważ niektóre z odpowiedzi tutaj były nieco mylące (jeśli nie nieprawidłowe).
Odpowiedź brzmi NIE , nie można po prostu przekazać parametru zakodowanego w base64 w ciągu zapytania do adresu URL, ponieważ znaki plus są konwertowane na SPACJĘ w globalnej tablicy $ _GET. Innymi słowy, jeśli wysłałeś test.php? MyVar = stringwith + sign to
//test.php
print $_GET['myVar'];
wynik byłby:
stringwith sign
Łatwym sposobem rozwiązania tego jest po prostu urlencode()
ciąg base64 przed dodaniem go do ciągu zapytania, aby uciec od znaków +, = i / do kodów% ##. Na przykład urlencode("stringwith+sign")
zwracastringwith%2Bsign
Podczas przetwarzania akcji PHP automatycznie dekoduje ciąg zapytania, gdy zapełni on globalną wartość $ _GET. Na przykład, jeśli wysłałem test.php? MyVar = stringwith% 2Bsign to
//test.php
print $_GET['myVar'];
wynikiem byłoby:
stringwith+sign
Zdajesz nie chcą urldecode()
zwrócony ciąg $ _GET jak s + 'zostaną zamienione na spacje.
Innymi słowy, jeśli wysłałem ten sam test.php? MyVar = stringwith% 2Bsign to
//test.php
$string = urldecode($_GET['myVar']);
print $string;
wynik jest nieoczekiwany:
stringwith sign
Byłby bezpieczny dla rawurldecode()
danych wejściowych, jednak byłby zbędny, a zatem niepotrzebny.
<br>
, więc nie musisz pisać dużo HTML. Mam nadzieję, że to pomoże. Zredagowałem trochę twoją odpowiedź, aby jeszcze bardziej ją poprawić.
Tak i nie.
Podstawowy zestaw znaków base64 może w niektórych przypadkach kolidować z tradycyjnymi konwencjami stosowanymi w adresach URL. Jednak wiele implementacji base64 pozwala na zmianę zestawu znaków w celu lepszego dopasowania adresów URL lub nawet dostarczenia go z jednym (np. Pythona urlsafe_b64encode()
).
Innym problemem, z którym możesz się spotkać, jest limit długości adresu URL, a raczej jego brak. Ponieważ standardy nie określają maksymalnej długości, przeglądarki, serwery, biblioteki i inne oprogramowanie współpracujące z protokołem HTTP mogą określać własne ograniczenia. Możesz rzucić okiem na ten artykuł: Często zadawane pytania na temat WWW: Jaka jest maksymalna długość adresu URL?
Jest to kod base64url, który możesz wypróbować, to tylko rozszerzenie powyższego kodu joeshmo.
function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
Teoretycznie tak, o ile nie przekroczysz maksymalnej długości ciągu adresu URL i / lub zapytania dla klienta lub serwera.
W praktyce może być trochę trudniej. Na przykład może wywołać wyjątek HttpRequestValidationException na platformie ASP.NET, jeśli wartość zawiera „on”, a ty zostawisz końcowe „==”.
Dla bezpiecznego base64.urlsafe_b64encode(...)
kodu URL, jak w Pythonie poniższy kod działa dla mnie w 100%
function base64UrlSafeEncode(string $input)
{
return str_replace(['+', '/'], ['-', '_'], base64_encode($input));
}
Tak, zawsze jest bezpiecznie. oczywiście base64 zawiera:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
ale łańcuch zakodowany base64 zwykle nie ma +
. +
zostanie przekonwertowany na puste miejsce, co spowoduje nieprawidłowy dekodowanie ciągu. /
jest bezpieczny w parze parametrów get. =
jest zawsze na końcu łańcucha zakodowanego w base64, a strona serwera może rozwiązać =
bezpośrednio.