1

Just for a brief overview. I have a system that can generate invoices and has a login system for a user to generate his/her invoices. Lets say the platform resides at /platform and the invoices in /platform/invoices and the platform is at the domain www.exmaple.com. People can log in and generate their invoices which effectively generates the invoice in the invoices folder and then via the url www.example.com/invoices/invoicename.pdf downloads the file. The invoices folder is publically accessible to allow the system to grab the file.

However if for example clientA navigated to www.example.com/invoices/invoicename-ownedbyclientB.pdf he would be able to download an invoice that did not belong to him.

I can certainly do things to mitigate this such as deleting the invoice after generation and downloads to keep the folder clean, disallow index on directories to stop easy navigation, change the system so that files are sent via email as opposed to downloaded to a system directory.

On the system side I can easily limit what people have access to as they are authenticated but what would be the best way to deal with the above situation. I have considered using htaccess or similar in this directory to ensure that calls originate from the server itself (I haven't check if this is possible, just an assumption at the moment).

2 Answers2

1

Create sub folder's like /platform/invoices/useridclientA/. And store clientA's invoices in this particular sub folder.

Further disallow Navigation to this folder directly via server URL's like https://www.example.com/platform/invoices/*.

Create a server side script(e..g PHP) which will validate the userid of ClientA and read the only clientA files on filesystem and allow him to download.

You can optionally further randomize filenames while generating invoices.

Sravan
  • 1,158
  • 5
  • 14
1

You are exposing the file in the directory to the user for download so htaccess would not work since everything you could do is checking the referrer which could be easily spoofed.

The clean way without user authorization is having a lookup table for file names which could look like the following:

+----------------------------------+
| Field            | Type          |
+------------------+---------------+
| file_id          | char(64)      |
| file_name        | varchar(100)  |
| expiration_date  | timestamp     |
+------------------+---------------+

The file_id field is a randomly chosen string. This string is exposed to the user as download URL. Internally you can store the file in a place which is not accessible from the internet. Additionally you could disable access to the file after a period of time which is defined in expiration_date. If the time is expired you could simply delete the link from the table. This would make enumeration a lot harder.

If you want to re-offer the download after expiration, you could add an additional field like download_token and link the expiration time to this token. Then you could reissue the token and define a new expiration date.

There are a lot of improvements and variations on this but I hope you get the basic idea. If you really want to be sure, tie an authorization and a user_file lookup table to the download.

Noir
  • 2,523
  • 13
  • 23