Wir haben zuvor über die Absicherung des HTTP-Servers geschrieben. Dieser Beitrag ist die andere Hälfte der Geschichte. Ein Client gilt normalerweise als die vertrauenswürdige Seite der Kommunikation, aber das ist er nicht: Er sendet Ihre API-Schlüssel, er folgt jeder Weiterleitung, die der entfernte Host zurückgibt, er liest die gesamte Antwort in den Speicher, und er speichert jedes Cookie, um dessen Speicherung die Antwort ihn bittet. Ein feindlicher oder auch nur kompromittierter Endpunkt kann alle vier dieser Verhaltensweisen gegen Sie wenden.
sgcWebSockets 2026.7 ergänzt eine Reihe clientseitiger Schalter, die jede dieser Lücken schließen. Jeder davon ist standardmäßig deaktiviert, ein Upgrade ändert also in einer bestehenden Anwendung nichts, bis Sie sich aktiv dafür entscheiden. Sie sind auf dem Low-Level-HTTP-Client verfügbar, auf jedem fertigen REST- und AI-Client sowie auf den HTTP/2- und HTTP/3-Clients.
Zugangsdaten, die einer Weiterleitung folgen
Das klassische clientseitige Leck. Sie rufen eine API mit einem Authorization-Header auf, der Server antwortet mit einem 302, der auf einen anderen Host zeigt, und der Client wiederholt die Anfrage dort pflichtbewusst, inklusive Header und Cookies. Ihr Bearer-Token wurde soeben einer Maschine übergeben, mit der Sie nie sprechen wollten. Die Weiterleitung muss dafür nicht einmal bösartig sein, ein Angreifer, der einen Open Redirect auf dem legitimen Host beeinflussen kann, genügt.
StripAuthOnCrossHostRedirect entfernt die Header Authorization und Cookie, sobald eine Weiterleitung den ursprünglichen Host verlässt. Die Anfrage folgt der Weiterleitung weiterhin, sie kommt nur ohne Ihre Zugangsdaten an.
uses
sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.StripAuthOnCrossHostRedirect := True;
oHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + vToken;
vResponse := oHTTP.Get('https://api.example.com/v1/account');
finally
oHTTP.Free;
end;
end;
Weiterleitungen, die auf einfaches HTTP herabstufen
Das zweite Weiterleitungsproblem. Sie starten auf https://, der Server antwortet mit einem Location, das mit http:// beginnt, und der Client wiederholt die Anfrage bereitwillig im Klartext. Alles auf dem Weg kann nun den Inhalt mitlesen und die Antwort umschreiben. Genau dieses Downgrade soll HSTS in Browsern verhindern, und bis jetzt hatte der HTTP-Client dafür kein Äquivalent.
NoInsecureRedirect verweigert eine Weiterleitung, die die Anfrage von HTTPS auf HTTP verschieben würde. Die Weiterleitung wird abgelehnt, statt ihr zu folgen.
oHTTP.NoInsecureRedirect := True;
// A 302 from https://api.example.com to http://api.example.com
// is now blocked instead of silently downgraded.
vResponse := oHTTP.Get('https://api.example.com/v1/data');
Die beiden Weiterleitungsschalter sind voneinander unabhängig, und in der Praxis wollen Sie beide. Schalten Sie den ersten ein, und eine Cross-Host-Weiterleitung trägt Ihr Token nicht mehr mit sich. Schalten Sie den zweiten ein, und eine Weiterleitung kann Ihnen die Transportsicherheit nicht mehr nehmen.
Antworten ohne Größenbegrenzung
Ein Standard-HTTP-Client liest alles, was der Server sendet. Wenn der Server einen Antwortkörper von zehn Gigabyte schickt, oder eine Chunked-Antwort, bei der ein einzelner Chunk eine Länge von zwei Gigabyte ankündigt, versucht der Client, Platz dafür zu reservieren. Das ist ein einzeiliger Denial of Service gegen Ihren eigenen Prozess, und der Angreifer muss dafür nichts kaputt machen, sondern Ihre Anfrage nur mit mehr Daten beantworten, als Sie erwartet haben.
Zwei Obergrenzen schließen das. MaxResponseSize begrenzt die Gesamtgröße eines Antwortkörpers, und MaxChunkSize begrenzt einen einzelnen Chunk einer Chunked-Antwort. Beide verstehen null als "unbegrenzt", was der Standard ist, es ändert sich also nichts, bis Sie sie setzen. Wird ein Limit überschritten, wird der Lesevorgang abgebrochen und eine Exception ausgelöst, der Client lässt den Puffer nicht weiter wachsen.
uses
sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.MaxResponseSize := 10 * 1024 * 1024; // 10 MB total, 0 = unlimited
oHTTP.MaxChunkSize := 1024 * 1024; // 1 MB per chunk, 0 = unlimited
vResponse := oHTTP.Get('https://api.example.com/v1/report');
finally
oHTTP.Free;
end;
end;
Wählen Sie eine Zahl, die widerspiegelt, was der Endpunkt tatsächlich zurückgeben soll. Wenn Sie eine JSON-API aufrufen, die mit wenigen Kilobyte antwortet, ist eine Obergrenze von wenigen Megabyte großzügig und macht aus einem unbegrenzten Lesevorgang trotzdem einen begrenzten.
Cookies, die eine ganze TLD beanspruchen
Eine Antwort kann ein Cookie mit einem Domain-Attribut senden. Nichts im Wire-Format hindert sie daran, Domain=com oder Domain=co.uk zu beanspruchen. Ein Client, der das akzeptiert, ist nun bereit, das Cookie an jeden Host unter diesem Suffix zu senden, und das ist bei Cookies gleichbedeutend damit, einen Generalschlüssel auszuhändigen. Browser verweigern das seit Jahren mithilfe der Public Suffix List.
RejectPublicSuffixCookies bringt dieselbe Regel in die Komponente. Ein Cookie, dessen Domain ein Public Suffix und keine echte registrierbare Domain ist, wird verworfen. Beachten Sie, dass das Aktivieren dieser Option auch die Cookie-Verwaltung im Client einschaltet, denn ein Cookie-Jar ist das, was sie filtert.
oHTTP.RejectPublicSuffixCookies := True;
// Set-Cookie: session=abc; Domain=co.uk -> rejected
// Set-Cookie: session=abc; Domain=example.co.uk -> accepted
2026.7 behebt außerdem zwei verwandte Cookie- und Weiterleitungsfehler, die zuvor stillschweigend falsch waren. Relative Location-Header werden jetzt korrekt in absolute URLs aufgelöst, eine 307- oder 308-Weiterleitung behält jetzt Methode und Body der Anfrage bei, wie es die Spezifikation verlangt, und ein Cookie, dessen Ablaufdatum nicht geparst werden kann, wird als Session-Cookie behandelt, statt verworfen zu werden. Max-Age hat weiterhin Vorrang vor Expires, wenn beide vorhanden sind.
Einen großen Body hochladen: Expect: 100-continue und Chunked-Anfragen
Nicht bei jeder neuen Option geht es um Angriffe, bei zweien geht es darum, keine Bandbreite zu verschwenden. Wenn Sie einen großen Body per POST an einen Endpunkt schicken, der ihn ohnehin ablehnen wird (falsche Zugangsdaten, falscher Content-Type, ein bereits ausgeschöpftes Kontingent), besteht das Standardverhalten darin, zuerst den gesamten Body über die Leitung zu schieben und danach die 401 zu lesen.
UseExpect100Continue sendet die Anfrage-Header mit einem Expect: 100-continue und wartet darauf, dass der Server signalisiert, dass er den Body annehmen will. Antwortet der Server stattdessen mit einem endgültigen Status, senden Sie die Nutzdaten nie. Kommt gar keine Freigabe an, wird der Body trotzdem gesendet, ein Server, der den Header ignoriert, funktioniert also weiterhin.
UseChunkedTransferEncoding deckt den umgekehrten Fall ab, einen Upload, dessen Größe Sie im Voraus nicht kennen. Der Body wird in Chunks statt mit einer festen Content-Length gesendet, Sie können ihn also aus einem Generator, einem Kompressor oder einer Pipe streamen, ohne ihn vorher komplett zu puffern.
uses
Classes, sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
oBody: TStream;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.UseExpect100Continue := True; // ask before uploading
oHTTP.UseChunkedTransferEncoding := True; // size not known up front
oBody := TFileStream.Create('large_upload.bin', fmOpenRead or fmShareDenyWrite);
try
vResponse := oHTTP.Post('https://api.example.com/v1/upload', oBody);
finally
oBody.Free;
end;
finally
oHTTP.Free;
end;
end;
Dieselben Schalter auf den fertigen API-Clients
Der interessante Teil ist, wo diese Eigenschaften angesiedelt sind. Sie werden auf TsgcHTTPAPI_client erneut veröffentlicht, der Basisklasse jedes fertigen REST-Clients der Bibliothek. Das heißt, Sie setzen sie direkt auf der Komponente, die Sie ohnehin schon verwenden, ohne nach dem darunterliegenden Low-Level-HTTP-Objekt greifen zu müssen.
Das umfasst die AI- und LLM-Clients (OpenAI, Anthropic, Gemini, DeepSeek, Grok, Mistral, Ollama), den OAuth2-Client, Google Cloud, WhatsApp, AWS SQS und WebPush sowie die Units der Amazon-AWS- und Google-Cloud-API.
uses
sgcHTTP_API_OpenAI;
var
oOpenAI: TsgcHTTP_API_OpenAI;
begin
oOpenAI := TsgcHTTP_API_OpenAI.Create(nil);
try
oOpenAI.StripAuthOnCrossHostRedirect := True; // never leak the API key
oOpenAI.NoInsecureRedirect := True; // never fall back to http
oOpenAI.RejectPublicSuffixCookies := True;
oOpenAI.MaxResponseSize := 32 * 1024 * 1024;
oOpenAI.MaxChunkSize := 1024 * 1024;
// ... use the client as usual
finally
oOpenAI.Free;
end;
end;
Ein API-Schlüssel, der an einen LLM-Anbieter geht, ist genau die Art von Zugangsdaten, die Sie nicht über eine Weiterleitung von der Domain des Anbieters weg schicken wollen. Genau hier kostet das Einschalten der Schalter also nichts und bringt sehr viel.
HTTP/2 und HTTP/3
Der HTTP/2-Client erhält denselben Schutz über sein Optionsobjekt TsgcWSHTTP2Client_Options, und der HTTP/3-Client stellt die Antwortbegrenzung direkt bereit.
uses
sgcHTTP;
var
oHTTP2: TsgcHTTP2Client;
begin
oHTTP2 := TsgcHTTP2Client.Create(nil);
try
oHTTP2.HTTP2Options.StripAuthOnCrossHostRedirect := True;
oHTTP2.HTTP2Options.NoInsecureRedirect := True;
oHTTP2.HTTP2Options.MaxResponseSize := 10 * 1024 * 1024;
finally
oHTTP2.Free;
end;
end;
// HTTP/3
oHTTP3.MaxResponseSize := 10 * 1024 * 1024;
Eine Zeile für eine sichere TLS-Grundeinstellung
Nichts davon hilft, wenn die TLS-Schicht überhaupt nichts überprüft. sgcWebSockets 2026.7 fügt dafür eine Voreinstellung hinzu. Jedes TLS-Optionsobjekt der Bibliothek, auf WebSocket- wie auf HTTP-Komponenten, veröffentlicht eine Eigenschaft Preset vom Typ TsgcTLSPreset. Ihr Standardwert ist tlspCustom, womit alles erhalten bleibt, was Sie von Hand konfiguriert haben.
Setzen Sie sie auf tlspSecureDefaults, dann werden Zertifikatsprüfung, TLS 1.2 oder höher und Hostnamen-Prüfung in einer einzigen Zeile eingeschaltet.
uses
sgcWebSocket_Types;
begin
oHTTP.TLSOptions.Preset := tlspSecureDefaults;
// certificate verification on, TLS 1.2+, hostname verification on
end;
Kombinieren Sie die Voreinstellung mit den Weiterleitungsschaltern und den Antwortbegrenzungen, und Sie haben einen Client, der prüft, mit wem er spricht, ein Downgrade verweigert, seine Zugangsdaten nicht an Dritte weitergibt und nicht dazu gebracht werden kann, unbegrenzt Speicher zu belegen.
.NET
Die verwaltete Edition liefert dieselben Schutzmechanismen in 2026.7. Das Entfernen der Zugangsdaten bei Weiterleitungen, die Sperre des HTTPS-Downgrades, die Obergrenzen pro Chunk und für die gesamte Antwort, die Ablehnung von Public-Suffix-Cookies, Expect: 100-continue und Chunked-Request-Bodys sind alle vorhanden, einschließlich der HTTP/2-Client-Reihe. Gleiche Namen, C#-Schreibweise.
client.StripAuthOnCrossHostRedirect = true;
client.NoInsecureRedirect = true;
client.RejectPublicSuffixCookies = true;
client.MaxResponseSize = 10 * 1024 * 1024;
client.MaxChunkSize = 1024 * 1024;
Verfügbarkeit
Die Härtungsoptionen des HTTP-Clients stehen in sgcWebSockets 2026.7 für Delphi 7 bis 13 und C++Builder (Win32/Win64, Linux64, macOS, Android und iOS) sowie in der .NET-Edition zur Verfügung. Alles hier Beschriebene ist optional und standardmäßig deaktiviert, ein Upgrade ist also ein reiner Austausch ohne Anpassungen.
Kunden mit einem aktiven Abonnement können den neuen Build im Kundenbereich herunterladen. Trial-Nutzer erhalten das aktualisierte Installationsprogramm unter esegece.com/products/websockets/download.
Fragen, Feedback oder Hilfe bei der Entscheidung, welche dieser Schalter Ihre Anwendung einschalten sollte? Nehmen Sie Kontakt auf, Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.
