Rejecting Microsoft Executables and Office Documents with Postfix

Update July 16th 2020: A reader has pointed out to me that the regular expression did not (or did not always) match if the filename of the attachment contained non-ASCII characters, opening a simple way to circumvent this header check. I was able to reproduce this behavior by sending a mail with a single attachment „täst.zip“ using Evolution which arrived at Postfix MTA with a MIME-structure like this:

...
Content-Type: multipart/mixed; boundary="=-PAoNeMrNohfkW7sWEPJ5"
...
--=-PAoNeMrNohfkW7sWEPJ5
Content-Type: application/zip; name*=ISO-8859-1''t%E4st.zip
Content-Disposition: attachment; filename*=ISO-8859-1''t%E4st.zip
...

Note the value of the Content-Type header, and there the part name*=ISO-8859-1''t%E4st.zip.

Please compare this to what arrives if i send a mail with an attachment „test.zip“ instead:

Content-Type: application/zip; name="test.zip"
Content-Disposition: attachment; filename="test.zip"

In the below suggestion for mime_header_checks i have made the following changes:

  • Change = to \*?= to allow for RFC 2231 Parameter Value Character Set and Language Information.
  • Include the surrounding sturcture from the second example in the EXAMPLES section of http://www.postfix.org/header_checks.5.html which specifically covers the case that the „.“ in the filename could arrive encoded as quoted printable =2E.

Here is a pcre-entry for Postfix‘ mime_header_checks that will cause Postfix to reject any email containing

  • a file potentially containing code that is executable on Microsoft operating systems (note that this also includes filenames ending with .js) or
  • a document for Microsoft Office (including Access, Excel, Powerpoint, Visio and Word including RTF Documents) or
  • some archive types (ZIP-, 7Zip-, LHA-Archives and MS Exchange data in TNEF format):
# Contents of file "/etc/postfix/mime_header_checks":
/^Content-(Disposition|Type).*name\s*\*?=\s*"?([^;]*(\.|=2E)(
    accd[bert]|
    do(b|[ct][mx]?)|rtf|
    pp(am|(s|t)[mx]?)|pot[mx]?|sld[mx]|
    v[dt]x|vs[dsxt]|
    xl(am?|l|m|[st][mx]?|sb|w)|
    386|
    ad[ep]|app|as[dfx]|
    ba[st]|
    cab|c[bp]l|chm|cmd|com|crt|csh|
    dll|
    exe|
    fxp|
    hlp|ht[aor]|
    in[fips]|isp|
    jar|jse?|
    ksh|
    lib|lnk|
    md[bet]|ms[cipt]|
    ocx|ops|
    pcd|pif|prg|
    reg|
    sc[rt]|sh[bms]?|swf|sys|
    url|
    vb[esx]|vcs|vxd|
    wm[dsz]|
    ws[cfh]|
    7z|lha|tnef|zip))(\?=)?"?\s*(;|$)/x
        REJECT Attachment of type $2 not accepted

Application of the Regular Expression

To prevent any mail containing such attachments from passing through your Postfix MTA, proceed as follows:

1. Install package postfix-pcre:

apt-get install postfix-pcre

2. Create a file /etc/postfix/mime_header_checks with the content shown above.

3. Include the following line in the file /etc/postfix/main.cf:

mime_header_checks = pcre:/etc/postfix/mime_header_checks

4. Restart the postfix service:

service postfix stop
service postfix start

Notes about the Regular Expression

  1. The regular expression will match a MIME-Header Content-Disposition or Content-Type.
  2. All matching of letters is done case-insensitively, i.e. the expression will match contenT-typE as well as .ZiP.
  3. Matching the filename ending is tricky, the relevant part of the expression is \s*([;'"]|$):
    1. The filename ending may immediately be followed by whitespace.
    2. It then is followed by either
      1. a single-quotation mark or
      2. a double-quotation mark or
      3. a semicolon or
      4. the end of line.

Here are more specific regular expressions that match specific attachment types:

Matching any attachment:

/^Content-(Disposition|Type).*name=/ REJECT Attachment not accepted.

Matching specific filename endings:

Machine code, compiled code and macro executables (this one is a beast, and i don’t believe it to be complete): (386|ad[ep]|app|as[dfx]|ba[st]|cab|c[bp]l|chm|cmd|com|crt|csh|dll|exe|fxp|
hlp|ht[aor]|in[fips]|isp|jar|jse?|ksh|lib|lnk|md[bet]|ms[cipt]|ocx|ops|
pcd|pif|prg|reg|sc[rt]|sh[bms]?|swf|sys|url|vb[esx]|vcs|vxd|wm[dsz]|ws[cfh])

Microsoft Office applications:

  • MS Access: (accd[bert])
  • MS Excel: (xl(am?|l|m|[st][mx]?|sb|w))
  • MS Powerpoint: (pp(am|[st][mx]?)|pot[mx]?|sld[mx])
  • MS Visio: (v[dt]x|vs[dsxt])
  • MS Word: (do(b|[ct][mx]?)|rtf)

Archives:

  • (7z|lha|tnef|zip)

Sources

Filename endings were collected from a variety of sources, notably: