SQL Injection Protection - Where and When [duplicate] - php

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 6 years ago.
I'm building a website which uses information passed through a URL to pick out information from a database table, but it was brought to my attention that doing this may cause a SQL Injection. As I thought this was only an issue where you were inserting information into a database, I'm a bit confused as to when, how and where you should protect your code.
Currently I have a url which looks like:
www.website.com/article.php?title=title&id=1
Which is shortened in htaccess to www.website.com/article/title/1
In my article.php page I then have:
<?php
if(isset($_GET["id"])){$url_id = $_GET["id"];}else{
header("Location: $site_url");
exit();
};
?>
<?php
if(isset($_GET["title"])){$url_title = $_GET["title"];}else{
header("Location: $site_url");
exit();
};
?>
<?php
$article_sql = "SELECT ...
I currently use mysqli_real_escape_string to prevent SQL Injection threats, but I'm unsure where to use it here. I'm guessing that adding...
...
<?php
if(isset($_GET["title"])){$url_title = $_GET["title"];}else{
header("Location: $site_url");
exit();
};
?>
<?php
$url_id = mysqli_real_escape_string($url_id); // ADDED
$url_title = mysqli_real_escape_string($url_title); // ADDED
?>
<?php
$article_sql = "SELECT
...
Should do the trick, but is this correct?

You already use mysqli_ so take advantage of it. Here is simple example based on code you provide:
<?php
// $mysqli is the connection
$article_sql = $mysqli->prepare("SELECT * FROM table WHERE url_id = ? AND url_title = ?");
$article_sql->bind_param("is", $url_id, $url_title);
$article_sql->execute();
$result = $article_sql->get_result();
while ($row = $result->fetch_array(MYSQLI_NUM)) {
foreach ($row as $r) {
print "$r ";
}
print "\n";
}

Related

How to obtain the value of a PHP variable through a SQL Query?

I'm currently working on a challenge problem which asks for you to submit a SQL Query in order to obtain an answer. However, it isn't a simple SQL injection, as the PHP source code has a little safeguard that only outputs an answer when a certain input is given. Here is the code below:
<?php
include "config.php";
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');
$answer = $_POST["answer"];
$debug = $_POST["debug"];
$query = "SELECT * FROM answers WHERE answer='$answer'";
echo "<pre>";
echo "SQL query: ", htmlspecialchars($query), "\n";
echo "</pre>";
?>
This simply outputs the SQL query I put in. Below it is the safeguard:
<?php
$con = new SQLite3($database_file);
$result = $con->query($query);
$row = $result->fetchArray();
if($answer == $CANARY) {
echo "<h1>Perfect!</h1>";
echo "<p>Your flag is: $FLAG</p>";
}
elseif ($row) {
echo "<h1>You are so close.</h1>";
} else {
echo "<h1>Wrong.</h1>";
}
?>
My theory is that one can display the value of $CANARY through the SQL Query, with the line that says echo "SQL query: ", htmlspecialchars($query), "\n"; However, I am at odds of how to do so.
I understand that there is a similar question about this challenge, but I think that doesn't really ask for how to put the PHP part into the SQL, just how to perform a SQL injection. My knowledge of PHP is limited, as I basically started learning it today when I started this problem; potentially this is a PHP injection?
Thanks to whoever can help me with this!
Yes. SQL injection can be.
For example, if set
$answer = "'; DELETE FROM answers WHERE ''='";
your code delete answers table
You need use
SQLite3::escapeString($answer)
And construction
$row = $result->fetchArray();
get array of values from table answers, and you need compare value from array, as i think

How would I do an sql injection to this? I am not asking for how to prevent this

Just a quick question since I am not experienced in this field at all. How would I do an sql injection to this?
I would like examples of sql injection.
Please don't comment to just type ' or '1' = '1 as that wont work. All it will reply with is the sentence from the elseif statement saying "You are so close."
<?php
include "config.php";
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');
$answer = $_POST["answer"];
$debug = $_POST["debug"];
$query = "SELECT * FROM answers WHERE answer='$answer'";
echo "<pre>";
echo "SQL query: ", htmlspecialchars($query), "\n";
echo "</pre>";
?>
<?php
$con = new SQLite3($database_file);
$result = $con->query($query);
$row = $result->fetchArray();
if($answer == $CANARY) {
echo "<h1>Perfect!</h1>";
echo "<p>Your flag is: $FLAG</p>";
}
elseif ($row) {
echo "<h1>You are so close.</h1>";
} else {
echo "<h1>Wrong.</h1>";
}
?>
How would I do an injection to this query?
Please don't mark this as a duplicate to that major post that I have already read. That post isn't the same as this query from what I've tried.
Just send the following string in $_POST["answer"]:
$_POST["answer"] = "' OR '1' = '1";
$answer = $_POST["answer"];
$query = "SELECT * FROM answers WHERE answer='$answer'";
Now, your query will read as follows:
SELECT * FROM answers WHERE answer='' OR '1' = '1'
It will give you all the rows from answers table. If you use this SQL query results to check whether the given answer by a user is correct or not; you will always get some rows, hence answer will always pass no matter what.
Similarly, for eg, one can get details of all the customers, their phone number, email addresses, etc; if one passes customer_id = "' OR '1' = '1"
Do read this thread completely: How does the SQL injection from the "Bobby Tables" XKCD comic work?

