SQL injection theory - php

I'm using ORM layer in databases all the time, so I don't mind about SQL injections, but a friend gave me this task and I still have no idea how to solve it.
I know the PHP script just checks if the return of the query is != null (username matching to entered username & password is found).
The query itself in PHP looks like:
$sql = "SELECT name FROM users WHERE name='".$name. "' AND password='".$password. "'";
What's the best way to archieve a return of this query != null OR retrieving valid login data (username & password). The password is stored plain in database. I know storing plain is bad and I know using PDO is good, but I have no idea how to solve this funny task he gave me, maybe because I use PDO all the time.

Say we have these two input variables:
$name = "iam";
$password = "aninjection";
Which results in this query:
$sql = "SELECT name FROM users WHERE name='iam' AND password='aninjection'";
And let's say now we add this to the $password variable:
$password = "aninjection' OR 1='1";
Which results in:
$sql = "SELECT name FROM users WHERE name='iam' AND password='aninjection' OR 1='1'";
This query will now result in true and show every name from the user table.
This is of course a basic example. We could also do more harm by dropping entire tables.

If you wanted to retrieve passwords you would inject
$name = "whatever";
$password = "' OR '1'='1' UNION ALL SELECT password from users;--";
This would then make the query
SELECT name FROM users WHERE name='whatever' AND password='' OR '1'='1' UNION ALL SELECT password from users;--'
See this answer for how an attacker would start to work this out from injecting into the query.

Related

Problem with SQL query with variable that calls by php

I wrote a SQL query for checking name in php, but it does not work.
I have no assumptions how to fix it, but I assume it's just mistake in syntax.
$username = $_POST["username"];
$nameCheckQuery = "SELECT username FROM users WHERE username '" . $username . "';";
$nameCheck = mysqli_query($db, $nameCheckQuery) or die("2: Name check query failed");
I receive error log on query.
The reason it's failing is likely due to you missing a = after username.
This code is open to SQL injection and you should use prepared statements.
The most basic of a prepared statement looks something like this:
$stmt = $db->prepare("SELECT * FROM users WHERE username = ?");
$username = $_POST['username'];
$stmt->bind_param('s', $username);
$result = $stmt->execute();
The main problem of your query is that you forget to insert = next to WHERE username.
You have to write:
$nameCheckQuery = "SELECT username FROM users WHERE username ='" . $username . "';";
Right now it works but......
The query you are using is not preventing a SQL INJECTION attack (one of the most used attack against database).
Please take a look at the ways you can connect to the database:
use PDO (it works with 12 database type);
use MSQLI (it works only with MYSQL database and you are using it);
In other word, if you are planning that you will move your application in another database type please consider to use PDO, instead.
Using PDO preventing SQL injection you have to prepare the SQL statement like this:
$stmt = $pdo->prepare("SELECT username FROM users WHERE username = ?");
$stmt->execute([$_POST['username']]);
$arr = $stmt->fetch();
For Starter, please use this escape string:
$username = $mysqli->real_escape_string($_POST["username"]);
Simply do it like this and don't get confused with quotes.
You can still print php variables inside single quote like this.
$nameCheckQuery = "SELECT username FROM users WHERE username = '$username'";
or to edit your code, this is how you can achieve it.
$nameCheckQuery = "SELECT username FROM users WHERE username ='" . $username."'";
Just to answer your question, it is Vulnerable to Sql Injection.
Reasons why Sql Injection occurs:
SQL Injection occurs when an attacker is able to send their own instructions to your database and the database executes those instructions. This occurs when a PHP developer has taken input from a website visitor and passed it to the database without checking to see if it contains anything malicious or bothering to clean out any malicious code.
SQL Injection can allow an attacker to access all of your website data. They can also create new data in your database which may include links to malicious or spam websites. An attacker may also be able to use SQL Injection to create a new administrative level user account which they can then use to sign-into your website and gain full access.
SQLi is a serious vulnerability because it is easy to exploit and often grants full access immediately.
This is how you can achieve it, which provides detailed functionality.
https://stackoverflow.com/a/60496/6662773

Is this update statement missing something?

