Code Monkey home page Code Monkey logo

modsecurity-docker's Introduction

ModSecurity Docker Image

Note

⚠️ This repository has been archived.

We used to build owasp/modsecurity-crs via owasp/modsecurity (this repository), but it has become error prone and cumbersome. We have opted to merge the two repositories and will no longer build owasp/modescurity.

Please visit https://github.com/coreruleset/modsecurity-crs-docker.

dockeri.co

Build Status GitHub issues GitHub PRs License

Supported tags and respective Dockerfile links

  • 3-YYYYMMDDHHMM, 3.0-YYYYMMDDHHMM, 3.0.8-YYYYMMDDHHMM, nginx (master/v3-nginx/Dockerfile) – last stable ModSecurity v3 on Nginx 1.22 official stable base image
  • 2-YYYYMMDDHHMM, 2.9-YYYYMMDDHHMM, 2.9.6-YYYYMMDDHHMM, apache (master/v2-apache/Dockerfile) – last stable ModSecurity v2 on Apache 2.4 official stable base image

⚠️ We changed tags to support production usage. Now, if you want to use the "rolling version", use the tag owasp/modsecurity:nginx or owasp/modsecurity:apache. If you need a stable long term image, use the one with the build date in YYYYMMDDHHMM format, example owasp/modsecurity:3-202209141209 or owasp/modsecurity:2.9.6-alpine-202209141209 for example. You have been warned.

🆕 We added healthchecks to the images. Containers already return HTTP status code 200 when accessing the /healthz URI. When a container has a healthcheck specified, it has a health status in addition to its normal status. This status is initially starting. Whenever a health check passes, it becomes healthy (whatever state it was previously in). After a certain number of consecutive failures, it becomes unhealthy. See https://docs.docker.com/engine/reference/builder/#healthcheck for more information.

Supported variants

