I learned a lot at Stackoverflow, it's my favorite programming website, and researching here I found the answers for many of my questions.
Now that I've finished the code I need to know: does it have any security flaw?
It needs to get the domain name from the url in order to see if a var file containing that expression exists on the directory and output it's content.
Your help is really appreciated!
Would be enough if I sanitize HTTP_HOST using htmlspecialchars and preg_replace? Using strip_tags would be overkill, no? Removing those special characters from the array is also redundant, don't you think?
Edit:
I'll alter the code and also add protection to the include files themselves. Many thanks!
No. You should be using a white-list of allowed expressions. For something as dangerous as include you definitely don't want to rely on black-list and simple sanitization.
You would also hardcode which directory contains your PHP files.
Supposing you keep all the *var.php files in a special directory (let's say /var/www/include/vars/) you could read them into an array, and confine the selection within the boundaries of that array, instead of just is_file()ing:
$vardir='/var/www/include/vars/';
$varfiles=array();
foreach(scandir($vardir) as $fn)
if(($fn!='.')&&($fn!='..'))
$varfiles[]="$vardir$fn";
/* Next, do whatever sanitizing you see fit */
if(array_find($fnvar)) include_once $fnvar;
Note that this, essentially, is a whitelist, mentioned in the comments: If you create a new {xyz}var.php in the $vardir directory, you are actually inserting a new entry in the whitelist.
So as #ack__ points out too, you can't avoid a whitelist one way or another...
Related
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;
}
?>
I wish to store certain pieces of code in database tables as templates but I am unsure as to whether they are going to create problems or not. I keep reading mixed messages from various different people in different posts and I am just not happy that I am clear on this subject.
I have already worked out that you cannot really echo/ print PHP into a webpage. Obviously you can echo strings of HTML but it becomes awkward when you try to do it with PHP code. The only way I have managed to do this is through eval which is apparently bad in most cases... so I am using another method to implement the templates (i.e. writing a php file to be used as an include file)
The main question I am asking is: is there really a problem with storing the PHP code strings (which include SQL statements) inside text type fields (mediumtext, longtext etc) in tables? Could those SQL statements ever do anything like execute actual actions or would they just remain as text strings?
Just to clarify, the reason I am storing strings of code is because they are templates to be used should the web administrator wish to allocate them to a specific area (div) of the pages.
Use SMARTY or Twig template engine. This will neatly solve your problem and you will not need to store anything in the database. It will also keep your PHP code completely separate from your HTML.
Another option is to use
I can see the need for code in the database for instance if you have multiple sites and want to do a source control between them, and not use any 3rd party software.. I would store in a database and then write the code on to a actual physical page, then run the php from that page...
Do not do this. If your database is ever compromised and someone injects malicious PHP, it may be executed. You should store the templates as files and call them when needed.
And you actually can echo/print PHP. You would do it using eval.
The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
I want to encode my codes with ionCube. But I do not know exactly how to prevent users from cracking it without encoding.
So I need some tips.
My project is a MVC.
Everything starts in index.php and it calls core.php and running goes.
How should I include files. How can I ensure that when a file is called it is the original one?
I know there is some PHP functions that print out function names, etc. I need to prevent this.
Users include index.php file from another file and try to get variables like using var_dump($_GLOBALS);
You can use the get_included_files function to see if there are other files included. But the best way is of course to trust your customers and regulate what they can and cannot do with your code through contracts.
We have a CMS editor where php is allowed to be used inside it, however we need to restrict access some commands such as file_get_contents, file(), and global.
Can someone help me with a boolean response regex for that? The text from the template is stored in a string.
I know, probably not an ideal method for this but it's all I can come up with for now :)
What you want to do is pretty much impossible. It is really hard to protect yourself against attacks if you allow people to execute code on your machine.
Here is the try I had on it: Sandbox. Source code.
What it does is basically maintain a large list of blacklisted functions for filesystem access, shell access, a.s.o (I allowed some functions for reading the filesystem like show_source that should not be allowed if you want to use it for something real.)
It also tries to protect from more hidden attacks like $func = 'unlink'; $func(__FILE__); by turning it into $func = 'unlink'; ${'___xyz'.!$___xyz=Sandbox::checkVarFunction($func)}(__FILE__) a.s.o.
PS: Still you probably don't want to allow people to run PHP code on your site. The risk is just by far too big. Instead I would allow people to use a templateing language inside the editor. A good candidate would be Twig, because it has a built in sandbox which allows you to restrict usage to certain tags, functions, ...
It's going to be very hard to protect yourself perfectly.
As I see it, you have a few options:
Search for predefined strings which is not allowed in your content (like file_get_contents) and display a error message saying that the user cannot save because of this. This will however lead to "hacks" where you'll end up searching for all possible characters, like () which can be valid in some cases.
Use token_get_all and try to parse the content as PHP. You can then loop through the whole source code, token by token, and see if you find a token you do not accept.
Write your own language or DSL for this. This language should only be capable of doing exactly what you want. Depending on your requirements, this can be the easiest and most maintainable way to go.
You can use preg_match for this. Use:
if(preg_match("#(file_get_contents|file)\(#i",$text))
What would be the safest way to include pages with $_GET without puttingt allowed pages in an array/use switch etc. I have many pages so no thank you.
$content = addslashes($_GET['content']);
if (file_exists(PAGE_PATH."$content.html")) {
include(PAGE_PATH."$content.html");
}
How safe is that?
Thanks.
This is very bad practice. You should setup a controller to handle dispatching to the code that needs to be executed or retrieved rather than trying to directly include it from a variable supplied by a user. You shouldn't trust user input when including files, ever. You have nothing to prevent them from including things you do not want included.
You'll sleep safer if you check the input for a valid pattern. e.g. suppose you know the included files never have a subdirectory and are always alphanumeric
if (preg_match('/^[a-z0-9]+$/', $_GET['page']))
{
$file=PAGE_PATH.$_GET['page'].".html";
if (file_exists($file))
{
readfile($file);
}
}
I've used readfile, as if the .html files are just static, there's no need to use include.
The possible flaw with your approach is that you can engineer a path to any HTML file in the system, and have it executed as PHP. If you could find some way to get an HTML file of your own devising on the filesystem, you can execute it through your script.
Match it against a regex that only accepts "a-zA-Z-".
edit: I don't think that blocking specific patterns is a good idea. I'd rather do, like I said, a regex that only accepts chars that we know that won't cause exploits.
Assuming the "allowed" set of pages all exist under PAGE_PATH, then I might suggest something like the following:
Trim page name
Reject page names which start with a slash (could be an attempt at an absolute path)
Reject page names which contain .. (could be an attempt at path traversal)
Explicitly prefix PAGE_PATH and include the (hopefully) safe path
If your page names all follow some consistent rules, e.g. alphanumeric characters, then you could in theory use a regular expression to validate, rejecting "bad" page names.
There's some more discussion of these issues on the PHP web site.
It looks generally safe as in you are checking that the page actually exists before displaying it. However, you may wish to create a blacklist of pages that people should not be able to view with the valid $_SESSION credentials. This can be done either with an array/switch or you can simply have all special pages in a certain directory, and check for that.
You could scan the directory containing all HTML templates first and cache all template names in an array, that you can validate the GET parameter against.
But even if you cache this array it still creates some kind of overhead.
Don't. You'll never anticipate all possible attacks and you'll get hacked.
If you want to keep your code free of arrays and such, use a database with two columns, ID and path. Request the page by numeric ID. Ignore all requests for ids that are not purely numeric and not in your range of valid IDs. If you're concerned about SEO you can add arbitrary page names after the numeric id in your links, just like Stack Overflow does.
The database need not be heavy-duty. You can use SQLite, for example.
The safest method involves cleaning up the request a bit.
Strip out any ../
Strip out ^\/
From there, make sure that you check to see if the file they're requesting exists, and can be read. Then, just include it.
You should use at least something like that to prevent XSS attacks.
$content = htmlentities($_GET['page'], ENT_QUOTES, 'UTF-8');
And addslashes won't protect you from SQL Injections.