23 Apr

Rails Tricks change of direction and The tale of an XSS in Phlex

Hi there,

You are receiving this email because you signed up to the Rails Tricks newsletter. You probably noticed that I haven't sent an email for a long time. The main reason for that is the articles I wrote recently doesn't really fit into the "Rails trick" category. But I believe they are still relevant to Rails developers, so I decided to change the newsletter format a little. The newsletter will be bi-weekly instead of weekly. It will still include one short article in the Ruby, Rails and security space. Besides that, if I write more than one article in that period, it will have links to those articles and if I came across anything I think is worth sharing, I might include that too with my thoughts on it.

This is the first such issue of the newsletter, so let's get into it.

The tale of an XSS in Phlex (CVE-2024-32463)

Phlex is a Ruby gem for building HTML components. Even though the HTML specification permits the usage of the javascript scheme in the href attribute of an anchor tag, Phlex doesn’t permit it to prevent an accidental XSS. When I had an initial look at the gem around its inception, I didn’t really checked how this filtering works, but a Twitter exchange with Joel reminded me to see if it can be bypassed somehow.

I downloaded the gem and found the bit of the code where this filtering was happening:
next if lower_name == "href" && v.start_with?(/\s*javascript:/i)

As you can see, the filter checks if the value for the attribute starts with any number of space characters followed by javascript:. To test the XSSI created a Rails app and a component with anchor tags, setting the anchor from a GET parameter. My first thought was that there might be a lack of downcasing the value, but that wasn’t true, so a payload like JaVaScript: didn’t work. Next thing I tried was the space and tab character and lo and behold the tab worked. The payload I used was java%09script:alert(%27XSS%27). So using the URL encoded tab character successfully bypassed the filter. But how would we persists this? Submitting the same payload in a form doesn’t work, because URL decoding only happens on GET pramaters. That’s actually easy to overcome because Rails uses both GET and POST params in the params hash, so we can submit the payload in the GET parameter and will be still assigned to the attribute.

Once I verified that the issue exists, I went to report it. This is where I usually get dissapointed because there is no clear way to report the issue. Not this time. Phlex has a Security.md with clear instructions about how to report a security issue. I also learned bout GitHub’s private advisory feature which Phlex uses to receive reports. It is a very neat way to handle reports in my opinion.

Joel fixed the issue pretty quickly and released new versions. If you use Phlex, upgrade to the latest version.

Recent posts from my blog

Securing a VPS
With the rise of Kamal, it became much easier to deploy and self-host a Rails apps, but there are a few things you still need to do yourself to secure your server.

Brute-forcing 2FA with Ruby
Ruby is a great language when you need to write a quick, on-off script. I needed just that while I was doing a security challenge.

Secure code review checklist
Checklists are really useful to ensure you don’t forget certain things, so why not create one for your code review process?

Active Record transaction callbacks
Active Record introduced transaction callbacks recently. This change allows you to have a callback for the whole transaction, rather than to just have callbacks on a record’s after_commit event.

The dangers of single line regular expressions
I solved a security challenge on Hack The Box recently. It was a Sinatra app using a single line regular expression to prevent malicious input.

That's it for this time, thanks for reading!