Is it possible for an attacker to see all files inside of /uploads?

Hey guys,

for a small university/school project I need to store files that are sent by users inside of uploads.
The files are quite big so storing them in DB is not an option for me. They don’t include sensible data but it would be something like serious cheating if you would be able to see all uploaded files.

It is absolutely okay that - if - you know the exact fileName you can get access to it however I don’t want someone to see all files in /uploads without knowing the exact fileNames.

Is there a possibility for someone that wants to cheat to get access to all files inside of /uploads with something like path-traversal?

Thanks for your time!

1 Like

The built-in upload plugin adds a ‘hash’ to each file name, so it would be difficult to predict any other names, given you know one. You can also set up a reverse proxy in front of Strapi, to prevent fetching the uploads directory as a list. Or you can simply pop an ‘index.html’ file in it, which will then be served instead of listing the contents. Anyone with a link to one file would then find it ‘quite hard’ to read others … But a brute force attack would still work.

If you want to deny access to any file, except to an ‘authorised’ user (authorised, that is, to view only that file) then you possibly need a new middleware module that filters requests for uploaded files and perhaps requires an authorisation header for this particular category. Or you could handle uploads in a completely new plugin and control access within its API routes.

1 Like

I would argue that it’s never a good reason to store files within the database. File systems always win on performance and compatibility.

Thanks @stevewlrls!
And also Thanks @dallasclark!

So if I access /uploads locally without an additional reverse-proxy i will not receive a list of files.
{"data":null,"error":{"status":404,"name":"NotFoundError","message":"Not Found","details":{}}}

However your answer indicates to me that you can actually get - somehow? - a list of all files in /uploads without me adding an additional reverse-proxy?

I have been browsing the code for the upload plugin and its default storage provider. The upload plugin actually stores all the information about ‘files’ in the Strapi database. Each entry includes a ‘url’ field, the value for which is created by the storage provider. The local storage provider creates a URL of the form /uploads/{hash}_{name}.{ext} and the upload plugin has a middleware handler [see code] that intercepts requests for these URLs and serves static files, but it only matches file paths - not the folder they are in.

If you did want to list all the files, the upload plugin does provide an API route (/upload/files), but what you get is the database items, just like any other collection. You also need to provide an auth token. From an item, you can then use the ‘url’ field to fetch the associated file.

So is there a way to list all uploads by hitting /uploads endpoint? (I am not talking about going through all the collections/records to get each individual url associated with the file)

Currently in my default set up, its similar to what @lolafkok is saying, /uploads → returns a 404, which is what I want it to do, but is there a way an attacker can get around it (other then brute force try to guess the urls)

No, there is no Koa route that exposes the uploads folder. And the only middleware that handles local uploads checks explicitly that a specific file is being requested.

As indicated above, there are endpoints (GET /api/upload/files) that will give users the ability to find a list of uploaded files. The endpoints will only work if they’re enabled in Strapi’s Admin >> Settings >> Roles (/admin/settings/users-permissions/roles).

Otherwise, unless your web hosting/setup has directory listing enabled like Apache’s Directory Listings then the raw files will not be easily found. Brute force is possible, but with the hash at the start of the filenames, it will become an excessively long time before a single file is found let alone more.

This thread gave me an attack of paranoia, so I started researching this topic.
Now I’ll have more thoughts before going to sleep, nice :slightly_smiling_face: :upside_down_face: