PHP Insert Into Error - php

I am started to learn coding start with HTML, CSS, and php. I created a basic form to test my skill. However, I got stuck with this. Can you help me on that?
I know that it is open to SQL injections, I am just trying to improve myself in coding and will use prepared statements and parameterized queries in real life.
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$mysql_host = "";
$mysql_username = "";
$mysql_password = "";
$mysql_database = "";
$conn = new mysqli ($mysql_host, $mysql_username, $mysql_password, $mysql_database);
$c_name = $_POST["club_name"];
$c_league = $_POST["league"];
$c_rank = $_POST["ranking"];
$c_prank = $_POST["previous_rank"];
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES ('$c_name', '$c_league, $c_rank, $c_prank);";
mysqli_query($conn, $sql);
if ($conn->query($sql) === TRUE) {
echo "kayit islendi";
}
else {
echo "Error". $sql ."<br>". $conn->error;
}
$conn->close();
}
?>
Everytime I used the form I got this error.
ErrorINSERT INTO... etc.

You are missing quotes around your insert values, here's the fixed sql:
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES ('$c_name', '$c_league', '$c_rank', '$c_prank');"
You were missing quotes around each value!
HOWEVER, this is an ill advised way of making database queries in production. Either use mysqli_real_escape_string to sanitize your strings(each of your variables will need this treatment) or use prepared statements.
Alternatively, and the way you should always use your DB is via the PDO wrapper. In this case you would use: PDO::quote. PDO offers a unified interface to the most popular databases there are. Here you can read more about PDO: http://php.net/manual/en/book.pdo.php
Coders prefer prepared statements to sanitizing their input. However this incurs extra communication with the mysql server vs writing a bit more code in php. Prepared statements are more involved then normal queries as they are cached on the SQL server and preprocessed waiting for data to be used, also having a miriad of question marks makes the code very hard to read especially if you start working in production and have a miriad of columns to fill. Here you can read more about the prepared statements:
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
Main takeaway:
never, EVER, EVER save unsanitized data to the DB!!Use mysqli_real_escape_string or PDO::quote or prepared statements, depending on situation.
use prepared statements for what they have been created for not just as a wholesale sanitizer tool, use them when you have to execute the same query repeatedly. Especially if this query is not an insert in which case I suggest you do mass insert like so:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9); read more here: https://dev.mysql.com/doc/refman/5.7/en/insert.html This has a caveat in that the maximum size of the sql with inserted values should never be larger then max_allowed_packet config.

You should use prepared statements. Not only does it prevent SQL injection attacks, it also avoids the pesky quoting issues you are currently facing
$sql = "INSERT INTO `club_data` (`club_name`, `league`, `ranking`, `previous_rank`)
VALUES (?, ?, ?, ?);";
$result = $conn->prepare($sql);
$result->bind_param('ssss', $c_name, $c_league, $c_rank, $c_prank);
echo $result->execute() === true ? 'kayit islendi' : 'Error'.$conn->error;

Related

Prevent URL Injections [duplicate]

