Securing Private Piwigo Albums

TL;DR if you just wanna see the code and simple install instructions see the Github repo

Update – The original code had a major rewrite to be used as a plugin that will not require any NGINX/Apache special features. Yet it can use advance features like X-Accel-Redirect/X-send-files if available.
Though the ideas and methods described in this article should work and are still good to understand the concept, a new and better implementation is available. Information about the new implementation is available in the Github repo.

As many other people I was looking for a solution to control and share my private photos with family and friends. Google, Facebook and other 3rd parties will allow you to share your content easily with your friends. But do you really know who has access to your private data ? who controls it ? and who owns it ?

Once you upload your images to a 3rd party providers you trust them to keep it private and secure, you could argue that this companies are doing a good and probably better job than many others, but even if we assume their system is 100% secure do you really want to share all your data with all your facebook friends ? do all the people you want to give access to your content have a Google account ?

So for me the obvious choice was to host my own image gallery.
I thought I might need to write something from scratch, but luckily Piwigo covers 99% of my use case so for now it seems like a good solution.

But one of the issues I had with Piwigo is that even for private content all the static files are available to be accessed directly with no user authentication Piwigo protects the file by “randomizing” part of the file name which is probably secure for most use cases but will not protect your content in any way if someone decides to pass the links forward (and I would prefer it to be 20 chars of real random data and not 8 chars of the file md5 hash).

When looking at security we should always consider our adversary. In this case we are considering very limited and week one. If you have data you want to keep private, don’t upload it to the Internet, better yet don’t keep it on a computer that is connected to the Internet or even better keep it only in a usb stick which is kept in a locked safe (and some prefer to keep it in a shoe box next to the safe). What I’m trying to say is that since we are any way want this data to be available to multiple parties online it is going to be very hard to keep it private from any one who will really want access to it. so the only thing I’m actually trying to prevent is my private images ending up on Google image search (I wish I had the time to write end to end encrypted fie sharing solution simple enough for my grandma to use but I currently don’t).

This issue is a known problem with Piwigo that others have tried to solve this issue but I couldn’t find a full solution that will work with videos and. Since Piwigo does all the hard work of access management I was sure there was an easy way to do it.

NGINX to the rescue

So apparently NGINX has this great little feature to called auth_request that guess what authorizes a request, using this directive NGINX will first proxy the request to another url and if that url returns successfully the request will be served if not it will be rejected. notice that NGINX doesn’t serve back the proxy result but actually continues to serve the original location, which means that we can still take advantage of NGINX when serving our static content (like cache, gzip and so on)

unfortunately we need to compile NGINX with the ‘–with-http_auth_request_module’ flag to have auth_request so you’ll need to download NGINX source and compile it yourself to get it working.
I used the following configuration for my server –

But you might need to install some extra libs depending on what you already have installed on your system

once the configuration pass you can build and install

now once we have NGINX with auth_request working we can go to the fun stuff.
Here is how to use auth_request to validate any request that goes to Piwigo uploads and derivatives location –

Pretty straight forward.
As you can see we are using the /auth.php file to validate the request.

now every request being made to /upload will only goes throe if auth.php returns a successful response. so what we need now is to have a script named auth.php in our server root that will know if the user can actually access the file.

I wont go into all the details of writing this script,but it wasn’t too complex. What I basically did is reversing the logic in Piwigo action.php detecting the image db record from the requested url and then testing to see if the user is allowed to access the file.This script will return 401 errors instead of 404 since we don’t want someone to try guessing which files we might have on the server. I’m not very fluent with Piwigo internals so I hope I haven’t missed any edge cases.

As a bonus we can take our NGINX site config a step farther and actually redirect the user to a default image if she doesn’t have access to the image she is asking.

If you haven’t you might want to take some more steps to harden your Piwigo system (like ssl and fail2ban and preventing direct access to php files in subfolders)

3 thoughts on “Securing Private Piwigo Albums

  1. ternyk says:

    I’m looking for the solution presented but working on Apache. Any ideas how to do it?

  2. n0 says:

    If you had the same capabilities of auth_request in apache you could use this
    plugin with apache. Unfortunately I don’t think apache has those capabilities.

    In theory you can use the same logic of the php script to actually serve the static file then use mod_rewrite in apache to redirect all static requests to the php file, but this might introduce some other security concern to your code and you need to make sure your not serving any sensitive files

  3. n0 says:

    If you have difficulties using this script, you can open an issue on github –
    I can’t promise I’ll fix it but you’ll probably want to give some info about your
    situation to be taken seriously

Comments are closed.