I want to make this page secure, but i dont know where should i start. Because i've got injected yesterday I treid mysql escaping string, but i didn't help much. And i dont know anything about PDO, can you hook me up? Here's the code.
<?php
//category.php
require_once('startsession.php');
require_once('php/mysql_prisijungimas.php');
include 'connect.php';
//first select the category based on $_GET['cat_id']
$sql = "SELECT
cat_id,
cat_name,
cat_description
FROM
categories
WHERE
cat_id = " . mysql_real_escape_string($dbc, trim($_GET['id']));
$result = mysql_query($sql);
if(!$result)
{
echo 'The category could not be displayed, please try again later.' . mysql_error();
}
else
{
if(mysql_num_rows($result) == 0)
{
echo 'This category does not exist.';
}
else
{
//display category data
while($row = mysql_fetch_assoc($result))
{
echo '<h2>Topics in ′' . $row['cat_name'] . '′ category</h2><br />';
}
//do a query for the topics
$sql = "SELECT
topic_id,
topic_subject,
topic_date,
topic_cat
FROM
topics
WHERE
topic_cat = " . mysql_real_escape_string($dbc, trim($_GET['id']));
$result = mysql_query($sql);
if(!$result)
{
echo 'The topics could not be displayed, please try again later.';
}
else
{
if(mysql_num_rows($result) == 0)
{
echo 'There are no topics in this category yet.';
}
else
{
//prepare the table
echo '<table border="1">
<tr>
<th>Topic</th>
<th>Created at</th>
</tr>';
while($row = mysql_fetch_assoc($result))
{
echo '<tr>';
echo '<td class="leftpart">';
echo '<h3>' . $row['topic_subject'] . '<br /><h3>';
echo '</td>';
echo '<td class="rightpart">';
echo date('d-m-Y', strtotime($row['topic_date']));
echo '</td>';
echo '</tr>';
}
}
}
}
}
?>
In your case surround the mysql_real_escape_string with quotes like so:
SELECT * FROM table WHERE ID = '".mysql_real_escape_String($_POST['ID'])."'
Note the extra single quotes. This will make it more secure but nevertheless its better to use prepared statements. Besides prefering to use prepared statements over mysql_query, as of php version 5.5.0 the function mysql_query() will be deprecated.
There is another topic on stackoverflow which anwsers the question 'How to prevent SQL injection in PHP Pdo'. You might find some samples and extra information :
How can I prevent SQL injection in PHP?
Related
I am trying to filter a mysql table using PHP, My aim is when the url is History.php?h_id=1 it only shows the rows that have one in the h_id (H_id is not a unique number)
My code is as below.
<html>
<head>
<title></title>
</head>
<body >
<?php
mysql_connect('localhost', 'root', 'matl0ck') or die(mysql_error());
mysql_select_db("kedb") or die(mysql_error());
$h_id = (int)$_GET['h_id'];
$query = mysql_query("SELECT * FROM Hist WHERE H_ID = '$h_id'") or die(mysql_error());
if(mysql_num_rows($query)=1){
while($row = mysql_fetch_array($query)) {
$id = $row['ID'];
$name = $row['Name'];
$datemod = $row['DateMod'];
$h_id = $row['H_ID'];
}
?>
<?php
$con=mysqli_connect("localhost","root","matl0ck","kedb");
// Check connection
if (mysqli_connect_errno()){
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM Hist");
echo "<table border='1'>
<tr>
<th>ID</th>
<th>Name</th>
<th>Date</th>
<th>H_ID</th>
</tr>";
while($row = mysqli_fetch_array($result))
{
echo "<tr>";
echo "<td>" . $row['ID'] . "</td>";
echo "<td>" . $row['Name'] . "</td>";
echo "<td>" . $row['DateMod'] . "</td>";
echo "<td>" . $row['H_ID'] . "</td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
<?php
}else{
echo 'No entry found. Go back';
}
?>
</body>
</html>
When I try to use this it shows all records that has a number in the h_id when I delete a number in this column it shows an error.
My table layout is as below.
Thank you
This is your syntactically incorrect statement
if(mysql_num_rows($query)=1){
A test is done using == and = is a value assignment
if(mysql_num_rows($query) == 1){
//------------------------^^
while($row = mysql_fetch_array($query)) {
$id = $row['ID'];
$name = $row['Name'];
$datemod = $row['DateMod'];
$h_id = $row['H_ID'];
}
Also
Your script is at risk of SQL Injection Attack
Have a look at what happened to Little Bobby Tables Even
if you are escaping inputs, its not safe!
Use prepared parameterized statements and therefore stick to the mysqli_ or PDO database extensions
Your general code seemed to get a bit confused, and you were getting data from a query "SELECT * FROM Hist" that you never seemed to use.
Also the while loop was being terminated before you actually consumed and output the results of the first query.
I also amended the code to use parameterized and prepared queries, and removed the use of the mysql_ which no longer exists in PHP7
<?php
// Use one connection for all script, and make it MYSQLI or PDO
$con=mysqli_connect("localhost","root","matl0ck","kedb");
if (mysqli_connect_errno()){
echo "Failed to connect to MySQL: " . mysqli_connect_error();
// if connection fails there is no point doing anything else
exit;
}
//$h_id = (int)$_GET['h_id'];
// prepare and bind values to make the code safe from SQL Injection
// also only select the rows you want
$sql = "SELECT ID, Name, DateMod, H_ID FROM Hist WHERE H_ID = ?";
$stmt = $con->prepare($sql);
if ( ! $stmt ) {
echo $con->error;
exit;
}
$stmt->bind_param("i", $_GET['h_id']);
$stmt->execute();
if ( ! $stmt ) {
echo $con->error;
exit;
}
// bind the query results 4 columns to local variable
$stmt->bind_result($ID, $Name, $DateMod, $H_ID);
echo "<table border='1'>
<tr><th>ID</th><th>Name</th><th>Date</th><th>H_ID</th></tr>";
if($con->affected_rows > 0){
echo "<table border='1'>
<tr><th>ID</th><th>Name</th><th>Date</th><th>H_ID</th></tr>";
while($stmt->fetch()) {
while($row = $stmt->fetch_array()) {
echo "<tr>";
echo "<td>$ID</td>";
echo "<td>$Name</td>";
echo "<td>$DateMod</td>";
echo "<td>$H_ID</td>";
echo "</tr>";
}
echo "</table>";
}else{
echo 'No entry found. Go back';
}
?>
Starting off, I'm kind of stumbling in the dark here with PHP/SQL, and don't really know how to bugtest that well, so forgive my vagueness about the exact nature of the problem. Moving on.
I have some code which grabs category ids, names, and descriptions from an SQL table, and saves the result to a variable. This is done through statement preparing to avoid an possibility of SQL injection. This value is then fed into some PHP which checks if the query had any response, and if so prints that into a table.
<?php
//create_cat.php
include_once (__DIR__ . '/../includes/db_connect.php');
include_once (__DIR__ . '/../includes/functions.php');
include_once (__DIR__ . '/header.php');
ini_set('display_errors',1); ini_set('display_startup_errors',1); error_reporting(-1);
$stmt = "SELECT
cat_id,
cat_name,
cat_description
FROM
categories";
if (login_check($mysqli) == true) {
if(!$result = $mysqli->query($stmt)){
echo 'The categories could not be displayed, please try again later.';
} else {
if ($result->num_rows === 0) {
echo 'No categories defined yet.';
} else {
//prepare the table
echo '<table border="1">
<tr>
<th>Category</th>
<th>Last topic</th>
</tr>';
while ($row = $result->fetch_assoc()) {
echo '<tr>';
echo '<td class="leftpart">';
echo '<h3>' . $row['cat_name'] . '</h3>' . $row['cat_description'];
echo '</td>';
echo '<td class="rightpart">';
echo 'Topic subject at 10-10';
echo '</td>';
echo '</tr>';
}
}
}
} else {
echo <<<error
<p>
<span class="error">You are not authorized to access this page.</span> Please login.
</p>
error;
}
include_once (__DIR__ . '/footer.php');
?>
However, the table SQL table definitely has values, but the PHP is only outputting: "The categories could not be displayed, please try again later."
Ok, got it working. I removed $stmt_prep commands, made sure to only use mysqli commands, and fixed some syntax errors. Code still has broken HTML, but the problem I was asking about is fixed.
If you wanted to keep the object oriented style, the main mistake was closing the statement before fetching the results. PHP will free up the statement at the end of the script anyway, but once you've called $stmt->close(); you won't be able to read any data from the query. Since PHP does copy by reference, $result = $stmt; doesn't copy the data, it just references the same closed statement.
The fetch syntax also isn't quite what you had: you need to bind some placeholder variables with eg $stmt->bind_result($name, $description); and then call $stmt->fetch() instead of fetch_assoc.
I'm not clear exactly what login_check does but it would seem to me that you'd want to put this check earlier so that the query is not executed if the user is unauthorized.
Your original code would end up looking something like:
<?php
if (login_check($mysqli) == true) {
$stmt = $mysqli->prepare($prep_stmt);
if ($stmt) {
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows == 0) {
echo 'No categories defined yet.';
} else {
//prepare the table
echo '<table border="1">
<tr>
<th>Category</th>
<th>Last topic</th>
</tr>';
$stmt->bind_result($name, $description);
while ($stmt->fetch()) {
echo '<tr>';
echo '<td class="leftpart">';
echo '<h3>' . $name . '</h3>'
. $description;
echo '</td>';
echo '<td class="rightpart">';
echo 'Topic subject at 10-10';
echo '</td>';
echo '</tr>';
}
}
} else {
echo 'The categories could not be displayed, please try again later.';
}
} else {
echo <<<error
<p>
<span class="error">You are not authorized to access this page.</span> Please
login.
</p>
error;
}
I want this data to display all the results, in the query I get 129 results. But when I display it on the page I only get one row. I have used very similar code to get multiple results before, so I know it`s something simple, but I just can't get it. Any thoughts would be greatly appreciated!
<?php
$sql = "SELECT SUM(datamb) AS value_sum FROM maindata GROUP BY phonenumber";
$sql1 = "select dataplan as currentplan from maindata GROUP BY phonenumber";
$sql2 = "SELECT DISTINCT phonenumber AS value_sum1 FROM maindata";
$result = mysql_query($sql);
if (!$result) {
echo "Could not successfully run query ($sql) from DB: " . mysql_error();
exit;
}
if (mysql_num_rows($result) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
$result1 = mysql_query($sql2);
if (!$result1) {
echo "Could not successfully run query ($sql1) from DB: " . mysql_error();
exit;
}
if (mysql_num_rows($result1) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
$result2 = mysql_query($sql2);
if (!$result2) {
echo "Could not successfully run query ($sql2) from DB: " . mysql_error();
exit;
}
if (mysql_num_rows($result2) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
while ($row = mysql_fetch_assoc($result)){
echo "<TABLE id='display'>";
echo "<td><b>Data Usage This Period: ". ROUND ($row["value_sum"],2) . "MB</b></td> ";
}
while ($row1 = mysql_fetch_assoc($result1)){
echo "<TABLE id='display'>";
echo "<td><b>Data Plan: ". $row1["currentplan"] . "</b></td> ";
}
while ($row2 = mysql_fetch_assoc($result2)){
echo "<TABLE id='display'>";
echo "<td><b>Phone Number: ". $row2["value_sum1"] . "</b></td> ";
}
?>
Updated based on suggestions - Very helpful thank you, I am very close, all values are correct but I can not get them in the same table, thoughts?
TRY To use ,
Loop in you code eg.
$result1 = mysql_query("SELECT DISTINCT phonenumber AS value_sum1 FROM maindata");
echo '<table>';
echo '<tr>';
echo '<th>id</th>';
echo '</tr>';
while($record = mysql_fetch_assoc($result))
{
echo '<tr>';
foreach ($record as $val)
{
echo '<td>'.$val.'</td>';
}
echo '</tr>';
}
echo '</table>';
Add
"LIMIT 0, 1" at the end of query
or
edit query like "select TOP 1 from....."
Lets make it easy on you ;)
have a look here how to use mysql_fetch_assoc
http://php.net/manual/en/function.mysql-fetch-assoc.php
follow the examples, you will be done in a sec.
I'm creating a small private forum to get some more knowledge about PHP/PDO etc. Now I have a weird bug/error/wrong piece of code that is not showing the echo. This is my code.
$sql2 = $db->prepare('SELECT topic_id, topic_subject,topic_date,topic_cat FROM topics WHERE topic_cat = :topid');
$sql2->bindParam(':topid', $_GET['id'], PDO::PARAM_INT);
$sql2->execute();
$result2 = $sql->rowCount();
if($result2 === FALSE){
echo 'The topics could not be displayed, please try again later.';
}
elseif ($result2 === 0){
echo 'There are no topics in this category yet.';
} else {
//prepare the table
echo '<table border="1">
<tr>
<th>Topic</th>
<th>Created at</th>
</tr>';
while($row = $sql2->fetch()) {
echo '<tr>';
echo '<td class="leftpart">';
echo '<h3>' . $row['topic_subject'] . '<br /><h3>';
echo '</td>';
echo '<td class="rightpart">';
echo date('d-m-Y', strtotime($row['topic_date']));
echo '</td>';
echo '</tr>';
}
}
It should show the echo at while($row = $sql2->fetch()), but it is not. Also I know there is not enough { and } but that's because the other part of the code is not relevant.
You appear to count the rows returned by $sql then loop through $sql2. Have you checked to see if there are any results in $sql2?
Im trying to order posts by their date, but whenever I try to do that I get this error:
Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in C:\localhost\bootstrap\category.php on line 58
DATABASE STRUCTURE: http://puu.sh/1630b
<?php
//category.php
include 'connect.php';
//first select the category based on $_GET['cat_id']
$sql = "SELECT
cat_id,
cat_name,
cat_description
FROM
categories
WHERE
cat_id = " . mysql_real_escape_string($_GET['id']);
$result = mysql_query($sql);
if(!$result)
{
echo 'The category could not be displayed, please try again later.' . mysql_error();
}
else
{
if(mysql_num_rows($result) == 0)
{
echo 'This category does not exist.';
}
else
{
//display category data
while($row = mysql_fetch_assoc($result))
{
echo '<h2>Topics in ′' . $row['cat_name'] . '′ category</h2><br />';
$title = $row['cat_name'];
include 'header.php';
}
//do a query for the topics
$sql = "SELECT
topic_id,
topic_subject,
topic_date,
topic_cat
FROM
topics
ORDER BY
topic_date DESC
WHERE
topic_cat = " . mysql_real_escape_string($_GET['id']);
$result = mysql_query($sql);
// if(!$result)
// {
// echo 'The topics could not be displayed, please try again later.';
// }
// else
// {
if(mysql_num_rows($result) == 0)
{
echo 'There are no topics in this category yet.';
}
else
{
//prepare the table
echo '<table border="1" class="table table-bordered table-striped" style="float: right; width: 990px;">
<tr>
<th>Topic</th>
<th>Created at</th>
</tr>';
while($row = mysql_fetch_assoc($result))
{
echo '<tr>';
echo '<td class="leftpart">';
echo '<h3>' . $row['topic_subject'] . '<br /><h3>';
echo '</td>';
echo '<td class="rightpart">';
echo date('d-m-Y', strtotime($row['topic_date']));
echo '</td>';
echo '</tr>';
echo '';
echo '';
}
echo '</table>';
echo '</div>';
}
// }
}
}
include('footer.php');
?>
I this case the problem will be in the commented lines 52 - 57 which are supposed to check if the mysql_query has been successful. Your query fails and returns false (boolean), which is a valid return value.
The error itself depends on your database table structure (isn't part of your link).
Your query that executes, fails and returned a boolean instead of a resource!
build in some error handling in your script.
do not use mysql_ functions, they are deprecated.
And now that you have edited your post, it is obvious that the ORDER BY comes after the WHERE.