This question already has an answer here:
How to prevent SQL Injection in Wordpress?
(1 answer)
Closed 6 years ago.
My website was recently got Hacked/Compromised. Via google I have learnt it is a victim of site injections. I believe I have cleaned and hopefully secured my website but I'm looking for ways to prevent it from ever happening again. I came across a code (see below) and wanted to know whether it will
1) work to prevent such attacks in the future? and
2) where should I add this code as my website is built in WordPress.
Any help or even better codes anyone can provide will be greatly appreciated, I'm new to programming.
Code:
<?php
if(isset($_REQUEST["id"])){
if(!is_int($_REQUEST["id"])){
//redirect this person back to homepage
} else {
$id_raw = trim(htmlentities($_REQUEST["id"]));
$id_secure = mysql_real_escape_string($id_raw);
$sql = "SELECT * FROM databasetable WHERE id='".$id_secure."'";
}
}
?>
PDO is an acronym for PHP Data Objects.
PDO is a lean, consistent way to access databases. This means developers can write portable code much easier. PDO is not an abstraction layer like PearDB. PDO is a more like a data access layer which uses a unified API (Application Programming Interface).
You basically have two options to achieve this:
Example:
$qry = $con->prepare('SELECT * FROM student WHERE name = :name');
$qry->execute(array('name' => $name));
foreach ($qry as $get) {
// do something with $get
}
Setting up database using PDO
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
A DSN is basically a string of options that tell PDO which driver to use, and the connection details... You can look up all the options here PDO MYSQL DSN.
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username,$password);
Note: If you get an error about character sets, make sure you add the charset parameter to the DSN. Adding the charset to the DSN is very important for security reasons, most examples you'll see around leave it out. MAKE SURE TO INCLUDE THE CHARSET!
You can also set some attributes after PDO construction with the setAttribute method:
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT id, firstname, lastname FROM MyGuests");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach(new TableRows(new RecursiveArrayIterator($stmt->fetchAll())) as $k=>$v) {
echo $v;
}
The way injection type attacks work, is by somehow getting an interpreter (The database) to evaluate something, that should have been data, as if it was code. This is only possible if you mix code and data in the same medium (Eg. when you construct a query as a string).Parameterised queries work by sending the code and the data separately, so it would never be possible to find a hole in that.
SQL Injection is a type of vulnerability in applications that use an SQL database. The vulnerability arises when a user input is used in a SQL Statement.
$n = $_GET['user'];
$sql = "SELECT password FROM tbl_login WHERE name = '$n' ";
As you can see the value the user enters into the URL variable user will get assigned to the variable $n and then placed directly into the SQL statement. This means that is possible for the user to edit the SQL statement.
$name = "admin' OR 1=1 -- ";
$query = "SELECT password FROM tbl_login WHERE name = '$n' ";
The SQL database will then receive the SQL statement as the following:
SELECT password FROM tbl_login WHERE name = 'admin' OR 1=1 -- '
To prevent SQL injections we will have to use something called prepared statements which uses bound parameters. Prepared Statements do not combine variables with SQL strings, so it is not possible for an attacker to modify the SQL statement. Prepared Statements combine the variable with the compiled SQL statement, this means that the SQL and the variables are sent separately and the variables are just interpreted as strings, not part of the SQL statement.
Prepared Statements with mySQLi.
Using the methods in the steps below, you will not need to use any other SQL injection filtering techniques such as mysql_real_escape_string(). This is because with prepared statements it is not possible to do conventional SQL injection.
mySQLi SELECT Query.
$n = $_GET['user'];
// Prepare the statement
if ($sql = $mysqli->prepare("SELECT password FROM tbl_login WHERE name=?")) {
// Bind a variable to the parameter as a string.
$sql->bind_param("s", $n);
// Execute the statement.
$sql->execute();
// Get the variables from the query.
$sql->bind_result($pass);
// Fetch the data.
$sql->fetch();
// Close the prepared statement.
$sql->close();
}
You will need to understand this:
Nothing is 100% secure.
All you can do is increase your level of security, by
implementing different security measures like filtering user input
before querying databases, using prepared statements.
Using a secure connection for server interaction by encrypting
the data using SHA or MD5 or some other salt encryption.
Using captcha in your forms to filter out bot attacks.
As far as your above code is concerned :
it is just checking whether the request id is an integer or not.
It is filtering out the special characters and then running the
query.
I would like to suggest you to check the below link :
https://www.owasp.org/index.php/PHP_Top_5
It will give you an insight of how to implement security in an application.

PHP Procedural Prepared Statement for Mysqli Multi Query

