Thursday, January 26, 2017

Decrypt OpenSSL binary through NGINX as it is received ( on the fly )

Leave a Comment

I have a small embedded Linux device that has 128 MB flash storage available to work with as a scratchpad. This device runs an NGINX web server. In order to do a firmware update - the system receives an encrypted binary file as an HTTPS POST through NGINX to the scratchpad. The system then decrypts the file and flashes a different QSPI flash device in order to complete the update.

The firmware binary is encrypted outside the device like this:

openssl smime -encrypt -binary -aes-256-cbc -in plainfile.zip -out encrypted.zip.enc -outform DER yourSslCertificate.pem 

The firmware binary is decrypted, after being received through NGINX, on the device like this:

openssl smime -decrypt -binary -in encrypted.zip.enc -inform DER -out decrypted.zip -inkey private.key -passin pass:your_password 

I'd really like to decrypt the binary as it is received ( on the fly ) through NGINX, so that it appears on the flash scratchpad in it's decrypted form.

I've been unable to find any existing NGINX modules on Google that would do this. How might I accomplish this? Thanks.

2 Answers

Answers 1

First of all, you need to understand one thing. While nginx will decrypt file - all other request will be blocked. That's why nginx does not support CGI, only FastCGI.

If it ok for you (for example, nginx used only for update purposes), you can use perl or lua extension: http://nginx.org/en/docs/http/ngx_http_perl_module.html, https://github.com/openresty/lua-nginx-module

Using this modules you can exec shell. For access uploaded file need to set client_body_in_file_only directive - https://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_in_file_only

Example for perl module (untested):

location /upload {   client_body_in_file_only clean;   perl 'sub {     my $r = shift;     if ($r->request_body_file) {        system("openssl smime -decrypt -binary -in ".$r->request_body_file." -inform DER -out /tmp/decrypted.zip -inkey private.key -passin pass:your_password");     }   }'; } 

But much better to use fastcgi. You can use light fastcgi wraper for it, for example, fcgiwrap https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/

Answers 2

There's a widely-known attack against non-event-based servers like Apache known as Slowloris, where the client initiates a number of HTTP requests without sending them in full (where each request is instead being sent in part for a prolonged interval, which is a very cheap operation, both to send and receive, for an event-based architecture like that of nginx, but at the same time is very expensive for some other servers).

As a proxy server, nginx protects its backends from such an attack. Indeed, protection may come at a cost in certain circumstances, and can be turned off with the …_request_buffering directives:

What you would do is disable the request buffering, and then pipe the incoming file directly to openssl as it is received.

Note that you can always use /dev/fd/0 in place of the filename to specify stdin (depending on the tool, using - in place of the filename may also be an option).

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment