diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index 4d10e4ca..a7eb4e85 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -394,7 +394,7 @@ jobs: strategy: fail-fast: false matrix: - target: ["setup", "docs", "fetchmail", "webmail", "admin", "traefik-certdumper", "radicale", "clamav", "rspamd", "postfix", "dovecot", "unbound", "nginx"] + target: ["setup", "docs", "fetchmail", "webmail", "admin", "traefik-certdumper", "radicale", "clamav", "rspamd", "oletools", "postfix", "dovecot", "unbound", "nginx"] steps: - uses: actions/checkout@v3 - name: Retrieve global variables @@ -439,7 +439,7 @@ jobs: strategy: fail-fast: false matrix: - target: ["setup", "docs", "fetchmail", "webmail", "admin", "traefik-certdumper", "radicale", "clamav", "rspamd", "postfix", "dovecot", "unbound", "nginx"] + target: ["setup", "docs", "fetchmail", "webmail", "admin", "traefik-certdumper", "radicale", "clamav", "rspamd", "oletools", "postfix", "dovecot", "unbound", "nginx"] steps: - uses: actions/checkout@v3 - name: Retrieve global variables diff --git a/README.md b/README.md index b6ed040b..54045d28 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Main features include: - **Web access**, multiple Webmails and administration interface - **User features**, aliases, auto-reply, auto-forward, fetched accounts - **Admin features**, global admins, announcements, per-domain delegation, quotas -- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner, [Snuffleupagus](https://github.com/jvoisin/snuffleupagus/) +- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner, [Snuffleupagus](https://github.com/jvoisin/snuffleupagus/), block malicious attachments - **Antispam**, auto-learn, greylisting, DMARC and SPF, anti-spoofing - **Freedom**, all FOSS components, no tracker included diff --git a/core/base/Dockerfile b/core/base/Dockerfile index bb18cb65..82c8cb9b 100644 --- a/core/base/Dockerfile +++ b/core/base/Dockerfile @@ -27,6 +27,7 @@ ENV \ FRONT_ADDRESS="front" \ SMTP_ADDRESS="smtp" \ IMAP_ADDRESS="imap" \ + OLETOOLS_ADDRESS="oletools" \ REDIS_ADDRESS="redis" \ ANTIVIRUS_ADDRESS="antivirus" \ ANTISPAM_ADDRESS="antispam" \ diff --git a/core/base/requirements-dev.txt b/core/base/requirements-dev.txt index 52874a86..5a9df4b1 100644 --- a/core/base/requirements-dev.txt +++ b/core/base/requirements-dev.txt @@ -45,6 +45,10 @@ watchdog # core/postfix postfix-mta-sts-resolver +# core/oletools +python-magic +oletools + # optional/fetchmail requests diff --git a/core/base/requirements-prod.txt b/core/base/requirements-prod.txt index 8b861cd5..0da5219b 100644 --- a/core/base/requirements-prod.txt +++ b/core/base/requirements-prod.txt @@ -41,6 +41,7 @@ MarkupSafe==2.1.1 marshmallow==3.18.0 marshmallow-sqlalchemy==0.28.1 multidict==6.0.2 +oletools==0.60.1 mysql-connector-python==8.0.29 packaging==21.3 passlib==1.7.4 @@ -51,7 +52,10 @@ psycopg2-binary==2.9.5 pycares==4.2.2 pycparser==2.21 Pygments==2.13.0 -pyparsing==3.0.9 +pyOpenSSL==22.1.0 +pyparsing==2.4.7 +python-dateutil==2.8.2 +python-magic==0.4.27 python-dateutil==2.8.2 pytz==2022.6 PyYAML==6.0 diff --git a/core/oletools/Dockerfile b/core/oletools/Dockerfile new file mode 100644 index 00000000..8bb98cd9 --- /dev/null +++ b/core/oletools/Dockerfile @@ -0,0 +1,31 @@ +# syntax=docker/dockerfile-upstream:1.4.3 + +# oletools image +FROM base + +ARG VERSION=local +LABEL version=$VERSION + +RUN set -euxo pipefail \ + ; apk add --no-cache netcat-openbsd libmagic libffi \ + ; curl -sLo olefy.py https://raw.githubusercontent.com/HeinleinSupport/olefy/f8aac6cc55283886d153e89c8f27fae66b1c24e2/olefy.py \ + ; chmod 755 olefy.py + +RUN echo $VERSION >/version + +HEALTHCHECK --start-period=60s CMD echo PING|nc -q1 127.0.0.1 11343|grep "PONG" +EXPOSE 11343/tcp + +USER nobody:nobody + +ENV \ + OLEFY_BINDADDRESS="0.0.0.0" \ + OLEFY_BINDPORT="11343" \ + OLEFY_OLEVBA_PATH="/app/venv/bin/olevba" \ + OLEFY_PYTHON_PATH="/app/venv/bin/python3" \ + OLEFY_TMPDIR="/dev/shm/" \ + OLEFY_MINLENGTH="300" \ + OLEFY_DEL_TMP="1" \ + OLEFY_DEL_TMP_FAILED="1" + +CMD /app/olefy.py diff --git a/core/rspamd/conf/composites.conf b/core/rspamd/conf/composites.conf new file mode 100644 index 00000000..68e03073 --- /dev/null +++ b/core/rspamd/conf/composites.conf @@ -0,0 +1,14 @@ +{% if SCAN_MACROS == 'True' %} +OLETOOLS_MACRO_MRAPTOR { + expression = "(OLETOOLS_A & OLETOOLS_W) | (OLETOOLS_A & OLETOOLS_X) | (OLETOOLS_W & OLETOOLS_X)"; + message = "Rejected (malicious macro - mraptor)"; + policy = "leave"; + score = 20.0; +} +OLETOOLS_MACRO_SUSPICIOUS { + expression = "OLETOOLS_FLAG | OLETOOLS_VBASTOMP | OLETOOLS_A"; + message = "Rejected (malicious macro)"; + policy = "leave"; + score = 20.0; +} +{% endif %} diff --git a/core/rspamd/conf/external_services.conf b/core/rspamd/conf/external_services.conf new file mode 100644 index 00000000..d299ed89 --- /dev/null +++ b/core/rspamd/conf/external_services.conf @@ -0,0 +1,64 @@ +{% if SCAN_MACROS == 'True' %} +oletools { + # default olefy settings + servers = "{{ OLETOOLS_ADDRESS }}:11343" + + # needs to be set explicitly for Rspamd < 1.9.5 + scan_mime_parts = true; + extended = true; + max_size = 3145728; + timeout = 20.0; + retransmits = 1; + + patterns { + OLETOOLS_MACRO_FOUND= '^.....M..$'; + OLETOOLS_AUTOEXEC = '^A....M..$'; + OLETOOLS_FLAG = '^.....MS.$'; + OLETOOLS_VBASTOMP = '^VBA Stomping$'; +# see https://github.com/decalage2/oletools/blob/master/oletools/mraptor.py + OLETOOLS_A = '(?i)\b(?:Auto(?:Exec|_?Open|_?Close|Exit|New)|Document(?:_?Open|_Close|_?BeforeClose|Change|_New)|NewDocument|Workbook(?:_Open|_Activate|_Close|_BeforeClose)|\w+_(?:Painted|Painting|GotFocus|LostFocus|MouseHover|Layout|Click|Change|Resize|BeforeNavigate2|BeforeScriptExecute|DocumentComplete|DownloadBegin|DownloadComplete|FileDownload|NavigateComplete2|NavigateError|ProgressChange|PropertyChange|SetSecureLockIcon|StatusTextChange|TitleChange|MouseMove|MouseEnter|MouseLeave|OnConnecting))\b|Auto_Ope\b'; + OLETOOLS_W = '(?i)\b(?:FileCopy|CopyFile|Kill|CreateTextFile|VirtualAlloc|RtlMoveMemory|URLDownloadToFileA?|AltStartupPath|WriteProcessMemory|ADODB\.Stream|WriteText|SaveToFile|SaveAs|SaveAsRTF|FileSaveAs|MkDir|RmDir|SaveSetting|SetAttr)\b|(?:\bOpen\b[^\n]+\b(?:Write|Append|Binary|Output|Random)\b)'; + OLETOOLS_X = '(?i)\b(?:Shell|CreateObject|GetObject|SendKeys|RUN|CALL|MacScript|FollowHyperlink|CreateThread|ShellExecuteA?|ExecuteExcel4Macro|EXEC|REGISTER|SetTimer)\b|(?:\bDeclare\b[^\n]+\bLib\b)'; + } + + # mime-part regex matching in content-type or filename + mime_parts_filter_regex { + #UNKNOWN = "application\/octet-stream"; + DOC2 = "application\/msword"; + DOC3 = "application\/vnd\.ms-word.*"; + XLS = "application\/vnd\.ms-excel.*"; + PPT = "application\/vnd\.ms-powerpoint.*"; + GENERIC = "application\/vnd\.openxmlformats-officedocument.*"; + } + # mime-part filename extension matching (no regex) + mime_parts_filter_ext { + doc = "doc"; + dot = "dot"; + docx = "docx"; + dotx = "dotx"; + docm = "docm"; + dotm = "dotm"; + xls = "xls"; + xlt = "xlt"; + xla = "xla"; + xlsx = "xlsx"; + xltx = "xltx"; + xlsm = "xlsm"; + xltm = "xltm"; + xlam = "xlam"; + xlsb = "xlsb"; + ppt = "ppt"; + pot = "pot"; + pps = "pps"; + ppa = "ppa"; + pptx = "pptx"; + potx = "potx"; + ppsx = "ppsx"; + ppam = "ppam"; + pptm = "pptm"; + potm = "potm"; + ppsm = "ppsm"; + slk = "slk"; + } +} +{% endif %} diff --git a/core/rspamd/conf/external_services_group.conf b/core/rspamd/conf/external_services_group.conf new file mode 100644 index 00000000..0b44b229 --- /dev/null +++ b/core/rspamd/conf/external_services_group.conf @@ -0,0 +1,40 @@ +{% if SCAN_MACROS == 'True' %} +# local.d/external_services_group.conf + +description = "Oletools content rules"; +symbols = { + "OLETOOLS" { + weight = 1.0; + description = "OLETOOLS found a Macro"; + one_shot = true; + }, + "OLETOOLS_MACRO_FOUND" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_AUTOEXEC" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_FLAG" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_VBASTOMP" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_A" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_W" { + weight = 0.0; + one_shot = true; + }, + "OLETOOLS_X" { + weight = 0.0; + one_shot = true; + }, +} +{% endif %} diff --git a/core/rspamd/conf/forbidden_file_extension.map b/core/rspamd/conf/forbidden_file_extension.map new file mode 100644 index 00000000..bc584455 --- /dev/null +++ b/core/rspamd/conf/forbidden_file_extension.map @@ -0,0 +1,68 @@ +ace +ade +adp +apk +appx +appxbundle +arj +bat +bin +cab +chm +class +cmd +com +cpl +diagcab +diagcfg +diagpack +dll +ex +ex_ +exe +hlp +hta +img +ins +iso +isp +jar +jnlp +js +jse +lib +lnk +lzh +mde +msc +msi +msix +msixbundle +msp +mst +msu +nsh +ocx +ovl +pif +ps1 +r01 +r14 +r18 +r25 +scr +sct +shb +shs +sys +vb +vbe +vbs +vbscript +vdl +vhd +vxd +wsc +wsf +wsh +xll diff --git a/core/rspamd/conf/multimap.conf b/core/rspamd/conf/multimap.conf index dd25c08e..7ee6669e 100644 --- a/core/rspamd/conf/multimap.conf +++ b/core/rspamd/conf/multimap.conf @@ -9,3 +9,16 @@ IS_LOCAL_DOMAIN_E { selector = "from('smtp'):domain"; map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; } + +FORBIDDEN_FILE_EXTENSION { + type = "filename"; + filter = "extension"; + map = [ + "/etc/rspamd/local.d/forbidden_file_extension.map", + ]; + prefilter = true; + action = "reject"; + symbol = "FORBIDDEN_FILE_EXTENSION"; + description = "List of forbidden file extensions"; + message = "Forbidden attachment extension"; +} diff --git a/docs/antispam.rst b/docs/antispam.rst index 3873be64..fb97e66a 100644 --- a/docs/antispam.rst +++ b/docs/antispam.rst @@ -155,3 +155,31 @@ For more information on using the multimap filter see the official `multimap doc .. _`1438`: https://github.com/Mailu/Mailu/issues/1438 .. _`1167`: https://github.com/Mailu/Mailu/issues/1167 .. _`1566`: https://github.com/Mailu/Mailu/issues/1566 + +Can I change the list of authorized file attachments? +----------------------------------------------------- + +Mailu rejects emails with file attachements it deems to be "executable" or otherwise dangerous. If you would like to tweak the block list, you can do so using the following commands: + + .. code-block:: bash + + docker-compose exec antispam cat /etc/rspamd/local.d/forbidden_file_extension.map > overrides/rspamd/forbidden_file_extension.map + docker-compose restart antispam + +Now the file `overrides/rspamd/forbidden_file_extension.map` can be edited, to make changes to the forbidden file extensions list. +For the changes to take effect, rspamd must be restarted. + +Mailu rejects emails with documents attached containing some macros. How can I fix it? +-------------------------------------------------------------------------------------- + +If configured to do so, Mailu uses a lightweight tool called `mraptor from oletools`_ to scan documents containing macros. By default only macros deemed potentially harmful are blocked, but there may be false positives. If you want to change the default behaviour, you may need to override the ``/etc/rspamd/local.d/composites.conf`` file in the antispam container. The following commands may be useful: + + .. code-block:: bash + + docker-compose exec antispam cat /etc/rspamd/local.d/composites.conf > overrides/rspamd/composites.conf + docker-compose restart antispam + +Now the file `overrides/rspamd/composites.conf` can be edited, to override the mraptor configuration in rspamd. +For the changes to take effect, rspamd must be restarted. + +.. _`mraptor from oletools`: https://github.com/decalage2/oletools/wiki/mraptor diff --git a/docs/configuration.rst b/docs/configuration.rst index f4510626..5ecfa347 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -100,6 +100,12 @@ by setting ``INBOUND_TLS_ENFORCE`` to ``True``. Please note that this is forbidd internet facing hosts according to e.g. `RFC 3207`_ , because this prevents MTAs without STARTTLS support or e.g. mismatching TLS versions to deliver emails to Mailu. +The ``SCAN_MACROS`` (default: True) setting controls whether Mailu will endavour +to reject emails containing documents with malicious macros. Under the hood, it uses +`mraptor from oletools`_ to determine whether a macro is malicious or not. + +.. _`mraptor from oletools`: https://github.com/decalage2/oletools/wiki/mraptor + .. _`RFC 3207`: https://tools.ietf.org/html/rfc3207 .. _fetchmail: diff --git a/docs/index.rst b/docs/index.rst index 0b37cf43..b73bf529 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,7 +28,7 @@ Main features include: - **Web access**, multiple Webmails and administration interface - **User features**, aliases, auto-reply, auto-forward, fetched accounts - **Admin features**, global admins, announcements, per-domain delegation, quotas -- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner, Snuffleupagus +- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner, [Snuffleupagus](https://github.com/jvoisin/snuffleupagus/), block malicious attachments - **Antispam**, auto-learn, greylisting, DMARC and SPF, anti-spoofing - **Freedom**, all FOSS components, no tracker included diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index cd470098..6eb4c409 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -103,16 +103,40 @@ services: - {{ dns }} {% endif %} +{% if oletools_enabled %} + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-{{ version }}} + hostname: oletools + restart: always + networks: + - noinet + depends_on: + {% if resolver_enabled %} + - resolver + dns: + - {{ dns }} + {% endif %} +{% endif %} + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-{{ version }}} hostname: antispam restart: always env_file: {{ env }} +{% if oletools_enabled %} + networks: + - default + - noinet +{% endif %} volumes: - "{{ root }}/filter:/var/lib/rspamd" - "{{ root }}/overrides/rspamd:/etc/rspamd/override.d:ro" depends_on: - front + - redis + {% if oletools_enabled %} + - oletools + {% endif %} {% if antivirus_enabled %} - antivirus {% endif %} @@ -202,3 +226,8 @@ networks: {% if ipv6_enabled %} - subnet: {{ subnet6 }} {% endif %} +{% if oletools_enabled %} + noinet: + driver: bridge + internal: true +{% endif %} diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index cc99912e..980788ce 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -58,6 +58,9 @@ WEBDAV={{ webdav_enabled or 'none' }} # Antivirus solution (value: clamav, none) ANTIVIRUS={{ antivirus_enabled or 'none' }} +# Scan Macros solution (value: true, false) +SCAN_MACROS={{ oletools_enabled or 'false' }} + ################################### # Mail settings ################################### diff --git a/setup/templates/steps/compose/02_services.html b/setup/templates/steps/compose/02_services.html index b6964bdf..2311e4a3 100644 --- a/setup/templates/steps/compose/02_services.html +++ b/setup/templates/steps/compose/02_services.html @@ -55,6 +55,15 @@ the security implications caused by such an increase of attack surface.

Fetchmail allows users to retrieve mail from an external mail-server via IMAP/POP3 and puts it in their inbox. +

+ + + Oletools scans documents in email attachements for malicious macros. It has a much lower memory footprint than a full-fledged anti-virus. +
+ diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index ce7ade70..5e503230 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -82,7 +82,7 @@ Or in plain english: if receivers start to classify your mail as spam, this post manage your email domains, users, etc.

- +
diff --git a/tests/build.hcl b/tests/build.hcl index d657cbb7..f5893b8c 100644 --- a/tests/build.hcl +++ b/tests/build.hcl @@ -34,6 +34,7 @@ group "default" { "antispam", "front", "imap", + "oletools", "smtp", "webmail", @@ -152,6 +153,15 @@ target "front" { tags = tag("nginx") } +target "oletools" { + inherits = ["defaults"] + context = "core/oletools/" + contexts = { + base = "target:base" + } + tags = tag("oletools") +} + target "imap" { inherits = ["defaults"] context = "core/dovecot/" diff --git a/tests/compose/core/docker-compose.yml b/tests/compose/core/docker-compose.yml index 1f9d6730..8d56a443 100644 --- a/tests/compose/core/docker-compose.yml +++ b/tests/compose/core/docker-compose.yml @@ -65,10 +65,20 @@ services: depends_on: - front + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-local} + hostname: oletools + restart: always + networks: + - noinet + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local} restart: always env_file: mailu.env + networks: + - default + - noinet volumes: - "/mailu/filter:/var/lib/rspamd" - "/mailu/dkim:/dkim" @@ -96,3 +106,6 @@ networks: driver: default config: - subnet: 192.168.203.0/24 + noinet: + driver: bridge + internal: true diff --git a/tests/compose/core/mailu.env b/tests/compose/core/mailu.env index 0b034008..7ea86f56 100644 --- a/tests/compose/core/mailu.env +++ b/tests/compose/core/mailu.env @@ -65,6 +65,9 @@ WEBDAV=none #Antispam solution ANTISPAM=none +# Scan Macros solution (value: true, false) +SCAN_MACROS=True + ################################### # Mail settings ################################### diff --git a/tests/compose/fetchmail/docker-compose.yml b/tests/compose/fetchmail/docker-compose.yml index c1a1a55c..067532fa 100644 --- a/tests/compose/fetchmail/docker-compose.yml +++ b/tests/compose/fetchmail/docker-compose.yml @@ -65,10 +65,20 @@ services: depends_on: - front + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-local} + hostname: oletools + restart: always + networks: + - noinet + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local} restart: always env_file: mailu.env + networks: + - default + - noinet volumes: - "/mailu/filter:/var/lib/rspamd" - "/mailu/dkim:/dkim" @@ -103,3 +113,6 @@ networks: driver: default config: - subnet: 192.168.203.0/24 + noinet: + driver: bridge + internal: true diff --git a/tests/compose/fetchmail/mailu.env b/tests/compose/fetchmail/mailu.env index 573acf20..0355f168 100644 --- a/tests/compose/fetchmail/mailu.env +++ b/tests/compose/fetchmail/mailu.env @@ -65,6 +65,9 @@ WEBDAV=none #Antispam solution ANTISPAM=none +# Scan Macros solution (value: true, false) +SCAN_MACROS=True + ################################### # Mail settings ################################### diff --git a/tests/compose/filters/01_email_test.sh b/tests/compose/filters/01_email_test.sh index 5af395c4..50e904f8 100755 --- a/tests/compose/filters/01_email_test.sh +++ b/tests/compose/filters/01_email_test.sh @@ -1,6 +1,6 @@ -python3 tests/email_test.py message-virus "tests/compose/filters/eicar.com" +python3 tests/email_test.py message-virus "tests/compose/filters/eicar.com.txt" if [ $? -eq 99 ]; then exit 0 else exit 1 -fi \ No newline at end of file +fi diff --git a/tests/compose/filters/03_email_macro.sh b/tests/compose/filters/03_email_macro.sh new file mode 100755 index 00000000..484fd5ff --- /dev/null +++ b/tests/compose/filters/03_email_macro.sh @@ -0,0 +1,13 @@ +# Malicious macros should be blocked +# see https://github.com/clr2of8/VBAstomp and https://github.com/decalage2/oletools/wiki/mraptor +python3 tests/email_test.py message-macro-stomp "tests/compose/filters/2003x32_word_msgbox_stomped_fakecode.doc" +if [ $? -ne 25 ]; then + exit 1 +fi +# This does Auto_Open + Alert() +python3 tests/email_test.py message-autoexec-macro "tests/compose/filters/excel4_sample_macro.slk" +if [ $? -ne 25 ]; then + exit 1 +fi + +exit 0 diff --git a/tests/compose/filters/2003x32_word_msgbox_stomped_fakecode.doc b/tests/compose/filters/2003x32_word_msgbox_stomped_fakecode.doc new file mode 100644 index 00000000..f6d78e45 Binary files /dev/null and b/tests/compose/filters/2003x32_word_msgbox_stomped_fakecode.doc differ diff --git a/tests/compose/filters/docker-compose.yml b/tests/compose/filters/docker-compose.yml index 41908a40..3eb2d84c 100644 --- a/tests/compose/filters/docker-compose.yml +++ b/tests/compose/filters/docker-compose.yml @@ -65,10 +65,20 @@ services: depends_on: - front + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-local} + hostname: oletools + restart: always + networks: + - noinet + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local} restart: always env_file: mailu.env + networks: + - default + - noinet volumes: - "/mailu/filter:/var/lib/rspamd" - "/mailu/dkim:/dkim" @@ -102,3 +112,6 @@ networks: driver: default config: - subnet: 192.168.203.0/24 + noinet: + driver: bridge + internal: true diff --git a/tests/compose/filters/eicar.com b/tests/compose/filters/eicar.com.txt similarity index 100% rename from tests/compose/filters/eicar.com rename to tests/compose/filters/eicar.com.txt diff --git a/tests/compose/filters/excel4_sample_macro.slk b/tests/compose/filters/excel4_sample_macro.slk new file mode 100644 index 00000000..3bd187ca --- /dev/null +++ b/tests/compose/filters/excel4_sample_macro.slk @@ -0,0 +1,68 @@ +ID;PWXL;N;E +P;PGeneral +P;P0 +P;P0.00 +P;P#,##0 +P;P#,##0.00 +P;P#,##0;;\-#,##0 +P;P#,##0;;[Red]\-#,##0 +P;P#,##0.00;;\-#,##0.00 +P;P#,##0.00;;[Red]\-#,##0.00 +P;P#,##0\ "$";;\-#,##0\ "$" +P;P#,##0\ "$";;[Red]\-#,##0\ "$" +P;P#,##0.00\ "$";;\-#,##0.00\ "$" +P;P#,##0.00\ "$";;[Red]\-#,##0.00\ "$" +P;P0% +P;P0.00% +P;P0.00E+00 +P;P##0.0E+0 +P;P#" "?/? +P;P#" "??/?? +P;Pdd/mm/yyyy +P;Pdd\-mmm\-yy +P;Pdd\-mmm +P;Pmmm\-yy +P;Ph:mm\ AM/PM +P;Ph:mm:ss\ AM/PM +P;Phh:mm +P;Phh:mm:ss +P;Pdd/mm/yyyy\ hh:mm +P;Pmm:ss +P;Pmm:ss.0 +P;P@ +P;P[h]:mm:ss +P;P_-* #,##0\ "$"_-;;\-* #,##0\ "$"_-;;_-* "-"\ "$"_-;;_-@_- +P;P_-* #,##0_-;;\-* #,##0_-;;_-* "-"_-;;_-@_- +P;P_-* #,##0.00\ "$"_-;;\-* #,##0.00\ "$"_-;;_-* "-"??\ "$"_-;;_-@_- +P;P_-* #,##0.00_-;;\-* #,##0.00_-;;_-* "-"??_-;;_-@_- +P;FCalibri;M220;L9 +P;FCalibri;M220;L9 +P;FCalibri;M220;L9 +P;FCalibri;M220;L9 +P;ECalibri;M220;L9 +P;ECalibri Light;M360;L55 +P;ECalibri;M300;SB;L55 +P;ECalibri;M260;SB;L55 +P;ECalibri;M220;SB;L55 +P;ECalibri;M220;L18 +P;ECalibri;M220;L21 +P;ECalibri;M220;L61 +P;ECalibri;M220;L63 +P;ECalibri;M220;SB;L64 +P;ECalibri;M220;SB;L53 +P;ECalibri;M220;L53 +P;ECalibri;M220;SB;L10 +P;ECalibri;M220;L11 +P;ECalibri;M220;SI;L24 +P;ECalibri;M220;SB;L9 +P;ECalibri;M220;L10 +P;ESegoe UI;M200;L9 +F;P0;DG0G8;E;M292 +B;Y2;X1;D0 0 1 0 +O;L;E;D;V0;K47;G100 0.001 +F;W1 1 17 +F;W2 16384 9 +NN;NAuto_Open;ER1C1 +C;Y1;X1;KFALSE;EALERT("This is a sample Excel 4 macro") +C;Y2;KTRUE;EHALT() +E diff --git a/tests/compose/filters/mailu.env b/tests/compose/filters/mailu.env index 89309641..cf9f7f2d 100644 --- a/tests/compose/filters/mailu.env +++ b/tests/compose/filters/mailu.env @@ -65,6 +65,9 @@ ANTIVIRUS=clamav #Antispam solution ANTISPAM=none +# Scan Macros solution (value: true, false) +SCAN_MACROS=True + ################################### # Mail settings ################################### diff --git a/tests/compose/webdav/docker-compose.yml b/tests/compose/webdav/docker-compose.yml index 5dfa6bc8..1391b68d 100644 --- a/tests/compose/webdav/docker-compose.yml +++ b/tests/compose/webdav/docker-compose.yml @@ -65,10 +65,20 @@ services: depends_on: - front + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-local} + hostname: oletools + restart: always + networks: + - noinet + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local} restart: always env_file: mailu.env + networks: + - default + - noinet volumes: - "/mailu/filter:/var/lib/rspamd" - "/mailu/dkim:/dkim" @@ -103,3 +113,6 @@ networks: driver: default config: - subnet: 192.168.203.0/24 + noinet: + driver: bridge + internal: true diff --git a/tests/compose/webdav/mailu.env b/tests/compose/webdav/mailu.env index c2fcc4cf..b7a9b718 100644 --- a/tests/compose/webdav/mailu.env +++ b/tests/compose/webdav/mailu.env @@ -65,6 +65,9 @@ WEBDAV=radicale #Antispam solution ANTISPAM=none +# Scan Macros solution (value: true, false) +SCAN_MACROS=True + ################################### # Mail settings ################################### diff --git a/tests/compose/webmail/docker-compose.yml b/tests/compose/webmail/docker-compose.yml index 14d1dae9..5e106105 100644 --- a/tests/compose/webmail/docker-compose.yml +++ b/tests/compose/webmail/docker-compose.yml @@ -65,10 +65,20 @@ services: depends_on: - front + oletools: + image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}oletools:${MAILU_VERSION:-local} + hostname: oletools + restart: always + networks: + - noinet + antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local} restart: always env_file: mailu.env + networks: + - default + - noinet volumes: - "/mailu/filter:/var/lib/rspamd" - "/mailu/dkim:/dkim" @@ -104,3 +114,6 @@ networks: driver: default config: - subnet: 192.168.203.0/24 + noinet: + driver: bridge + internal: true diff --git a/tests/compose/webmail/mailu.env b/tests/compose/webmail/mailu.env index f87f3262..ddc845fa 100644 --- a/tests/compose/webmail/mailu.env +++ b/tests/compose/webmail/mailu.env @@ -65,6 +65,9 @@ WEBDAV=none #Antispam solution ANTISPAM=none +# Scan Macros solution (value: true, false) +SCAN_MACROS=True + ################################### # Mail settings ################################### diff --git a/towncrier/newsfragments/2510.feature b/towncrier/newsfragments/2510.feature new file mode 100644 index 00000000..a6ad675b --- /dev/null +++ b/towncrier/newsfragments/2510.feature @@ -0,0 +1 @@ +Implement OLETools and block bad macros in office documents diff --git a/towncrier/newsfragments/2511.misc b/towncrier/newsfragments/2511.misc new file mode 100644 index 00000000..b584e3c4 --- /dev/null +++ b/towncrier/newsfragments/2511.misc @@ -0,0 +1 @@ +Block executable file formats by default. Ask your users to zip them up if required.