PHP eval - evaluate code that contains variables - php

I'm building a module based CMS in which the admin can also create custom modules (along with predefined ones). Custom modules accept PHP code that will be evaluated when the module is displayed. Only the admin (single or plural) can edit this code, and only on the admin-page.* The script of the module is then stored in a database.
Let's say that, for example, a custom module is written in a way that it queries some information from the database - an older message to the management, if you will - into a variable, that is of course now user submitted data. Is it possible that this data will be somehow executed if it contains malicious php code? Or does eval handle variables the same way as it does with native PHP code?
I'm including an example, that the admin coded to list all user submitted messages.
PHP code to be eval()'d
$result = mysqli_query($con, "SELECT msg FROM messages;");
while ($message = mysqli_fetch_array($result))
{
echo $message['msg'];
}
If one of the $message['msg'] variables is "; echo "you are screwed"; rmdir('root'), will that be executed, or echoed?
*I know that the code can be edited by 'anyone' if the database is compromised, or if the code explicitly allows users to overwrite its contents, but it's strongly discouraged of course. I've left several warnings for these.

in this case you're just selecting and displaying the data... so the possibilities for attach is less...
$result = mysqli_query($con, "SELECT msg FROM messages;");
while ($message = mysqli_fetch_array($result))
{
echo $message['msg'];
}
say if it is like...
$result = mysqli_query($con, "SELECT msg FROM messages where some=".$get/post-some.";");
while ($message = mysqli_fetch_array($result))
{
echo $message['msg'];
}
theres possible attack of sql injection in $getsomelike appending 'or 1=1' at end or other types...
so you need to use PDO or mysql_real_escape_string while passing values... or just prepared statements...

Related

Passing function result into sqli

