Email Header Injection in mime-mail

By James Parker - May 23, 2017

mime-mail is a Haskell library used to compose and render emails. It is typically used in server-side software to send automated emails or construct emails from user supplied inputs.

While working on a website where I was constructing emails with POST data supplied by the user, I discovered that the mime-mail package was vulnerable to a header injection vulnerability. When browsing mime-mail's source code, I noticed that email headers were not being sanitized before being rendered. This meant that an attacker could insert additional email headers by injecting CLRF (\r\n) characters between the malicious headers. As a result, attackers could control parameters including the From, To, Reply-To, CC, BCC, and Subject fields. Since the emails are sent from the website, attackers could use this vulnerability to send spam, phish users for credentials, leak private information, or deface the site.

We can demonstrate the vulnerability with ghci, Haskell's REPL:

Network.Mail.Mime Prelude> let to = [Address Nothing "test@test"]
Network.Mail.Mime Prelude> let from = Address Nothing "test@test>\nCc: <"
Network.Mail.Mime Prelude> let body = plainPart "Hi\nThis is a test.\nBye"
Network.Mail.Mime Prelude> renderMail' $ Mail from to [] [] [] [[body]]
"From: <test@test>\nCc: <>\nTo: <test@test>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8\nContent-Transfer-Encoding: quoted-printable\n\nHi\r\nThis is a test=2E\r\nBye"

In this example, an attacker controlling the From address inserts a CC recipient. The email's raw string output provided by renderMail' includes the injected CC header, so will receive the email even though it shouldn't.

After discovering the vulnerability, I emailed Michael Snoyman, mime-mail's developer. We decided that stripping all control characters from email headers was an appropriate fix. Shortly after, I submitted a pull request implementing the sanitization change, and Michael released the updated version to hackage. The fix is included in mime-mail version 0.4.13. I recommend updating to at least this version if you use mime-mail to compose emails in server-side applications.