Contributions

De Wiki Seb35
Aller à la navigation Aller à la recherche

J’expose sur cette page mes contributions en cours ou à venir à des logiciels libres (ou autres domaines de la culture libre).

Logiciels

PdfParser

Pull Request #600 - Fix ASCII85 decoding in a specific case - proposé le 2023-05-02 - tests unitaires ajouté le 2023-05-27

flus.io

Issue #594 - Items en double ouverte le 2023-05-19 - à suivre, éventuellement chercher à résoudre

Idées

2023-05-21 - nginx + RFC 9110 - utilisation trop fréquente du code 505 HTTP Version Not Supported

En parcourant des logs d’un serveur nginx, je constate des requêtes GET / HTTP/7.9 [1], alors que, en 2023, la version la fréquente de HTTP est 2.0 et la 3.0 vient d’être publiée (juin 2022) : mettre une version de HTTP égale à 7.9 n’est donc pas une erreur du client mais est une sonde en phase de reconnaissance (soit du fuzzing, soit ciblant un logiciel précis). L’occurence de telles requêtes semble très rare toutefois.

Utiliser un code 5xx laisse à penser que c’est un problème du serveur, hors le serveur ne peut pas implémenter une version de HTTP qui n’existe pas (encore), c’est donc une erreur du client. Ce raisonnement touche au standard RFC 9110 section 15.6.6 plus qu’à nginx.

Pour les sysadmins qui observent les logs et particulièrement les erreurs 5xx (qui sont des problèmes soit dans les implémentations (à corriger) soit opérationnels (performance notamment)), ça oblige à avoir un traitement fin : est-ce que la version HTTP existe (client peut-être légitime) ou n’existe pas (attaque obligatoirement) ?

Du côté de nginx, je serais d’avis de retourner une erreur 400 (à défaut d’un meilleur code 4xx), soit avec une liste fixée dans le code disant les versions potentiellement acceptées à l’époque (actuellement ça serait erreur 400 pou HTTP > 3.0 et erreur 505 pour HTTP <= 3.0 s’il n’y a pas de module pour HTTP 3.0 puisqu’il pourrait y en avoir puisque le standard est disponible). Pour laisser plus de flexibilité, il pourrait être créé un paramètre dans la configuration pour permettre aux sysadmins de changer la version maximum existante sans avoir à changer la version de nginx tout de suite. Ce paramètre pourrait être abusé par les sysadmins qui ne voudraient pas avoir de codes 5xx même si une nouvelle version de HTTP devient disponible et que des clients peuvent alors commencer à la demander.

2023-05-21 - nginx - utilisation plus exhaustive du code 405 Method Not Allowed

En parcourant des logs d’un serveur nginx et observant les attaquants opportunistes, je remarque que les méthodes HTTP exotiques ne sont pas rejetées avec le code "405 Method Not Allowed". Par exemple la configuration try_files $uri =404; donne :

  • requête = "DELETE /fichier-inexistant.pdf HTTP/1.1" réponse = "404 Not Found" car le fichier n’existe pas
  • requête = "DELETE /fichier-existant.pdf HTTP/1.1" réponse = "405 Not Allowed"

Il serait intéressant qu’il y ait un paramètre de configuration methods_allowed GET HEAD POST; par exemple pour refuser inconditionnellement des méthodes exotiques pour le serveur en question afin de limiter encore plus la surface d’attaque.

La RFC 9110 section 9.1 Method > Overview dit que l’implémentation des méthodes GET et HEAD est obligatoire, toutes les autres sont optionnelles et peuvent changer dynamiquement.

Il y a déjà dans le code de nginx des retours "405 Not Allowed" selon les modules (chercher la constante NGX_HTTP_NOT_ALLOWED, par exemple ngx_http_static_module.c retourne 405 si la méthode n’est pas GET, HEAD ou POST ; ou ngx_http_empty_gif_module.c retourn 405 si la méthode n’est pas GET ou HEAD), mais il serait préférable que ça retourne toujours 405 si aucun module n’est en capacité de répondre (ou laisser à l’administrateur la possibilité de faire cette liste dans la conf).

PS : je ne suis pas complètement sûr que la fonctionnalité n’existe pas déjà, il est possible que mon observation vienne du fait que Debian compile nginx avec --with-http_dav_module, et peut-être que le verbe DELETE pourrait potentiellement répondre même si on a explicitement ou implicitement dav_methods off; dans le contexte.

Actions à faire

  1. Compiler nginx sans aucun module
  2. Parcourir https://nginx.org/en/docs/dev/development_guide.html
  3. Re-tester
  4. Confirmer ou non le problème
  5. Éventuellement investiguer comment ça se comporte si on active le module dav
  6. Par rapport au problème que j’observe (en nginx 1.14 de Debian 10 buster et 1.18 de Debian 11 bullseye, y compris après avoir retiré tous les modules dynamiques), l’explication la plus vraisemblable est que les nouvelles versions de nginx ont corrigé le problème (entre 1.18 et 1.23)

Compilation

Avec nginx 1.23.0 bddd3f76e3e5 (2023-05-23T00:45:18+04:00)

./auto/configure --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/tmp/nginx/usr/share/nginx --conf-path=/tmp/nginx/etc/nginx/nginx.conf --http-log-path=/tmp/nginx/var/log/nginx/access.log --error-log-path=/tmp/nginx/var/log/nginx/error.log --lock-path=/tmp/nginx/var/lock/nginx.lock --pid-path=/tmp/nginx/run/nginx.pid --modules-path=/tmp/nginx/usr/lib/nginx/modules --http-client-body-temp-path=/tmp/nginx/var/lib/nginx/body --http-fastcgi-temp-path=/tmp/nginx/var/lib/nginx/fastcgi --http-proxy-temp-path=/tmp/nginx/var/lib/nginx/proxy --http-scgi-temp-path=/tmp/nginx/var/lib/nginx/scgi --http-uwsgi-temp-path=/tmp/nginx/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-threads --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-http_addition_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-http_xslt_module

Il n’y a pas le problème : curl -v -X DELETE 'http://127.0.0.1:8080/fichier-existant.txt' et curl -v -X DELETE 'http://127.0.0.1:8080/fichier-inexistant.txt' retournent 405 Not Allowed (et le module dav est innocent).