I have made a database where email id and corresponding name and password is stored. I have successfully obtained a form's data.. where the user enters updated name and password. But the problem is occuring with the query which is as follows
$db = mysqli_connect(all details)...
$name = $_POST['name'];
$password = $_POST['password']:
$email = $_POST['email'];
$query = "UPDATE mytable SET name='$name',password='$password' WHERE emailid='$email'";
$result = mysqli_query($db,$query);
Though I am getting all form values succesffuly and until and unless I put the 'where' clause.It works.But obviously updates all values. i want it to work with where..but so far unsuccessful :(
you need to put {} around the variables if its surrounded by quote ''
so your query should look like this
$query = "UPDATE mytable SET name='{$name}',password='{$password}' WHERE emailid='{$email}'";
$result = mysqli_query($db,$query);
EDIT : also before saving data to database make sure to filter and validate data
You need to make sure that emailid exists in mytable, you truly intended to filter by it and in your database scheme it has a type which supports the posted data. It seems that you are sending strings, like 'foo#bar.lorem' and your emailid is an int or something in the database scheme. Check it by running
desc mytable;
You need to put curly brackets around variables if you use apostrophe around them, but as a matter of style I like to close the string and attach the $variable with a . as this coding style is closer to me personally.
If everything fails, see what is generated, by echoing out the query string, try to run that directly, see what the error is and fix until...
... until it is fixed.
Also, you do not encrypt the password and your code is vulnerable to SQL injection too. Please, read about password encryption and SQL injection and then protect your project against these dangers.
You can write your statement as:
$query = "UPDATE mytable SET name='".$name."',password='".$password."' WHERE emailid='".$email."'";
using . as string concatenating operator

Hacking PHP code with SQL injection

I have some code like this which is open to SQL injection. We got hacked and now we fixed it. I just want to know what the inputs (username and password) must be in order to hack this code. I mean even if you input
username = something' OR 'x'='x
Then you can retrieve the password of the first user in the table regardless of the username. However, inside the if we check whether this password is correct. I am assuming the password was very easy (as easy as 123456) and the hacker made a brute-force from a dictionary. However I am wondering if there is another way to hack this code using some injection other than brute-forcing the password.
<?php
$username=$_POST['username'];
$password=$_POST['password'];
$result=runQuery("SELECT password FROM tbl_users WHERE username='".$username."''");
$row=mysql_fetch_array($result);
if($row['password']==$password){
-- do sth... create a cookie etc..
}
else{
--go to another page...
}
?>
Use variable binding in PDO library.
If hacker pass value:
$username = "' OR * OR '"
then query will be:
SELECT password FROM tbl_users WHERE username='' OR * OR ''; - this will be select any user.
But hacker can:
$username = "'; DELETE * FROM tbl_users WHERE username = * OR '";
SELECT password FROM tbl_users WHERE username = ''; DELETE * FROM tbl_users WHERE username = * OR '';
Or can made UPDATE to change any password.
Safety? mysql_real_escape_string or preg_match("/^[a-zA-Z0-9]{3,15}$/", $username), for example.
Using boolean blind or time blind injection hacker can retrieve all the database structure.
Example:
username = 'admin' and if(1=1, sleep(10), 5222) #
This query gonna take 10 second to return and confirm that your condition is true or false. Using the information_schema and SQL condition test you can retrieve all databases information.

How to Inject SQL in this Example

My question is pretty specific, but I think it will help in my overall understanding of security and SQL injection. I am running a local webpage with a simple form for the purpose seeing how SQL injection works first hand, by doing it to my own database and webpage. I keep changing the way my php file validates a user so I can see the differences. I am a beginner and the php file is very simple on purpose. My current php code is:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$conn = mysql_connect('localhost', 'root', 'password');
mysql_select_db(test1);
$query = "SELECT username, password FROM users WHERE username = '$username'";
$result = mysql_query($query) or die("Query failed: " . mysql_error());
$arr = mysql_fetch_array($result);
if($arr['username'] == $username && $arr['password'] == $password && strlen($username) > 0){
header('Location:index.php');
}else{
header('Location:login.html');
}
?>
I have no idea if this is a good or bad way of validating. I just want to know an example of how to inject it because I can't figure this one out. MySQL_query() only allows 1 statement so I can't chain together statements, and I don't know what else to do to it. I have changed the file so I can do
' or 1=1; -- types of injection, but obviously that one will not work here. So just curious. Thanks.
The following passed to username would return all the rows:
' or '1'='1
In general its simply not a good idea to pass unvalidated input to a SQL query.
Send this as username:
a' and(select 1 from(select count(*),concat((select concat_ws(0x3a,version(),database())),floor(rand(0)*2))x from information_schema.tables group by x)a) union select 1,'
I'm not sure but I think it's not possible to get redirected to index.php, but the above example will show you something interesting.
Such security holes should never be left non sanitized because a malicious user can get even the mysql's root user password if SELECT command is permitted to mysql table and so on.
By the way, you should never display mysql_error()s to end-users.
Consider the following query :
SELECT username, password FROM users WHERE username = 'anything' AND 0 =1
UNION ALL
SELECT '\'anything\' AND 0 =1
UNION ALL
SELECT \'user\',\'password\'','password'
If $_POST['password'] equals word 'password', your validation will fail and let unauthorized user to access protected page.
You are not doing any validation on your post parameters before you execute your statement. This is bad! And SQL injection is easily possible.
For example:
SELECT username, password FROM users WHERE username = '$username' AND (SELECT 1 FROM ([Almost any SQL statement you want...]))
I.E.
$username = "' AND (SELECT 1 FROM ([Almost any SQL statement you want...])); --"
Make sure you validate your parameters before using them in a SQL statement.

Querying PHPMYADMIN with two constraints

I am trying to create a login script that pulls information by verifying that the username is part of a group. In other words i am using two "ands" to verify info. Am i doing this correctly?
PHP:
$check = mysql_query("SELECT username ,password FROM customers WHERE username = '".$_POST['user_name']."' and group_name='".$group_name."'")or die(mysql_error());
Brandon Horsley and Matt Gibson already mentioned it as comments - think about SQL injection. Next thing is that I strongly don't recommend to use die(mysql_error()). Otherwise an experienced user might be able to "read something" out of that.
The easiest way is to use mysql_real_escape_string() (http://de.php.net/mysql_real_escape_string) - so you could adapt your code just like that (I assume that $group_name is also a value that can be manipulated by user):
<?php
// ...
$check = mysql_query("SELECT username, password FROM customers WHERE username = '". mysql_real_escape_string($_POST['user_name']) ."' and group_name = '". mysql_real_escape_string($group_name) ."'") or die('error);
// ...
?>

Categories