I'm new to this and I know I'm probably doing this entire thing the wrong way, but I've been at it all day trying to figure it out. I'm realizing there's a big difference between programming a real project of my own rather than just practicing small syntax-code online. So, I lack the experience on how to merge/pass different variables/scopes together. Understanding how to fit everything within the bigger picture is a completely different story for me. Thanks in advance.
What I'm trying to do, is to make the function "selectyacht" output data in a different location from where it's being called (in viewship.php). The output data (in viewship.php) needs to be only certain fields (not everything) returned and those results will be scattered all over the html page (not in a table). In addition to that, I have this variable: "$sqlstatement" (in sqlconn.php) that I'm trying to bring outside the function because I don't want to repeat the connection function every time. I tried a global variable, as much as I shouldn't, and it thankfully it gave me an error, which means I have to find a better way.
Basically my struggle is in understanding how I should structure this entire thing based on two factors:
To allow the second conditional statement in sqlconn.php to be typed
as least often as possible for different "selectyacht" functions
that will come in the future.
To allow the connection instance in sqlconn.php to reside outside the function since it will be used many times for different functions.
Returning data in a different place from where it's being called in viewship.php because the call will be a button press, not the results to be shown.
This is probably very simple, but yet it eludes me.
P.S. Some of this code is a copy/paste from other resources on the internet that I'm trying to merge with my own needs.
sqlconn.php
<?php
$servername = "XXXXXXXX";
$username = "XXXXXXXX";
$password = "XXXXXXXX";
$dbname = "XXXXXXXX";
// Instantiate the connection object
$dbconn = new mysqli($servername, $username, $password, $dbname);
// Check if the connection works or show an error
if ($dbconn->connect_error) {
die("Connection failed: " . $dbconn->connect_error);
}
// Create a query based on the ship's name
function selectyacht($shipname) {
global $sqlstatement;
$sqlstatement = "SELECT * FROM ships WHERE Name=" . "'" . $shipname . "'";
}
// Put the sql statement inside the connection.
// Additional sql statements will be added in the future somehow from other functions
$query = $dbconn->query($sqlstatement);
// Return the data from the ship to be repeated as less as possible for each future function
if ($query->field_count > 0) {
while($data = $query->fetch_assoc()) {
return $data;
}
}
else {
echo "No data found";
}
// Close the connection
$dbconn->close();
?>
viewship.php
<html>
<body>
<?php include 'sqlconn.php';?>
<!-- ship being selected from different buttons -->
<?php selectyacht("Pelorus");?>
<br>
<!-- This is the output result -->
<?php echo $data["Designer"];?>
<?php echo $data["Length"];?>
<?php echo $data["Beam"];?>
<?php echo $data["Height"];?>
</body>
</html>
Mate, I am not sure if I can cover whole PHP coding standards in one answer but I will try to at least direct you.
First of all you need to learn about classes and object oriented programming. The subject itself could be a book but what you should research is autoloading which basically allows you to put your functions code in different files and let server to include these files when you call function used in one of these files. This way you will be able to split code responsible for database connection and for performing data operations (fetching/updating/deleting).
Second, drop mysqli and move to PDO (or even better to DBAL when you discover what Composer is). I know that Internet is full of examples based on mysqli but this method is just on it's way out and it is not coming back.
Next, use prepared statements - it's a security thing (read about SQL injection). Never, ever put external variables into query like this:
"SELECT * FROM ships WHERE Name=" . "'" . $shipname . "'";
Anyone with mean intentions is able to put there string which will modify your query to do whatever he wants eg. erase your database completely. Using prepared statements in PDO your query would look like this:
$stmt = $this->pdo->prepare("SELECT * FROM ships WHERE Name = :ship_name");
$stmt->bindValue(':ship_name', $shipname);
Now to your structure - you should have DB class responsible only for database connection and Ships class where you would have your functions responsible eg. for fetching data. Than you would pass (inject) database connection as an argument to class containing you selectYacht function.
Look here for details how implementation looks like: Singleton alternative for PHP PDO
For
'Returning data in a different place from where it's being called'
If I understand you correctly you would like to have some field to input ship name and button to show its details after clicking into it. You have 2 options here:
standard form - you just create standard html form and submit it with button click redirecting it to itself (or other page). In file where you would like to show results you just use function selectYacht getting ship name from POST and passing it to function selectYacht and then just printing it's results (field by field in places you need them)
AJAX form - if you prefer doing it without reloading original page - sending field value representing ship name via AJAX to other page where you use selectYacht function and update page with Java Script

Using eval(); to execute php direct from the database

