How to prevent sql injection in a site [duplicate] - php

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 9 years ago.
I have the following code in my php file:
session_start();
include "connect.php";
if (isset($_POST['email']) && isset($_POST['password'])) {
$email = htmlspecialchars(mysqli_real_escape_string($conn, $_POST['email']));
$password = htmlspecialchars(mysqli_real_escape_string($conn, $_POST['password']));
function process() {
include "connect.php";
if (isset($_POST['email']) && isset($_POST['password'])) {
$email = $_POST["email"];
$password = $_POST["password"];
}
mysqli_select_db($conn, "users");
$sql = "SELECT * FROM users WHERE email='$email' AND password='$password'";
$result = mysqli_query($conn, $sql);
$count = mysqli_num_rows($result);
if ($count >= 1) {
$_SESSION['id'] = $id;
$_SESSION['email'] = $email;
$_SESSION['password'] = $password;
header('location:index.php');
} else {
echo "Email/Password is incorrect";
}
}
if ($email != "" or $password != "") {
if (isset($_POST['submit'])) {
process();
} else {
echo "Error: " . mysql_error();
}
}
}
How would I go about preventing sql injection in my login page?
I searched on the internet and most sites said I must use the mysqli_real_escape_string() function, but this did not seem to change things at all when I used the sql injection in my site again.
please help :)

Yes, use PDO and prepare statements with try/catch blocks. When using prepare, each passes as a secure parameter, eliminating risk of injection.

Use sql prepare :)
http://www.php.net/manual/en/mysqli.prepare.php
From what I know this filters any sql injection

foreach($_POST as $key => $value) $_POST[$key] = mysqli_real_escape_string($value);
Most simple way, anyway i suggest of use prepare statements

First of all, - to avoid sql injection you need to filter any kind of user input. And simplest way to do it, is to use PDO

You need to use prepared statements. I think following code snippet will give you some idea how to use it. please change according to your requirements
/* Create a prepared statement */
if($stmt = $mysqli -> prepare("SELECT * FROM users WHERE email=? AND password=?")) {
/* Bind parameters
s - string, b - blob, i - int, etc */
$stmt -> bind_param("ss", $email, $password);
/* Execute it */
$stmt -> execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
$_SESSION['id'] = $row['id'];
$_SESSION['email'] = $row['email'];
$_SESSION['password'] = $row['password'];
header('location:index.php');
/* Close statement */
$stmt -> close();
}
/* Close connection */
$mysqli -> close();
Docs Link: http://www.php.net/manual/en/mysqli.prepare.php
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
http://forum.codecall.net/topic/44392-php-5-mysqli-prepared-statements/

Related

