security research & pentest
How to Fail Successfully ?

Hello, this blog describes the entire process my close friend Unsal and I went through while researching a vulnerability. The path we followed and the path we ended up on turned out to be completely different. After a period where we thought we had failed and were heading in the wrong direction, we kept going and ultimately succeeded. Throughout this journey, we first understood the scope of a vulnerability as a single pov, then after communicating with Gareth Heyes who originally discovered the vulnerability, we recognized the second pov and changed our research approach.

Along the way there were mistakes, growth, and frankly plenty of judgmental emails. But in the end, with the CVE we obtained on an application with 22 K+ stars on GitHub, it was an adventure where we truly understood the phrase "How to fail successfully?"

This blog post covers two aspects of a vulnerability in order, so I recommend reading it all the way through to fully understand the details.

Gareth Heyes has also covered different exploits and scenarios related to this topic on his blog, so I strongly recommend reading his work as well.

The Beginning

The starting point of this entire journey was after reading Gareth Heyes' article. I was incredibly impressed by the depth of his research, and wanting to dive deeper, it all began with this message:

Telegram message - Research beginning

-Look at me
-If you are not saying I am going to look into my own projects tonight
-I have a research task after Iftar
+Okay
+Around what time?
-19.10 is Iftar
+Let me send you the documents I have

Vulnerability Analysis

To understand what Gareth Heyes described in his article, we first need to understand how SMTP messages are delivered:

In SMTP requests, the email is delivered to the address specified in the RCPT TO header. The "From" or "To" addresses within the Data section do not indicate the actual sender or the real recipient of the email.

SMTP request example

For example, anonymous "prank" email services manipulate the "From" and "To" addresses that come after the "Data" value. Let's examine an SMTP request from a sample prank site:

Prank site SMTP request

In the request shown above, the address that actually sends the email (Mail From) differs from the value in the "From" header. When you view this email in clients like Outlook, the sender's email address will appear as "[email protected]".

This is because SMTP carries address information in two separate layers, and the purposes of these layers are independent of each other.

LayerHeader FieldsPurpose
EnvelopeMAIL FROM, RCPT TOActual routing addresses, header values that MTAs look at
HeaderFrom:, To:, CC:Display-only information shown to users by the email client

In other words, the email always goes to the address in RCPT TO. The reason I'm mentioning this is so that when we refer to "the person the email was delivered to" in later sections, we already know where to look.

As also stated by Gareth Heyes in his article, according to the RFC2047 documentation, encoded data can be used in SMTP requests:

RFC2047 explanation

So what does this mean? For example, when we want to send an email to [email protected], we can write the email address using Q encoding as =?utf-8?q?saadetelif=40lzzapsecurity.com?=

Q Encoding example

or using base64 as =?utf-8?b?c2FhZGV0ZWxpZkBsenphcHNlY3VyaXR5LmNvbQ==?=.

Base64 Encoding example

So in what situation does the vulnerability emerge? If an email library accepts email addresses in RFC2047 format and the application using this library has its MTA configuration set to decode RFC2047, the following scenario arises:

If the application allows sending requests to certain domains during the registration step or in email-sending features, and the domain check examines the part after the @ symbol, this is an indicator of a vulnerability.

Why?

Let's take the following email address as an example:

=?utf-8?q?saadetelif=40lzzapsecurity=3e=00=0A=0D?=@alloweddomain.com

Since alloweddomain.com comes after the @ symbol, it will pass the application's domain check. But will the application actually send the email to alloweddomain.com?

RCPT TO decode result

In the scenario we're discussing, no. As you can see in the request above, when we provide the payload, the RCPT TO value actually goes to <saadetelif@lzzapsecurity>. The remaining part of the input may throw an error depending on the SMTP server, or the second part may be ignored entirely.

When this situation is realized, the exploit steps occur in the following order:

The library accepts the RFC2047-encoded email address => The MTA decodes it per RFC2047 => The email is delivered not to the target email address but to a different one.

To test this stage, we examined most email processing libraries we could find on GitHub and prepared report templates for disclosure. We used AI for library discovery and report automation.

Our research adventure that started at 8:00 PM continued until 4:00 AM, and during this time we kept Telegram's UDP ports quite busy:

Telegram research process

At this stage, we observed that the vast majority of the libraries we targeted accepted encoded data:

Library test results - 22 out of 23 libraries affected

Since this article is for educational purposes and we did not reach an agreement with the libraries, we chose not to disclose their names. However, we can see that 22 out of 23 libraries exhibited this behavior.

At this point, we wanted to prepare sample applications to report to library maintainers, visualizing which domain was being bypassed and proving it with functions belonging to the libraries:

Sample application showing domain bypass

One of the mistakes we made here was that instead of stating "this vulnerability occurs if MTAs decode in this manner," we directly showed the output after it left the library as if it were being routed that way. We proved that the libraries accepted requests with =? structures, but since we didn't demonstrate the misconfigured MTA scenario we were trying to highlight, I don't think it received the seriousness it deserved.

For example, we believe things would have been different if we had actually routed the following request through a misconfigured MTA:

MTA configuration example

Some library maintainers expressed that they believed the responsibility lay not with them but with the MTAs, and in our discussions we communicated that we simply wanted to report the issue.

Some library maintainers did make updates. For example, after we contacted the Govalidator library, we received an email from the maintainer stating that the following commit was made:

Govalidator Update Commit

Some maintainers' approach, however, was like this:

Library maintainer response

After receiving some reactions and rejections during this process, we wanted to understand whether we were making a mistake somewhere, so we reached out to Gareth Heyes. He confirmed that what we had done was part of the scope covered in his article, but additionally -- and this was the part we had overlooked -- he pointed out that even without MTAs, the libraries themselves decoded the RFC2047-encoded email addresses during extraction. This meant the issue could be triggered entirely at the library level, before the email even reached an MTA or SMTP server.

At this point, we shifted our research in this direction, but instead of focusing on libraries, we wanted to target applications that use these libraries. When selecting which applications to target, we considered the following criteria:

- There must be a domain allow list or domain block list that can be bypassed
- These allow/block lists should be present in the registration step (best exploit scenario)
- And of course, RFC2047 support

Within this framework, the application that caught our attention the most and where we believed we could trigger the vulnerability was Forem, which had 22.7K stars on GitHub.

After setting up and examining the application, we found that we could create an allow list. We created an allowlist with lzzapsecurity.com and submitted the following payload:

=?utf-8?q?test1234=40v2ycjxkm94pldktx9tv8tu3ef5l19rxg.oastify.com=3e?=@lzzapsecurity.com
Forem registration screen

We observed that the application's backend did not block special characters and accepted this email address:

Backend accepted the email address

The email address's reflection on SMTP was the RFC2047-decoded version:

Decoded payload on SMTP

At this stage, in case of errors being thrown on SMTP, we also provided the following alternative payloads:

[email protected]

[email protected]

[email protected]

=?utf-8?q?test=40attacker.com=3e=0A=0D?=RCPTTO:[email protected]

After all these stages, we progressed to the point where Forem accepted the vulnerability and a CVE was requested through GitHub.

Forem Security Advisory

Closing

Honestly, this entire process felt like a powerful internal feedback experience on how we should approach our research.

At the same time, we realized that the trial-and-error process is inevitable when trying to understand a vulnerability, and that we need to keep moving forward without losing motivation. All of this provided us with significant growth, not just technically but mentally as well.

Until the next adventure.