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?
Related
still getting my feet wet with php and mysqli, have so much to learn, but at this point this question is one of my most important priorities.
I did some research about this issue but am currently overwhelmed by pretty sophisticated stuff for my level, to be honest. I'd like to find the simplest most efficient way to "automatically" generate a great number of pages each with varying data in it.
the example of page 1's code below is extremely simplified, because the actual page actually has a lot more stuff, but the simplified example serves, I hope, to make my point.
<?php
$servername = "servername";
$username = "username";
$password = "password";
$db= "db";
$conn = mysqli_connect("servername","username","password","db");
$query = "SELECT word FROM demo WHERE group=1";
$result = $conn->query($query);
$row = mysqli_fetch_assoc($result);
$word = $row['word'];
echo $word;
?>
in my table I have / would have something like 500 entries (records?) in the 'group' column, numbered 1, 2, 3 etc all the way to 500.
for my specific purpose, I absolutely need to create as many online pages as there are groups -- in this example, 500 pages.
page 2's echo would have to refer to group 2, page 3's echo would have to refer to group 3, and so on.
obviously, there's a way to do this without copying and pasting the code 500 times and manually changing the group in each! haha. but what's the simplest way?
thank you in advance for any understanding and help, and either way, have an awesome day.
If I'm understanding you correctly, I believe you're waiting to create pages from the database Dynamically. You can use a get variable in the request http://yoursite.com/page.php?group=1.
Then in your code update your query to do:
$query = "SELECT word FROM demo WHERE group=".$_GET['group'];
That query is insecure, as any user could inject raw mysql into the $_GET['group'] variable.
$group = mysqli_real_escape_string($conn, $_GET['group']);
$query = "SELECT word FROM demo WHERE `group`='$group'";
This is much safer.
So PHP will look for a file called index.php by default in any directory that it accesses. You can place such a file in the root of public_html or www or where ever your site accesses. Now in this file you can do something like:
<?php
if($_GET['group']){ //Make sure you have the var
$query = "SELECT word FROM demo WHERE `group`=?"; //The query with param
if ($stmt = mysqli_prepare($conn, query){ // try it out
mysqli_stmt_bind_param($stmt, "i", $_GET['group']); // bind the data
$stmt->execute(); //run it
$result = $stmt->get_result(); // get results
//use result to echo and stuff
}
} else {
//Do something incase there is not a group specified.
echo "Nothing here";
}
?>
Now when you go to your site you will get something like 'localhost/index.php' and see Nothing here but if you type localhost/index.php?group='55' you will have access to the page 55 data in result.
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...
I posted in a previous question how to get my rating script to work. I have now finally got it to work using maths rather than the avg function but i still have two questions to ask.
Q1) Is there a better way of displaying my results other than using echo all the time
Q2) How do i add in my other three performance values in to this script they are all in the same table
<?php
mysql_connect("localhost", "username", "password") or die ("sorry we could not connect to our servers");
mysql_select_db("db") or die ("sorry we could not our database");
$find_data = mysql_query("SELECT * FROM rating");
while($row = mysql_fetch_assoc($find_data))
{
$id = $row['id'];
$current_rating = $row['Reliability_timekeeping'];
$reviews = $row['reviews'];
$new_rating = $current_rating / $reviews;
echo "($reviews Reviews)";
echo "Reliability & timekeeping: ";
echo round($new_rating,1);
echo "/10";
}
?>
sorry for my writing skill writing is not my strong point and still new to php
You can use a template engine that fills your data in to a template that you can write like HTML with some additional placeholders. A template engine has some great advantages over echoing out the values:
separate code from layout
reusable
better maintainability and readability
Here are some of the template engines I used in PHP, they also have good documentation to get you started:
Smarty
Twig
To avoid using echo all the time, you can just accumulate all the output in a variable and use a single echo. As a good practice, in my scripts I try to use just one echo at the script end. This will make each page a few mili-seconds faster, as less PHP / web server interactions will be necessary:
$Response = "";
$Response .= "($reviews Reviews)".
"Reliability & timekeeping: ".round($new_rating,1)."/10";
...
more code
...
echo $Response;
Just indent and break lines in a way that the code gets readable, and everything will be fine.
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.
If I build my pages like this do I have to check if news_id is numeric in news.php too? Or is this safe?
index.php:
if (ctype_digit($_GET['news_id'])) include('news.php');
news.php:
$query = mysql_query("SELECT * FROM news WHERE news_id = $_GET[news_id]");
$row = mysql_fetch_assoc($query);
if (!mysql_num_rows($query)) exit('The news you're trying to read do not exist.');
The other answers are absolutely correct, you should never allow any user input directly into your database, or any other sensitive area.
You should validate/sanitize all input from $_GET, $_POST etc... You can use PHP’s built in filter functions or use those built into a framework such as Cake PHP or Symphony, which both make handling user data a lot easier.
jonstjohn has a good point you are leaving yourself open sql injection this way, and other forms of attack based around feeding malicious code into you application.
Worth reading Jeff Atwood’s 25 most dangerous programming mistakes for a bit of background on these issues, and others besides.
Short answer: Yes, you should.
Someone might (and will) request news.php, bypassing index.php.
You really should escape your data and sanitize it before sending it into MySQL. No guarantee someone won't try to send something malicious in through the post data.
$news_id = (int)$_GET[news_id];
$query = mysql_query("SELECT * FROM news WHERE news_id = " .
mysql_real_escape_string($news_id));
$row = mysql_fetch_assoc($query);
if (!mysql_num_rows($query)) exit('The news you're trying to read do not exist.');
It's not safe;
Don't check, convert it to integer using intval();
Never, ever put GPC variables in SQL without escaping or casting;