Baking Mojolicious Cookies revisited: a case study of solving security problems through security by obscurity

Known for its agility and simplicity, the Mojolicious framework is especially valued in niche industries with a Perl heritage. In our recent security assessment, the use of under-the-radar technology introduced unique features and challenges. Learn how we overcame these difficulties.

Jakub Kramarz 2024.10.29   –   5 MIN read

“What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?”

— Larry Wall, the creator of Perl programming language

Connect with the author on LinkedIn!

Mojolicious framework and its signed cookies

During a recent security assessment, we encountered an application developed using Mojolicious, a Perl web framework. While being a modern, powerful, and flexible web framework, it is typically less visible in terms of mainstream adoption compared to frameworks like Ruby on Rails or Django. It has become well-regarded for its simplicity, flexibility, and powerful features that allow rapid web development.

Information about the sites and companies using Mojolicious isn’t widely documented in easily verifiable public sources. It may or may not be used for many public-facing websites or relied upon for backend services and high-performance internal apps. However, it has a dedicated user base, especially in industries that have historically used Perl (if there were any).

One aspect that caught our attention was how the framework implements sessions, particularly how session data is stored and protected. Mojolicious implements sessions as signed cookies stored on the client side, consisting of the Base64-encoded JSON with session-related information, some padding, and the HMAC-SHA256 signature to prevent tampering. 

Sounds just like JWT, right? Remember that: 

“The camel has evolved to be relatively self-sufficient. On the other hand, the camel has not evolved to smell good. Neither has Perl.”

Programming Perl: Unmatched Power for Text Processing and Scripting, Larry Wall

Cookie Signature Mechanism

Before diving into the application’s Perl code to reverse-engineer the exact details of how the session cookies were being signed and managed, I decided to take a step back and investigate whether any prior research had been done on this topic. After a brief search, I came across an insightful article written by Antoine Cervoise on Synacktiv in 2021, titled  “Baking Mojolicious Cookies”. In this article, Antoine detailed the encoding and signing process used by Mojolicious for session cookies and even provided insights into how weak signing secrets could be cracked.

Armed with this knowledge, I was prepared to apply the techniques discussed in the article to our assessment. However, I soon noticed a significant discrepancy: the signature algorithm in our case did not match what Antoine had described – it was no longer HMAC-SHA1. Additionally, when I attempted to use popular brute-force tools like hashcat and john (which are often employed for cracking weak HMAC signatures), I encountered unexpected input validation errors related to the cookies’ length. Something was clearly different about this application and was definitely related to the length of session cookies.

Developers’ Response to Brute Force Attacks in Mojolicious

As I dug deeper into the issue, I discovered that shortly after Antoine had published his findings, the Mojolicious team made a tiny change to how session cookies are handled. Specifically, they introduced a modification in the framework that pads session values to 1025 bytes by default. This update can be traced back to the pull request #1791 (pad session values to 1025 bytes by default) on its GitHub repository.

The reasoning provided by the developers for this change was particularly interesting. According to the pull request, the padding was introduced to prevent “a very specific brute force attack” that could be executed using “a common tool if the encrypted message was short enough.” Upon closer inspection, I realized that this essentially referred to the brute-force attack on the cookie’s HMAC-SHA256 signature using hashcat in scenarios where the signing secret was weak or known.

The decision by the Mojolicious developers to introduce the padding raises important questions: Did it make the brute-forcing of the signing secret more difficult? Are the applications more secure now? In essence, the padding of approximately one kilobyte of capital “Z” characters in the cookies effectively only breaks the input validation of hashcat. Sessions in these applications were and are as secure as their signing secret.

Mojolicious Cookies vs. JWT

There are other examples of long, HMAC-SHA256-signed client-side stored session cookies in use – one of the most prominent ones being JWT (JSON Web Token). It is a popular standard, widely used across many modern web applications as a compact, URL-safe means of representing claims between parties.

Recognizing the similarities between Mojolicious session cookies and JWTs, I decided to simply try combining the capabilities of the hashcat’s JWT cracking module that is highly compute optimized and GPU accelerated. It also contains simplified input validation mechanisms used in the HMAC-SHA256 cracking process, previously used for for Mojolicious secrets.

It worked! Here you can find this new module on a merge request: Pull Request #4090 · hashcat/hashcat.

Connect with the author on LinkedIn!

Thoughts on Strengthening Security in Development

Actually, I could have read Joel Berger’s (member of the Mojolicious Core Team) blog article on “The Secret Life of Sessions” and discovered that the default secret for an application is just the name of the script (so called application moniker). But how would I verify if developers declared a stronger secret?

Testing tools, including those used for penetration testing, should be viewed as allies in strengthening the robustness of software rather than as obstacles.

Fortunately, there’s now an ongoing discussion started by Stig Palmquist on making these secrets non-predictable in the pull request #2200.

For regular web frameworks and regular JWT tokens, an attempt to brute-force the signature using a list of common weak secrets is something that we do on every security assessment. Finding that the signing secret is not strong enough may simply show that the application or test environment prepared for the security audit is misconfigured.

Jakub Kramarz
Jakub Kramarz Senior IT Security Consultant