Snyk Fetch The Flag - TimeOff

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.

Snyk Fetch The Flag - TimeOff

📄 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_path se construye directamente con uploaded_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:

Snyk Fetch The Flag - TimeOff

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.

Snyk Fetch The Flag - TimeOff

Desde el panel My Requests, verificamos que podemos descargar el archivo, confirmando que la aplicación es vulnerable.

Snyk Fetch The Flag - TimeOff

Snyk Fetch The Flag - TimeOff

Finalmente, usamos el mismo método para leer la flag con el payload:

../../../../../../../../../timeoff_app/flag.txt

Snyk Fetch The Flag - TimeOff

Snyk Fetch The Flag - TimeOff

Snyk Fetch The Flag - TimeOff

And successfully complete the challenge. 🎉

🚩 Flag

flag{52948d88ee74b9bdab130c35c88bd406}