Sinatra is a popular DSL (domain-specific language) for creating web apps quickly in Ruby. It's widely used for its simplicity. But even lightweight frameworks like Sinatra can have security flaws. In this post, we'll break down CVE-2022-45442: a vulnerability affecting Sinatra (versions 2. up to, but not including, 2.2.3 and 3. up to, but not including, 3..4) that opens the door to a particular attack called Reflected File Download (RFD). We'll show how attackers could exploit this bug, provide a code example, and tell you how to defend your apps.
What Is a Reflected File Download (RFD) Attack?
Reflected File Download (RFD) is a web attack where hackers trick a victim into downloading a file with a name and sometimes content they control. The attacker uses URL and HTTP header manipulation to get a browser to save the file with an attacker-supplied filename and extension (like .html or .bat). This can result in social engineering or even direct code execution if the user opens the file.
For an RFD attack, two things are usually needed
- The app uses user-supplied input to set the Content-Disposition header (this sets the download filename).
The app makes no validation or sanitization of this user input.
If attackers can set the filename to something like malware.bat, and the victim downloads and opens it, bad things can happen.
How Sinatra Was Vulnerable
In vulnerable versions of Sinatra (before 2.2.3 and 3..4), the framework often allowed developers to set the Content-Disposition response header using user input without enforcing any checks. For example, a naive download endpoint might look like:
get '/download' do
filename = params[:file] # user input from query, e.g. ?file=something.txt
content = get_file_contents(filename)
headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
content
end
If you visited /download?file=mybat.bat, Sinatra would send a download for "mybat.bat". Worse, attackers could try things like /download?file=evil.html, or even inject line breaks into the filename to further manipulate the headers.
`
https://victim-app.example.com/download?file=malicious.html
Victim Opens File:
If the file contains harmful HTML or JavaScript, and the victim opens it locally, it could lead to local execution or further phishing.
Advanced Attack:
If the attacker uses newline characters and clever payloads, they might even inject new headers or alter the file contents, increasing the risk.
Here's a simple Sinatra app (vulnerable version)
require 'sinatra'
get '/download' do
filename = params[:file]
# BAD: No sanitization!
headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
"This file has the name you chose: #{filename}\n"
end
Running this app and visiting
http://localhost:4567/download?file=my_poc.html
produces the download with the filename my_poc.html. The attacker can craft a malicious HTML file here.
Version 3..4
The patch ensures that any user-controlled filename in Content-Disposition is sanitized, stripping out dangerous characters or extensions. It also blocks certain mime types and patterns, and further protects against header injection.
Recommendations
- Upgrade Sinatra: Get to at least 2.2.3 (for 2.x) or 3..4 (for 3.x). See Sinatra changelog.
`ruby
filename = File.basename(params[:file].to_s.gsub(/[^\w\.\-]/, '_'))
headers['Content-Disposition'] = %{attachment; filename="#{filename}"}
<br>- <b>Avoid Dangerous Extensions:</b> Don't allow files with extensions like .bat, .exe, .html, etc., unless you have a specific reason and strict safeguards.<br>- <b>Monitor Dependencies:</b> Use tools like bundler-audit or Gemnasium to track vulnerable gems.<br><br>---<br><br>## References<br><br>- CVE-2022-45442 in NVD<br>- Sinatra security advisory<br>- Sinatra changelog<br>- OWASP RFD details<br><br>---<br><br>## Summary<br><br>Sinatra apps (before 2.2.3 / 3..4) are vulnerable to <b>Reflected File Download</b> thanks to unsafe use of user input in Content-Disposition` headers. This lets attackers trick users into downloading files with attacker-chosen names and extensions, which can be dangerous. The fix is simple: upgrade Sinatra and sanitize all user input used in filenames. Don’t let a simple header ruin your users’ day!
---
Stay safe, keep dependencies up-to-date, and don’t trust user input – ever!
Timeline
Published on: 11/28/2022 21:15:00 UTC
Last modified on: 02/01/2023 15:47:00 UTC