I'm trying to write a script that allows the upload of php files for parsing. Most of the tutorials and security information I can find on Google and here assume you're only allowing the upload of images (so use getimagesize, etc).
How do I confirm a file uploaded is really a PHP file without relying on the headers? Also -- I don't plan on storing the file in any way, I just want to grab the contents, parse it, and dump the info -- is there a very secure way to just grab the contents without actually saving the file to temp? If I do have to save it to temp, if I just grab the contents and then quickly delete it, am I still facing security threats and, if so, how do I dampen them?
What sort of sanitization do I need to do to PHP file contents to prevent misuse of the system? Basically, is there a way for a malicious user to 'inject' running code if I'm just parsing the contents as text?
If you just want to get the content of the file, use file_get_contents(), you get the contents of the file as a string.
http://us1.php.net/manual/en/function.file-get-contents.php
And then just use regular expression or w/e you use to parse with strings.
Related
I want to be able to upload a CSV file to a Webpage, and then have PHP store that information to a array and do stuff with it WITHOUT saving the CSV file to the server. How is that possible?
Looking into it, there's the normal GET and POST, which upload the file to the server. There's also PUT, but it looks like it just saves on top of an already existing file on the server.
And from the looks of the process to extract data from a CSV, PHP needs to know the location of the file.
Is it possible to just have the PHP work with the CSV file without saving it to the server somewhere? That way I don't have to worry about security issues with uploading files to a server. I don't need to hold onto the CSV data afterwords, just manipulate it in the current session.
When a file is uploaded to the server from a form, the file is stored temporarily ( $_FILES['someinputname']['tmp_name'] ) . No one says you have to do anything with this file before you can use it. You can read directly from the temporary path and forget about it. This, of course, does not leave you free from harm. Validating the file type is what you expect and not of malicious nature MUST be done before doing anything with a file you don't trust.
No lazy way around being safe.
CSV is just a text file. So you can read the file using javascript from client side and get the text from the file.
Javascript - read local text file
And then send the text to server and then work with it.
I wonder if I can create a php file with php code (my project is to write a php based online poker game) and it would be nice if I could add/delete tables from php, but in order to do that I need some code to generate the php file which will be associated with that specific table. (code on every table would be the same, just need something that will allow me to create a .php file for the life time of a table). Also can you tell me how to php-delete it after wards? Thanks ahead.
You can do this simply by having the code written to a file with
file_put_contents($filename, $content).
This will create a new file if it doesn't exist. If it exists it will truncate the file and write the new content.
To read dynamic code you could use eval($codeString). This would interpret the $codeStringas code. NOT RECCOMENDED because if there is ANY user input involved in the $codeString, it would be a huge security risk! (Read the WARNING below!)
To get the contents from a file, you could use $fileContents=file_get_contents($filename)
If you want to write to files with appending text and so on, you need to get deeper in to the php filesystem. A nice place to start is w3 schools: http://www.w3schools.com/php/php_ref_filesystem.asp
You should look at three major functions of writing to files:
fopen();
fwrite();
fclose();
Warning!
Reading dynamic generated code, whether it is from files or just strings, can be really dangerous. Especially if it gets any kind of user- or dynamic input. This is because php-files are capable of editing, creating and deleting ALOT on your server. I would recommend you to find an alternate solution!
You can use file_put_contents Or touch.
file_put_contents() will create the file if not exists and will write provided data in to the file.
touch() will create the file.
I've built a bulk user import engine for my web application and it's working perfectly. I'm now sitting here asking myself, is it secure? After all, the content of this file is being pumped into my database!
Not being the wisest security nerd around I need a little advice here.
Users are not able to rename the file after it's uploaded.
When the file is uploaded, its name is instantly changed.
Files must be .csv and have a csv relative mimetype for the upload to work.
The uploaded file is stored in a directory not accessible via the WWW and is deleted as soon as the import has completed, usually a few hundred milliseconds.
I'm opening the file and removing blank lines during the import
What about the actual content of the file? How can I sanitize the file to ensure it doesn't contain any executable code? I looked at the PHP manual and saw that as of PHP 4.3.5 getcsv() is binary safe, but being totally honest, I'm not 100% sure as to what that means.
I'm currently thinking about converting the CSV content into an array and creating a function that escapes the array content. Any other suggestions or is the above completely safe?
You can try using array_walk() to run mysql_escape_string() or your database's equivalent to be doubly sure everything is kosher.
function escape_sql(&$item, $key)
{
$item = mysql_escape_string($item);
}
array_walk($input_array, 'escape_sql');
If your array is multi-dimensional you can use array_walk_recursive(), which operates similarly.
An HTML form, a php file and a text file.
The form has one input box, it sends the inputted string to the PHP file using GET or POST. The PHP file writes the string to the text file using fopen 'a', fwrite and fclose and does no sanitization at all.
The text file is set to permission 777 and is in the same folder as the other files.
Are there any security concerns here? Is it possible for someone to send something using the form that will do any damage? If yes, what?
What about if the txt file is set to 666?
Never execute
Depending on what the use of this file, there shouldn't be much risk involved. Just make sure the file is never executed.
This means, never eval() the content of this file, or change it into a .php or any other executable file.
However, if the content is ever to be written on a page, or viewable by the user, you will have security risks doing this.
I typically use 3 ways to improve security writing to files. 1) Move file out of webroot and into some folder with restricted access like cgi-bin. The path to the file and any passwords should also be saved outside of the webroot. 2) Then you include the sensitive data by including it on your page. So if PHP parser fails people only see a variable name and no details. 3) If your are doing a post or get to the file which is doing the writing you can also check the values carefully and stip out characters, script, etc. that could cause problems.
From a web-security point of view, I do not see any problems, as long as the path of the text file is hardcoded or secured in any other way. You haven't said anything though about what happens if the file is missing or read-only (yes, it can happen, for example if the file system is mounted read-only by the administrator).
That being said, this use case is also completely useless, as the text file serves only as a data sink. A data sink that is never read from is useless. The problems may arise when you want to read from the file.
I am in the middle of making a script to upload files via php. What I would like to know, is how to display the files already uploaded, and when clicking on them open them for download. Should I store the names and path in a database, or just list the conents of a directory with php?
Check out handling file uploads in PHP. A few points:
Ideally you want to allow the user to upload multiple files at the same time. Just create extra file inputs dynamically with Javascript for this;
When you get an upload, make sure you check that it is an upload with is_uploaded_file;
Use move_uploaded_file() to copy the file to wherever you're going to store it;
Don't rely on what the client tells you the MIME type is;
Sending them back to the client can be done trivially with a PHP script but you need to know the right MIME type;
Try and verify that what you get is what you expect (eg if it is a PDF file use a library to verify that it is), particularly if you use the file for anything or send it to anyone else; and
I would recommend you store the file name of the file from the client's computer and display that to them regardless of what you store it as. The user is just more likely to recognise this than anything else.
Storing paths in the database might be okay, depending on your specific application, but consider storing the filenames in the database and construct your paths to those files in PHP in a single place. That way, if you end up moving all uploaded files later, there is only one place in your code you need to change path generation, and you can avoid doing a large amount of data transformation on your "path" field in the database.
For example, for the file 1234.txt, you might store it in:
/your_web_directory/uploaded_files/1/2/3/1234.txt
You can use a configuration file or if you prefer, a global somewhere to define the path where your uploads are stored (/your web directory/uploaded files/) and then split characters from the filename (in the database) to figure out which subdirectory the file actually resides in.
As for displaying your files, you can simply load your list of files from the database and use a path-generating function to get download paths for each one based on their filenames. If you want to paginate the list of files, try using something like START 0, LIMIT 50; in mySQL. Just pass in a new start number with each successive page of upload results.
maybe you should use files, in this sense:
myfile.txt
My Uploaded File||my_upload_dir/my_uploaded_file.pdf
Other Uploaded File||my_upload_dir/other_uploaded.html
and go through them like this:
<?php
$file = "myfile.txt";
$lines = file($file);
$files = array();
for($i=0;$i<=count($lines)-1;$i++) {
$parts = explode($lines[$i]);
$name = parts[0];
$filename = parts[1];
$files[$i][0] = $name;
$files[$i][1] = $filename;
}
print_r($files);
?>
hope this helps. :)
What I always did (past tense, I haven't written an upload script for ages) is, I'd link up an upload script (any upload script) to a simple database.
This offers some advantages;
You do not offer your users direct insight to your file system (what if there is a leak in your 'browse'-script and you expose your whole harddrive?
You can store extra information and meta-data in an easy and efficient way
You can actually query for files / meta-data instead of just looping through all the files
You can enable a 'safe-delete', where you delete the row, but keep the file (for example)
You can enable logging way more easily
Showing files in pages is easier
You can 'mask' files. Using a database enables you to store a 'masked' filename, and a 'real' filename.
Obviously, there are some disadvantages as well;
It is a little harder to migrate, since your file system and database have to be in sync
If an operation fails (on one of both ends) you have either a 'corrupt' database or file system
As mentioned before (but we can not mention enough, I'm afraid); _Keep your uploading safe!_
The MIME type / extension issue is one that is going on for ages.. I think most of the web is solid nowadays, but there used to be a time when developers would check either MIME type or extension, but never both (why bother?). This resulted in websites being very, very leaky.
If not written properly, upload scripts are big hole in your security. A great example of that is a website I 'hacked' a while back (on their request, of course). They supported the upload of images to a photoalbum, but they only checked on file extension. So I uploaded a GIF, with a directory scanner inside. This allowed me to scan through their whole system (since it wasn't a dedicated server; I could see a little more then that).
Hope I helped ;)