I have a PHP code that opens a CSV file using fgetcsv then reads through each rows then constructs a "Insert Into" query and attaches it to a variable named $MyQuery. This is the most understandable way for me when trying to update my database using information from a CSV file downloaded from the company website. This is working as I expected using the code below:
if (mysqli_multi_query($conn, $MyQuery))
{
do
{
/* store first result set */
if ($result = mysqli_store_result($conn))
{
mysqli_free_result($result);
}
} while (mysqli_next_result($conn));
}
Recently I learned about Prepared Statements and how they can secure your queries.
PROBLEM: How can I do multiquery with prepared statement in Procedural Mysqli way? I tried researching, a lot says it isn't possible. Some say it is possible but by creating different variables for each queries which is impossible for me as I will be inserting over 10000 records to my database from the CSV file. Is there any other ways to achieve this?
I'm thinking it can be done by looping through each records then doing a prepared-statement version of Insert Into but I thought doing 10000 Insert Into SQL commands would be very slow.
I am not 100% sure what you are asking but fallowing might work. First of all I would use pdo for connecting to a database. Fallowing is just a basic outline of what I think you want to do.
$pdo = new PDO('mysql:host=localhost;dbname=mydatabase', 'myusername', 'mypassowrd');
$query = "
INSERT INTO table (colum1, colum2, colum3)
VALUES (:info1, :info2, :info3)
";
$stmt = $pdo->prepare($query);
do
{
$stmt->execute(array(':info1'=>$my_info1, ':info2'=>$my_info2, ':info3'=>$my_info3));
} while( your condition);
There is two advantages for prepared statements. First is security and the second allows to do the same query over and over changing the values. This will make each of queries fast if you prepare them.
here is a ling that can explain more about prepared statements
http://php.net/manual/en/pdo.prepared-statements.php
I am adding a Procedural way of doing it using mysqli.
$query = "
INSERT INTO table (colum1, colum2, colum3)
VALUES (?, ?, ?)
";
if ($stmt = mysqli_prepare($conn, $query))
{
do
{
mysqli_stmt_bind_param($stmt, "sss", $my_info1, $my_info2, $my_info3);
mysqli_stmt_execute($stmt);
} while( your condition)
}
I am not sure why you are using mysqli_store_result(), mysqli_free_result(), or mysqli_next_result(). Since inserting rows produces no results.

Protect generic sql query statements

Any way to prevent malicious sql statements without using prepared statements and parameterized queries?
Example after simplify:
<?php
$con = mysqli_connect($_POST['db_server'], $_POST['db_user'],
$_POST['db_password'], $_POST['db_database']) or die(mysql_error());
$result = mysqli_query($con, $_POST['query_message']);
?>
Is it possible to check out the parameter $_POST['query_message'] is safe or not?
You should always build your queries within your code and then sanitise any variables you're going to use within them. NEVER pass the query or the database connection variables in via $_POST unless your user is querying the database via that form, in which case I'd recommend you just install phpMyAdmin.
As for sanitising your variables, if you really don't want to use PDO's prepared statements, you can sanitise incoming integers as follows:
$id = (isset($_POST['id']) ? (int)$_POST['id'] : null);
if ($id) {
$sql = "SELECT *
FROM `table`
WHERE `id` = {$id}";
}
And for strings use this:
$username = (isset($_POST['username']) ? mysqli_real_escape_string($con, $_POST['username']) : null);
if ($username) {
$sql = "SELECT *
FROM `table`
WHERE `username` = {$username}";
}
You can also call real_escape_string() directly on your $con object as follows:
$username = (isset($_POST['username']) ? $con->real_escape_string($con, $_POST['username']) : null);
However, as with #Shankar-Damodaran above, I highly suggest you do use PDO prepared statements to query your database.
Why you don't wanna use Prepared Statements ? That is really weird. I strongly suggest you should go for it.
You could make use of mysqli::real_escape_string for escaping quotes that is commonly used for SQL Injection Attacks.
Something like...
OOP Style
$message = $mysqli->real_escape_string($_POST['query_message']);
Procedural Style
$message = mysqli_real_escape_string($link,$_POST['query_message']);
other way is using:
htmlentities($query);
as an extra you could use preg_match() regular expressions to avoid
the inclusion of certain words (SELECT, DROP, UNION .......)
Example:
try{
$query = sprintf("SELECT * FROM users WHERE id=%d", mysqli_real_escape_string($id));
$query = htmlentities($query);
mysqli_query($query);
}catch(Exception $e){
echo('Sorry, this is an exceptional case');
}
There are real world cases where prepared statements are not an option.
For a simple example, a web page page where you can do a search on any number of any columns in the database table. SAy that table has 20 searchable columns. you would need a huge case statement that has all 20 single column queries, all 19+18+17+16+15+14+13+... 2 column queries, all possible 3 column queries... that's a LOT of code. much less to dynamically construct the where clause. That's what the OP means by prepared statements being less flexible.
Simply put, there is no generic case. If there was, php would have it already.
real_escape_string can be beaten. a common trick is to % code the character you are trying to escape so real_escape_string doesn't see it. then it gets passed to mysql, and decoded there. So additional sanitizing is still required. and when all characters used in injection are valid data, it's a PITA, because you can't trust real_escape_string to do it.
If you are expecting an integer, it's super easy.
$sanitized=(int)$unsanitized;
done.
If you are expecting a small text string, simply truncating the string will do the trick. does't matter that it's not sanitized if there's not enough room to hold your exploit
But there is no one size fits all generic function that can sanitize arbitrary data against sql injection yet. If you write one, expect it to get put into php. :)

