CVE-2016-10345 (published 2017-04-18T20:59Z)

In Phusion Passenger before 5.1.0, a known /tmp filename was used during passenger-install-nginx-module execution, which could allow local attackers to gain the privileges of the passenger user.

Severity: MEDIUM
CVSS v2 base score: 4.6 (AV:L/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 7.8, HIGH (CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-264
cwe_name: Permissions, Privileges, and Access Controls
description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.

Fix information:
repo_url: https://github.com/phusion/passenger
commit_details: repo_url: https://github.com/phusion/passenger
author: Daniel Knoppel (Phusion)
author_date: 2016-11-09 12:07:35+01:00
msg: Fix writing a tmp file with a predictable name in
passenger-install-nginx-module.

With access to the system, a user could plant a symlink in /tmp that
resulted in a chosen-file overwrite attempt whenever
passenger-install-nginx-module was run, using the access rights of
the executing user, potentially even with chosen content.
repository: repo_url: https://github.com/phusion/passenger
repo_name: phusion/passenger
description: A fast and robust web server and application server for Ruby, Python and Node.js
repo_language: C++
owner: phusion
file_changes: filename: CHANGELOG
change_type: ModificationType.MODIFY
diff: @@ -16,6 +16,7 @@ Next version (not yet released)
  * Fixes an issue where passenger-config couldn't restart an app if the TMPDIR variable was set to /tmp
  * `passenger-install-apache-module` now suggests the correct apache package on Ubuntu Xenial. Closes GH-1884.
  * [Standalone] The TempDirToucher will now spend most of its time with reduced privileges, except when it's actively touching files. This allows it to be killed when Passenger is quit in most circumstances. Closes GH-1678.
+ * Fixes a file overwrite vulnerability caused by a predictable temporary file being written by `passenger-install-nginx-module`. Thanks to Jeremy Evans for reporting this.
  * [Standalone] Fixes starting Passenger as a non-extant user. Closes GH-1849.
  * Improved look of the error pages for failing to spawn an application (development & production mode), and Error ID is now also shown in production mode.
  * [Standalone] Enable ipv6 support by default in builtin nginx. Closes GH-1873.

programming_language: Markdown
filename: passenger-install-nginx-module
change_type: ModificationType.MODIFY
diff: @@ -38,11 +38,11 @@
 require 'digest/sha2'
 require 'optparse'
 require 'fileutils'
+require 'tmpdir'
 PhusionPassenger.require_passenger_lib 'platform_info/ruby'
 PhusionPassenger.require_passenger_lib 'platform_info/openssl'
 PhusionPassenger.require_passenger_lib 'abstract_installer'
 PhusionPassenger.require_passenger_lib 'utils/terminal_choice_menu'
-PhusionPassenger.require_passenger_lib 'utils/tmpio'
 PhusionPassenger.require_passenger_lib 'utils/shellwords'
 
 DOWNLOAD_OPTION = {
@@ -566,19 +566,21 @@ def build_nginx_configure_command(prefix, extra_configure_flags = nil)
 
   def pcre_is_installed?
     if @pcre_is_installed.nil?
-      @pcre_is_installed = begin
-        File.open('/tmp/passenger-check.c', 'w') do |f|
-          f.puts("#include <pcre.h>")
-        end
-        Dir.chdir('/tmp') do
-          # Nginx checks for PCRE in multiple places...
-          system("(gcc -I/usr/local/include -I/usr/include/pcre " <<
-            "-I/usr/pkg/include -I/opt/local/include " <<
-            "-c passenger-check.c) >/dev/null 2>/dev/null")
+      Dir.mktmpdir do |safe_tmpdir|
+        @pcre_is_installed = begin
+          File.open("#{safe_tmpdir}/passenger-check.c", 'w') do |f|
+            f.puts("#include <pcre.h>")
+          end
+          Dir.chdir("#{safe_tmpdir}") do
+            # Nginx checks for PCRE in multiple places...
+            system("(gcc -I/usr/local/include -I/usr/include/pcre " <<
+              "-I/usr/pkg/include -I/opt/local/include " <<
+              "-c passenger-check.c) >/dev/null 2>/dev/null")
+          end
+        ensure
+          File.unlink("#{safe_tmpdir}/passenger-check.c") rescue nil
+          File.unlink("#{safe_tmpdir}/passenger-check.o") rescue nil
         end
-      ensure
-        File.unlink('/tmp/passenger-check.c') rescue nil
-        File.unlink('/tmp/passenger-check.o') rescue nil
       end
     end
     return @pcre_is_installed

programming_language: Ruby