Upgrading nginx 1.10.3 on Debian 9 (stretch) to avoid CVE-2017-7529 vulnerability

Solution 1:

There are multiple ways to obtain nginx 1.13.3 and above. You can compile it yourself, use the stretch-backports repository, or you can add nginx's own apt repository. In this answer I will be walking you through the last one as it's probably the easiest to do out of all three.

nginx's website has a dedicated page on how to set up their repository, but there's more to it, especially if you want to avoid this specific vulnerability as of right now. The stable branch will install 1.12.0 which is still vulnerable (it was patched in 1.12.1+ and 1.13.3+), so you will need to use mainline, which will install 1.13.5.

In the best case scenario switching the nginx version should be as simple as running a few commands and you'll be done in 2-3 minutes with minimal downtime. To be able to get back up and running ASAP, let's start with preparing for the install. First, you need to add the repository to your apt configuration, add the signing key, and update the package list:

$ sudo echo "deb http://nginx.org/packages/mainline/debian/ stretch nginx
deb-src http://nginx.org/packages/mainline/debian/ stretch nginx" > /etc/apt/sources.list.d/nginx.list
$ wget -qO - https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
$ sudo apt update

Next, run the following command:

$ sudo apt remove nginx-common

This will effectively uninstall nginx from the system, but will preserve your configuration files, save for a systemd service file which is easy to restore.

Next install nginx from the new repository:

$ sudo apt install nginx

Be aware that this will ask you if you want to replace certain configuration files, like this:

Configuration file '/etc/nginx/nginx.conf'
 ==> Modified (by you or by a script) since installation.
 ==> Package distributor has shipped an updated version.
   What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
 The default action is to keep your current version.
*** nginx.conf (Y/I/N/O/D/Z) [default=N] ?

Make sure you don't enter Y, just press Enter or enter N each time you're prompted to avoid losing your current configuration.

If you accidentally overwrote your nginx.conf you'll - at the very least - need to change the last line in the file from include /etc/nginx/conf.d/*.conf; to include /etc/nginx/sites-enabled/*; to restore the previous inclusion behavior.

You can verify the newly installed version:

$ nginx -v
nginx version: nginx/1.13.5

Finally, you will notice that trying to run service nginx start now fails with the following message:

Failed to start nginx.service: Unit nginx.service is masked.

This is because removing nginx-common also wiped /lib/systemd/system/nginx.service which was previously used by systemd to manage nginx. To restore this file, simply create it using the command below:

$ echo "[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target
" > /lib/systemd/system/nginx.service

Finally, run systemctl unmask nginx followed by systemctl enable nginx, and now you should be able to manage the service just like before, with all your previous settings intact.

$ service nginx start