is it safe to pass an id of data selected from mysql database across pages and use it to fetch and display more data in php? [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 5 years ago.
I have a web page where after connecting to and selecting courses from the database, the courses are displayed with a link to view each course as below:
<div class="col-md-4">
//query db action and assign the query to $result
$result = $dbcon->query($query);
if($result -> num_rows > 0){
//If courses are available(rows > 0), fetch and display them
while($row = $result->fetch_object()){
echo '<h2>'.$row->course_title.'</h2';
echo '<p>'.$row->course_description.'</p>';
echo 'View Course';
}
}
</div>
And this is the code for view.php page:
if(isset($_GET['action']) && $_GET['action'] == "view"){
//Assign var $id to the id from the _GET array
$id = $_GET['t'];
//Use the $id to fetch course details from the database
$query = ("SELECT * FROM courses WHERE course_id = '$id'");
//Query the db action
$result = $db_connect->query($query);
$rows = mysqli_num_rows($result);
if($result && $rows > 0){
while($row = $result->fetch_object()){
echo '<div class="col-md-10">';
echo '<h1>'.$row->course_title.'</h1>';
echo '<p>'.$row->course_description.'</p>';
echo '<div class="col-md-6"><span class="inline-elm">'.$row->course_subject.'</div>';
echo '<div class="col-md-6"><span>'.$row->course_level.'</p></div>'</div>';
}
}
}
My problem is that I'm not sure whether this is proper and of course, safe to do or there is a safer/proper way to do it. Will really appreciate your answers. Thanks
It's fine to pass ids inside urls, but they should be handled like any other data, ie properly sanitized, validated and escaped. A prepared statement is a good way to do this. At the very least, here, since you expect an int, you can do:
$id = intval($_GET['t']);
Note that prepared statements do not protect against XSS vulnerabilities which would occur if doing "echo $id" without wrapping it in htmlspecialchars. Input sanitization is always nice, if it's an int, stick an intval on it! You never know...

How TO Avoid '=' 'or' [duplicate]

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
i make PHP site
With USER / Pass Login
But USer can Skip This Page BY Use
'=' 'or'
‘ or 1=1
Like this
Code Here In File Login_Check.php
`
include("includeszzz/host_conf.php");
include("includeszzz/mysql.lib.php");
$obj=new connect;
$obj1=new connect;
$username=$_GET["username"];
$password=$_GET["password"];
//echo $username;
//echo $password;
$sql="select username from admin where username='$username'";
$obj->query($sql);
$U_num=$obj->num_rows();
//echo $U_num;
if($U_num!=0) {
$sql1="select password from admin where username='$username' and password='$password'";
$obj1->query($sql1);
$P_num=$obj1->num_rows();
if($P_num!=0) {
session_start();
$_SESSION["zizo"]="$username";
//header("location: welcome.php");
echo "1";
} else {
echo "Invalid Password Please Try Again";
}
} else {
echo "Invalid Username Please Try Again";
}
`
You want to avoid using user data in queries without any type of sanitation.
http://php.net/manual/en/security.database.sql-injection.php
"Example #5 A more secure way to compose a query..."
<?php
settype($offset, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// please note %d in the format string, using %s would be meaningless
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$offset);
?>
If the database layer doesn't support binding variables then quote
each non numeric user supplied value that is passed to the database
with the database-specific string escape function (e.g.
mysql_real_escape_string(), sqlite_escape_string(), etc.). Generic
functions like addslashes() are useful only in a very specific
environment (e.g. MySQL in a single-byte character set with disabled
NO_BACKSLASH_ESCAPES) so it is better to avoid them.
Do not print out any database specific information, especially about
the schema, by fair means or foul. See also Error Reporting and Error
Handling and Logging Functions.
You may use stored procedures and previously defined cursors to
abstract data access so that users do not directly access tables or
views, but this solution has another impacts.
Additionally, you can make use of Binding Parameters:
http://php.net/manual/en/pdo.prepared-statements.php
<?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();
?>

SQL Injections PDO Protect

I have one question
In my aplication all SQL Queries are with PDO. For Example Notes:
<?php
include "config.php";
$User_Check = $_SESSION['Login_User'];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
Notes = $_POST["Notes"];
try {
$sql = $conn->prepare('UPDATE Accounts SET Notes = :Notes WHERE Username = :User_Check');
$sql->execute(array('Notes' => $Notes, 'User_Check' => $User_Check));
header('Location: home.php?Message=Uspesno');
} catch(PDOException $e) {
header('Location: home.php?Message=Greska');
}
}
$sql = $conn->prepare('SELECT Notes FROM Accounts WHERE Username = :User_Check');
$sql->execute(array('User_Check' => $User_Check));
$row = $sql->fetch(PDO::FETCH_ASSOC);
$SelectNotes = $row['Notes'];
conn = null;
?>
Now I wnat to know how much is this way secure? Can anyone do SQL Injection? And do I need to add some other form of protection? Thanks!
As long as the string passed to prepare() is static (i.e. does not contain any variables), you should be safe from SQL injections.
The important part is separating user input from your SQL statements, and you do that by having the SQL passed to prepare() and the user input to execute().
Similar question: How does a PreparedStatement avoid or prevent SQL injection?
(The question is tagged java, but neither the question nor the answer are specific to Java.)
With PDO you don't need to escape string for prevent sql injection because prepare fx do this job.
So yes your requests are secure.

Categories