Uploading large files can be a pain using PHP. Theres no single setting to increase the file size limit and the settings that do exist are spread between different configuration files. Furthermore the error codes for file upload failures are quite vague.

Uploading

After a little Googling the first thing you'll find is adjusting the php.ini configuration file. This will be enough to solve the problem in some cases. These are the values that need to be changed.

max_input_time = 600
upload_max_filesize = 10M
post_max_size = 10M
  • max_input_time is the time from when you start uploading a file to when PHP starts executing
  • upload_max_filesize is the maximum size allowed for each file in the request
  • post_max_size is the total size allowed for the request. It includes all files and anything else within the request body

If you don't have access to php.ini you can also make these changes in .htaccess. Setting these values within your php script using the ini_set function will not work because they would be set after the upload has happened.

Sometimes the default place PHP stores uploaded files in the systems temp directory. This can cause issues if the file you are uploading is larger than the partition that the temp directory is located on. You can change the upload_tmp_dir directive to remedy this. 

Are you using FastCGI? By default you can only upload 131Kb within the request body. You'll need to edit your Apache httpd.conf file to increase this limit. Look for the IfModule directive for fcgid_module and add the following between it. The value is specified in bytes.

FcgidMaxRequestLen 128000000

Processing

You may want to process the file once it's uploaded. To do this you need to make more changes to the php.ini file.

memory_limit = 256M
max_execution_time = 300

Should I be doing this?

There are better ways of handling large uploads and the chances are you shouldn't be doing this on a public facing website.

A good option is to split the file into chunks using the HTML 5 File API, upload each chunk separately via ajax. If the users connection drops out you will only have to resend a small chunk rather than start the whole upload again. Once all parts are uploaded have a queue worker join the chunks and do any necessary processing to the file.

Asda Gifts Data Leak

Asda is one of the big four supermarkets in the UK. As well as having an online grocery store they have a sister site called Asda Gifts that sells days out and personalised items. The vulnerability described in this post exposed full names, phone numbers (if they had been added by the customer) and addresses for all account holders.

Like most online stores Asda Gifts has a page that lets customers add or edit their addresses. Multiple addresses can be added per account with each one having a unique ID. The page to edit an address is loaded via ajax and displayed in a popup on the main account page. The popups content (open in a separate tab) is shown below.

The ajax request to generate the popup content contained the parameter DeliveryDetailId. I decided to make a second account and try and access the address stored on my first account by its ID. It worked; the popups content was displayed normally with my address filled out in the form fields. Taking it a step further I signed out and tried to access it again while not logged in. It still worked. It turned out there were absolutely no authorisation checks occurring.

After creating an address on the second account I noticed its ID was only a few digits different from the first one. They were being assigned consecutively. Creating a script to scrape all addresses by iterating through the IDs would have been trivial. Judging by the ID of my address (727675) there are a lot of entries in the system.

Fortunately the data leak was fixed quickly. After reporting to Asda via email they responded within a day. It was patched on May 6th. When trying to visit the page in question a message is now displayed letting the user know they are not authorised to view the information.

Timeline

  • Reported: 4th May
  • Acknowledged: 5th May
  • Fixed: 6th May