Snyk Fetch The Flag - TimeOff
En este desafío de CTF, se nos asigna la tarea de realizar un pentest en una aplicación web basada en el patrón Modelo-Vista-Controlador (MVC) y desarrollada en Ruby on Rails. La aplicación permite a los empleados de una empresa solicitar tiempo de descanso, y se nos proporciona el código fuente junto con dos credenciales (admin y user).
Al analizar la aplicación, notamos que el formulario para solicitar tiempo de descanso permite la subida de archivos, lo cual es un punto de interés a revisar en cualquier auditoría web.
📄 Archivo time_off_requests_controller.rb
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
Aquí observamos un problema crítico:
- No hay validación del nombre del archivo antes de guardarlo.
storage_pathse construye directamente conuploaded_file.original_filename, lo que puede llevar a una vulnerabilidad Path Traversal.
storage_path = storage_directory.join(uploaded_file.original_filename)
Para confirmar la vulnerabilidad, realizamos una solicitud de subida y observamos la petición generada:
Probamos a leer el archivo /etc/passwd utilizando un payload típico de Path Traversal: ../../../../../../../../../etc/passwd. Tras enviar el formulario, recibimos una respuesta HTTP 302 Found, lo que indica que el archivo fue almacenado.
Desde el panel My Requests, verificamos que podemos descargar el archivo, confirmando que la aplicación es vulnerable.
Finalmente, usamos el mismo método para leer la flag con el payload:
../../../../../../../../../timeoff_app/flag.txt
And successfully complete the challenge. 🎉
🚩 Flag
flag{52948d88ee74b9bdab130c35c88bd406}








