I'm playing with various ajax uploaders. When analyzing their server-side code, I see something like this:
#unlink($_FILES['file']['tmp_name'])
It is either muted one (like above), so does nothing (in my case) or unmuted one, so throws a warning, that access to temporary folder is prohibited (in my case) and breaks execution of a script.
What am I missing? I was always told, that we should not touch temporary files transmited via PHP form. Because this is unnecessary (and somethimes prohibited, like in my case). PHP will do all the cleaning, when script ends -- i.e. remove all uploaded temporary files.
What is the reason in code like above? Is it for the case, when script breaks, PHP is halted with some critical error and thus isn't able to remove temporary files? Or there is another reason?
Edit: It is quite pity, that I found this kind of mistake even in Plupload example code.
As per comments - there's nothing you've missed. Unlinking shouldn't be done by the user-code, such things might not be permitted and can fail due to various reasons.
Related
I would like to write a script to edit a css file or maybe even a slideshow for instance where a form will update the variables in my php document. I've been doing some reading and some say editing a php file directly is bad news due to security issues and to use xml.
I am not connecting to databases or anything like that. So my question is is this correct to write script to directly write/update a php file to changes its variables?
Thank you.
if you can correctly sanitize your input then it is a usable aproach. The worst that can happen is code injection. So do check for variable length and content very strictly. It is like eval(); only worse, as everyone else will run it to. If there are only variables to change you might consider using an .ini file for configuration. And Use the data in that from your PHP script
In general you should not run PHP scripts as a user with permissions to write to its own executable code; it means any file write vulnerability immediately escalates to a code execution vulnerability.
Writing dynamic data into a PHP file is risky. You would need to know how to serialise/escape any value to a PHP literal exactly; any error could result in code execution. Watertight code generation is in general a tricky thing.
There is almost certainly a better way to approach whatever it is you are doing. Putting data in a static store such as a config file or database, and reading the data at run-time, would seem to be the place to start.
I'm building a website which loads dynamically from a SQL database. To do that, I've created a PHP file that handles ALL AJAX and Post and Get requests (and every page has a couple of php include).
The PHP is not very long yet (250 lines), but it could get much longer eventually.
Everything is wrapped in <?php **** ?> tags, and is clearly and methodically composed of switch and case. So I only need a couple of lines each time.
My question is: Does every include request load/download all the file, or just the corresponding part? Rephrasing, will a hypothetically 10,000 line long script slow down the browser, or just the response time from the server?
I have concerns about all this.
Thanks in advance.
PS: This idea of unifying sql requests comes from a computer engineer friend that's always insisting on Multititer Architecture.
When you include a file, the entire files contents are inserted/executed into the script at that point. Depending on what is going on with the includes, you could be slowing down the response if you are including files that are not necessary for the response.
http://us3.php.net/manual/en/function.include.php
I have a great solution! (And this was my own question)
Instead o parsing a variable $option to enter a switch case case case .... case case endswitch I thought I could just split the PHP into a lot of different PHP's with the name of their corresponding case.
So, instead of using case('sports'), I will now use a <?php include('some_folder/'.$option.'.php');?> which will avoid converting to binary the whole file every time is called.
Since PHP is processed on the server, the included file will come all along and it will just have to deal with 20 lines of code instead of 400 (and, eventually, many more).
Definitively, thanks
I have lots of files that may or not have php tags (<?php... ?>) inside it.
first off, i need to check if the php tags exist in those files. no problem here. i use fopen, save the content to a variable, and strpos to do this.
next, if it has php tags, i save that to a temporary file and then use ob_start() include, and ob_get_clean() to save the output to a variable for further processing.
is there an alternative to doing this method? perhaps a more simpler one, like not having to save that to a temporary file but instead process it from the variable?
another alternative i have in mind is use fopen and strpos to check if the tags is present in the file and then use ob_start(), include (the original file), and ob_get_clean() to save the output to a variable for further processing.
any comments?
i would appreciate any response and/or comments.
btw, in case you might ask, i am working on a backend that accepts input from users that may or may not include php tags.
You question doesn't really mention what you're actually doing, so I'm assuming you're doing the incredibly dangerous "parse out code in <?php ?> blocks so that it can be run". Short answer: don't do this.
Okay I guess that's not an answer, more of a statement. But here's why: even if your users are all trusted users and they're all in your personal circle of friends and they're all experts, you only need one slipup to screw up the entire system. An accidental unlink()? too bad, now you're all screwed. And no, "we don't have to worry about that, everyone's cool" is not a good retort. Someone, at some point, is going to screw up, and the longer that takes, the more you stand to lose =)
With that said, it depends what you want to do. If you want to run it all in place, then just save the input to a temp file, include() that file, and then unlink() it again. The entire thing will execute in scope, and it will have been treated as if it was a normal PHP file on your system.
warning THIS IS INCREDIBLY DANGEROUS, NEVER DO THIS ON A NON-SANDBOXED, PUBLIC SERVER, EVEN IF IT'S ON AN INTRANET. THIS APPROACH IS LITERALLY A FULL ANONYMOUS REMOTE ACCESS SOLUTION warning
If you want to strip out the code and non-code to deal with them separately, as if they have nothing to do with each other, a simple non-greedy preg_match_all to find the code blocks, then doing an str_replace to kill them off in the original submitted content will give you an array of code blocks, and an input string with those blocks removed. Job done (although I'm not sure why you wouldn't use separate submission processes for the content and code in that case, since they'll be independent of each other).
This is the simplest way of doing it I can think of:
<?php
function fileHasPHPTags($fileName) {
return strpos(file_get_contents($fileName),"<?php")!==false;
}
?>
Uber simple example to illustrate the point:
$message = $_POST['message'];
$fp = fopen("log.txt", "a");
fwrite($fp, $message);
fclose($fp);
Should I be sanitizing user input for the $_POST['message'] variable?
I understand prepared statements (for database sanitization) and htmlentities (if I were outputting the POST message back to the screen at some time) but in this case, the input is simply sitting in a log file that will be read by a small PHP script (via fopen())
Is the answer dependent on how it will be read? For example if I do open the log file via fopen() it should be htmlentities, and if I plan to download the log file and read it with Excel (for filtering purposes), there is nothing to be done?
Your code is basically innocent. The only "obvious" attack would be to repeatedly upload data to your server, eventually exhausting your disk space.
"sanitizing" is something that's situational. It's not something you can just sprinkle on code to make it better, like you can with salt on food. Perhaps you'll sanitize the $_POST data to prevent SQL injection attacks, but then use the data in an HTML context - now you're vulnerable to XSS attacks. Perhaps it's an image upload, and you do basic MIME-type determination to make sure it IS an image. That's all fine and dandy, but then someone uploads kiddy porn, which will pass the "is it an image" test, and now you've got a much bigger problem.
Since you're accepting user data and writing it out to a file, there is nothing that can be done with this code (except the disk space problem) to abuse your system. You cannot embed some data sequence into the data that'd cause PHP, or the underlying OS, to suddenly stop writing that data out to disk and start executing it. It doesn't matter WHAT kind if data is being uploaded, because it's never being used in a context where it could be used to affect the script's execution. You're simply sucking in some data from the webserver, and spitting it out to disk. You're not allowing the user to influence which file is written to (unless your users have shell-level access to the server and could, say, create a symlink called 'log.txt' pointing at some OTHER more critical file).
The real problem comes AFTERWARD... what do you do with this file after it's been written? If your later code does something silly like
include('log.txt');
then now you DO have a problem - you've now taken this "innocent" data sitting in a file on the disk and turned it into potentially executable code. All it takes is a simple <?php exec('rm -rf /') ?> anywhere in that file to trash your server.
As well, consider something like the inherently idiotic "security" measure that was PHP's magic_quotes. The PHP developers (WRONGLY and STUPIDLY) assumed that ANY data submitted from the outside world would only EVER be used in an SQL context, and did SQL escaping on ALL data, regardless of its ultimate purpose. And to make it worse, they simply assumed that all databases use backslashes for their escape sequence. That's all fine and dandy if you never use anything but MySQL, but what if you're on, say, SQL Server? Now you have to translate the PHP-provided Miles O\'Brien to Miles O''Brien, essentially having to UNDO what PHP did for you automatically.
TL;DR: Don't use shotgun 'sanitization' methods, they're almost always useless/pointless and just involve more work before AND after. Just use context-specific methods at the time you're using the data.
You should sanitize user input, but how is entirely dependent on what the input is for. "Sanitizing" refers to the idea of making sure input is safe or sane for a particular use. The term cannot be more specific until you settle on use cases.
You don't need to worry about the PHP reading/writing functions like fopen(). Be concerned with steps that actually parse or analyze the input. Some possible examples:
If a file will be displayed in a basic log reader, you might need to make sure that each input is limited to a certain length and doesn't contain line breaks or your chosen field delimiter, and the beginning of each line is a valid time stamp.
If a file will be displayed in a web browser, you might need to make sure inputs do not include scripts or links to other resources (like an IMG tag).
Excel files would have similar concerns regarding line length, time stamps, and delimiters. You don't have to worry about someone including executable code as long as Excel will be parsing the file as text. (Also, modern Excel versions give you warnings about included macros before running them.)
The general rule is to validate input and sanitize output.
If it is possible to validate your input in any way, then you should. If not, then you should sanitize it when output to make sure it is safe for the context it is used.
e.g. if you know that each message should be less than 100 characters regardless of how it is used, the script that reads the POST data could validate and reject any request whose POST data contains input that is 100 characters or over.
Validation is an "all or nothing" approach that rejects anything that doesn't follow certain rules regardless of output context, whereas sanitisation is the process of "making something safe" depending on the context. I think it's important to make that distinction.
In your case the sample code you provided does not output (except for the puposes of processing by another script). It is more of a storage operation than an output operation in that the message could be written to a database just as easily as the file system. The main attack surface that would need locking down in this case appears to be file permissions and making sure that nothing can read or write to the file other than the scripts you intend to do this and under the correct context. For example, I realise your example was simplified, but in that specific case you should make sure that the file is written to a location above your web root, or to a location that has folder permissions set appropriately. Otherwise, you may have inadvertantly given access for anyone on the web to read http://www.example.com/log.txt and if they can write to it too it may be possible to leverage some sort of XSS attack if they can trick a browser into reading the file as HTML. Old versions of Internet Explorer try and detect the MIME type rather than rely on the server header value of text/plain (see here also). These vulnerabilities may be slightly off topic though, and I just mention them to be thorough and as an example of making sure the files themselves are locked down appropriately.
Back to your question: In your case your validation should take place by the script that processes log.txt. This should validate the file. Note that it is validating the file here, not the raw message. The file should be validated using its own rules to make sure the data is as expected. If the script directly outputs anything, this is where the sanitisation should take place to match the context of the output. So to summarise the process of validation and sanitisation for your application would be:
Create log: Web browser ---POST---> get_message.php ---> validate that message is valid ---fwrite()--> log.txt
Process log: log.txt ---fopen()---> process.php ---> validate that file is valid ---> anything output? then sanitise at this stage.
The above assumes that the correct authorisation is made before processing takes place by the scripts (i.e. that the current user has permissions in your application to logmessages or process logs.)
I would sanitize it. When it comes to logs, just make sure you put it into reserved space - for instance, if the log is one record per line, strip the new lines and other stuff from user's input so he cannot fool you.
Take a look at Attack Named Log Injection
Also be very careful when it comes to displaying the log file. Make sure no output can harm your reader.
You append to a file in the current directory - this seems to be downloadable via browser, so you're creating a security hole. Place the file outside of the document root (best), or protect it via .htaccess.
You should sanitize all user input. Always. What this means depends on how you use this data. You seem to write to a text logfile, so you would want to let only printable and whitespace-class chars through. Sanitize defensively: do NOT specify bad charcodes and let everything else through, but define a list/classes of "good" chars and just let these good chars through.
Depending on your use case, you may want to flock() the log file, to prevent multiple parallel requests from mixing up in your file:
$logtext = sanitizeLog($_POST[Message']);
$fd = fopen( "/path/to/log.txt", "a");
if(flock($fd, LOCK_EX)) {
fseek($fd, 0, SEEK_END);
fwrite($fd, $logtext);
flock($fd, LOCK_UN);
}
fclose($fd);
I've omitted checks for fopen() results...
Regarding PHP's fwrite() function, there's no need to sanitize: fwrite() just writes that to a file that it gets passed along.
Regarding the log-file, you might wish to sanitize. Here is why:
Suppose an attacker post a multiple line value as message. If your log was before the post
line 1
line 2
then it is after the post
line 1
line 2
line 3
remainder of line 3
very remainder of line 3
because attacker posted this:
line 3\nremainder of line 3\nvery remainder of line 3
Note: One time posted vs. 3 lines added.
That said: How posted data needs to be sanitized, fully depends on your application.
Is there a way to append or remove a line of text from a file using PHP.
I am in the process of writing a hosting control panel for my specific web hosting stack and would like to be able to make changes to the files with minimal requirements to touch the file system, and as such would like not to have to rewrite the whole file to add or remove a configuration option.
There is no way to remove a line from a file without first parsing the file into lines and then writing it out again.
You can append to a file by using fopen with the $mode set to 'a'
$fp = fopen('myfile', 'a');
For appending, you should use fopen with the $mode of a.
See this please, on how to delete a line from the file.
Yes, you can open files in append mode:
$fh = fopen('testFile.txt', 'a');
If you now write to the file, the new content gets appended.
See fopen and from this documentation:
'a': Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
Removing the last line is not possible though.
Working with files in PHP is full of pitfalls, particularly wrt concurrency and locking. The fact that you are writing config files implies also that you are exposing tasks normally only available to a user with root privileges over the web. You did not mention these things in your post, but your question is trivial in comparison to addressing these issues.
Regarding your question - although its fairly trivial to implement what you propose (e.g. by exec'ing sed - although you did not did say what OS this is running on) I'd recommend creating a copy of the original file in some other representation - obvious candidates would be a database - where you can apply sequence numbers to the lines and easily create a gap to populate, or a PHP SplDoublyLinkedList stored in the session. Then once the user has effected as many changes as they require, regenerate the file in a single operation from the working representation.
Note that, ultimately, regardless of how you implement the solution the solution will rewrite the entire file - its just a question of how much of this process is exposed within your code.
Bear in mind, that what you are doing is just the same as most php web scripts - except while they manipulate and reqrite HTML, you're doing it with a different file type - so you might want to look at how other PHP templating systems are written, and consider whether you can create a template for your config files.
HTH
C.
If you need to change something in the middle of the file, you have to read it, parse it and save it back. Othwerwise you can only append something to the end of it.
You should not be concerned about the cost of this operation though, as it's a configuration file that won't likely be changed a hundred times every second, it should take negligible time.
If you want more flexibility in access/update/delete I think you should consider moving your configuration file to a database table.