• Query Chronicles
  • Posts
  • Application-level Denial of Service using an Unconstrained Number

Application-level Denial of Service using an Unconstrained Number

I’m Sim4n6 and you received the Query Chronicles because you are either interested in the currently being written ebook “CodeQL for Beginners” or as a loyal subscriber to the newsletter.

In both cases, Query Chronicles is a publication designed to feature a security report with a #CodeQL focus in mind, and this edition is about Triggering an Application-level Denial of Service Remotely.

Due to the absence of a limit on the incoming number days when requesting stats for the graph in Sidekiq (a ruby background processor), it was possible to trigger a denial of service remotely. The question now is how?

GET /sidekiq/?days=999999999 HTTP/2 

The below exploit was enough to cause an overload of the system, affecting the Web UI, and making the web application unavailable to all users. Thus, impacting heavily the Availability metric in a CVSS scoring system.

This unusual situation was already fixed in CVE-2022-23837. The commit 7785ac1399 halts, with a 401 Unauthorized, in case the value of days is not within a reasonable interval (days < 1 || days > 180) .

The root cause of the issue is that a remotely controlled-user value can reach a condition controlling the number of times an operation can be repeated. But that value cannot be trusted.

Upon investigating the parent commit 0a4de94d76, the vulnerable code is the following sink.

dates = 
@start_date.downto(@start_date - @days_previous + 1).map { 
|date| date.strftime("%Y-%m-%d") 
}

The basic operation date.strftime() can be repeated as many times as @start_date - @days_previous + 1 with the problem that days_previous could be anything and may come from a maliciously intended user.

We can generalize such a hypothesis where days is an incoming user-controlled value that is not limited in any way by an upper/lower limit. This means the following ruby code snippets are all vulnerable if days value can be remotely handed.

1.upto(days)  

days.times() 

days.downto(1)

for i in 1..days 

until days

To identify such an issue at scale, a CodeQL Query would be mainly composed of three parts:

  1. The source is remote user-controlled data.

  2. The sink is one of the vulnerable codes mentioned above.

  3. The sanitizer is when the developer sets an upper/lower limit to the incoming number, which would omit some false positives.

And that’s all for now.

Please, in case any idea or a possible improvement crosses your mind regarding this issue, feel free to send a reply to this email.