Technos & Psyche

Add CSP Nonce Support in Nginx

July 11, 2020

Generating a nonce for your application does not involve recompiling nginx anymore, thanks to dynamic modules!

Compile Dynamic Modules

Get needed nginx modules

Check the current version of nginx you’re using, then download the sources here: https://nginx.org/en/download.html

Download the Nginx Development Kit and the set-misc-module.

Extract the archives so that your folder structure looks like this:

- nginx
  - nginx-1.17.10
  - ngx_devel_kit-0.3.1
  - set-misc-nginx-module-0.32

Configure Arguments

Grab the configure arguments of the nginx version currently installed on your server:

nginx -V

The output should look like this:

nginx version: nginx/1.17.10 (Ubuntu)
built with OpenSSL 1.1.1f  31 Mar 2020
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-Pmk9_C/nginx-1.17.10=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

Save the arguments somewhere and add the references to ngx_devel_kit and set-misc-nginx-module to it:

--add-dynamic-module=../ngx_devel_kit-0.3.1
--add-dynamic-module=../set-misc-nginx-module-0.32

Run ./configure with your arguments.

Compile the modules

It’s time to compile now!

cd nginx-1.17.10
make modules

If compilation was successful, check the objs folder for these files:

#+BEGIN_SRC ngx_http_set_misc_module.so ndk_http_module.so #+END_SRC bash

Load modules in Nginx

Upload the .so files to your server and put them in /usr/lib/nginx/modules.

Now edit your nginx.conf and load them before the http block:

load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_set_misc_module.so;

Generate and Replace Nonce

Open your virtual host file and put the following lines in the server block, replacing <NONCE_PLACEHOLDER> with a string of your choice:

Use a unique value for <NONCE_PLACEHOLDER> and keep it safe!

# Generate and Replace NONCE
set_secure_random_alphanum $cspNonce 32;
sub_filter_once off;
sub_filter_types *;
sub_filter <NONCE_PLACEHOLDER> $cspNonce;

Update CSP Header

Update your CSP Header to include your nonce:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$cspNonce'; object-src 'none'; style-src 'self' 'nonce-$cspNonce'; img-src 'self' data: blob:; media-src 'self'; frame-src 'none'; font-src 'self'; connect-src 'self'";

Add Nonce to your application

Add the following meta tag to the head of your html, replacing <NONCE_PLACEHOLDER> with your nonce-string:

<meta name="csp-nonce" content="<NONCE_PLACEHOLDER>">

The nonce-string will be replaced by nginx with a unique nonce everytime the page is loaded.

Sources

Tags: nonce nginx security csp