sgcIndy 2026.6 porte son attention sur le côté serveur. Cette version ajoute un ensemble d'options de renforcement de la sécurité activables aux composants serveur TLS, TCP et HTTP, fermant un certain nombre de classes d'attaques bien connues contre lesquelles le code Indy sous-jacent ne se prémunissait jamais : un callback de vérification de certificat qui échoue en mode ouvert, les connexions Slowloris au compte-gouttes, les corps et en-têtes de requête sans limite, et le smuggling de requêtes HTTP. Elle livre également les premières primitives post-quantiques d'encapsulation de clé ML-KEM-768.
Chaque nouvelle protection adopte par défaut le comportement précédent, de sorte que les applications existantes ne sont pas affectées tant que vous ne les activez pas. Cet article passe en revue chacune d'elles avec des extraits Delphi prêts à coller.
Serveurs TLS renforcés
Le correctif le plus important concerne le callback de vérification du pair OpenSSL. Dans Indy d'origine, le callback de vérification peut échouer en mode ouvert : lorsqu'un serveur demande un certificat client, la décision finale était pilotée par le callback utilisateur et ignorait le verdict d'OpenSSL lui-même, de sorte qu'un callback renvoyant un succès acceptait un certificat expiré, auto-signé ou non approuvé. Le nouvel indicateur TIdSSLOptions.StrictVerify impose le résultat d'OpenSSL, de sorte qu'un gestionnaire OnVerifyPeer personnalisé ne peut que restreindre davantage la décision, jamais l'assouplir.
Trois autres indicateurs activent des options OpenSSL que les en-têtes déclaraient déjà mais que la bibliothèque n'appliquait jamais : DisableCompression atténue CRIME, DisableRenegotiation bloque la renégociation initiée par le client (un DoS asymétrique en CPU) sur OpenSSL 1.1.0h et versions ultérieures, et ServerCipherPreference fait en sorte que l'ordre de chiffrement du serveur l'emporte dans la négociation plutôt que celui du client.
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;
Définissez VerifyMode sur [sslvrfPeer, sslvrfFailIfNoPeerCert] conjointement avec StrictVerify lorsque vous voulez un TLS mutuel qui rejette réellement un certificat client inconnu.
Arrêter Slowloris
Un client Slowloris ouvre de nombreuses connexions et distille un octet à la fois, sans jamais terminer la requête, afin d'immobiliser chaque thread de travail. La défense naturelle ressemble à un délai de lecture, mais il existe une subtilité qu'il vaut la peine de connaître : le ReadTimeout d'Indy est un délai d'inactivité. Chaque octet qui arrive le réinitialise, de sorte qu'un client qui envoie un octet toutes les quelques secondes maintient la connexion en vie indéfiniment.
2026.6 ajoute un véritable délai de lecture total à TIdIOHandler via SetReadDeadline. Il est vérifié à chaque lecture, de sorte qu'il se déclenche même tant que des octets continuent d'arriver au compte-gouttes. Le serveur HTTP le câble automatiquement grâce à la nouvelle propriété RequestReadTimeout, qui borne le temps de réception de la ligne de requête et des en-têtes et se réinitialise à chaque requête 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;
Pour un TIdTCPServer personnalisé, vous pouvez appliquer le même délai à la main autour de votre boucle de lecture. Passez 0 pour l'effacer.
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;
Limites de requête pour les serveurs HTTP
Un serveur HTTP qui lit tout ce qu'un client déclare est une cible facile d'épuisement de la mémoire. Une seule requête peut annoncer Content-Length: 2000000000 et le serveur tentera de mettre en mémoire tampon deux gigaoctets, ou de diffuser un corps en chunks sans fin, ou d'envoyer des millions d'octets d'en-tête. 2026.6 ajoute trois plafonds et une vérification de smuggling à TIdCustomHTTPServer.
MaxRequestBodySize plafonne le Content-Length et la somme du corps en chunks et répond 413 Payload Too Large lorsqu'il est dépassé. MaxHeaderTotalSize plafonne le total des octets d'en-tête et répond 431 Request Header Fields Too Large. StrictRequestParsing rejette les requêtes volontairement ambiguës, comme un message qui porte à la fois Content-Length et Transfer-Encoding: chunked (le vecteur classique de smuggling de requêtes) ou une taille de chunk négative, en répondant 400 Bad Request. La boucle d'en-têtes de trailer en chunks est désormais bornée elle aussi, de sorte qu'un attaquant ne peut plus maintenir une connexion ouverte avec un flux infini de lignes de trailer.
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
Au niveau TCP brut, TIdIOHandler.MaxInputBufferSize borne le tampon d'entrée cumulé pour tout protocole bâti sur l'IOHandler, ce qui empêche une lecture préfixée par la longueur ou une ligne surdimensionnée de faire croître le tampon sans limite.
// inside OnConnect / OnExecute of any Indy server
AContext.Connection.IOHandler.MaxInputBufferSize := 1024 * 1024; // 1 MB cap
Activable par conception
Aucune de ces options ne modifie le comportement par défaut. Les champs ont tous pour valeur par défaut « désactivé » (0 pour les limites de taille et de délai, False pour les indicateurs booléens), de sorte qu'un projet qui passe à 2026.6 se comporte exactement comme sur 2026.5. Vous activez précisément les protections dont votre déploiement a besoin, et le même code compile de Delphi 7 jusqu'à RAD Studio 13 et Free Pascal.
Également dans cette version
2026.6 introduit les premières primitives post-quantiques d'encapsulation et de décapsulation ML-KEM-768, disponibles sur OpenSSL 3.5 et versions ultérieures. Elles exposent une API TBytes simple afin que vous puissiez intégrer une étape d'encapsulation de clé post-quantique dans une poignée de main hybride aux côtés de l'échange ECDH classique.
Côté build, la compilation des paquets C++Builder n'échoue plus avec l'erreur MSBuild MSB1008 lorsque RAD Studio est installé dans un chemin contenant des espaces. Le paramètre DCC_BpiOutput est désormais entre guillemets.
Mise à niveau
2026.6 est une mise à niveau directe. Il n'y a aucun changement cassant et rien à migrer, car chaque nouvelle protection est activable. Examinez les extraits ci-dessus et activez les options qui conviennent à votre serveur.
sgcIndy est gratuit. Téléchargez la dernière version depuis esegece.com/products/sgcindy/download.
Des questions, des retours ou de l'aide pour renforcer votre serveur ? Contactez-nous, vous recevrez une réponse des personnes qui ont écrit le code.