I am atm making a website where I'm storing all of my HTML based pages in a mysqli database, and I came to this problem where I couldn't execute my PHP code by using echo. So I found this solution where I had to use eval(); in order for my PHP code to run, I heard it could be really dangerous if you do not validate it correctly.
$firstname = htmlspecialchars($mysqli->real_escape_string($row['firstname']));
So far this is how I have been validating it, would this be secure enough?
Note: that line of code is used when I request the information from the database, to be display on the page.
I'm sorry if I haven't explained myself well enough, I'm still new to this. :)
This is how i get my pages from the database.
<?php
if (isset($_GET["page"]) && $_GET["page"] != null) {
$query = "SELECT * FROM pages WHERE pagename = '$_GET[page]'";
$result = $mysqli->query($query);
while ($row = $result->fetch_array(MYSQLI_ASSOC)){
$pagetitle = $row["pagetitle"];
$pagename = $row["pagename"];
$pagecontent = $row["pagecontent"];
}
} else {
$query = "SELECT * FROM pages WHERE pagename = 'index.php'";
$result = $mysqli->query($query);
while ($row = $result->fetch_array(MYSQLI_ASSOC)){
$pagetitle = $row["pagetitle"];
$pagename = $row["pagename"];
$pagecontent = $row["pagecontent"];
}
}
?>
real_escape_string simply removes any characters that might be used for SQL injection. If you execute user input as PHP code you give your users the same possibilities you have in your php scripts. Including running system commands to remove all files from your server for example.
You don't want to be doing this. That particular case you are mentioning, can you elaborate on that? There is probably a better solution to your problem.
I'd just like to say that you're doing two things here that are generally considered bad practices.
Storing code that will be executed in a database. (Always store code in text files, that way they're version controlled and also less vulnerable to sql attacks).
Using eval().
Both are these are bad ideas and will almost certainly bite you in the ass at some point.
What is it that you're trying to do?

Which protocol will be less "expensive"?

I am adding some server-side form validations (using php) in case one of the users of my site has javascript turned off. On one form, there are 10 separate input fields that can be changed. Could someone please tell me which protocol will use less system resources? In the first, I write some mySQL variables to check the user's current settings, and compare these with the posted settings. If all 10 posted values are identical to the current values, don't UPDATE database, else UPDATE the database:
$login_id = $_SESSION['login_id'];
$sql1 = mysql_fetch_assoc(mysql_query("SELECT value1 FROM login WHERE login_id =
'$login_id'"));
$sql1a = $sql1['value1'];
// Eight More, then
$sql10 = mysql_fetch_assoc(mysql_query("SELECT value10 FROM login WHERE login_id =
'$login_id'"));
$sql10a = $sql10['value10'];
$Value1 = $_POST['Value1'];
// Eight More, then
$Value10 = $_POST['Value10'];
//Other validations then the following
if (($sql1a == $Value1)&&($sql2a == $Value2)&&.......($sql10a == $Value10)) {
echo "<script>
alert ('You haven't made any changes to your profile');
location = 'currentpage.php';
</script>";
}
else {
$sqlUpdate = mysql_query("UPDATE login SET value1 = '$Value1',....value10 = '$Value10'
WHERE login_id = '$login_id'");
echo "<script>
alert ('Your profile has been updated!');
location = 'currentpage.php';
</script>";
}//End php
OR is it less expensive to just use the user-posted values (keep the $_POST variables) and avoid checking with the comparison line: (($sql1a == $Value1)&&($sql2a == $Value2)&&.......($sql10a == $Value10)) and just go right to
//Other validations then the following
$sqlUpdate = mysql_query("UPDATE login SET value1 = '$Value1',....value10 = '$Value10'
WHERE login_id = '$login_id'");
echo "<script>
alert ('Your profile has been updated!');
location = 'currentpage.php';
</script>";
Thanks for any input on this!
If I understand correctly, your question is whether it's OK for performance to check the profile for modifications. For me, after I've checked your code, this is about much more than just performance...
Let's start with the performance: AFAIK MySQL queries are slower than basic PHP comparisions, that's true - but on this scale, I really don't think it matters much. We're talking about two very basic queries which won't handle a lot of data.
Let's think about what the end user will see (UX): in the second scenario, the user will not have the most exact feedback telling him/her that no modification has been done. On a profile modification screen, I suppose that might not be intentional, so I would tell that we haven't modified anything. (Also, performing an unnecessary UPDATE query is not the most elegant.)
#aehiilrs is right, please pay attention to that comment. This style of MySQL usage is particularly bad for security - if you keep going with this, you will create a lot of security holes in your PHP code. And those are really easy to discover and exploit, so please, have a good look on the alternatives, starting with PDO as mentioned. Any good PHP book out there will show you the way. You can also have a look at a great Q/A here on StackOverflow: How can I prevent SQL injection in PHP?
I wonder whether it's a good idea to try to update the user interface like you did - I would strongly prefer loading another PHP without any <script> magic in the output. In the result PHP, you can always display something like a CSS-styled statusbar for displaying info like that.

preventing xss in jquery, php, mysql in some examples - please advice

For a while I am more and more confused because of possible XSS attack vulnerabilities on my new page. I've been reading a lot, here on SO and other googled sites. I'd like to secure my page as best as it is possible (yes, i know i cant be secure 100%:).
I also know how xss works, but would like to ask you for pointing out some vulnerable places in my code that might be there.
I use jquery, javascript, mysql, php and html all together. Please let me know how secure it is, when i use such coding. Here's idea.
html:
<input name="test" id="id1" value="abc">
<div id="button"></div>
<div id="dest"></div>
jQuery:
1. $('#id').click (function() {
2. var test='def'
3. var test2=$('#id1').val();
4. $.variable = 1;
5. $.ajax({
6. type: "POST",
7. url: "get_data.php",
8. data: { 'function': 'first', 'name': $('#id').val() },
9. success: function(html){
10. $('#dest').html(html);
11. $('#id1').val = test2;
12. }
13. })
14. })
I guess it's quite easy. I have two divs - one is button, second one is destination for text outputted by "get_data.php". So after clicking my button value of input with id 'id1' goes to get_data.php as POST data and depending on value of this value mysql returns some data. This data is sent as html to 'destination' div.
get_data.php should look like this:
[connecting to database]
switch($_POST['function']) {
case 'first':
3. $sql_query = "SELECT data from table_data WHERE name = '$_POST[name]'";
break;
default:
$sql_query = "SELECT data from table_data WHERE name = 'zzz'";
}
$sql_query = mysql_query($sql_query) or die(mysql_error());
$row = mysql_fetch_array($sql_query);
echo $row['data']
For now consider that data from mysql is free from any injections (i mean mysql_real_escaped).
Ok, here are the questions:
JQuery part:
Line 2: Can anybody change the value set like this ie. injection?
Line 3 and 11: It's clear that putting same value to as was typed before submiting is extremely XSS threat. How to make it secure without losing functionality (no html tags are intended to be copied to input)
Line 4: Can anybody change this value by injection (or any other way?)
Line 8: Can anybody change value of 'function' variable sent via POST? If so, how to prevent it?
Line 10: if POST data is escaped before putting it into database can return value (i mean echoed result of sql query) in some way changed between generating it via php script and using it in jquery?
PHP part:
Please look at third line. Is writing: '$_POST[name]' secure? I met advice to make something like this:
$sql_query = "SELECT data from table_data WHERE name = " . $_POST['name'];
instead of:
$sql_query = "SELECT data from table_data WHERE name = '$_POST[name]'";
Does it differ in some way, especially in case of security?
Next question to the same line: if i want to mysql_real_escape() $_POST['name'] what would be the best solution (consider large array of POST data, not only one element like in this example):
- to mysql_real_escape() each POST data in each query like this:
$sql_query = "SELECT data from table_data WHERE name = " . mysql_real_escape($_POST['name']);
to escape whole query before executing it
$sql_query = "SELECT data from table_data WHERE name = " . $_POST['name'];
$sql_query = mysql_real_escape($sql_query);
to write function that iterates all POST data and escapes it:
function my_function() {
foreach ( $_POST as $i => $post ) {
$_POST[$i] = mysql_real_escape($post)
}
}
What - in your opinion is best and most secure idea?
This post became quite large but xss really takes my sleep away :) Hope to get help here dudes once again :) Everything i wrote here was written, not copied so it might have some small errors, lost commas and so on so dont worry about this.
EDIT
All right so.. if I understand correctly filtering data is not necessery at level of javascript or at client side at all. Everything should be done via php.
So i have some data that goes to ajax and further to php and as a result i get some another kind of data which is outputted to the screen. I am filtering data in php, but not all data goes to mysql - part od this may be in some way changed and echoed to the screen and returned as 'html' return value of successfully called ajax. I also have to mention that I do not feel comfortable in OOP and prefering structural way. I could use PDO but still (correct me if i am wrong) i have to add filtering manually to each POST data. Ofcourse i get some speed advantages. But escaping data using mysql_real_escape looks to me for now "manual in the same level". Correct me if i am wrong. Maybe mysql_realescape is not as secure as PDO is - if so that's the reason to use it.
Also i have to mention that data that doesnt go to database has to be stripped for all malicious texts. Please advice what kind of function I should use because i find a lot of posts about this. they say "use htmlentities()" or "use htmlspecialchars()" and so on.
Consider that situation:
Ajax is called with POST attribute and calls file.php. It sends to file.php POST data i.e. $_POST['data'] = 'malicious alert()'. First thing in file.php I should do is to strip all threat parts from $_POST['data']. What do you suggest and how do you suggest I should do it. Please write an example.
XSS is Cross-site scripting. You talk about SQL injection. I will refer to the latter.
JQuery Part
It's possible to change every single JavaScript command. You can try it yourself, just install Firebug, change the source code or inject some new JavaScript code into the loaded page and do the POST request. Or, use tools like RestClient to directly send any POST request you like.
Key insight: You cannot control the client-side. You have to expect the worst and do all the validation and security stuff server-side.
PHP Part
It is always a good idea to double-check each user input. Two steps are usually mandatory:
Validate user input: This is basically checking if user input is syntactically correct (for example a regex that checks if a user submitted text is a valid email address)
Escape database queries: Always escape dynamic data when feeding it to a database query. Regardless where it's coming from. But do not escape the whole query string, that could yield in unexpected results.
Maybe (and hopefully) you will like the idea of using an ORM solution. For PHP there are Propel and Doctrine for instance. Amongst a lot of other handy things, they provide solid solutions to prevent SQL injection.
Example in Propel:
$result = TableDataQuery::create()
->addSelectColumn(TableDataPeer::DATA)
->findByName($_POST['name']);
Example in Doctrine:
$qb = $em->createQueryBuilder();
$qb->add('select', 'data')
->add('from', 'TableData')
->add('where', 'name = :name')
->setParameter('name', $_POST['name']);
$result = $qb->getResult();
As you can see, there is no need for escaping the user input manually, the ORM does that for you (this is refered as parameterized queries).
Update
You asked if PDO is also an ORM. I'd say PDO is a database abstraction layer, whereas an ORM provides more functionality. But PDO is good start anyway.
can firebug any malicious code in opened in browser page and send
trash to php script that is somwhere on the server?
Yes, absolutely!
The only reason you do validation of user input in JavaScript is a more responsive user interface and better look & feel of your web applications. You do not do it for security reasons, that's the server's job.
There is a firefox addon to test your site for XSS, it called XSS Me
Also you can go to
http://ha.ckers.org/xss.html
for most XSS attacks
and go to
http://ha.ckers.org/sqlinjection/
for most sql injection attacks
and try these on your site

PHP form submission

I've built mini content management system. In my page add form i'm using ckeditor. for text are named content
<textarea id="content" style="width:100%" name="content"></textarea>
Adding all data from form into db table with following php code. (Function filter used for sanitizing data)
<?php
require '../../core/includes/common.php';
$name=filter($_POST['name'], $db);
$title=filter($_POST['title'], $db);
$parentcheck=filter($_POST['parentcheck'],$db);
if(isset ($_POST['parent'])) $parent=filter($_POST['parent'],$db);
else $parent=$parentcheck;
$menu=filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);
if(isset($_POST['submit'])&&$_POST['submit']=='ok'){
$result=$db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')") or die($db->error);
$new_id = $db->insert_id;
$result2=$db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')") or die($db->error);
header("location:".$wsurl."admin/?page=add");
}
?>
FUNCTION FILTER (data sanitization)
function filter($data, $db)
{
$data = trim(htmlentities(strip_tags($data)));
if (get_magic_quotes_gpc())
$data = stripslashes($data);
$data = $db->escape_string($data);
return $data;
}
I got questions about it. (I'm newbie to ajax.)
Currently i'm submitting data with standart php (page refreshes
every time). How to modify code for ajax submission?
I have only one button for submitting data. I want to create second
button "save" which will update db fields via ajax
How can i create autosave function (which periodically saves form in the background and informss user about it, just like on Stackoverflow) via ajax?
Thx in advance
Let's suppose you want to use jQuery to do the ajax business for you, you need to setup a periodic POST of the data in the textarea (note that in some browsers GET requests have a limit).
On the first POST, you need to tell the PHP script "this is the first POST" so that it knows to INSERT the data, it should then return to you some identifying characteristic. Every other time you POST data, you should also send this identifying characteristic, let's just use the primary key (PK). When you POST data + PK, the PHP script should run an update query on the SQL.
When constructing these, the thing to think about is sending data from the browser using JavaScript to a PHP script. The PHP script gets only whatever packet of data you send, and it can return values by producing, for instance, JSON. Your JavaScript code can then use those return values to decide what to do next. Many beginners often make the mistake of thinking the PHP can make calls to the JS, but in reality it's the other way around, always start, here, with the JS.
In this instance, the PHP is going to save data in the database for you, so you need to ship all the data you need to save to the PHP. In JS, this is like having some magic function you call "saveMyData", in PHP, it's just like processing a form submission.
The JavaScript side of this looks something like this (untested):
<script type="text/javascript">
var postUpdate = function(postKey){
postKey = postKey || -1;
$.post("/myscript.php",
/* note that you need to send some other form stuff
here that I've omitted for brevity */
{ data: $("#content").value(), key: postKey },
function(reply){
if(reply.key){
// if we got a response containing the primary key
// then we can schedule the next update in 1s
setTimeout(function(){postUpdate(reply.key);}, "1000");
}
}
});
};
// first invocation:
postUpdate();
</script>
The PHP side will look something like this (untested):
Aside: your implementation of filter should use mysql_real_escape_string() instead of striptags, mysql_real_escape_string will provide precisely the escaping you need.
<?php
require '../../core/includes/common.php';
$name = filter($_POST['name'], $db);
$title = filter($_POST['title'], $db);
$parentcheck = filter($_POST['parentcheck'],$db);
if(isset($_POST['parent'])){
$parent = filter($_POST['parent'],$db);
}else{
$parent = $parentcheck;
}
$menu = filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);
$pk = intval($_POST['key']);
if($pk == -1 || (isset($_POST['submit']) && $_POST['submit']=='ok')){
$result = $db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')")
or die($db->error);
$new_id = $db->insert_id;
$result2 = $db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')")
or die($db->error);
$pk = $db->insert_id;
echo "{\"key\": ${pk}}";
// header("location:".$wsurl."admin/?page=add");
}else if($pk > 0){
$result2 = $db->query("UPDATE pages SET content='$content' WHERE id='$pk')")
or die($db->error);
echo "{\"key\": ${pk}}";
}
For AJAX, you can use jQuery's ajax API. It is very good and is cross-browser.
And for saving and auto-saving: you can use a temporary table to store your data. When the user presses the save button or when your data is auto-saved, you save your data to the table using AJAX and return a key for the newly created row. Upon future auto-save/save button events, you update the temporary table using AJAX.
And one word of advice, use a framework for your PHP and Javascript. I personally use Symfony and Backbone.js. Symfony checks for CSRF and XSS automatically and using Doctrine prevents SQL-injection too. There are other frameworks available (such as CodeIgniter, CakePHP and etc.) but I think Symfony is the best.
Edit: For the auto-save functionality, you can use Javascript SetTimeout to call your AJAX save function, when the page loads for the first time.
With regard to security issues:
Your silver bullet function is fundamentally flawed, it does not work, will never work and can never work.
SQL has different escaping needs than hmtl.
The functions you use counteract each other. escape_string adds \, stripslashes removes them.
Never mind the order of the functions, you need to use a specialized escape function for one and only one purpose.
On top of that you are using depreciated functions.
For MySQL this is mysql_real_escape_string. Note that escape_string (without the real) is depreciated, because it is not thorough enough. Use real_escape_string instead. On mysqli escape_string is an alias for real_escape_string.
See:
How does the SQL injection from the "Bobby Tables" XKCD comic work?
The ultimate clean/secure function

Categories