CVE-2023-32676 (published 2023-05-26T23:15Z)

Autolab is a course management service that enables auto-graded programming assignments. A Tar slip vulnerability was found in the Install assessment functionality of Autolab. To exploit this vulnerability an authenticated attacker with instructor permissions needs to upload a specially crafted Tar file. Using the install assessment functionality an attacker can feed a Tar file that contain files with paths pointing outside of the target directory (e.g.,  `../../../../tmp/tarslipped1.sh`). When the Install assessment form is submitted the files inside of the archives are expanded to the attacker-chosen locations. This issue has been addressed in version 2.11.0. Users are advised to upgrade.

CVSS v3 base score: 7.2, HIGH (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/autolab/Autolab
commit_details: repo_url: https://github.com/autolab/Autolab
author: Joey Wildman
author_date: 2023-05-18 14:23:46-07:00
msg: Merge pull request from GHSA-x9hj-r9q4-832c

* use Archive.in_dir? to check entry files in archive stay within archive

* run rubocop

* check that file is specifically within assessment directory

* address PR comment
repository: repo_url: https://github.com/autolab/Autolab
repo_name: autolab/Autolab
description: Course management service that enables auto-graded programming assignments.
repo_language: Ruby
owner: autolab
file_changes: filename: assessments_controller.rb
change_type: ModificationType.MODIFY
diff: @@ -187,22 +187,27 @@ class AssessmentsController < ApplicationController
     # If all requirements are satisfied, extract assessment files.
     begin
       course_root = Rails.root.join("courses", @course.name)
+      assessment_path = Rails.root.join("courses", @course.name, asmt_name)
       tar_extract.rewind
       tar_extract.each do |entry|
         relative_pathname = entry.full_name
+        entry_file = File.join(course_root, relative_pathname)
+        # Ensure file will lie within course, otherwise skip
+        next unless Archive.in_dir?(Pathname(entry_file), Pathname(assessment_path))
+
         if entry.directory?
-          FileUtils.mkdir_p(File.join(course_root, relative_pathname),
+          FileUtils.mkdir_p(entry_file,
                             mode: entry.header.mode, verbose: false)
         elsif entry.file?
           FileUtils.mkdir_p(File.join(course_root, File.dirname(relative_pathname)),
                             mode: entry.header.mode, verbose: false)
-          File.open(File.join(course_root, relative_pathname), "wb") do |f|
+          File.open(entry_file, "wb") do |f|
             f.write entry.read
           end
-          FileUtils.chmod entry.header.mode, File.join(course_root, relative_pathname),
+          FileUtils.chmod entry.header.mode, entry_file,
                           verbose: false
         elsif entry.header.typeflag == "2"
-          File.symlink entry.header.linkname, File.join(course_root, relative_pathname)
+          File.symlink entry.header.linkname, entry_file
         end
       end
       tar_extract.close

programming_language: Ruby
filename: courses_controller.rb
change_type: ModificationType.MODIFY
diff: @@ -1110,9 +1110,9 @@ private
 
         output_dir = if archive
                        extFilesDir
-                      else
-                        baseFilesDir
-                      end
+                     else
+                       baseFilesDir
+                     end
         output_file = File.join(output_dir, pathname)
 
         # skip if the file lies outside the archive

programming_language: Ruby