Using Use prepared statements and parameterized queries in PHP and MySQLi [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 4 years ago.
I am learning how to use prepared statements in my simple login system to make it more secure.
I have followed a few different tutorials to get it working but cant get it to work. When i enter the username and password wrong it gives me the error. When i enter the username and password correct i still get the error.
What am i doing wrong?
I am new to this so apologies for any obvious errors.
I have also looked into hashing my password as it is being stored as plain text in the database at the moment but that will be my next step after i get this working.
Here is my code:
<?php
error_reporting(E_ALL); ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
if($SERVER['REQUESTMETHOD'] == 'POST') {
if (empty($POST['username']) || empty($POST['password'])) {
$error = "Enter Username and Password";
}
else
{
// Define $username and $password
$username = $_POST['username'];
$password = $_POST['password'];
//connect to database
include('dbconx.php');
}
$stmt = $con->prepare("SELECT * from admin where password=? AND username=?");
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$stmt->bind_result($id, $username, $password);
$stmt->store_result();
if($stmt->num_rows == 1) //To check if the row exists
{
$_SESSION['login_user'] = $username; // Initializing Session
header("location: confirm.php"); // Redirecting To Other Page
}
else {
$error = "Username or Password is incorrect";
}
mysqli_close($con); // Closing Connection
}
?>
You have your bound parameter arguments backwards. Your query binds password then username but your bind_param() uses $username then $password.
I've never been a fan of using the number of rows returned to determine existence. Instead, you can simply use fetch(). It will return a boolean value indicating whether or not there was a result.
For example
$stmt = $con->prepare('SELECT id from admin where password = ? AND username = ?');
$stmt->bind_param('ss', $password, $username); // note the order
$stmt->execute();
$stmt->bind_result($id);
if ($stmt->fetch()) {
$_SESSION['login_user'] = $username;
$_SESSION['login_user_id'] = $id; // probably important
header("Location: confirm.php");
exit; // always exit after a "Location" header
} else {
$error = "Username or Password is incorrect";
}
mysqli_stmt::store_result should be called before mysqli_stmt::bind_result, also you would need to call mysqli_stmt::seek_data and mysqli_stmt::fetch to get the result.
Example :
<?php
$db = new Mysqli(...);
$inputUsername = $_POST['username'] ?? '';
$inputPassword = $_POST['password'] ?? '';
$statment = $db->prepare('SELECT `id`,`username`,`password` FROM `admin` WHERE `username` = ?');
$statment->bind_param('s',$inputUsername);
$statment->execute();
$statment->store_result();
$statment->bind_result($id,$username,$password);
if($statment->num_rows) {
$statment->data_seek(0);
$statment->fetch();
/**
* this is not secure
* #see http://php.net/manual/en/function.password-hash.php
*/
if($inputPassword === $password) {
echo sprintf('Welcome, %s!',$username);
} else {
echo 'Incorrect password!';
}
} else {
echo sprintf('No such user with the given username (%s)',$inputUsername);
}
$statment->close();
$db->close();
Removed bind_result and store_result for get_result and fetch_assoc. It makes getting db records more flexible and stable.
Also added exit(); after redirection so no other codes will be executed after redirect command.
Typo in:
if (empty($POST['username']) || empty($POST['password']))
^ $POST should be $_POST instead.
$error is not being checked properly if empty or not. And still goes through mysqli functions block even if there is an error. Fixed that by creating an appropriate if statement that encloses the mysqli funtions block.
Also added proper indentation to the code for readability.
New Code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
$_POST['username'] = isset( $_POST['username'] ) ? $_POST['username'] : '';
$_POST['password'] = isset( $_POST['password'] ) ? $_POST['password'] : '';
if($_SERVER['REQUEST_METHOD'] == 'POST') {
if (empty($_POST['username']) || empty($_POST['password'])) {
$error = "Enter Username and Password";
}
else{
// Define $username and $password
$username = $_POST['username'];
$password = $_POST['password'];
//connect to database
include('dbconx.php');
}
if( $error == "" ) {
$stmt = $con->prepare("SELECT * from students where username=? AND password=?");
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows == 1) {
$row = $result->fetch_assoc();
$_SESSION['login_user'] = $row['username']; // Initializing Session
header("location: confirm.php");exit(); // Redirecting To Other Page
}
else {
$error = "Username or Password is incorrect";
}
mysqli_close($con); // Closing Connection
}
echo $error;
}
?>

Catchable fatal error: Object of class mysqli_result could not be converted to string on line 12

