[BEZPIECZEŃSTWO] 7 min czytania

[BEZPIECZEŃSTWO] Najlepsze praktyki bezpieczeństwa Base64

Ważne kwestie bezpieczeństwa przy pracy z kodowaniem Base64 w aplikacjach webowych.

Styczeń 2025 | security

// BASE64 TO NIE SZYFROWANIE

Najkrytyczniejszym błędnym wyobrażeniem o bezpieczeństwie jest traktowanie Base64 jako szyfrowania. Base64 to tylko kodowanie - jest całkowicie odwracalny bez żadnego klucza czy hasła.

Każdy może natychmiast dekodować dane Base64. Nigdy nie polegaj na Base64 dla bezpieczeństwa lub ochrony danych.

// ❌ ŹLE: Używanie Base64 jako 'bezpieczeństwa'
const password = 'secret123';
const encoded = btoa(password); // cGFzc3dvcmQ=
// Każdy może to natychmiast odkodować!

// ✅ DOBRZE: Odpowiednie hashowanie hasła
import bcrypt from 'bcrypt';
const password = 'secret123';
const hashedPassword = await bcrypt.hash(password, 12);
// To jest rzeczywiście bezpieczne

// WALIDACJA WEJŚCIA

Zawsze waliduj wejście Base64 aby zapobiec atakom iniekcji i błędom aplikacji:

Odpowiednia walidacja zapobiega złośliwemu wejściu powodującemu problemy bezpieczeństwa lub awarie aplikacji.

// Waliduj format Base64
function isValidBase64(str) {
    // Sprawdź format: tylko prawidłowe znaki Base64
    const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
    if (!base64Regex.test(str)) {
        return false;
    }
    
    // Sprawdź długość (musi być wielokrotnością 4)
    if (str.length % 4 !== 0) {
        return false;
    }
    
    // Test dekodowania
    try {
        atob(str);
        return true;
    } catch (e) {
        return false;
    }
}

// Bezpieczne dekodowanie z walidacją
function safeBase64Decode(input, maxLength = 10000) {
    if (typeof input !== 'string') {
        throw new Error('Wejście musi być ciągiem znaków');
    }
    
    if (input.length > maxLength) {
        throw new Error('Wejście zbyt długie');
    }
    
    if (!isValidBase64(input)) {
        throw new Error('Nieprawidłowy Base64');
    }
    
    return atob(input);
}

// ZAPOBIEGANIE XSS

Dane Base64 mogą zawierać złośliwe skrypty po dekodowaniu. Zawsze oczyszczaj wyjście przy wyświetlaniu zdekodowanej zawartości:

Nigdy nie ufaj wejściu Base64 od użytkowników. Zawsze oczyszczaj przed renderowaniem w HTML.

// ❌ NIEBEZPIECZNE: Bezpośrednie wstrzykiwanie HTML
function displayDecodedData(base64) {
    const decoded = atob(base64);
    document.innerHTML = decoded; // Podatność XSS!
}

// ✅ BEZPIECZNE: Oczyszczaj wyjście
function safeDisplayDecodedData(base64) {
    const decoded = atob(base64);
    
    // Utwórz węzeł tekstowy (bez wykonywania HTML)
    const textNode = document.createTextNode(decoded);
    container.appendChild(textNode);
    
    // Lub escapuj jednostki HTML
    const escaped = decoded
        .replace(/&/g, '&')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;');
    
    container.innerHTML = escaped;
}

// LIMITY ROZMIARU

Kodowanie Base64 zwiększa rozmiar danych o ~33%. Implementuj limity rozmiaru aby zapobiec atakom DoS:

Nieograniczone wejście Base64 może zużywać nadmierną pamięć i moc obliczeniową.

  • > Ustaw maksymalne limity długości wejścia
  • > Monitoruj użycie pamięci podczas przetwarzania
  • > Implementuj timeouty dla długich operacji
  • > Używaj strumieniowania dla dużych zbiorów danych
  • > Rozważ kompresję przed kodowaniem
  • > Ogranicz szybkość operacji Base64

// BEZPIECZNA OBSŁUGA TOKENÓW

Przy używaniu Base64 dla tokenów lub wrażliwych ID, przestrzegaj najlepszych praktyk bezpieczeństwa:

Odpowiednia obsługa tokenów zapobiega nieautoryzowanemu dostępowi i atakom opartym na tokenach.

// Tworzenie bezpiecznego tokenu
function createSecureToken() {
    // Używaj kryptograficznie bezpiecznych wartości losowych
    const array = new Uint8Array(32);
    crypto.getRandomValues(array);
    
    // Konwertuj do Base64 i zrób URL-safe
    const base64 = btoa(String.fromCharCode(...array))
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
    
    return base64;
}

// Bezpieczna walidacja tokenu
function validateToken(token, expectedLength = 43) {
    if (typeof token !== 'string') {
        return false;
    }
    
    // Sprawdź długość
    if (token.length !== expectedLength) {
        return false;
    }
    
    // Sprawdź format URL-safe Base64
    const urlSafeBase64Regex = /^[A-Za-z0-9_-]+$/;
    return urlSafeBase64Regex.test(token);
}

// BEZPIECZEŃSTWO DATA URI

Base64 data URI mogą zawierać złośliwą zawartość. Zawsze waliduj i oczyszczaj data URI:

Złośliwe data URI mogą wykonywać skrypty, ładować zewnętrzne zasoby lub zawierać nieodpowiednią zawartość.

// Waliduj data URI
function validateDataURI(dataUri, allowedTypes = ['image/png', 'image/jpeg']) {
    const dataUriRegex = /^data:([a-zA-Z0-9][a-zA-Z0-9\/+]*);base64,(.+)$/;
    const match = dataUri.match(dataUriRegex);
    
    if (!match) {
        throw new Error('Nieprawidłowy format data URI');
    }
    
    const [, mimeType, base64Data] = match;
    
    // Waliduj typ MIME
    if (!allowedTypes.includes(mimeType)) {
        throw new Error(`Nieobsługiwany typ MIME: ${mimeType}`);
    }
    
    // Waliduj dane Base64
    if (!isValidBase64(base64Data)) {
        throw new Error('Nieprawidłowy Base64 w data URI');
    }
    
    // Sprawdź rozmiar
    const sizeEstimate = (base64Data.length * 3) / 4;
    if (sizeEstimate > 1024 * 1024) { // limit 1MB
        throw new Error('Data URI zbyt duży');
    }
    
    return { mimeType, base64Data };
}

// LISTA KONTROLNA BEZPIECZNEJ IMPLEMENTACJI

  • > Nigdy nie używaj Base64 jako szyfrowania lub środka bezpieczeństwa
  • > Zawsze waliduj format i długość wejścia Base64
  • > Oczyszczaj zdekodowane wyjście przed wyświetlaniem
  • > Implementuj limity rozmiaru i timeouty
  • > Używaj URL-safe Base64 dla aplikacji webowych
  • > Waliduj typy MIME dla data URI
  • > Używaj kryptograficznie bezpiecznych wartości losowych dla tokenów
  • > Implementuj odpowiednią obsługę błędów
  • > Monitoruj potencjalne ataki DoS
  • > Regularne audyty bezpieczeństwa kodu obsługi Base64