| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente |
| resume-technique:reaction [20/08/2025 21:14] – Daneel Olivaw | resume-technique:reaction [11/10/2025 13:16] (Version actuelle) – Daneel Olivaw |
|---|
| ===== Protection anti-robots par reaction ===== | ===== Protection anti-robots par reaction ===== |
| |
| Nous utilisons [[https://blog.ppom.me/fr-reaction/|reaction]], une alternative efficiente à fail2ban, pour bannir temporairement les robots dont le comportement est abusif, notamment le balayage agressif des serveurs, visant à énumérer et attaquer les applications potentiellement vulnérables. | Nous utilisons [[https://blog.ppom.me/fr-reaction/|reaction]], une alternative efficiente à fail2ban, pour bannir temporairement les adresses à l'origine d'un comportement abusif. |
| | |
| | On considère comme abusif, notamment : les requêtes envoyées à nos systèmes à un rythme trop élevé, les activités de reconnaissance de nos systèmes, les tentatives d'exploitation de vulnérabilités réelles ou supposées de nos systèmes, les requêtes malformées.... |
| |
| ==== Filtres pour nginx ==== | ==== Filtres pour nginx ==== |
| |
| <file> | <file json reaction.jsonnet> |
| filters: { | filters: { |
| // nginx's default combined log format: | // nginx's default combined log format: |
| // Make sure you don't have honnest use cases for those requests, or your clients may be banned for 2 weeks! | // Make sure you don't have honnest use cases for those requests, or your clients may be banned for 2 weeks! |
| suspectRequests: { | suspectRequests: { |
| regex: [ | regex: import 'reaction/nginx_regex.jsonnet', |
| // Response "400 Bad request" if query type not GET nor POST | |
| @'^<ip> - [^\[]+\[[^\]]+\] "[^PG][^"]*" 400', | |
| @'^<ip> - [^\[]+\[[^\]]+\] "[^"][^OE][^"]*" 400', | |
| @'^<ip> - [^\[]+\[[^\]]+\] "[^"]{2}[^ST][^"]*" 400', | |
| // (?:[^/" ]*/)* is a "non-capturing group" regex that allow for subpath(s) | |
| // example: /code/.env should be matched as well as /.env | |
| // ^^^^^ | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*\.aws/', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*\.env ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*\.git/config ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*auth.html ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*auth1.html ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*password.txt ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*passwords.txt ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*dns-query ', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*info\.php[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*phpinfo\.php[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*wp-content/[^"]*\.php[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*wp-login\.php[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*wp-includes[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*xmlrpc\.php[^"]*" 4[0-9][0-9]', | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*config\.json [^"]*" 4[0-9][0-9]', | |
| // Likely scanning or recon | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*\.DS_Store [^"]*" 4[0-9][0-9]', // macOS | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*api/v2/hoverfly/version [^"]*" 4[0-9][0-9]', // Hoverfly | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application[^"]*" 4[0-9][0-9]', // Microsoft Exchange eDiscovery | |
| @'^<ip>.*"GET /json/login_session [^"]*" 4[0-9][0-9]', // HP iLO remote console | |
| @'^<ip>.*"GET /owa/auth/logon.aspx [^"]*" 4[0-9][0-9]', // Microsoft Exchange | |
| @'^<ip>.*"GET /photo/webapi/query\.[^"]*" 4[0-9][0-9]', // Synology PhotoStation API | |
| // Likely exploit attempts | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*phpunit/(?:[^/" ]*/)*Util/PHP/eval-stdin.php', // CVE-2017-9841 | |
| @'^<ip>.*"GET /(?:[^/" ]*/)*autodiscover\.json[^"]*@[^"]*[Pp]ower[Ss]hell', // CVE-2022-41082 | |
| @'^<ip>.*"GET /owa/auth/x.js [^"]*" 4[0-9][0-9]', // CVE-2021-26855 | |
| // Unusual QUERY type (WebDav, ...) with an error response | |
| @'^<ip> - [^\[]+\[[^\]]+\] "PROPFIND [^"]*" 4[0-9][0-9]', | |
| @'^<ip> - [^\[]+\[[^\]]+\] "PROPPATCH [^"]*" 4[0-9][0-9]', | |
| @'^<ip> - [^\[]+\[[^\]]+\] "PUT [^"]*" 4[0-9][0-9]', | |
| ], | |
| retry: 2, | retry: 2, |
| retryperiod: '6h', | retryperiod: '6h', |
| }, | }, |
| }, | }, |
| | </file> |
| | |
| | <file json reaction/nginx_regex.jsonnet> |
| | [ |
| | // Response "400 Bad request" if query type not GET nor POST |
| | @'^<ip> - [^\[]+\[[^\]]+\] "[^PG][^"]*" 400', |
| | @'^<ip> - [^\[]+\[[^\]]+\] "[^"][^OE][^"]*" 400', |
| | @'^<ip> - [^\[]+\[[^\]]+\] "[^"]{2}[^ST][^"]*" 400', |
| | // (?:[^/" ]*/)* is a "non-capturing group" regex that allow for subpath(s) |
| | // example: /code/.env should be matched as well as /.env |
| | // ^^^^^ |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*\.aws/', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*\.env ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*\.git/config ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*auth.html ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*auth1.html ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*password.txt ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*passwords.txt ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*dns-query ', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*info\.php[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*phpinfo\.php[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*wp-content/[^"]*\.php[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*wp-login\.php[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*wp-includes[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*xmlrpc\.php[^"]*" 4[0-9][0-9]', |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*config\.json [^"]*" 4[0-9][0-9]', |
| | // Likely scanning or recon |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*\.DS_Store [^"]*" 4[0-9][0-9]', // macOS |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*api/v2/hoverfly/version [^"]*" 4[0-9][0-9]', // Hoverfly |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application[^"]*" 4[0-9][0-9]', // Microsoft Exchange eDiscovery |
| | @'^<ip>.*"GET /json/login_session [^"]*" 4[0-9][0-9]', // HP iLO remote console |
| | @'^<ip>.*"GET /owa/auth/logon.aspx [^"]*" 4[0-9][0-9]', // Microsoft Exchange |
| | @'^<ip>.*"GET /photo/webapi/query\.[^"]*" 4[0-9][0-9]', // Synology PhotoStation API |
| | // Likely exploit attempts |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*phpunit/(?:[^/" ]*/)*Util/PHP/eval-stdin.php', // CVE-2017-9841 |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*autodiscover\.json[^"]*@[^"]*[Pp]ower[Ss]hell', // CVE-2022-41082 |
| | @'^<ip>.*"GET /owa/auth/x.js [^"]*" 4[0-9][0-9]', // CVE-2021-26855 |
| | @'^<ip>.*"GET /(?:[^/" ]*/)*(\.|%2e){2}(/|%2f)[^"]*" 4[0-9][0-9]', // CWE-22, https://owasp.org/www-community/attacks/Path_Traversal |
| | @'^<ip>.*"POST /(?:[^/" ]*/)*(\.|%2e){2}(/|%2f)[^"]*" 4[0-9][0-9]', // CWE-22, https://owasp.org/www-community/attacks/Path_Traversal |
| | // Unusual QUERY type (WebDav, ...) with an error response |
| | @'^<ip> - [^\[]+\[[^\]]+\] "PROPFIND [^"]*" 40[0345]', |
| | @'^<ip> - [^\[]+\[[^\]]+\] "PROPPATCH [^"]*" 40[0345]', |
| | @'^<ip> - [^\[]+\[[^\]]+\] "PUT [^"]*" 40[0345]', |
| | ] |
| </file> | </file> |