diff --git a/.gitignore b/.gitignore
index 8f918f9..c1c3fc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ docs.built/
dd-sso/docker/api/src/api/static/templates/*.html
dd-sso/docker/api/src/api/static/templates/*.json
dd-sso/docker/keycloak/themes/dd-custom
+dd-sso/admin/src/admin/node_modules/
.idea/
*.log
# External, unmodified files
diff --git a/dd-ctl b/dd-ctl
index 0abbbc2..d374967 100755
--- a/dd-ctl
+++ b/dd-ctl
@@ -870,6 +870,17 @@ special_image_tags() {
done
}
+enable_waf() {
+ # Enable waf
+ echo "Enable rules ModSecurity"
+ docker exec dd-waf-apache bash -c 'sed -i.orig -e "s/modsecurity Off/modsecurity On/" /etc/apache2/sites-enabled/000-default.conf'
+ echo "Done"
+ echo "Restart Apache - ModSecurity"
+ docker restart dd-waf-apache
+ echo "Done"
+}
+
+
push_images() {
#
# Note this requires docker login on the registry
@@ -984,6 +995,9 @@ case "$OPERATION" in
securize)
securize
;;
+ waf)
+ enable_waf
+ ;;
setconf)
setconf "$@"
;;
diff --git a/dd-waf/docker-compose-parts/modsecurity.yml b/dd-waf/docker-compose-parts/modsecurity.yml
index 319ce5b..63b6c49 100644
--- a/dd-waf/docker-compose-parts/modsecurity.yml
+++ b/dd-waf/docker-compose-parts/modsecurity.yml
@@ -9,5 +9,6 @@ services:
restart: unless-stopped
volumes:
- /etc/localtime:/etc/localtime:ro
+ - ${SRC_FOLDER}/modsecurity/rules:/etc/apache2/modsecurity.d/dd-rules:rw
networks:
- - dd_net
\ No newline at end of file
+ - dd_net
diff --git a/dd-waf/docker/haproxy/haproxy.conf b/dd-waf/docker/haproxy/haproxy.conf
index 73bfde7..a7a11b9 100644
--- a/dd-waf/docker/haproxy/haproxy.conf
+++ b/dd-waf/docker/haproxy/haproxy.conf
@@ -38,6 +38,9 @@ frontend tf_waf
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt if letsencrypt-acl
+ # Internal traffic
+ use_backend bk_web if { src 192.168.0.0/16 }
+
default_backend bk_waf
# Traffic secured by the WAF arrives here
diff --git a/dd-waf/docker/modsecurity/000-default.conf b/dd-waf/docker/modsecurity/000-default.conf
index 851b74c..32ca2d0 100644
--- a/dd-waf/docker/modsecurity/000-default.conf
+++ b/dd-waf/docker/modsecurity/000-default.conf
@@ -1,17 +1,14 @@
- modsecurity on
+ modsecurity Off
modsecurity_rules_file /etc/apache2/modsecurity.d/modsec_rules.conf
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
- #ErrorLog ${APACHE_LOG_DIR}/error.log
- #CustomLog ${APACHE_LOG_DIR}/access.log combined
- ErrorLog /dev/stderr
- TransferLog /dev/stdout
-
+ ErrorLog /var/log/apache2/error.log
+ CustomLog /var/log/apache2/access.log combined
ProxyPreserveHost On
- ProxyRequests off
- ProxyVia Off
- ProxyPass "/" "http://dd-waf-haproxy:81/"
- ProxyPassReverse "/" "http://dd-waf-haproxy:81/"
+ ProxyRequests off
+ ProxyVia Off
+ ProxyPass "/" "http://dd-waf-haproxy:81/"
+ ProxyPassReverse "/" "http://dd-waf-haproxy:81/"
diff --git a/dd-waf/docker/modsecurity/Dockerfile b/dd-waf/docker/modsecurity/Dockerfile
index aa79389..b8f3b8b 100644
--- a/dd-waf/docker/modsecurity/Dockerfile
+++ b/dd-waf/docker/modsecurity/Dockerfile
@@ -1,4 +1,4 @@
-# Install Modsecurity in a Docker container;
+# Install Modsecurity in a Docker container
FROM ubuntu:20.04 as production
ARG DEBIAN_FRONTEND=noninteractive
# update/upgrade your system
@@ -9,8 +9,8 @@ RUN apt-get install -y g++ flex bison curl apache2-dev \
doxygen libyajl-dev ssdeep liblua5.2-dev \
libgeoip-dev libtool dh-autoreconf \
libcurl4-gnutls-dev libxml2 libpcre++-dev \
- libxml2-dev git wget tar apache2 \
- certbot python3-certbot-apache
+ libxml2-dev git wget tar apache2
+# certbot python3-certbot-apache
# Download LibModsecurity
RUN wget https://github.com/SpiderLabs/ModSecurity/releases/download/v3.0.8/modsecurity-v3.0.8.tar.gz
@@ -32,23 +32,31 @@ RUN cd ~/ModSecurity-apache && \
make && \
make install
+
+# logs should go to stdout / stderr
+RUN set -ex \
+ && ln -sfT /dev/stderr /var/log/apache2/error.log \
+ && ln -sfT /dev/stdout /var/log/apache2/access.log \
+ && ln -sfT /dev/stdout /var/log/apache2/other_vhosts_access.log
+
# Load the Apache ModSecurity Connector Module
RUN echo "LoadModule security3_module /usr/lib/apache2/modules/mod_security3.so" >> /etc/apache2/apache2.conf
# Configure ModSecurity
-RUN mkdir /etc/apache2/modsecurity.d && \
+RUN mkdir -p /etc/apache2/modsecurity.d/dd-rules && \
cp modsecurity-v3.0.8/modsecurity.conf-recommended /etc/apache2/modsecurity.d/modsecurity.conf && \
cp modsecurity-v3.0.8/unicode.mapping /etc/apache2/modsecurity.d/ && \
sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/apache2/modsecurity.d/modsecurity.conf
ADD modsec_rules.conf /etc/apache2/modsecurity.d/
# Install OWASP ModSecurity Core Rule Set (CRS) on Ubuntu
-RUN git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /etc/apache2/modsecurity.d/owasp-crs && \
- cp /crs-setup.conf /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf
+RUN git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git /etc/apache2/modsecurity.d/owasp-crs
+ADD crs-setup.conf /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf
# Activate ModSecurity
RUN mv /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf.old
ADD 000-default.conf /etc/apache2/sites-available/
+ADD rules_apps.conf /etc/apache2/modsecurity.d/owasp-crs/rules/000-dd-apps.conf
RUN a2enmod proxy_http
@@ -56,4 +64,9 @@ EXPOSE 80
CMD apachectl -D FOREGROUND
# Testing ModSecurity
-#curl http:///index.php?exec=/bin/bash
\ No newline at end of file
+#curl http:///index.php?exec=/bin/bash
+
+# TODO
+# Juntas capas y reducir peso
+# user no root
+
diff --git a/dd-waf/docker/modsecurity/crs-setup.conf b/dd-waf/docker/modsecurity/crs-setup.conf
index fb455ec..04a85d1 100644
--- a/dd-waf/docker/modsecurity/crs-setup.conf
+++ b/dd-waf/docker/modsecurity/crs-setup.conf
@@ -379,13 +379,13 @@ SecAction \
# Example: for WebDAV, add the following methods: CHECKOUT COPY DELETE LOCK
# MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK
# Uncomment this rule to change the default.
-#SecAction \
-# "id:900200,\
-# phase:1,\
-# nolog,\
-# pass,\
-# t:none,\
-# setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"
+SecAction \
+ "id:900200,\
+ phase:1,\
+ nolog,\
+ pass,\
+ t:none,\
+ setvar:'tx.allowed_methods=GET HEAD POST OPTIONS PUT'"
# Content-Types that a client is allowed to send in a request.
# Default: |application/x-www-form-urlencoded| |multipart/form-data| |multipart/related|
diff --git a/dd-waf/docker/modsecurity/modsec_rules.conf b/dd-waf/docker/modsecurity/modsec_rules.conf
index eb53ad4..cc36a54 100644
--- a/dd-waf/docker/modsecurity/modsec_rules.conf
+++ b/dd-waf/docker/modsecurity/modsec_rules.conf
@@ -1,4 +1,4 @@
Include "/etc/apache2/modsecurity.d/modsecurity.conf"
Include "/etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf"
+#Include "/etc/apache2/modsecurity.d/dd-rules/*.conf"
Include "/etc/apache2/modsecurity.d/owasp-crs/rules/*.conf"
-Include "/etc/apache2/modsecurity.d/dd-rules.conf"
\ No newline at end of file
diff --git a/dd-waf/docker/modsecurity/rules_apps.conf b/dd-waf/docker/modsecurity/rules_apps.conf
new file mode 100644
index 0000000..87c88cf
--- /dev/null
+++ b/dd-waf/docker/modsecurity/rules_apps.conf
@@ -0,0 +1,67 @@
+# Rules
+#######
+
+SecRule REQUEST_FILENAME "@endsWith /apps/user_status/heartbeat" \
+ "id:99000001,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ ctl:ruleRemoveById=911100"
+
+SecRule REQUEST_FILENAME "@rx /apps/text/session/(?:create|fetch|sync|close)$" \
+ "id:99000002,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ ver:'OWASP_CRS/3.2.0',\
+ setvar:'tx.allowed_methods=%{tx.allowed_methods} PUT DELETE'"
+
+SecRule REQUEST_FILENAME "@contains /auth/saml2/sp/saml2-acs.php" \
+ "id:99000003,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ ctl:ruleRemoveById=920440"
+
+SecRule REQUEST_FILENAME "@contains /auth/saml2/sp/saml2-logout.php" \
+ "id:99000004,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ ctl:ruleRemoveById=920440"
+
+SecRule REQUEST_FILENAME "@contains /apps/text/session" \
+ "id:99000005,\
+ phase:1,\
+ pass,\
+ t:none,\
+ nolog,\
+ ctl:ruleRemoveById=911100"
+
+SecRule REQUEST_FILENAME "@contains /apps/user_status/heartbeat" "phase:1,id:99000006,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /remote.php/dav" "phase:1,id:99000007,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /apps/text/session" "phase:1,id:99000008,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /socket.io" "phase:1,id:99000009,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /auth/realms/master/avatar-provider" "phase:1,id:99000010,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /lib/ajax/service-nologin.php" "phase:1,id:99000011,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /lib/ajax/service.php" "phase:1,id:99000012,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"
+
+SecRule REQUEST_FILENAME "@contains /apps/polls/poll" "phase:1,id:99000013,nolog,chain"
+ SecRule REQUEST_BODY_LENGTH "@eq 0" "ctl:requestBodyAccess=off"