I'm getting this error for the following php code on line 12. I'm trying to insert data into a table and if it succeeds, redirect to another page after alert.
<?php
session_start();
include 'dbconn.php';
$name = $_POST["name"];
$hof = $_POST["hof"];
$tier = $_POST["tier"];
$services = $_POST["services"];
$proced = $_POST["proced"];
$addr = $_POST["addr"];
$phone = $_POST["phone"];
$depname = $_SESSION['depname'];
$qry = "INSERT INTO '.$depname.'(name,hof,tier,services,method,address,phone) VALUES ('$name','$hof','$tier','$services','$proced','$addr','$phone')"; //This is where the problem is;
if(mysqli_query($conn,$qry) === TRUE) {
echo "<script type='text/javascript'>alert('Success');
window.location='welcome.php';
</script>";
}
else{
echo "<script type='text/javascript'>alert('Error');
window.location='welcome.php';
</script>";
}
?>
In addition to what everyone else said this should fix your errors. You will still have security problems that you need to fix.
Also, I don't use mysqli I use PDO so you will have to forgive me if the syntax is slightly wrong.
Your problem is that mysqli_query() doesn't return a row. You need to need to fetch a row from your result and then assign it to $_SESSION['depname']
Login.php should look like this
// Note we are using prepared statements to prevent SQL injections
// Also note the use of backticks `, which are used for identifiers
$mysqli = new mysqli('host', 'user', 'password', 'database');
$stmt = $mysqli->prepare('SELECT `id`,`depname` FROM `admin` WHERE `username` = ? and password = ?');
$stmt->bind_param('ss', $myusername, $mypassword);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows == 1) {
session_start();
$row = $result->fetch_assoc();
$_SESSION['depname'] = $row['depname'];
header("location: welcome.php");
exit;
}
Other Script
<?php
session_start();
include 'dbconn.php';
$name = $_POST["name"];
$hof = $_POST["hof"];
$tier = $_POST["tier"];
$services = $_POST["services"];
$proced = $_POST["proced"];
$addr = $_POST["addr"];
$phone = $_POST["phone"];
$depname = $_SESSION['depname'];
$qry = "INSERT INTO `{$depname}` (`name`,`hof`,`tier`,`services`,`method`,`address`,`phone`) VALUES (?,?,?,?,?,?,?)";
// prepare our query to prevent sql injections
$stmt = $mysqli->prepare($qry);
$stmt->bind_param('sssssss', $name, $hof, $tier, $services, $proced, $addr, $phone);
$stmt->execute();
// not sure why you aren't using header here like #JayBlanchard said, but whatever
if($stmt->affected_rows == 1) {
echo "<script type='text/javascript'>alert('Success');
window.location='welcome.php';
</script>";
}
else
{
echo "<script type='text/javascript'>alert('Error');
window.location='welcome.php';
</script>";
}

Inserting data into multiple SQL tables from single form

