Na wejściu KSeF chroni poufność faktury przed bramką WAF, ale przez to oślepia WAF na treść faktury. Na wyjściu KSeF odsłania fakturę przed bramką WAF, więc WAF może ją widzieć.
Czyli ten sam WAF jest jednocześnie: ślepy tam, gdzie powinien wykrywać złośliwy XML, widzący tam, gdzie nie powinien widzieć treści faktury.
To jest architektoniczny absurd!
Oficjalna dokumentacja KSeF potwierdza, że przy wysyłce faktura ma być zaszyfrowana: AES-256-CBC dla treści faktury, a klucz symetryczny jest szyfrowany RSAES-OAEP z SHA-256/MGF1. Dokumentacja mówi też o weryfikacji skrótów faktury i zaszyfrowanej faktury. Jednocześnie przy pobieraniu pojedynczej faktury dokumentacja mówi po prostu: "Zwraca fakturę o podanym numerze KSeF", a przykłady pokazują pobranie faktury jako string invoice albo byte[] invoice. Natomiast dopiero przy asynchronicznym eksporcie paczek faktur wymagane jest przekazanie informacji o szyfrowaniu do zaszyfrowania wygenerowanych paczek.
Czyli wygląda to tak:
- wysyłka do KSeF — faktura szyfrowana aplikacyjnie,
- pobranie pojedynczej faktury — faktura wraca jako zwykła odpowiedź API po HTTPS,
- pobranie paczki faktur — paczka może być szyfrowana według danych podanych przez klienta, które zna bramka WAF, więc może ona też zlecić pobranie dla siebie paczki faktur.
WAF na brzegu nie może sensownie analizować treści zaszyfrowanej faktury przychodzącej do KSeF. Może widzieć żądanie, ścieżkę API, nagłówki, tokeny, rozmiary, częstotliwość, adres IP, wzorce ruchu, ale nie widzi właściwego XML-a faktury, jeśli ten XML jest zaszyfrowany aplikacyjnie dla MF.
To oznacza, że klasyczna rola WAF-a przy wejściu zostaje częściowo wykastrowana. WAF nie zobaczy w treści faktury podejrzanych konstrukcji XML, prób wstrzyknięcia, nietypowych znaków, dziwnych struktur, złośliwych fragmentów, które ujawnią się dopiero po odszyfrowaniu wewnątrz systemu.
Niemniej XML może nieść ładunek ataku. Może próbować uderzyć w parser XML, walidator, transformację XSLT, generator wizualizacji, system raportowy, eksport, program księgowy albo dowolny późniejszy komponent, który tę fakturę przetwarza. OWASP opisuje m.in. XXE, czyli ataki na aplikację parsującą XML, które przy źle skonfigurowanym parserze mogą prowadzić do ujawniania danych, SSRF, skanowania portów z perspektywy serwera i innych skutków systemowych. OWASP zaleca też wyłączanie DTD i zewnętrznych encji, bo to chroni również przed atakami odmowy usługi typu "Billion Laughs".
Oficjalna dokumentacja KSeF pokazuje, że oni ten problem częściowo widzą. Weryfikacja faktury obejmuje poprawność XML, zgodność ze schematem, UTF-8, zakaz instrukcji przetwarzania XML, zakaz niezalecanych znaków Unicode, limity rozmiaru i inne kontrole. W changelogu KSeF 2.4.0 wprost napisano, że zaostrzono weryfikację treści XML: dokument nie może zawierać niezalecanych znaków Unicode ani instrukcji przetwarzania XML.
Czyli oni muszą robić kontrolę po odszyfrowaniu, już wewnątrz systemu. WAF na brzegu nie jest w stanie wykonać pełnej kontroli treści zaszyfrowanej faktury, bo jej nie widzi.
To nie musi automatycznie oznaczać podatności. Jeśli po odszyfrowaniu istnieje osobna, twarda, izolowana strefa dekryptująco-walidacyjna, z poprawnie skonfigurowanymi parserami, bez DTD, bez encji zewnętrznych, bez niebezpiecznych transformacji, z limitami rozmiaru, czasu parsowania, głębokości drzewa XML i ścisłym XSD — taki system może być bezpieczny.
Jednak taka architektura staje się schizofreniczna!
Bo normalnie WAF ma być bramkarzem przed budynkiem. Tutaj przy fakturze przychodzącej bramkarz widzi zapieczętowaną paczkę. Nie wie, czy w środku jest dokument, granat, robak, trucizna czy trociny. Paczka przechodzi przez bramę i dopiero w środku ktoś ją otwiera.
A przy fakturze wychodzącej jest odwrotnie: bramkarz nagle widzi dokument w pełnej treści. To jest dokładnie odwrócona logika bezpieczeństwa!
Czy to zwiększa niebezpieczeństwo? Tak!
Dotąd pisałem głównie o ryzyku podglądu faktur przez zagraniczną bramkę na wyjściu.
Teraz dochodzi drugi problem: ryzyko oślepienia zagranicznej bramki na wejściu, czyli sytuacja, w której WAF nie jest w stanie wykonać jednej ze swoich podstawowych funkcji wobec najważniejszej treści przesyłanej do systemu.
KSeF używa WAF-a tam, gdzie WAF jest suwerennościowo niebezpieczny, i oślepia WAF-a tam, gdzie WAF byłby bezpieczeństwowo potrzebny.
Na wejściu faktura jest zaszyfrowana, więc Imperva nie może jej sprawdzić. Na wyjściu faktura jest jawna, więc Imperva może ją przeczytać. Trudno wymyślić głupszą konfigurację z punktu widzenia państwa: ślepota tam, gdzie potrzebna jest kontrola, i widoczność tam, gdzie potrzebna jest poufność.
Co mogliby powiedzieć projektanci? Prawdopodobnie broniliby się tak: WAF nie musi widzieć treści faktury, bo treść faktury jest sprawdzana po odszyfrowaniu przez system KSeF. I to jest technicznie możliwa odpowiedź. Jednak ona potwierdza mój zarzut architektoniczny.
Bo wtedy trzeba zapytać: po co w ogóle zagraniczny WAF na wejściu do centralnego systemu faktur, skoro najważniejszej treści nie widzi? Odpowiedzą: chroni przed DDoS, skanowaniem, atakami na endpointy, nadużyciami protokołu, botami, anomaliami ruchu.
Wtedy jego rola nie jest kontrolą bezpieczeństwa faktury, tylko ochroną transportu i dostępności. A skoro tak, to jeszcze trudniej uzasadnić, dlaczego ten sam zagraniczny punkt ma widzieć faktury na wyjściu.
WAF w KSeF jest jak celnik będący agentem obcego wywiadu, któremu przy wjeździe każą przepuszczać zaplombowane tiry bez zaglądania do środka, a przy wyjeździe dają mu do ręki pełny manifest każdego transportu. Państwo nazwało to bezpieczeństwem...
Grzegorz GPS Świderski
Twitter.com/gps65
t.me/KanalBlogeraGPS
"WAF w KSeF jest jak celnik będący agentem obcego wywiadu, któremu przy wjeździe każą przepuszczać zaplombowane tiry bez zaglądania do środka, a przy wyjeździe dają mu do ręki pełny manifest każdego transportu. Państwo nazwało to bezpieczeństwem..."
Tak jest pod każdym kamieniem tej kupy.