Why will similar mysql query not execute?

Using PHP PDO with MYSQL
The following works
$customer = "2";
$ammount = "123.50";
$sql = $db->query("INSERT INTO transactions(transaction_customer,transaction_ammount) VALUES ($customer,$ammount)");
The following does not work
$biggy = "Jim";
$chum = "Tester";
$sql = $db->query("insert into customers(customer_firstname,customer_lastname,customer_telephone) values ($biggy,$chum,'7576632423');");
Any ideas why?
Your first example works because you are working with numbers.
You need quotes around the strings in the 2nd SQL statement
$sql = $db->query("insert into customers(customer_firstname,customer_lastname,customer_telephone) values ('$biggy','$chum','7576632423');");
You can avoid pitfalls like this using PHP's PDO and using prepared statements rather than writing SQL by hand. I highly recommend you look into it :)
Strings need to be quoted.
... values ('$biggy','$chum','7576632423');");
You should be using mysql_real_escape_string too, though.

I am worried about SQL Injections. Is this safe?

I am starting a very basic site that uses a single line form to post into a database and then later echo that $comment variable on the page. I don't know PDO, but am willing to learn if I truly need it for something this simple.
else
mysql_query("INSERT INTO posts (postid, post_content)
VALUES ('', '$comment <br />')");
}
mysql_close($con);
Above this code I have basic strpos commands to block out some of the things I don't want posted.
Am I going to experience any issues with injections down the road from how I am doing this?
No, it's not safe, you need to use mysql_real_escape_string to escape $comment.
But, PDO is nothing difficult and make your code stronger.
// create the connection. something like mysql_connect/mysql_error
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
// create the prepared statement.
$stmt = $dbh->prepare("INSERT INTO posts (postid, post_content) VALUES (?, ?)");
// execute it with parameters.
$stmt->execute(array('', $comment.'<br>'));
Yes this is dangerous. All someone has to do is put a single quote then the SQL code they want after. Use $comment = mysql_real_escape_string($comment) before this statement if you want to fix it the old way or use PDO prepared statements as the newer way. Here is a basic example from the documentation:
<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
?>
This is susceptible to sql injection as your $comment is input from the user they may as well enter some SQL command and your PHP code will end up executing the same.
Consider $comment value is set to 'TRUNCATE TABLE USERS;' the USERS table could be anything which might be critical for your app.
In PHP I believe you safeguard against sql injection by using mysql_real_escape_string(). Read up on it.
Refer this doc for details abt SQL innjection: https://docs.google.com/document/d/1rO_LCBKJY0puvRhPhAfTD2iNVPfR4e9KiKDpDE2enMI/edit?pli=1
Binding form input data to mysql query is the perfect solution to the sql injection. Use binaParam method for this purpose.
No, judging only by the code you’ve posted here, you are not protected against SQL injections. Here’s a simple example for $comment:
'), (null, (select concat(user(),':',password) s from mysql.user where concat(user,'#',host)=user() LIMIT 1) --
This will add another row containing the login credentials of the current user. With LOAD_FILE he could also be able to read files from your file system. He could also write arbitrary files on the file system:
' + (select '<?php echo "Hello, World!";' into dumpfile '/path/to/your/document_root/foobar.php')) --
With this technique the attacker could upload arbitrary files to your server, e. g. a web shell to run arbitrary commands on your system.
So you definitely must protect yourself against SQL injections whereby automatic escaping using prepared statements or parameterized statements is favored over manual escaping using functions like mysql_real_escape_string.

Categories