Hey.. I'm a bit stuck on PHP code to insert data into multiple SQL tables. I an unable to get the data into both tables within a single action. This is for a registration page to create a user login and start of company profile. Any suggestions would be much appreciated. Thanks
<?php
session_start();
if(isset($_SESSION['user'])!="")
{
header("Location: home.php");
}
include_once 'resources/php/dbconnect.php';
if(isset($_POST['btn-signup']))
{
$uname = mysql_real_escape_string($_POST['uname']);
$email = mysql_real_escape_string($_POST['email']);
$upass = md5(mysql_real_escape_string($_POST['pass']));
$orgname = mysql_real_escape_string($_POST['orgname']);
$uname = trim($uname);
$email = trim($email);
$upass = trim($upass);
$orgname = trim($orgname);
// email exist or not
$query = "SELECT user_email FROM users WHERE user_email='$email'";
$result = mysql_query($query);
$count = mysql_num_rows($result); // if email not found then register
if($count == 0){
if(mysql_query("START TRANSACTION;
INSERT INTO users('user_name','user_email','user_pass')
VALUES('$uname','$email','$upass');
INSERT INTO companies('name','owner_id')
VALUES('$orgname','$email');
END;"))
{
?>
<script>alert('Registration Successful');</script>
<?php
}
else
{
?>
<script>alert('error while registering you...');</script>
<?php
}
}
else{
?>
<script>alert('Sorry Email ID already taken ...');</script>
<?php
}
}
?>
As you can see here the mysql extension is deprecated and you MUST stop using it. Great alternatives are PDO and mysqli
You should also use Prepared Statements to safeguard your code against SQL Injection attacks.
To complete a Transaction using PDO you can do this:
$conn->query("START TRANSACTION");
$stmt = $conn->prepare("INSERT INTO users(user_name,user_email,user_pass) VALUES(?,?,?)");
try
{
$stmt->bindValue(1,$user_name);
$stmt->bindValue(1, $user_email);
$stmt->bindValue(3, $user_pass);
$stmt->execute();
$secondStmt = $conn->prepare("INSERT INTO companies(name,owner_id) VALUES(?,?)");
$secondStmt->bindValue(1, $name);
$secondStmt->bindValue(2, $owner_id);
$secondStmt->execute();
$conn->query("COMMIT"); //This commits all changes if no error occured
}
catch(Exception $e)
{
$conn->query("ROLLBACK"); //This reverts any changes made in case of an error
}
You can do two inserts like this:
$queryUsers = INSERT INTO users('user_name','user_email','user_pass')
VALUES('$uname','$email','$upass');
mysql_query($queryUsers);
$queryCompanies = INSERT INTO companies('name','owner_id')
VALUES('$orgname','$email');
mysql_query($queryCompanies);
In addition, carefully with mysql_query, is deprecated, try to use mysqli().
Regards

How can i prevent SQL injection when using MySQLi? [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 9 years ago.
How would i prevent SQL injections in a SQL query like this?
<?php
$mysqli = new mysqli("ip", "username", "pass", "database");
/* check connection */
if (mysqli_connect_errno()) {
printf("Sorry, the login server is 'Under Maintainance'");
exit();
}
$username = $_POST["username1"];
$username = strtolower($username);
$password = $_POST['password1'];
$hash = sha1(strtolower($username) . $password);
$query = "SELECT * FROM accounts WHERE name='$username'";
if ($result = $mysqli->query($query)) {
/* determine number of rows result set */
$rownum = $result->num_rows;
if($rownum != 0)
{
while ($row = $result->fetch_assoc()) {
{
$acct = $row['acct'];
$pass = $row['pass'];
}
if($hash == $pass){
session_start();
$_SESSION['name']=$username;
$_SESSION['acct']=$acct;
header('Location:index.php');
} else {
echo 'There was an error when logging in. Make sure your password and username are correct.';
}
}
$result->close();
}
else
{
echo 'Account does not exist. Please Register an account before logging in.';
}
$mysqli->close();
}
?>
I have already added encryption but i cannot seem to find a prevention method that i know how to use yet. Also, is it possible for a user to use a MySQL injection without using an input box? (page dissection???)
Encryption and query sanitation are not related.
You're already using mysqli, which is nice, but you don't sanitize the input to the query (namely $username, which probably doesn't need to be strtolowered either).
You should use properly parameterized queries for sanitation.
$query = "SELECT * FROM accounts WHERE name = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->bind_result($acct, $pass);
$stmt->fetch();
//$act and $pass are now properly set
The limits on SQL injection have nothing to do with the user. It's even possible for you to accidentally inject yourself in your own code, and injection does not even have to be malicious. For that reason, you should always properly parameterize your queries even if you don't think there's any risk of malicious injection.

Get id on my login system

I have to make a login system on my website, but my users don't have the same things on their sites so I will $_GET my users' customers_id (from database) in the URL when they are logged in.
But I cannot see how.
my login code is this.
<?php
$email = $_POST['user'];
$password= $_POST['pass'];
$login = $_POST['login'];
$user_custermers_id = $_GET['id'];
if($login == 'Login' || isset($login))
{
global $wpdb;
$get = mysql_query("SELECT * FROM das_custermer_users WHERE email = '$email' AND password ='" . md5($password)."'") or die(mysql_error());
$result = mysql_num_rows($get);
if($result == 0)
{
$msg = "Wrong E-mail or Password";
}
else
{
session_start();
$_SESSION['email'] = $email;
header("location: http://dashboard.tg.com");
}
}
?>
You're writing really bad and dangerous code. What if I catch $_POST['email'] and change it to '--;DELETE your_data_base; ?
You don't check what data you have and SQL injection is possible in your example.
if($login == 'Login' || isset($login))
this condition is without sense because if there is $login== 'login' then isset is TRUE so second OR condition is unneccesary
session_start();
you should move it to 1st line.
global is an old PHP syntax avoid it.
$user_custermers_id = $_GET['id']; this is really bad. You should cast to to int or use intval()
If I were you I would use PDO connection. PDO has PDOStatement::rowCount you can use this property to check if there are any rows.
PDO throws exceptions so mysql_errror() is not needed. mysql_num_rows() is deprecated as of PHP 5.5.0, and will be removed in the future so avoid it.
I found this sample in internet. This code should be also in try catch block to handle exceptions
$login = mysql_escape_string(trim($_POST['login']));
$pass = mysql_escape_string(trim($_POST['pass']));
$dbh = new PDO('mysql:host=localhost;dbname=mydatabase', 'user', 'pass');
$sth = $dbh->prepare("SELECT * FROM table WHERE login = ? AND pass = ?");
$sth->bindParam(1, $login);
$sth->bindParam(2, md5($pass));
$sth->execute();
if ($sth->rowCount() > 0)
{
// session stuff,
// refresh page
}

Categories