Snyk Fetch The Flag - TimeOff
In this CTF challenge, we are tasked with performing a pentest on a web application following the Model-View-Controller (MVC) pattern, developed in Ruby on Rails. The application allows employees to request time off, and we are provided with the source code and two credentials (admin and user).
While reviewing the application, we noticed that the time-off request form allows file uploads, which is always an interesting point to investigate during a security audit.
📄 Relevant Code of time_off_requests_controller.rb file
if params[:doc]
uploaded_file = params[:doc][:file]
if uploaded_file
storage_directory = Rails.root.join("public", "uploads")
FileUtils.mkdir_p(storage_directory) unless Dir.exist?(storage_directory)
storage_path = storage_directory.join(uploaded_file.original_filename)
Rails.logger.info "Saving uploaded file to: #{storage_path}"
File.open(storage_path, "wb") do |file|
file.write(uploaded_file.read)
end
doc = Document.new(
name: params[:doc][:file_name],
file_path: uploaded_file.original_filename
)
doc.time_off_request = @time_off_request
doc.save
end
end
This code presents a critical security flaw:
- The filename is not validated before being saved.
storage_pathis built directly fromuploaded_file.original_filename, which opens the possibility for Path Traversal attacks.
storage_path = storage_directory.join(uploaded_file.original_filename)
To verify the issue, we create an upload request and inspect how the request is formatted:
We attempt to read /etc/passwd using the Path Traversal payload: ../../../../../../../../../etc/passwd. After submitting the form, we receive an HTTP 302 Found response, confirming that the file was stored.
In the My Requests panel, we confirm that we can download the file, proving that the application is vulnerable.
Finally, we retrieve the flag using the same method with the payload:
../../../../../../../../../timeoff_app/flag.txt
Y logramos completar el desafío. 🎉
🚩 Flag
flag{52948d88ee74b9bdab130c35c88bd406}








