I have this code:
if(isset($_POST['submit'])) {
$name = $_POST['name'];
$query = mysqli_query($conn, "select name from accounts where name = '{$name}'");
if($query) {
echo "success";
} else {
echo "error";
}
}
?>
<form action="" method="post">
Name: <input type="text" name="name"><br><br>
<input type="submit" name="submit" value="Add">
</form>
And I have written this in the form and submitted, only return (error), and the table was not deleted.
For mysqli, multiple statements or multi queries must be executed with mysqli::multi_query()
So change
$query = mysqli_query($conn, "select name from accounts where name = '{$name}'");
to
$query = mysqli_multi_query($conn, "select name from accounts where name = '{$name}'");
then retry what you want in your own machine.
Of course, usually hacker will just gain privilege by logging as "admin" and then do whatever he/she wants (in that case just performing single query in a select statement thru a SQL attack will do and do not need to execute multi-queries)
[additional point]
For single query SQL attack, submit the following:
1}' or 1=1 or '{1=1
which will become:
select name from accounts where name='{1}' or 1=1 or '{1=1}'
or
1}' or name='admin' or '{1=1
which will become:
select name from accounts where name='{1}' or name='admin' or '{1=1}'
Hence, to avoid SQL attacks, please use parameterized prepared statements.
For details, you may refer to :
php mysqli prepared statements select
For example, if you will send like such request:
1';DROP table accounts where id!='123454321344321
For reason request encoding, you can use + sign instead of spaces.
I am writing an example with PHP simulate $name argument:
//That's a mean it is request variable
$name = "1';DROP table accounts where id!='123454321344321";
$query = mysqli_query($conn, "select name from accounts where name = '{$name}'");
if($query) {
echo "success";
} else {
echo "error";
}
Related
Attempting to insert a Score based on the User's Session ID and POST , I've set up the database to use the UserID as a foreign key constraint but dont know how to do an insert query.
enter image description here
Database Values ^^
My attempt below
<?php
include("php/functions.php");
include('connections/conn.php');
$userID = $_SESSION["userID"];
//echo "all good here";
$newsoanxscore = mysqli_real_escape_string($conn, $_POST['socanxscore']);
$insertquery = "INSERT INTO socanxscore(socialanxietyscore)" . "VALUES('$newsoanxscore')";
$result = mysqli_query($conn, $insertquery) or die(mysqli_error($conn));
mysqli_close($conn);
?>
My insert form
<form action="insertsoanxietyscore.php" method="post">
Insert your score <input type="number" name="socanxscore" /><br><br>
<input type="submit" />
</form>
There are a few things here that may be helpful.
Firstly, you are not passing the user ID into your insert query. which can be written in this case as.
$insertquery = "INSERT INTO socanxscore(socialanxietyscore, UserId) VALUES('$newsoanxscore', '$userID')";
Secondly, please take the time to explore prepared queries to prevent SQL injection when passing end-user input to a database table. You may find the following resource useful.
http://php.net/manual/en/mysqli.prepare.php
go for this:
<?php
session_start();
include("php/functions.php");
include('connections/conn.php');
$userID = $_SESSION["userID"];
if(isset($_POST["socanxscore"]))
{
$query=INSERT INTO socanxscore(socialanxietyscore) VALUES('$newsoanxscore') WHERE userID=$userID";
$result = mysqli_query($conn, $insertquery) or die(mysqli_error($conn));
}
else
{
ehco "error";
}
mysqli_close($conn);
?>
I have been trying to create a reset password feature for my website, where the user can insert the already registered email and that will generate a random OTP and will be stored in the same column as the user's details such as
id firstname lastname username email resetpassword
1 name last user email OTP
this is my code but it's not working.
<?php
require 'dbh.php';
session_start();
$random = mt_rand(1000,1000000);
$email = $_POST['email'];
$sql = "SELECT Email FROM registeredusers WHERE Email='$email'";
$result = mysqli_query($connection,$sql);
$emailCheck = mysqli_num_rows($result);
if (empty($email))
{
echo "please fill out all the fields";
}
else{
$result = mysqli_query($connection,$sql);
$sql = "UPDATE registeredusers SET ResetPassword='$random' WHERE Email='$email'";
Header("Location: submitOTP.php");
}
?>
I am just trying this out so the form looks something like this
<form action="resetPassword.php" method="POST">
<input type="text" value="email" name="email"></input>
<input type="submit" value="submit"></input>
</form>
You should firts assigne the sql code and after execute the query
$sql = "UPDATE registeredusers SET ResetPassword='$random' WHERE Email='$email'";
$result = mysqli_query($connection,$sql);
otherwise you simply repeat the previous (select ) query ..
and be careful for avoid sql injection take a look at prepared query and binding param
I have created a webpage that gets the user to login, if they havent got an account then they can register and is creates a new user for them.
This is the table users in the database (user_registration)
user_id username password email wage
1 johnsmith jsmith99 jsmith#gmail.com 0
2 davidscott dscott95 davidscott#gmail.com 0
When a new user registered, the default value for the wage is 0. I want them to be able to edit this through the use of a form - this is the HTML code for the form:-
<form method="post" action="<?php $_PHP_SELF ?>">
<input name="new-wage" type="text" id="new-wage" class="textbox" placeholder="New Wage">
<input name="update" type="submit" id="update" value="Update" class="btn">
</form>
PHP Code: (note- the php and the html form are all in the same file(index.php) )
<?php
if(isset($_POST['update']))
{
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
die('Could not connect: ' . mysql_error());
}
$user_id = $_SESSION['MM_Username'];;
$wage = $_POST['new-wage'];
$query = "UPDATE users ".
"SET wage = '$wage' ".
"WHERE user_id = '$user_id'" ;
mysql_select_db('user_registration');
$retval = mysql_query( $query, $conn );
if(! $retval )
{
die('Could not update data: ' . mysql_error());
}
echo "Updated data successfully\n";
mysql_close($conn);
}
else
{
?>
When i fill in this form and hit the update button, it reloads the webpage and displays Updated data successfully which is exactly what should happen. BUT - when I refresh the table in PHP My Admin, it keeps the wage as 0, and not what i entered in the form.
Has anyone got any ideas what might be wrong with my code?
Thanks in advance for any answers.
PS.- I know that I have used the functions mysql_* and not mysqli_, simply because i dont know how to convert it, can you also help me with this??
You are vulnerable to sql injection attacks.
Plus, you don't seem to call session_start() so $_SESSION is probably empty, leading to $user_id being empty, and your query not matching anything. A simple var_dump($query) will show you what's actually going on there.
You need to check mysql_affected_rows() as well, to see if anything actually got updated.
Based on what you said in the comments:
This:
$user_id = $_SESSION['MM_Username'];
$wage = $_POST['new-wage'];
$query = "UPDATE users ".
"SET wage = '$wage' ".
"WHERE user_id = '$user_id'" ;
Should be this:
$user = $_SESSION['MM_Username'];
$wage = $_POST['new-wage'];
$query = "UPDATE users ".
"SET wage = '$wage' ".
"WHERE username = '$user'";
As you wanted to update the records based on the user id but you passed in the username as the parameter!
However, I'm assuming you want to update by the user_id, as that is unique for each user, and thus a more robust design.
To do that you'd have to add another $_SESSION variable that stores the user id when they log in. Call it $_SESSION['MM_Id'] or whatever. The name is arbitrary.
You also have an unclosed else statement at the end of your code:
else
{
?>
Either close it or remove it.
As Mark said, your code is susceptible to SQL injection attacks, a commonly abused mistake. I'd recommend looking at PDO (my personal favorite). If you're new to object-oriented programming, it may be difficult, but it offers more power, flexibility, and security. Plus, object-oriented programming is an important concept anyway.
To protect your current code from injection, use mysql_real_escape_string()...
$user = mysql_real_escape_string($_SESSION['MM_Username']);
$wage = mysql_real_escape_string($_POST['new-wage']);
$query = "UPDATE users ".
"SET wage = '$wage' ".
"WHERE username = '$user'";
This prevents people form putting in special characters (such as quotes) to attack your queries. I gotta run, but if you read up on SQL injection, you'll understand!
So I've been trying to replicate a second order SQL Injection. Here's an example template of two php based sites that I've prepared. Let's just call it a voter registration form. A user can register and then you can check if you're a registered voter or not.
insert.php
<?php
$db_selected = mysql_select_db('canada',$conn);
if (!db_selected)
die("can't use mysql: ". mysql_error());
$sql_statement = "INSERT into canada (UserID,FirstName,LastName,Age,State,Town)
values ('".mysql_real_escape_string($_REQUEST["UserID"])."',
'".mysql_real_escape_string($_REQUEST["FirstName"])."',
'".mysql_real_escape_string($_REQUEST["LastName"])."',
".intval($_REQUEST["Age"]).",
'".mysql_real_escape_string($_REQUEST["State"])."',
'".mysql_real_escape_string($_REQUEST["Town"])."')";
echo "You ran the sql query=".$sql_statement."<br/>";
$qry = mysql_query($sql_statement,$conn) || die (mysql_error());
mysql_close($conn);
Echo "Data inserted successfully";
}
?>
select.php
<?php
$db_selected = mysql_select_db('canada', $conn);
if(!db_selected)
die('Can\'t use mysql:' . mysql_error());
$sql = "SELECT * FROM canada WHERE UserID='".addslashes($_POST["UserID"])."'";
echo "You ran the sql query=".$sql."<br/>";
$result = mysql_query($sql,$conn);
$row=mysql_fetch_row($result);
$sql1 = "SELECT * FROM canada WHERE FirstName = '".$row[1]."'";
echo "The web application ran the sql query internally=" .$sql1. "<br/>";
$result1 = mysql_query($sql1, $conn);
$row1 = mysql_fetch_row($result1);
mysql_close($conn);
echo "<br><b><center>Database Output</center></b><br><br>";
echo "<br>$row1[1] $row1[2] , you are a voter! <br>";
echo "<b>VoterID: $row[0]</b><br>First Name: $row[1]<br>Last Name: $row[2]
<br>Age: $row[3]<br>Town: $row[4]<br>State: $row[5]<br><hr><br>";
}
?>
So I purposely made this vulnerable to show how second order SQL Injection works, a user can type in a code into the first name section (where I am currently stuck, I've tried many different ways but it seems that I can't get it to do anything).
Then when a person wants to activate the code that he has inserted in the first name section, all he needs to do is just type in the userID and the code will be inserted.
For example:
I will type into the insert.php page as:
userid = 17
firstname = (I need to inject something here)
lastname = ..
age = ..
town = ..
state = ..
Then when I check for my details, and type in 17, the SQL script injected will be activated.
Can I get few examples on what sort of vulnerabilities I can show through this?
What is there to demonstrate?
Second order SQL injection is nothing more than SQL injection, but the unsafe code isn't the first line.
So, to demonstrate:
1) Create a SQL injection string that would do something unwanted when executed without escaping.
2) Store that string safely in your DB (with escaping).
3) Let some other piece of your code FETCH that string, and use it elsewhere without escaping.
EDIT: Added some examplecode:
A table:
CREATE TABLE tblUsers (
userId serial PRIMARY KEY,
firstName TEXT
)
Suppose you have some SAFE code like this, receiving firstname from a form:
$firstname = someEscapeFunction($_POST["firstname"]);
$SQL = "INSERT INTO tblUsers (firstname) VALUES ('{$firstname }');";
someConnection->execute($SQL);
So far, so good, assuming that someEscapeFunction() does a fine job. It isn't possible to inject SQL.
If I would send as a value for firstname the following line, you wouldn't mind:
bla'); DELETE FROM tblUsers; //
Now, suppose somebody on the same system wants to transport firstName from tblUsers to tblWhatever, and does that like this:
$userid = 42;
$SQL = "SELECT firstname FROM tblUsers WHERE (userId={$userid})";
$RS = con->fetchAll($SQL);
$firstName = $RS[0]["firstName"];
And then inserts it into tblWhatever without escaping:
$SQL = "INSERT INTO tblWhatever (firstName) VALUES ('{$firstName}');";
Now, if firstname contains some deletecommand it will still be executed.
Using a first name of:
' OR 1 OR '
This will produce a where clause in the second SQL of
WHERE FirstName = '' OR 1 OR ''
Therefore the result will be the first record in the table.
By adding a LIMIT clause, you can extract all rows from the table with:
' OR 1 ORDER BY UserID ASC LIMIT 0, 1 --
Obviously it will only extract 1 row at a time, so you would need to repeat that and increment the 0 in the LIMIT. This example uses a comment -- to terminate the remaining SQL which would otherwise cause the query to fail because it would add a single quote after your LIMIT.
The above is a simple example, a more complex attack would be to use a UNION SELECT which would give you access to the entire DB through the use of information_schema.
Also you are using addslashes() in one of your queries. That is not as secure as mysql_real_escape_string() and in turn: escaping quotes with either is not as secure as using prepared statements or parameterised queries for example in PDO or MySQLi.
I'm trying to update a table from a form.
I have 3 pages. The first one queries all of the rows from my table with an "edit" link.
When edit is clicked (page 2) the code pulls the $id and puts it in the url. The $id is pulled from the url and is used in a query to fill a form.
My problem is passing the updated form info to my table. Basically the update isn't happening.
Second page
<?php
include '../db/config.php';
include '../db/opendb.php';
$id = $_GET["id"];
$order = "SELECT * FROM tableName where id='$id'";
$result = mysql_query($order);
$row = mysql_fetch_array($result);
?>
<form method="post" action="edit_data.php">
<input type="hidden" name="id" value="<?php echo "$row[id]"?>">
<tr>
<td>Title</td>
<td>
<input type="text" name="title" size="20" value="<?php echo"$row[title]"?>">
</td>
</tr>
<tr>
<td>Post</td>
<td>
<input type="text" name="post" size="40" value="<?php echo
"$row[post]"?>">
</td></tr>
<tr>
<td align="right">
<input type="submit" name="submit value" value="Edit">
</td>
</tr>
</form>
third page
include '../db/config.php';
include '../db/opendb.php';
$query = "UPDATE tableName SET '$_POST[title]', '$post[post]' WHERE id='$id'";
mysql_query($query);
It should be
UPDATE tableName SET `title` = {$_POST['title']}, `post` = {$_POST['post']}...
Ask yourself, what are you setting?
Your SQL statement for the database update is wrong. It should include a listing of not only the new values but also the corresponding field names. This means it should look more like this:
$query = "UPDATE tableName SET `title` = {$_POST['title']}, `post` = {$_POST['post']} WHERE id = '$id'";
Notice that you also should embrace fields of $_POST inside of strings with curly brackets ({}) or put them outside of the quotes. (like " = " .$_POST['title']. ", "). This is absolutely necessary if you use the standard way to access those with he quotes (e.g. not $_POST[title] but $_POST['title'] or $_POST["title"]).
Additionally you should add the following to your code:
Some error handling, currently you don't even know if something went wrong. The simplest way is to check the return value of the mysql_query() function for null and if it is null, get the mysql error message with mysql_error().
Escaping for passed values. Currently you directly pass the posted data into a mysql query which is very insecure. (See for example SQL-Injection on wikipedia) You should use mysql_real_escape_string() on all form data before inserting them into queries. This escapes all parts that could be malicious.
if (isset($_POST[title])){
$title = mysql_real_escape_string(trim($_POST['title']));
}else{
$title = NULL;
}
if (isset($_POST[post])){
$post = mysql_real_escape_string(trim($_POST['post']));
}else{
$post = NULL;
}
$query = "UPDATE tableName SET title='$title', post='$post' WHERE id='$id'";
mysql_query($query);
I would also recommend mysqli functions instead of mysql and I probably wouldn't call a variable and table column 'post' to avoid confusion.
That is because you are not setting the values. In the statement:
$query = "UPDATE tableName SET '$_POST[title]', '$post[post]' WHERE id='$id'";
you should pass column names to be updated.
If you are not using PDO statements yet to prevent SQL injection attacks then you should use more protection then just mysql_real_escape_string(). On top of escaping the data you should be validating that the submitted data is in fact what you are expecting.
Ie. In your code here:
$id = $_GET["id"];
$order = "SELECT * FROM tableName where id='$id'";
$result = mysql_query($order);
$row = mysql_fetch_array($result);
If you added:
if(is_numeric($_GET['id'])){
$id = mysql_real_escape_string(trim($_GET["id"]));
$order = "SELECT id, title, post FROM tableName where id='$id'";
$result = mysql_query($order);
$row = mysql_fetch_array($result);
}
This would at least validate what you are executing is in fact an ID number (That is, if ID is actually a number ;) . You can apply this logic to all your inputs if you are not yet using PDO statements. If you are expecting letters then validate for letters, numbers validate for numbers, escape special characters. Again, this is bare minimum. I would really suggest reading up on the hundreds of SQL injection techniques and start reading up on PDO's.
Also, in regards to using the SELECT * statement. I would try and avoid it. It adds a layer of vulnerability to your statements, if you change the order of the fields in your table and you are using $row[0] (Numbered requests) it can muck things up and lastly if your table contains additional fields with data that is unrelated to the ones you need then you are using on this page then you are loading information you don't need to.
$order = "SELECT id, title, post FROM tableName where id='$id'";
Would solve that nicely. :) Good luck!