sgcIndy 2026.6 skupia uwagę na stronie serwerowej. To wydanie dodaje zestaw opcjonalnych opcji wzmocnienia bezpieczeństwa do komponentów serwerowych TLS, TCP i HTTP, zamykając szereg dobrze znanych klas ataków, przed którymi bazowy kod Indy nigdy nie chronił: wywołanie zwrotne weryfikacji certyfikatu działające w trybie fail-open, powolne połączenia Slowloris, nieograniczone treści i nagłówki żądań oraz przemyt żądań HTTP. Dostarcza również pierwsze prymitywy postkwantowej enkapsulacji klucza ML-KEM-768.
Każda nowa ochrona domyślnie zachowuje poprzednie działanie, więc istniejące aplikacje pozostają nienaruszone, dopóki jej nie włączysz. Ten wpis omawia kolejno każdą z nich wraz z gotowymi do wklejenia fragmentami kodu w Delphi.
Wzmocnione serwery TLS
Najważniejsza poprawka dotyczy wywołania zwrotnego weryfikacji partnera w OpenSSL. W standardowym Indy wywołanie zwrotne weryfikacji może działać w trybie fail open: gdy serwer żąda certyfikatu klienta, ostateczna decyzja była sterowana wywołaniem zwrotnym użytkownika i ignorowała własny werdykt OpenSSL, więc wywołanie zwrotne, które zwracało sukces, akceptowało certyfikat wygasły, podpisany samodzielnie lub niezaufany. Nowa flaga TIdSSLOptions.StrictVerify wymusza wynik OpenSSL, więc niestandardowy obsługujący OnVerifyPeer może decyzję jedynie dalej zaostrzyć, nigdy złagodzić.
Trzy kolejne flagi podłączają opcje OpenSSL, które nagłówki już deklarowały, ale biblioteka nigdy ich nie stosowała: DisableCompression ogranicza CRIME, DisableRenegotiation blokuje renegocjację inicjowaną przez klienta (atak DoS o asymetrycznym obciążeniu CPU) w OpenSSL 1.1.0h i nowszych, a ServerCipherPreference sprawia, że to kolejność szyfrów serwera wygrywa negocjację zamiast kolejności klienta.
uses
IdHTTPServer, IdSSLOpenSSL;
var
oServer: TIdHTTPServer;
oSSL: TIdServerIOHandlerSSLOpenSSL;
begin
oServer := TIdHTTPServer.Create(nil);
oSSL := TIdServerIOHandlerSSLOpenSSL.Create(oServer);
oSSL.SSLOptions.CertFile := 'server.pem';
oSSL.SSLOptions.KeyFile := 'server.key';
oSSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_3];
// opt-in hardening, every flag defaults to False
oSSL.SSLOptions.StrictVerify := True; // enforce the OpenSSL verdict
oSSL.SSLOptions.DisableCompression := True; // CRIME
oSSL.SSLOptions.DisableRenegotiation := True; // renegotiation DoS
oSSL.SSLOptions.ServerCipherPreference := True; // server picks the cipher
oServer.IOHandler := oSSL;
oServer.Active := True;
end;
Ustaw VerifyMode na [sslvrfPeer, sslvrfFailIfNoPeerCert] razem z StrictVerify, gdy chcesz mieć wzajemne TLS, które faktycznie odrzuca nieznany certyfikat klienta.
Zatrzymanie Slowloris
Klient Slowloris otwiera wiele połączeń i przesyła po jednym bajcie naraz, nigdy nie kończąc żądania, aby zablokować każdy wątek roboczy. Naturalna obrona wygląda jak limit czasu odczytu, ale jest tu subtelność warta poznania: ReadTimeout w Indy to limit czasu bezczynności. Każdy przybywający bajt go resetuje, więc klient, który wysyła bajt co kilka sekund, utrzymuje połączenie przy życiu w nieskończoność.
2026.6 dodaje prawdziwy całkowity termin odczytu do TIdIOHandler za pomocą SetReadDeadline. Jest sprawdzany przy każdym odczycie, więc zadziała nawet wtedy, gdy bajty wciąż napływają kropla po kropli. Serwer HTTP podłącza go automatycznie poprzez nową właściwość RequestReadTimeout, która ogranicza czas na odebranie wiersza żądania i nagłówków oraz resetuje się dla każdego żądania keep-alive.
uses
IdHTTPServer;
var
oServer: TIdHTTPServer;
begin
oServer := TIdHTTPServer.Create(nil);
oServer.DefaultPort := 8080;
// close any client that has not finished sending the request
// line and headers within 5 seconds, even if it keeps dripping bytes
oServer.RequestReadTimeout := 5000;
oServer.Active := True;
end;
W przypadku niestandardowego TIdTCPServer możesz zastosować ten sam termin ręcznie wokół swojej pętli odczytu. Przekaż 0, aby go wyczyścić.
procedure TForm1.ServerExecute(AContext: TIdContext);
var
vLine: string;
begin
// bound the whole request to 5 seconds of total read time
AContext.Connection.IOHandler.SetReadDeadline(5000);
try
vLine := AContext.Connection.IOHandler.ReadLn;
// ... handle the request ...
finally
AContext.Connection.IOHandler.SetReadDeadline(0);
end;
end;
Limity żądań dla serwerów HTTP
Serwer HTTP, który odczytuje wszystko, co deklaruje klient, jest łatwym celem wyczerpania pamięci. Pojedyncze żądanie może ogłosić Content-Length: 2000000000, a serwer spróbuje buforować dwa gigabajty, albo strumieniować nieskończoną treść fragmentowaną, albo wysłać miliony bajtów nagłówka. 2026.6 dodaje trzy limity oraz kontrolę przemytu do TIdCustomHTTPServer.
MaxRequestBodySize ogranicza Content-Length oraz zsumowaną treść fragmentowaną i odpowiada 413 Payload Too Large, gdy zostanie przekroczony. MaxHeaderTotalSize ogranicza całkowitą liczbę bajtów nagłówków i odpowiada 431 Request Header Fields Too Large. StrictRequestParsing odrzuca żądania, które są celowo niejednoznaczne, takie jak komunikat zawierający jednocześnie Content-Length i Transfer-Encoding: chunked (klasyczny wektor przemytu żądań) lub ujemny rozmiar fragmentu, odpowiadając 400 Bad Request. Pętla nagłówków końcowych (trailer) treści fragmentowanej jest teraz również ograniczona, więc atakujący nie może już utrzymywać połączenia otwartego nieskończonym strumieniem wierszy końcowych.
oServer.MaxRequestBodySize := 10 * 1024 * 1024; // 10 MB, else 413
oServer.MaxHeaderTotalSize := 64 * 1024; // 64 KB, else 431
oServer.StrictRequestParsing := True; // reject CL+TE smuggling, else 400
Na surowej warstwie TCP TIdIOHandler.MaxInputBufferSize ogranicza skumulowany bufor wejściowy dla dowolnego protokołu zbudowanego na IOHandler, co powstrzymuje odczyt z prefiksem długości lub zbyt duży wiersz przed nieograniczonym powiększaniem bufora.
// inside OnConnect / OnExecute of any Indy server
AContext.Connection.IOHandler.MaxInputBufferSize := 1024 * 1024; // 1 MB cap
Opcjonalne z założenia
Żadna z tych opcji nie zmienia domyślnego działania. Wszystkie pola są domyślnie wyłączone (0 dla limitów rozmiaru i czasu, False dla flag logicznych), więc projekt, który aktualizuje się do 2026.6, zachowuje się dokładnie tak samo jak na 2026.5. Włączasz dokładnie te zabezpieczenia, których potrzebuje Twoje wdrożenie, a ten sam kod kompiluje się od Delphi 7 po RAD Studio 13 oraz Free Pascal.
Również w tym wydaniu
2026.6 wprowadza pierwsze prymitywy postkwantowej enkapsulacji i dekapsulacji ML-KEM-768, dostępne w OpenSSL 3.5 i nowszych. Udostępniają proste API TBytes, dzięki czemu możesz dodać postkwantowy krok enkapsulacji klucza do hybrydowego uzgadniania obok klasycznej wymiany ECDH.
Po stronie kompilacji, kompilacja pakietów C++Builder nie kończy się już błędem MSBuild MSB1008, gdy RAD Studio jest zainstalowane w ścieżce zawierającej spacje. Parametr DCC_BpiOutput jest teraz ujęty w cudzysłów.
Aktualizacja
2026.6 to aktualizacja typu drop-in. Nie ma żadnych zmian łamiących zgodność ani niczego do migracji, ponieważ każda nowa ochrona jest opcjonalna. Przejrzyj powyższe fragmenty kodu i włącz opcje pasujące do Twojego serwera.
sgcIndy jest darmowe. Pobierz najnowszą wersję z esegece.com/products/sgcindy/download.
Pytania, opinie lub pomoc we wzmocnieniu bezpieczeństwa Twojego serwera? Skontaktuj się z nami, otrzymasz odpowiedź od osób, które napisały ten kod.
