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.
Related
I am teaching myself php and MySQL, and right now I have a problem with MySQL.
I want to compare the phone number that the user put in with the phone number in MYSQL, and if it is in MYSQL to not register it again.
My code:
<?php
require_once 'connection/connection.php';
// Variables from HTML to php
$worker_Name = $_POST['workerNameFromHtml']; // worker Name
$worker_City = $_POST['workerCityFromHtml']; // workerCity
$worker_career = $_POST['workerCareerFromHtml']; // worker career
$worker_PhoneNumber = $_POST['workerPhonNumberFromHtml']; // worker Phone Number
$worker_SecondPhoneNumber = $_POST['workerSecondPhoneNumberFromHtml']; // worker Second Phone Number
$submt=$_POST['submitFromHtml'];
if($submt){
$qry = ( "SELECT workrPhoneNumber FROM workersTable WHERE workrPhoneNumber = '$worker_PhoneNumber'") or die(mysql_error());
$result = $connect->query($qry);
$num = $result->num_rows;
if ($num == 1) {
$here = "INSERT INTO workersTable VALUES('','$worker_Name','$worker_City','$worker_career','$worker_PhoneNumber','$worker_SecondPhoneNumber')";
$query = $connect->query($here);
print "Successfully added!";
}
else {print "This number has already been entered Thank you for your cooperation!";}}
$connect->close();
So far I have not found a solution to this problem.
your biggest problem here is that you are trying to include variables inside of a string.
"SELECT workrPhoneNumber FROM workersTable WHERE workrPhoneNumber = '$worker_PhoneNumber'"
If you want to do it this way, you need to concatenate your variables with your string.
"SELECT workrPhoneNumber FROM workersTable WHERE workrPhoneNumber = '".$worker_PhoneNumber."'"
Keep in mind if you do this you will want to sanitize your variables first to prevent SQL injections. Also, when you INSERT variables, you will actually want to use a prepared statement like this:
"INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)"
where the 1st set of values are the names of your columns in the database and the second set are your PHP variables you are putting into it.
trying to submit data from a form but does not seem to be working. Can't spot any problems?
//Include connect file to make a connection to test_cars database
include("prototypeconnect.php");
$proId = $_POST["id"];
$proCode = $_POST["code"];
$proDescr = $_POST["descr"];
$proManu = $_POST["manu"];
$proCPU = $_POST["cpu"];
$proWPU = $_POST["wpu"];
$proBarCode = $_POST["barcode"];
$proIngredients = $_POST["ingredients"];
$proAllergens = $_POST["allergenscon"];
$proMayAllergens = $_POST["allergensmay"];
//Insert users data in database
$sql = "INSERT INTO prototype.Simplex_List (id, code, descr, manu, cpu, wpu, barcode, ingredients, allergenscon, allergensmay)
VALUES ('$proId' , '$proCode', '$proDescr' , '$proManu' , '$proCPU' , '$proWPU' , '$proBarCode' , '$proIngredients' , '$proAllergens' , '$proMayAllergens')";
//Run the insert query
mysql_query($sql)
First and foremost, please do not use mysql_*** functions and please use prepared statements with
PDO http://php.net/manual/en/pdo.prepare.php
or mysqli http://php.net/manual/en/mysqli.quickstart.prepared-statements.php instead. Prepared statements help protect you against sql injection attempts by disconnecting the user submitted data from the query to the database.
You may want to try using mysql_real_escape_string http://php.net/manual/en/function.mysql-real-escape-string.php to ensure no stray " or ' is breaking your query.
$proId = mysql_real_escape_string($_POST["id"]);
$proCode = mysql_real_escape_string($_POST["code"]);
$proDescr = mysql_real_escape_string($_POST["descr"]);
$proManu = mysql_real_escape_string($_POST["manu"]);
$proCPU = mysql_real_escape_string($_POST["cpu"]);
$proWPU = mysql_real_escape_string($_POST["wpu"]);
$proBarCode = mysql_real_escape_string($_POST["barcode"]);
$proIngredients = mysql_real_escape_string($_POST["ingredients"]);
$proAllergens = mysql_real_escape_string($_POST["allergenscon"]);
$proMayAllergens = mysql_real_escape_string($_POST["allergensmay"]);
Additionally ensure your form is being submitted by calling var_dump($_POST) to validate the data
You can also see if the query is erroring by using mysql_error http://php.net/manual/en/function.mysql-error.php
if (!mysql_query($sql)) {
echo mysql_error();
}
advices about PDO, prepared statements were done.
1) Do you have a database and connection to it?
Look at your prototypeconnect.php and find database name there. check that its name and password is similar that u have.
2) Do you have a table named prototype.Simplex_List in your database?
a) IF YOU HAVE:
check if your mysql version >= 5.1.6
http://dev.mysql.com/doc/refman/5.1/en/identifiers.html
b) IF YOU HAVE BUT ITS NAME is Simplex_List:
b-1) if your database name IS NOT prototype:
replace your
$sql = "INSERT INTO prototype.Simplex_List
with
$sql = "INSERT INTO Simplex_List
b-2) if your database name IS prototype:
you should escape your $_POST data with mysql_real_escape_string as #fyrye said.
c) IF YOU HAVE NOT:
you should create it
3) Check your table structure
does it have all theese fields id, code, descr, manu, cpu, wpu, barcode, ingredients, allergenscon, allergensmay?
if you have there PRIMARY or UNIQUE keys you should be sure you are not inserting duplicate data on them
but anyway replace your
$sql = "INSERT INTO
with
$sql = "INSERT IGNORE INTO
PS: its not possible to help you without any error messages from your side
I have created this code for testing of SQL injection.
<?php
mysql_connect('localhost', 'root', '');
mysql_select_db("test");
$id = $_POST['data'];
$query = "SELECT * FROM members WHERE memberId ='" . $id . "'";
$q = mysql_query($query);
if (mysql_num_rows($q) == 0)
{
printf("<h4>Wrong user ID!</h4>");
}
else
{
while ($row = mysql_fetch_array($q))
{
printf("<h4>Your ID is %s</h4>", $row["memberId"]);
}
}
?>
When variable $id is 1' OR '1'='1, I can see all IDs in the table members.
I would like also realize DROP TABLE, but I can't figure out what to insert in variable id $id. I have tried to insert 123'; DROP TABLE sql injection-- in $id.
Do you have any idea what to insert in $id or how to modify this code?
In the console it would be: '; drop table members; select '
However you are using mysql_query and it supports only a single statement.
Here is what the manual says:
mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.
Also check this question.
As suggested there you can try using multi_query in your example.
another day another question...
I need to write PHP script to update mySQL database.
For example: updating profile page when user want to change their first name, last name or etc.
Here is my php script so far, it doesn't work. Please help!
<?php
# $db = new MySQLi('localhost','root','','myDB');
if(mysqli_connect_errno()) {
echo 'Connection to database failed:'.mysqli_connect_error();
exit();
}
if (isset($_GET['id'])) {
$id = $db->real_escape_string($_GET['id']);
$First_Name2 = $_POST['First_Name2'];
$query = "UPDATE people SET $First_Name2 = First_Name WHERE `Id` = '$id'";
$result = $db->query($query);
if(! $result)
{
die('Could not update data: ' . mysql_error());
}
echo "Updated data successfully\n";
$db->close();
}
?>
THank you.
Your sql is wrong. Apart from the gaping wide open SQL injection attack vulnerability, you're generating bad sql.
e.g. consider submitting "Fred" as the first name:
$First_Name2 = "Fred";
$query = "UPDATE people SET Fred = First_name WHERE ....";
now you're telling the db to update a field name "Fred" to the value in the "First_Name" field. Your values must be quoted, and reversed:
$query = "UPDATE people SET First_name = '$First_Name2' ...";
You are also mixing the mysqli and mysql DB libraries like a drunk staggering down the street. PHP's db libraries and function/method calls are NOT interchangeable like that.
In short, this code is pure cargo-cult programming.
I have two files in use. The first is a front end select box with a list of dynamically populated char/text values that uses POST to send the selected value to a back end file. This back end file assigns this value to a variable and that variable is then used in the following query:
$query = "SELECT DoctorName, Speciality FROM hospital WHERE HospitalName =".$hosname;
However, I keep getting the Invalid Query message I have set in my or die(); and I have no idea why. The full section of php code on the backend file is as follows:
$conn = mysqli_connect("localhost", "root", "") or die ("No connection");
mysqli_select_db($conn, "hospitaldb") or die("db will not open");
$hosname=$_POST['valuelist'];
$query = "SELECT DoctorName, Speciality FROM hospital WHERE HospitalName =".$hosname;
$result = mysqli_query($conn, $query) or die("Invalid query");
echo "<table border='1'><tr><th>mDoctorName</th><th>Speciality</th></tr>";
while($row = mysqli_fetch_array($result))
{
echo "<tr><td>" . $row[0] . "</td><td>" . $row[1] . "</td></tr>";
}
echo "</table>";
mysqli_close($conn);
Note: I have checked that the value from the select box is being passed in using print and it is. Any help would be greatly appreciated.
*I am only testing this locally but thanks to all who recommended mysql_real_escape_string() to protect against injections.*
It looks like you're not wrapping the value in quotes, so the query is malformed. My PHP is rusty, excuse me if there is a syntax error in my example, below:
$query = "SELECT DoctorName, Speciality FROM hospital WHERE HospitalName ='".$hosname ."';";
However, the string concatenation leaves you open to SQL Injection (http://en.wikipedia.org/wiki/SQL_injection). Consider using prepared statements http://php.net/manual/en/pdo.prepare.php
The resulting SQL query you want would be something like;
SELECT DoctorName, Speciality FROM hospital WHERE HospitalName = 'MyHospital'
In other words, you need to add quotes to your query creation;
$query = "SELECT DoctorName, Speciality FROM hospital WHERE HospitalName = '".$hosname."'";
You should really also escape the hospital name using mysql_real_escape_string() before just inserting it into a query.
Actually, your error is you need to surround your variable in single quotes like:
$query = "SELECT DoctorName, Speciality FROM hospital WHERE HospitalName ='".$hosname."'";
I'm assuming $hosname is a string. Your query is failing because you haven't quoted it.
$query = "SELECT DoctorName, Speciality FROM hospital
WHERE HospitalName = '" . mysql_real_escape_string($hosname) . "'";
Note I added mysql_real_escape_string as well as the quotes to protect from SQL Injection attacks. You should read and learn about SQL Injection attacks because your code is vulnerable to them. Also consider using PDO which helps take care of these things for you.
Use ' (quotes) around your .$hosname variable name.