We have support for alpine linux variants of the base images. Just add -alpine and you will get it. Examples:

  • 3-alpine-YYYYMMDDHHMM, 3.0-alpine-YYYYMMDDHHMM, 3.0.8-alpine-YYYYMMDDHHMM, nginx-alpine (master/v3-nginx/Dockerfile-alpinelast stable ModSecurity v3 on Nginx 1.22 Alpine official stable base image
  • 2-alpine-YYYYMMDDHHMM, 2.9-alpine-YYYYMMDDHHMM, 2.9.6-alpine-YYYYMMDDHHMM, apache-alpine (master/v2-apache/Dockerfile-alpine) – last stable ModSecurity v2 on Apache 2.4 Alpine official stable base image

⚠️ We changed tags to support production usage. Now, if you want to use the "rolling version", use the tag owasp/modsecurity:nginx-alpine or owasp/modsecurity:apache-alpine. If you need a stable long term image, use the one with the build date in YYYYMMDDHHMM format, example owasp/modsecurity:3-202209141209-alpine or owasp/modsecurity:2.9.6-202209141209 for example. You have been warned.

Supported architectures

We added the docker buildx support to our docker builds so additional architectures are supported now. As we create our containers based on the official apache and nginx ones, we can only support the architectures they support.

There is a new file docker-bake.hcl used for this purpose. To build for new platforms, just use this example:

$ docker buildx use $(docker buildx create --platform linux/amd64,linux/arm64,linux/arm/v8)
$ docker buildx bake -f docker-bake.hcl

We require a version of buildx >= v0.9.1. Visit the official documentation for instructions on installing and upgrading buildx. You can check which version you have using:

docker buildx version
github.com/docker/buildx v0.9.1 ed00243a0ce2a0aee75311b06e32d33b44729689

If you want to see the targets of the build, use:

docker buildx bake -f ./docker-bake.hcl --print

We are building now for these architectures:

  • linux/amd64
  • linux/i386
  • linux/arm64
  • linux/arm/v7

You can find additional examples on how to use buildx in this repository's GitHub actions.

Quick reference

What is ModSecurity

ModSecurity is an open source, cross platform Web Application Firewall (WAF) engine for Apache, IIS and Nginx. It has a robust event-based programming language which provides protection from a range of attacks against web applications and allows for HTTP traffic monitoring, logging and real-time analysis.

How to use this image

This image only contains ModSecurity built from the code provided on the ModSecurity Github Repo. THE CORE RULE SET IS NOT PROVIDED IN THIS IMAGE, but it should not be hard to extend. On the other hand, IF YOU WANT MODSECURITY WITH THE CORE RULE SET please visit the OWASP Core Rule Set (CRS) DockerHub Repo.

  1. Create a Dockerfile in your project and copy your code into container.

    FROM owasp/modsecurity:apache
    COPY ./public-html/ .
    
  2. run the commands to build and run the Docker image.

    $ docker build -t my-modsec .
    $ docker run -p 8080:80 my-modsec
    
  3. Visit http://localhost:8080 and your page.

Nginx based images breaking change

⚠️ WARNING
Nginx based images are now based on upstream nginx. This changed the way the config file for nginx is generated.

If using the Nginx environment variables is not enough for your use case, you can mount your own nginx.conf file as the new template for generating the base config.

An example can be seen in the docker-compose file.

💬 What happens if I want to make changes in a different file, like /etc/nginx/conf.d/default.conf? You mount your local file, e.g. nginx/default.conf as the new template: /etc/nginx/templates/conf.d/default.conf.template. You can do this similarly with other files. Files in the templates directory will be copied and subdirectories will be preserved.

TLS/HTTPS

The TLS is configured by default on port 443. Note: The default configuration uses self signed certificates, to use your own certificates (recommended) COPY or mount (-v) your server.crt and server.key into /usr/local/apache2/conf/. Please remember you'll need to forward the HTTPS port.

$ docker build -t my-modsec .
$ docker run -p 8443:443 my-modsec

We use sane intermediate defaults taken from the Mozilla SSL config tool. Please check it and choose the best that match your needs.

You can use variables on nginx and apache to always redirect from http to https if needed (see APACHE_ALWAYS_TLS_REDIRECT and NGINX_ALWAYS_TLS_REDIRECT below).

Proxying

ModSecurity is often used as a reverse proxy. This allows one to use ModSecurity without modifying the webserver hosting the underlying application (and also protect web servers that modsecurity cannot currently embedd into). The proxy is set by default to true and the location is defined by BACKEND environment variable. The SSL is enabled by default.

$ docker build -t my-modsec . -f
$ docker run -p 8080:80 -e PROXY_SSL=on -e BACKEND=http://example.com my-modsec

ServerName

It is often convenient to set your servername. To do this simply use the SERVER_NAME environment variable passed to docker run. By default the servername provided is localhost.

$ docker build -t modsec .
$ docker run -p 8080:80 -e SERVER_NAME=myhost my-modsec

Apache ENV Variables

Name Description
ACCESSLOG A string value indicating the location of the custom log file (Default: /var/log/apache2/access.log)
APACHE_ALWAYS_TLS_REDIRECT A string value indicating if http should redirect to https (Allowed values: on, off. Default: off)
APACHE_LOGFORMAT A string value indicating the LogFormat that apache should use. (Default: '"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' (combined). Tip: use single quotes outside your double quoted format string.) ⚠️ Do not add a `
APACHE_METRICS_LOGFORMAT A string value indicating the LogFormat that the additional log apache metrics should use. (Default:'"%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i""' (combined). Tip: use single quotes outside your double quoted format string.) ⚠️ Do not add a `
BACKEND A string indicating the partial URL for the remote server of the ProxyPass directive (Default: http://localhost:80)
BACKEND_WS A string indicating the IP/URL of the WebSocket service (Default: ws://localhost:8080)
ERRORLOG A string value indicating the location of the error log file (Default: /var/log/apache2/error.log)
H2_PROTOCOLS A string value indicating the protocols supported by the HTTP2 module (Default: h2 http/1.1)
LOGLEVEL A string value controlling the number of messages logged to the error_log (Default: warn)
METRICS_ALLOW_FROM A string indicating a range of IP adresses that can access the metrics (Default: 127.0.0.0/255.0.0.0 ::1/128)
METRICS_DENY_FROM A string indicating a range of IP adresses that cannot access the metrics (Default: All)
METRICSLOG A string indicating the path of the metrics log (Default: /dev/null)
PORT An integer value indicating the port where the webserver is listening to (Default: 80)
PROXY_ERROR_OVERRIDE A string indicating that errors from the backend services should be overridden by this proxy server (see ProxyErrorOverride directive). (Allowed values: on, off. Default: on)
PROXY_PRESERVE_HOST A string indicating the use of incoming Host HTTP request header for proxy request (Default: on)
PROXY_SSL_CERT_KEY A string indicating the path to the server PEM-encoded private key file (Default: /usr/local/apache2/conf/server.key)
PROXY_SSL_CERT A string indicating the path to the server PEM-encoded X.509 certificate data file or token identifier (Default: /usr/local/apache2/conf/server.crt)
PROXY_SSL_CHECK_PEER_NAME A string indicating if the host name checking for remote server certificates is to be enabled (Default: on)
PROXY_SSL_VERIFY A string value indicating the type of remote server Certificate verification (Default: none)
PROXY_SSL A string indicating SSL Proxy Engine Operation Switch (Default: off)
PROXY_TIMEOUT Number of seconds for proxied requests to time out (Default: 60)
REMOTEIP_INT_PROXY A string indicating the client intranet IP addresses trusted to present the RemoteIPHeader value (Default: 10.1.0.0/16)
REQ_HEADER_FORWARDED_PROTO A string indicating the transfer protocol of the initial request (Default: https)
SERVER_ADMIN A string value indicating the address where problems with the server should be e-mailed (Default: root@localhost)
SERVER_NAME A string value indicating the server name (Default: localhost)
SSL_CIPHER_SUITE A string indicating the cipher suite to use. Uses OpenSSL list of cipher suites (Default: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
SSL_ENGINE A string indicating the SSL Engine Operation Switch (Default: off)
SSL_HONOR_CIPHER_ORDER A string indicating if the server should honor the cipher list provided by the client (Allowed values: on, off. Default: off)
SSL_PORT Port number where the SSL enabled webserver is listening (Default: 443)
SSL_PROTOCOL A string for configuring the usable SSL/TLS protocol versions (Default: "all -SSLv3 -TLSv1 -TLSv1.1")
SSL_PROXY_PROTOCOL A string for configuring the proxy client SSL/TLS protocol versions (Default: "all -SSLv3 -TLSv1 -TLSv1.1")
SSL_PROXY_CIPHER_SUITE A string indicating the cipher suite to connect to the backend via TLS. (Default "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
SSL_SESSION_TICKETS A string to enable or disable the use of TLS session tickets (RFC 5077). (Default: off)
SSL_USE_STAPLING A string indicating if OSCP Stapling should be used (Allowed values: on, off. Default: on)
TIMEOUT Number of seconds before receiving and sending timeout (Default: 60)
WORKER_CONNECTIONS Maximum number of MPM request worker processes (Default: 400)

Note: Apache access and metric logs can be disabled by exporting the nologging=1 environment variable, or using ACCESSLOG=/dev/null and METRICSLOG=/dev/null.

Nginx ENV Variables

Name Description
ACCESSLOG A string value indicating the location of the access log file (Default: /var/log/nginx/access.log)
BACKEND A string indicating the partial URL for the remote server of the proxy_pass directive (Default: http://localhost:80)
DNS_SERVER A string indicating the name servers used to resolve names of upstream servers into addresses. For localhost backend this value should not be defined (Default: not defined)
ERRORLOG A string value indicating the location of the error log file (Default: /proc/self/fd/2)
LOGLEVEL A string value controlling the number of messages logged to the error_log (Default: warn)
METRICS_ALLOW_FROM A string indicating a single range of IP adresses that can access the metrics (Default: 127.0.0.0/24)
METRICS_DENY_FROM A string indicating a range of IP adresses that cannot access the metrics (Default: all)
METRICSLOG A string value indicating the location of metrics log file (Default: /dev/null)
NGINX_ALWAYS_TLS_REDIRECT A string value indicating if http should redirect to https (Allowed values: on, off. Default: off)
PORT An integer value indicating the port where the webserver is listening to (Default: 80)
SET_REAL_IP_FROM A string of comma separated IP, CIDR, or UNIX domain socket addresses that are trusted to replace addresses in REAL_IP_HEADER (Default: 127.0.0.1). See set_real_ip_from
REAL_IP_HEADER Name of the header containing the real IP value(s) (Default: X-REAL-IP). See real_ip_header
REAL_IP_RECURSIVE A string value indicating whether to use recursive reaplacement on addresses in REAL_IP_HEADER (Allowed values: on, off. Default: on). See real_ip_recursive
PROXY_SSL_CERT A string value indicating the path to the server PEM-encoded X.509 certificate data file or token value identifier (Default: /etc/nginx/conf/server.crt)
PROXY_SSL_CERT_KEY A string value indicating the path to the server PEM-encoded private key file (Default: /etc/nginx/conf/server.key)
PROXY_SSL_CIPHERS A String value indicating the enabled ciphers. The ciphers are specified in the format understood by the OpenSSL library. (Default: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
PROXY_SSL_DH_BITS A numeric value indicating the size (in bits) to use for the generated DH-params file (Default 2048)
PROXY_SSL_OCSP_STAPLING A string value indicating if ssl_stapling and ssl_stapling_verify should be enabled (Allowed values: on, off. Default: off)
PROXY_SSL_PREFER_CIPHERS A string value indicating if the server ciphers should be preferred over client ciphers when using the SSLv3 and TLS protocols (Allowed values: on, off. Default: off)
PROXY_SSL_PROTOCOLS A string value indicating the ssl protocols to enable (default: TTLSv1.2 TLSv1.3)
PROXY_SSL_VERIFY A string value indicating if the client certificates should be verified (Allowed values: on, off. Default: off)
PROXY_TIMEOUT Number of seconds for proxied requests to time out connections (Default: 60s)
SSL_PORT Port number where the SSL enabled webserver is listening (Default: 443)
TIMEOUT Number of seconds for a keep-alive client connection to stay open on the server side (Default: 60s)
WORKER_CONNECTIONS Maximum number of simultaneous connections that can be opened by a worker process (Default: 1024)

ModSecurity ENV Variables

All these variables impact in configuration directives in the modsecurity engine running inside the container. The reference manual has the extended documentation, and for your reference we list the specific directive we change when you modify the ENV variables for the container.

Name Description
MODSEC_AUDIT_ENGINE A string used to configure the audit engine, which logs complete transactions (Default: RelevantOnly). Accepted values: On, Off, RelevantOnly. See SecAuditEngine for additional information.
MODSEC_AUDIT_LOG A string indicating the path to the main audit log file or the concurrent logging index file (Default: /dev/stdout)
MODSEC_AUDIT_LOG_FORMAT A string indicating the output format of the AuditLogs (Default: JSON). Accepted values: JSON, Native. See SecAuditLogFormat for additional information.
MODSEC_AUDIT_LOG_TYPE A string indicating the type of audit logging mechanism to be used (Default: Serial). Accepted values: Serial, Concurrent (HTTPS works only on Nginx - v3). See SecAuditLogType for additional information.
MODSEC_AUDIT_LOG_PARTS A string that defines which parts of each transaction are going to be recorded in the audit log (Default: 'ABIJDEFHZ'). See SecAuditLogParts for the accepted values.
MODSEC_AUDIT_STORAGE A string indicating the directory where concurrent audit log entries are to be stored (Default: /var/log/modsecurity/audit/)
MODSEC_DATA_DIR A string indicating the path where persistent data (e.g., IP address data, session data, and so on) is to be stored (Default: /tmp/modsecurity/data)
MODSEC_DEBUG_LOG A string indicating the path to the ModSecurity debug log file (Default: /dev/null)
MODSEC_DEBUG_LOGLEVEL An integer indicating the verboseness of the debug log data (Default: 0). Accepted values: 0 - 9. See SecDebugLogLevel.
MODSEC_DISABLE_BACKEND_COMPRESSION A string indicating whether or not to disable backend compression (Default: Off). Allowed values: On, Off. See SecDisableBackendCompression for more. Only supported in ModSecurity 2.x, will have not effect on 3.x
MODSEC_PCRE_MATCH_LIMIT An integer value indicating the limit for the number of internal executions in the PCRE function (Default: 100000) (Only valid for Apache - v2). See SecPcreMatchLimit
MODSEC_PCRE_MATCH_LIMIT_RECURSION An integer value indicating the limit for the depth of recursion when calling PCRE function (Default: 100000)
MODSEC_REQ_BODY_ACCESS A string value allowing ModSecurity to access request bodies (Default: On). Allowed values: On, Off. See SecRequestBodyAccess for more information.
MODSEC_REQ_BODY_LIMIT An integer value indicating the maximum request body size accepted for buffering (Default: 13107200). See SecRequestBodyLimit for additional information.
MODSEC_REQ_BODY_LIMIT_ACTION A string value for the action when SecRequestBodyLimit is reached (Default: Reject). Accepted values: Reject, ProcessPartial. See SecRequestBodyLimitAction for additional information.
MODSEC_REQ_BODY_JSON_DEPTH_LIMIT An integer value indicating the maximun JSON request depth (Default: 512). See SecRequestBodyJsonDepthLimit for additional information.
MODSEC_REQ_BODY_NOFILES_LIMIT An integer indicating the maximum request body size ModSecurity will accept for buffering (Default: 131072). See SecRequestBodyNoFilesLimit for more information.
MODSEC_RESP_BODY_ACCESS A string value allowing ModSecurity to access response bodies (Default: On). Allowed values: On, Off. See SecResponseBodyAccess for more information.
MODSEC_RESP_BODY_LIMIT An integer value indicating the maximum response body size accepted for buffering (Default: 1048576)
MODSEC_RESP_BODY_LIMIT_ACTION A string value for the action when SecResponseBodyLimit is reached (Default: ProcessPartial). Accepted values: Reject, ProcessPartial. See SecResponseBodyLimitAction for additional information.
MODSEC_RESP_BODY_MIMETYPE A string with the list of mime types that will be analyzed in the response (Default: 'text/plain text/html text/xml'). You might consider adding application/json documented here.
MODSEC_RULE_ENGINE A string value enabling ModSecurity itself (Default: On). Accepted values: On, Off, DetectionOnly. See SecRuleEngine for additional information.
MODSEC_STATUS_ENGINE A string used to configure the status engine, which sends statistical information (Default: Off). Accepted values: On, Off. See SecStatusEngine for additional information.
MODSEC_TAG A string indicating the default tag action, which will be inherited by the rules in the same configuration context (Default: modsecurity)
MODSEC_TMP_DIR A string indicating the path where temporary files will be created (Default: /tmp/modsecurity/tmp)
MODSEC_TMP_SAVE_UPLOADED_FILES A string indicating if temporary uploaded files are saved (Default: On) (only relevant in Apache - ModSecurity v2)
MODSEC_UPLOAD_DIR A string indicating the path where intercepted files will be stored (Default: /tmp/modsecurity/upload)
MODSEC_DEFAULT_PHASE1_ACTION ModSecurity string with the contents for the default action in phase 1 (Default: 'phase:1,log,auditlog,pass,tag:\'\${MODSEC_TAG}\'')
MODSEC_DEFAULT_PHASE2_ACTION ModSecurity string with the contents for the default action in phase 2 (Default: 'phase:2,log,auditlog,pass,tag:\'\${MODSEC_TAG}\'')

modsecurity-docker's People

Contributors

awapf avatar binbashing avatar bittner avatar bostrt avatar csanders-git avatar dnrce avatar franbuehler avatar fzipi avatar karelorigin avatar khiemdoan avatar rubiev avatar theseion avatar zugao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

modsecurity-docker's Issues

SSL certificated are not loaded in Nginx image

We were using tag owasp/modsecurity-crs:3.3.2-nginx to build our application image on top of it. It worked fine until image under that tag was updated in DockerHub and our SSL certificates suddenly stopped working. No changes were done on our side, we just rebuilt our image with the same source code and the same FROM tag. If we build from original image of the same underlying Nginx version - it works ok.

The issue is reproducible with current owasp/modsecurity-crs:3.3.2-nginx and also with latest owasp/modsecurity-crs:3.3.4-nginx-202209221209

There is no issue with image owasp/modsecurity-crs@sha256:4ab21fb9a6cab32fc04b15017b4dce68c6080ca6293726321f31077a7cf76468 which was under the owasp/modsecurity-crs:3.3.2-nginx tag at the time of our successful build 19.11.2021.

We attach SSL certificate from disk using ssl_certificate and ssl_certificate_key settings in server section of Nginx config. Actually those cert files are mapped to container as secrets in docker-compose.yml file.

Issue manifests itself as an SSL error when trying to open application page in Chrome browser, and missing SSL certificate, substituted somehow with self-signed one. See screenshots below:

image

image

Manual workflow for testing all architectures

We should add a manual triggered workflow that runs against all architectures. As this build in particular takes a really long time to run, we should only do it selectively.

👉 Another option is to try and run it in parallel because we don't need to have the manifest generated in the run.

Change directory permissions for temporary files

Looking at debug error logs, found:

Apache-Error: [file "apache2_util.c"] [line 273] [level 3] [client 172.25.0.1] ModSecurity: Multipart parsing error: Multipart: Failed to create file: /tmp/modsecurity/tmp/20210905-110250-YTSj2euvr-37s-pgdt6MeAAAAME-file-J0nssC [hostname "localhost"] [uri "/post"] [unique_id "YTSj2euvr-37s-pgdt6MeAAAAME"]

We need to add permissions to the www-data user, and we can just allow o+rwx on the /tmp/modsecurity/tmp directory, just in case.

docker-entrypoint.d is unused

In nginx official image, entrypoint runs each script in docker-entrypoint.d folder as initialization. For better compatilibity, isn't it better to move the current docker-entrypoint.sh in docker-entrypoint.d as another script?

[modsecurity-crs-nginx] ERROLOG does not reflect REAL_IP_HEADER

The nginx container does not properly reflect the REAL_IP_HEADER in the ERRORLOG file within property client_ip.

docker-compose.yml

environment:
   SET_REAL_IP_FROM: "0.0.0.0/0"
   REAL_IP_HEADER: "X-Forwarded-For"
   REAL_IP_RECURSIVE: "on"

waf.log (ERRORLOG)

[...] clientip: 192.168.44.2 

This is the internal IP of the public facing traefik container for SSL termination. The docker compose logs output formats the client ip properly in front of the error message.

With modsecurity-crs-apache and the following docker-compose it is working properly though.

docker-compose.yml

environment:
   REMOTEIP_INT_PROXY: "192.0.0.0/8"

No Graceful Shutdown for Apache

Unfortunately since we use the apachectl -D FOREGROUND command to start Apache, the SIGTERM will only stop the apachectl process which won't relay it to the actual Apache process. This means that in a typical container environment, the SIGTERM is sent, apachectl is terminated but apache remains running in the background. Once the timeout (i.e. ca. 30s) is over, the apache process will be forcefully killed (by SIGKILL) which prevents any graceful shutdown.

We could solve this in an entrypoint script which traps the SIGTERM signal and then calls apachectl graceful-stop.

Host header modified in reverse proxy mode

Hi, the Host header seems incorrect in reverse proxy mode, it always points to localhost independently from BACKEND value, so most website refuse this type of connection

I ran this command:
docker run -p 80:80 -e PROXY_SSL=on -e BACKEND=http://sitename imagename
bug

Unable to start container with mounted /etc/nginx/nginx.conf

Hi,

after pulling the most recent image starting the container is no longer possible due to an error with sed:

sed: cannot rename /etc/nginx/nginx.conf: Device or resource busy

This seems to have been introduced with #105.
In my setup I mount the nginx.conf from my host into the container - which is incompatible with the sed renaming (cf. https://github.com/coreruleset/modsecurity-docker/blob/master/v3-nginx/docker-entrypoint.d/91-update-resolver.sh @ line 12)

Minimal compose:

version: "3"
services:
  nginx:
    image: owasp/modsecurity:nginx
    restart: always
    volumes:
      - /host/nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 80:80

I am actually unsure on whether this should be used differently - yet at least on the nginx dockerhub there are many references wrt. mounting the nginx.conf from the host (see https://hub.docker.com/_/nginx) into the container.

In https://github.com/nginxinc/docker-nginx/blob/master/entrypoint/30-tune-worker-processes.sh I found the following line

touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; }

which they seem to have for this very reason.

ModSecurity not compiled with GeoIP support on arm64

Hi, when running the nginx image on arm64 arch, I have to disable (delete) the CRS REQUEST-910-IP-REPUTATION rule to be able to start nginx, otherwise it fails with

nginx: [emerg] "modsecurity_rules_file" directive Rules error. File: /etc/modsecurity.d/owasp-crs/rules/REQUEST-910-IP-REPUTATION.conf. Line: 76. Column: 22. This version of ModSecurity was not compiled with GeoIP or MaxMind support.  in /etc/nginx/conf.d/modsecurity.conf:2

The amd64 arch doesn't have this problem.

I can see that libgeoip-dev is installed in the owasp/modsecurity:nginx image before building ModSecurity, so I don't understand why it fails. I have tried installing various packages (libgeoip1 libgeoip-dev geoip-database geoip-database-extra geoip-bin) into the container, but it doesn't help. Am I missing something? Could you please verify that ModSecurity gets built with GeoIP or MaxMind support on arm64?

Thanks so much for providing this image.

Consolidate development of Docker images

I'm working with colleagues on operating ModSecurity+CRS on modern infrastructure for some months, and we've seen a few challenges that make it hard to do sustainable software development.

What's wrong?

The industry needs a set of official images that are both trustworthy and easy to work with. Modern software development requires us to react quickly, hence we need sane defaults and convenient ways to override the default configuration. Container security is a growing concern, hence we must ensure the smallest attack surface possible -- without compromising development and operation convenience.

We need to:

How can we help?

We have some capacity (and need) to work on consolidating the existing container image efforts. You can see our efforts in the related images on Docker Hub (e.g. vshn/modsecurity, vshn/modsecurity-crs).

My colleagues and I have extensive experience with crafting and running container images. If we could help maintain the Docker images in https://github.com/CRS-support (e.g. modsecurity-docker and modsecurity-crs-docker) that may free some of your resources for maintaining the CRS rules.

Can we help maintaining? Would that be possible?

Docker image for nginx rests on 1.20.2

Hi,

according to https://github.com/coreruleset/modsecurity-docker/blob/master/v3-nginx/Dockerfile#L1 the nginx-based modsecurity Docker image rests on nginx 1.20.2. According to https://nginx.org/en/download.html the latest stable version of nginx is 1.22.0.

Intially I came across this via openssl and a CVE that should be fixed in 1.1.1p. The openssl version in the latest modsecurity docker image is 1.1.1n. Should I bump the nginx version to 1.22.0 by myself (during the docker build)?

Best regards
Jörg Liebig

AuditLog in JSON

Hi,

We are using 3.0.4 image and we can not configure format logs in JSON :
SecAuditLogFormat JSON

{"error":"ModSecurity was not compiled with JSON support."}

Are you going to fix that ?

Thanks for the reply

Things Needed For Docker

This container is going to be run as a reverse proxy basically.

It should:

  • SSL CERT: generate its own self-signed SSL cert to accept TLS traffic. User can replace with their own SSL cert after it is up and running if they want
  • HIGHER VERSION: we should build Apache from source so we get 2.4.38 which has quite a bit more than 2.4.29, the latest version in Ubuntu:18.04 LTS
  • DEFAULT SITE FILE: we should add in a default site file that sets up the correct ProxyPass directives. The IP address to pass the requests too will be a variable the user will provide on the command-line during docker run.
  • DOCKERFILE SECURITY: we can probably put some limits on the container by dropping certain kernel privileges, restricting resource consumption, etc. There are some easy/quick commands to do this
  • RANDOM: random other things I'm forgetting :)

Future Cool Stuff:

  • We can make a helm chart for ModSecurity!
  • This helm chart could be used to install ModSecurity firewall layer on any K8s cluster...going to be cool stuff

X-Forwarded-* headers are swallowed by Nginx proxy_pass

The owasp/modsecurity image, as of PR #38, allows to specify a service to be protected by the WAF via the BACKEND environment variable.

In Apache, this backend is served via mod_proxy's ProxyPass and ProxyPassReverse directives, and sets the X-Forwarded-Proto, X-Real-IP, X-Unique-ID request headers for serving the backend service.

In Nginx, we attempt to make the external behavior identical, i.e. also providing the request headers mentioned above to the backend service, which is done using several proxy_set_header directives in a location block having proxy_pass ${BACKEND}.

Unfortunately, for some reason, those (magic) request headers a removed from the request header before they reach the ${BACKEND} in Nginx, so the request looks slightly different. This should be fixed.

This is a follow-up issue on: #38

Upgrade nginx version to 1.20.1

This fixes

    *) Security: 1-byte memory overwrite might occur during DNS server
       response processing if the "resolver" directive was used, allowing an
       attacker who is able to forge UDP packets from the DNS server to
       cause worker process crash or, potentially, arbitrary code execution
       (CVE-2021-23017).

Switching to owasp/modsecurity:nginx - unable to audit log to file

Hi everyone, after switching from owasp/modsecurity:3-nginx to owasp/modsecurity:nginx modsecurity seems to be unable to log anything to audit log (configuration didn't change at all).

nginx.conf:

modsecurity on;
modsecurity_rules_file /etc/modsecurity.d/include.conf;

include.conf:

Include /etc/modsecurity.d/modsecurity.conf
Include /etc/modsecurity.d/crs-setup.conf
Include /etc/modsecurity.d/rules.d/*.conf

modsecurity.conf:

SecRuleEngine DetectionOnly
...
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogFormat JSON
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/modsec_audit.log
..

crs-setup.conf

SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"

I noticed that compared to owasp/modsecurity:3-nginx a lot of envs are set in owasp/modsecurity:nginx, e.g.

MODSEC_AUDIT_LOG=/dev/stdout
MODSEC_AUDIT_LOG_FORMAT=JSON
MODSEC_AUDIT_LOG_TYPE=Serial
MODSEC_AUDIT_STORAGE=/var/log/modsecurity/audit/
..

Would those be preferred over the defined values in the modsecurity.conf? Didn't find any information on this anywhere.
Yet even after unsetting all of those and making the environment the same as in owasp/modsecurity:3-nginx doesn't help.
Any input is much appreciated!

Remove status engine call

The status call to TW servers is failing. This takes an unnecesary call, and startup times are longer.

We are switching this to Off by default.

This is coming from the modsecurity.conf recommended config:

# Improve the quality of ModSecurity by sharing information about your
# current ModSecurity version and dependencies versions.
# The following information will be shared: ModSecurity version,
# Web Server version, APR version, PCRE version, Lua version, Libxml2
# version, Anonymous unique id for host.
SecStatusEngine On

Lets add it to our override and turn it Off as default.

Build multiple architectures

There is a related issue in coreruleset/modsecurity-crs-docker#19 for building additional architectures. While we don't have the time to build from scratch a new architecture, we can leverage the fact that both nginx and apache base containers have already builds for different architectures.

We should build for:

  • linux/amd64
  • linux/arm/v8
  • linux/arm/v7
  • linux/i386

Others might come afterwards.

docker build issue

While building from this, I get the following error: Perhaps someone can help?

https://github.com/coreruleset/modsecurity-docker/blob/master/v3-nginx/Dockerfile

Step 25/33 : COPY --from=build /etc/modsecurity.d/unicode.mapping /etc/modsecurity.d/unicode.mapping
---> 2a4e88899044
Step 26/33 : COPY --from=build /etc/modsecurity.d/modsecurity.conf /etc/modsecurity.d/modsecurity.conf
---> 1d0cbff3141c
Step 27/33 : COPY src/etc/modsecurity.d/*.conf /etc/modsecurity.d/
COPY failed: no source files were specified

Can't start the container

Hello, I can't find a way to run the ModSecurity 3.3 NGINX Docker image

docker run --rm -it owasp/modsecurity-crs:3.3-nginx
2022/03/08 16:52:51 [emerg] 1#1: invalid parameter "${METRICS_ALLOW_FROM}" in /etc/nginx/includes/location_common.conf:10
nginx: [emerg] invalid parameter "${METRICS_ALLOW_FROM}" in /etc/nginx/includes/location_common.conf:10

Any tips?

AccessLog and TransferLog are both enabled, preventing disabling access logs properly

This one comes from coreruleset/modsecurity-crs-docker#82.

While we are using the provided environment ACCESSLOG in

CustomLog ${ACCESSLOG} "env=!nologging"
, we are also unconditionally sending the logs to stdout using TransferLog in . Also, METRICSLOG and ACCESSLOG can be disabled by exporting the nologging=1 variable, and that is not documented (it is used by the /healtz and /metrics/apache endpoints).

Additionally, we would like to provide an APACHE_LOGFORMAT variable so the access log format can be tuned.

mod_security failing to link with lua5.1-dev

Hi All,

when i compile mod_security with lua5.1-dev its failing to link to lua library, at the same time lua5.2-dev working without issues. I have a use-case where in, i need to use lua5.1. I tried few things but not able to figure out why things are breaks, can anyone help me out

mod_security version: 2.9.3
lua version: 5.1

image

size question

nginx base is around 130MB in my docker builds, but modsecurity-docker jumps to > 500MB. Is this something that can be optimized? This also results in the CRS image to be > 500MB.

Allow the setting of SecRequestBodyLimitAction through an environment variable

The issue:

I am using ModSecurity as a proxy in front of a file server. Everything works fine in DetectionOnly mode. But as soon as I set MODSEC_RULE_ENGINE=on, the file upload fails.

With the following log message:

2022/01/15 15:45:13 [error] 30#30: *1 Request body limit is marked to reject the request, client: 1.1.1.1, server: domain.com, request: "PUT /public.php/webdav/ZAP_2.11.1.dmg HTTP/1.1", host: "domain.com"
2022/01/15 15:45:13 [error] 30#30: *1 client intended to send too large body: 222978300 bytes, client: 1.1.1.1, server: domain.com, request: "PUT /public.php/webdav/ZAP_2.11.1.dmg HTTP/1.1", host: "domain.com"

The reason for this is, that if DetectionOnly is set, the default for SecRequestBodyLimitAction is ProcessPartial and if MODSEC_RULE_ENGINE=on is set the default is for SecRequestBodyLimitAction is Reject which causes the file upload to fail as seen above.

My request:

Make the SecRequestBodyLimitAction in the modsecurity-override.conf configurable via ENV variable allowing me to set it in the Docker or Docker-Compose file.

This would prevent me from needing to overwrite your override.conf 😇

The Nginx base image has a lot of security problems

I have been looking in to switching my Nginx that uss modsecurity and CRS over to this official image.

Using the Trivy docker image scanner we get the following summary for the nginx image used as base:

$ trivy nginx:1.17.9
2020-04-16T08:26:11.391+0200    INFO    Detecting Debian vulnerabilities...

nginx:1.17.9 (debian 10.3)
==========================
Total: 116 (UNKNOWN: 0, LOW: 19, MEDIUM: 82, HIGH: 13, CRITICAL: 2)

If we instead switch over and use the alpine version of the same image, we get the following:

$ trivy nginx:1.17.9-alpine
2020-04-16T08:28:03.984+0200    INFO    Detecting Alpine vulnerabilities...

nginx:1.17.9-alpine (alpine 3.10.4)
===================================
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 0, CRITICAL: 0)

Not perfect, but much better.

As a nice side effect we also get a much smaller image:

nginx:1.17.9         size: 127MB
nginx:1.17.9-alpine  size: 19.7MB

Docker image uses the root user

Do you consider moving the base docker images for docker and apache to 'unprivileged' images, i.e. images not running with root user by default ?
This could be achieved for nginx using a different base image or by changing the default permissions of some folders/files.

Remove building ssdeep and yajl libs

Both ssdeep and yajl libraries are now available in for all the versions we are using, so it doesn't make sense to build them.

Also, they haven't changed since quite some time, so we don't need to set some specific version.

So let's:

  • remove ssdeep build step
  • remove yajl build step
  • add libfuzzy and libyajl packages for alpine and debian builds (for both stages)
  • remove version argument
  • remove the ssdeep binary. ModSecurity should use it as a library, and we save some bytes.

New images only built with architecture: `arm`

New images published to DockerHub (3.0.5 / 3.0 / 3) are only published as arm images, breaking any dependent containers using amd64. Any chance of including the other architectures?

Add support for different log formats

In #126 we added support for setting the log format. This format is used for access log, error log and transfer log. It would be nice to have separate variables to control the log format for each of these logs independently.

Reverse proxy for multiple domains possible?

Hi,

im trying to use this container to be a reverse proxy for multiple domains (Ex. x.com goes to 10.10.10.10 and y.com goes to 10.10.10.11)

From what i've seen there is only one value and no conditions applicable to the BACKEND variable.

I was wondering what i could to overcome this, i've created custom vhosts and modified the httpd.conf to use them, but im getting an HSTS error whereas with the BACKEND variable it was working fine but with only one domain.

Regards,
Daniel D.

owasp/modsecurity:3-nginx proxy-cache not working

" owasp/modsecurity:3-nginx" when used with the caching directive, the whole thing stops to work.
Tried the default one:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=edge-cache:10m inactive=60m max_size=1g use_temp_path=off;

Thought it was a root privilege problem so tried following folder which is owned by nginx:
proxy_cache_path /var/log/nginx levels=1:2 keys_zone=edge-cache:10m inactive=60m max_size=1g use_temp_path=off;
Still to no vail.

I suggest changing the owner-ship of /var/cache/nginx to the user->nginx.

Even tried to change the user from nginx to root in the configuration file but still didn't work.
#user nginx;
user root;
worker_processes auto;

The same problem occurs when using rate-limiting:
limit_req_zone $remote_addr zone=rate_limit1:12m rate=5r/m;

I think its is permission related issue.

Nginx.conf is empty during multiple POD deployments

Hi,

Our Nginx.conf is externalized from our Docker images.

This file is sometimes empty after multiple POD start simultaneously.

The issue seems to come from the following lines in the entrypoint.sh :
for FILE in ${FILES[*]}; do if [ -f $FILE ]; then envsubst "$ENV_VARIABLES" <$FILE | sponge $FILE fi done

An empty Stdout seems to be send to the sponge command that produce an empty nginx file.

Do you have already saw this behaviour on your environnements ?

Collapse branches into single branch

There should be a single branch for all these Docker images. Usually this is the pattern most orgs do. See what Nginx does: https://github.com/nginxinc/docker-nginx

Because we don't have this right now, this repo looks very unmaintained, even though in reality it's not, it's just the latest commits are on a different branch than the one users land one when they first click.

Let me think of a folder structure and then submit to you all for approval / a first glance

@franbuehler @csanders-git

ModSecurity libraries not found!

Hi I'm getting an error while building the docker image from the Dockerfile given. Error details are as below.

Step 8/12 : RUN cd /opt/ModSecurity-apache/  &&  ./autogen.sh && ./configure && make && make install
 ---> Running in ba6c92078428
configure.ac:10: installing './compile'
configure.ac:8: installing './install-sh'
configure.ac:8: installing './missing'
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
configure: looking for Apache module support via DSO through APXS
configure: found APXS at /usr/bin/apxs2
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking dependency style of gcc... none
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
configure: looking for libmodsecurity
checking for msc_init in -lmodsecurity... no
configure: error: ModSecurity libraries not found!
The command '/bin/sh -c cd /opt/ModSecurity-apache/ &&     ./autogen.sh &&     ./configure &&     make &&     make install' returned a non-zero code: 1

Any idea why this error is coming and how to fix this?

Unclear ENV variables

Hi All,

not sure if this the right place to ask, apologies in advance

I am having trouble understanding where the below big list of env variable are being used inside container, I am aware what is the pupose of each of these env's but what i don't understand is that where is this being used in inside the image/container. Can someone help me out on this.

Branch: master

image

Post Images to GCR

Our Docker images should also be posted Google Container Registry:

  1. GCR does automated vuln analysis. For instance the current container image has 329 vulns, with 5 of them being pretty serious: https://gcr.io/crs-support/modsecurity-docker/v3/apache-apache

  2. GCR can be secured with 2FA by the admins, which for some reason Docker Hub does not have

  3. For the base image, we can you GCP Managed Based Images, which are pretty hardened / secured: https://cloud.google.com/container-registry/docs/managed-base-images

  4. We can link GCR to Github in a variety of ways, such that when new code is pushed to Github, if it has a tag on it it can kick off a build of the image in GCR. If we want can also send to Cloud Build for testing...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.