I'm creating a SQL Injection demo as a project for my class. I've created a login page but i cant seem to be able to inject it. Here is what I have written for the page. I have tried blind SQLi creating multiple clauses withing the username field. The only other thing I can think of is to use subqueries or to change my code to make it easier.
EDIT* Trying to Inject the username field *
<?php // Check to see if there was a request method that is a post type
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
// Check to see if username field is null
if (!empty($_POST['username'])) {
// Connect to the server using credentials
$con = mysql_connect('localhost','root','sqlcool1');
// If the connection was not successful
if (!$con){
echo 'OUCH';
die('Could not connect: '.mysql_error());
}
// Select the correct database from the server
$db = mysql_select_db('injectme',$con);
// Pass a sql query through the table to pull the user field that was entered in the form
// Return the results in an array
$sql = mysql_query('SELECT * FROM user WHERE username = "' . $_POST['username'] . '"');
$row = mysql_fetch_row($sql);
// compare $row["password"] to $_post["password"]
// if they match it's good: log them in
// if not, they're beat: don't log them in
if ($_POST["username"] == $row[1] && $_POST["password"] == $row[2]) {
// do something to let them know that it worked
echo('<html>
<head>
<meta http-equiv="refresh" content="3; url=search.php">
</head>
<body>
<p style="color:green">logged in</p>
</body>
</html>');
} else {
// do something to let them know it didn't work
echo('<p style="color: red">Invalid username or password.</p>');
echo('<form name="login" action="login.php" method="POST">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" name="submit_button" value="Submit">
<button type="submit" formaction="register.php">Register</button>
</form>');
}
//Close the connected session with the server
mysql_close($con);
} else {
// Repost Form
echo ('<p style="color: red"> No username / password provided.</p>');
echo('<form name="login" action="login.php" method="POST">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" name="submit_button" value="Submit">
<button type="submit" formaction="register.php">Register</button>
</form>');
}
}
else
{
echo('<form name="login" action="login.php" method="POST">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" name="submit_button" value="Submit">
<button type="submit" formaction="register.php">Register</button>
</form>');
}
?>
The code you have posted is entirely vulnerable and can be used to view the content of the entire database. One way to exploit it is with time based attack where you create an artificially long response time if a condition is true.
Consider the following username :
" UNION SELECT (WHEN "A" = (SUBSTR(password, 1, 1)) THEN SLEEP(5) ELSE 1 END) AS username, 1 as password FROM user LIMIT 0, 1 --
If the response is longer than 5 seconds, you can know the value of the first character is "A" otherwise just test for an other character. After that you just have to repeat the same pattern for other position in the string until you have found all characters of the password. After that, you can just directly use the admin password. Since it requires a lot of queries those type of attack are often scripted.
If you want to read more about it, it's called Blind SQL Injection.
To successfully exploit this vulnerability, you need to be able to inject some code such that the resulting SQL statement will return something that will pass the later test:
$_POST["username"] == $row[1] && $_POST["password"] == $row[2]
So the second column needs to be equal to the submitted username and the third row needs to be equal to the submitted password.
Now as the injection happens with the submitted username, you have a problem.
Because you cannot supply a username that fulfills both the inject some data into the result set aspect and the inject a value for the username that is identical to the injected code that injects a value for the username aspect.
The former is quite easy (assuming three columns in user):
username := '" UNION SELECT 1, "admin", "'
password := ''
This results in:
SELECT * FROM user WHERE username = "" UNION SELECT 1, "admin", ""
However, the $_POST["username"] == $row[1] part remains unresolvable as you would need to make the second SELECT return the submitted username as username column value. And that’s just not possible.
Now if you just remove the $_POST["username"] == $row[1] it works fine.
It depends on what you are trying to inject. If you are trying to inject a second query, this is not possible - the mysql_query function does not support multiple queries. From the docs:
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.
Of course, it is still vulnerable to additional WHERE clause injections.
Related
Really can't finish my project because of this condition. My project is a Login Page.
It always continues to the first if condition, but it is for else condition. I just only started studying this php now, although it is being taught to us last week.
login.php
<?php
session_start();
include 'register/dbconnect.php';
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$sql = "SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'";
$result = mysqli_query($connect, $sql);
if (!$row = mysqli_fetch_assoc($result)) {
header("Location: index.php");
} else {
header("Location: login/home/home.php");
}
?>
index.php (in the login form part)
<form action="login.php" method="POST">
<input type="text" name="uid" class="loginField" placeholder="Enter your username" required><br />
<input type="password" name="pwd" id="passss" class="loginField" placeholder="Enter your password" required>
<img src="withAcc/img/blindeye.png" onMouseOver="showPass()" onMouseOut="hidePass()" id="eye1" class="eyes"><br /><br />
<p><input type="checkbox" id="keepSigned" value=""> <label for="keepSigned">Stay signed in</label>
Forgot password?</p>
<input type="Submit" value="Login" id="logInBut" ><br />
<p>Do you have an account? Register</p>
</form>
Edited login.php
if (!$row = $result->fetch_assoc()) {
header("Location: index.php");
} else {
header("Location: login/home/home.php");
}
I edited it like this, but it neither works. It always going to index.php, although the username and password is stored in the database.
This is a pretty strange condition:
if (!$row = mysqli_fetch_assoc($result)) {
And I can't help but wonder if some combination of operator precedence and query success/failure is going to silently produce unexpected results here. I imagine a more intuitive way of doing this would be to check the number of rows in the query result:
if (mysqli_num_rows($result) > 0) {
However, there are a couple other improvements you should make as well to round this out a bit better. First, as mentioned in comments on the question above, you should definitely make use of prepared statements to avoid SQL injection. This is important not only for security but also for general stability and debugging of your code. (Directly using input as code like you currently do makes you much more responsible for the syntax of that code, which often leads to errors.)
Additionally, after executing a query (and before examining the results of that query, so before your if statement) you should check if the query was successful. If it's not successful, your $result variable will be null. So check if $result is null and if it is, don't try to use it for logging in. Instead, examine the error from the database. Something as simple as:
echo mysqli_error($connect);
Also, and this is very important, you are currently storing user passwords in plain text. This is a very, very bad thing. User passwords should always be hashed so that they can't be retrieved in their original form. PHP has some built-in functionality to help with this.
i have created a leaderboard for a website which displays users high scores for a game. but whe the user goes to edit their high score, it doesnt change in the database or on the screen. does anybody know how to update the database using a post method. my code is below.
require_once('../sokodatabase.php');
//require_once('../sokodatabase.php');
//require_once('../sokodatabase.php');
if(isset($_POST['userId'])){
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$query = "
UPDATE leaderboardhighscores
SET highScores=".$_POST["highScores"].", rankNo=".$_POST["rankNo"]."
WHERE userId=".$_POST["userId"];
var_dump($_POST);
echo $query;
#mysqli_query($dbc, $query);
}
}
$manager = new DatabaseManager;
$manager->SelectHighScores();
?>
<form method="post" action="highScores.php">
high score <input type="text" name="highScores"/>
rankNo <input type="text" name="rankNo"/>
userId <input type="text" name="userId"/>
<input type="submit" value="Submit">
</form>
You have to provide attention to SQL injections!
Normally, you check for the submit button:
<input type="submit" name="submit" value="Submit">
Then
if(isset($_POST['userId'])){
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
goes to:
if(isset($_POST['submit'])){
If your query does not work, you can make die($query) to see it and perform it via phpMyAdmin. Or you can use mysqli_error to display any occured error after executing it.
Please note, that with your code only numeric values are possible. If your fields are not numeric, you should use this:
$query = "
UPDATE leaderboardhighscores
SET highScores='".mysqli_real_escape_string($dbc, $_POST["highScores"])."', rankNo='".mysqli_real_escape_string($dbc, $_POST["rankNo"])."'
WHERE userId=".intval($_POST["userId"]);
Need name for the submit input type in-order to submit the form...
Like
<input type="submit" name="userId" value="Submit">
if(isset($_POST['userId']))
I am having trouble thinking out a good way to update my query depending on user $_POST values. Basically I have user management search button, where site administrator can search for his sites users. In my example:
<div id="website_user_management_search_left">
<div id="website_user_management_search_left_leftside">
<p>Name:</p>
<p>Surname:</p>
<p>Telephone:</p>
<p>Group:</p>
<p>Discount group:</p>
</div>
<div id="website_user_management_search_left_rightside">
<input type="text" name="#" value="#" id="userSearch_name">
<input type="text" name="#" value="#" id="userSearch_surname">
<input type="text" name="#" value="#">
<input type="text" name="#" value="#">
<input type="text" name="#" value="#">
<input type="submit" id="button_adminUserSearch" value="Search">
</div>
Then after pressing "Search" button AJAX sends request to retrieve results, but how can I handle this dynamic query?
For example - if user just presses "Search" query would look like:
mysqli_query($dbconnect,"SELECT * FROM accounts");
For example - if user specifys $_POST["name"] value, query would look like:
mysqli_query($dbconnect,"SELECT * FROM accounts WHERE name='".$_POST["name"]."'");
Problem is - how can I efficiently handle this kind of query? It would be dumb to check which values is "isSet" and then make tons of query cases.
I hope you understood my problem and can help out with it, because it`s kinda hard to explain it.
Maybe you're looking for something like it :
if(empty($_POST['name'])) {
$name = null;
} else $name = $_POST['name'];
Then in your statement, your condition would be :
WHERE (name=:name OR :name is null)
If name isset, it will search for this name, else it will return true and query will not be affected
You could do something like that:
mysqli_query($dbconnect,"SELECT * FROM accounts WHERE name LIKE'%".$_POST["name"]."%'");
But there are two little problems:
You don't have escaped your user input data with mysqli_escape_string() and:
You shouldn't do that. A better way would be to add a where clause only, if name POST data is set:
$where = '';
if ($_POST['name']) {
$where = ' WHERE name = '".$name."'"';
}
mysqli_query($dbconnect,"SELECT * FROM accounts" . $where);
Well I am pretty much trying to create database with some table, the values in the table and check them in phpMyAdmin. I am able to create the table and database, but not the values
2.) when I add the isset $_post['submit'] variable, when I click the submit button, nothing is getting created. Is there a syntax error I am not seeing?
<html>
<body>
<p> welcome to my Page
Please insert the data below
<br>
<br>
<form action="input.php" method="post">
<p> Name: <input type="text" name="name">
<p> Age: <input type="text" name="age">
<p> Address: <input type="text" name="address">
<p> Email: <input type="text" name="email">
<input type="submit" value="Send!" name="submit">
</form>
<?php
if(isset($_POST['submit'])){
//connects to the sql database
$con = mysql_connect("localhost", "willc86", "tigers330");
if (!$con) {
echo 'can not connect to Database' . "<br>";
}
//creates the database in mySQL
$db = mysql_query("CREATE DATABASE form");
if (!$db) {
echo 'Did not create database';
}
//select the database and connect to it. on where you want to create tables.
mysql_select_db("form", $con);
//create the table once "form database" is selected
$table = "CREATE TABLE users (
Name varchar(30),
Age varchar(30),
Address varchar(30),
Email varchar(30)
)";
mysql_query($table,$con);
//insert the data from the form
$value= "INSERT INTO users (Name, Age, Address, Email)
VALUES ('$_POST[name]','$_POST[age]','$_POST[address]','$_POST[email]')";
mysql_query($value,$con);
mysql_close();
}//end of submit
?>
</body>
</html>
Your form action is input.php, is your file called input.php as well? Otherwise you'd be executing input.php when you're submitting the form instead of executing the PHP on your page.
I think user willc86 don't have access rights for create databases.
In second your script is incorrect, because it run for each "user add" operation and tried create database and table.
You can create it once in phpadmin and use in your script only insert.
No point in highlighting particular errors here as others are unlikely to have the exact same issue. Better to just give you the tools/means to debug the issue for yourself.
Instead of:
mysql_query($table,$con);
Try:
$res = mysql_query($table,$con);
if($res === false){
throw new Exception(mysql_error($conn));
}
Better yet, use PDO.
First of all your code is fine if this file name is input.php. There can be few reasons, one that you have incorrect credentials second that the user does not have a right to create table, for that go to Phpmyadmin and give user all rights.
Secondly and most importantly, use Prepared statements or mysqli otherwise you are vulnerable to SQL Injection
For that do go through this post
How can I prevent SQL injection in PHP?
I have a simple Form along side a PHP update query that simply isn't working! I know the PHP is working on the page as there are several validation checks that need to be passed before hand which are working perfectly. The form its self is inside the Colorbox Popup tool.
My HTML Form Code is:
<div id="stylized" class="myform">
<form action="#" method="post">
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>" />
<label>First Name:<span class="small">Enter your forename</span></label>
<input id="first_name" type="text" name="first_name" maxlength="50" placeholder="e.g. Joe" required autofocus/>
<div class="spacer"></div>
<input type="submit" id="update" name="update" value="Continue to Step 2!">
</form>
</div>
With the PHP Code as follows (this is above the HTML code on the page):
<?php
if($_POST['update']){
$user_i = $_POST['user_id'];
$f_name = $_POST['first_name'];
$first_name = ucfirst($f_name);
mysql_query("UPDATE user SET first_name = '$first_name' WHERE user_id = '$user_i'") or die(mysql_error());
} ?>
The actual submit appears to be working, with the Popup refreshing afterwards, but the database does not update! I have triple checked the syntax and the database fields. 'user' and 'first_name' and 'user_id' is correct.
Update: Because the popup box refreshes, I cannot view the error's from the 'or die(mysql_error()) unfortunately, other wise i might have been one step closer.
Any help would be hugely appreciated.
Many thanks in advance.
When you say pop-up box, I assume you are using ajax to communicate from the form to the server, which as you stated is difficult to view submitted data. If this is the case try:
error_log(serialize($_POST));
This will force an entry in your error log with the $_POST data in serialized format, so you can check the values you are submitting are populated correctly.
You will also want to sanitize the variables you are adding to the SQL:
$sql = "UPDATE user SET first_name = " . mysql_real_escape_string($first_name) . " WHERE user_id = " . mysql_real_escape_string($user_i) . " LIMIT 1";
mysql_query($sql);
I would:
print_r($_POST); to view the POST data.
Generate the SQL from a string so it can be printed for debugging purposes, like so:
$sql = "UPDATE user SET first_name = '$first_name' WHERE user_id = '$user_i'";
echo $sql;
mysql_query($sql) or die(mysql_error());
One of these techniques will likely tell you why the PHP-generated SQL doesn't update your database record.
you set your user_id field by echo $user_id; but your variable name is set to $user_i = $_POST['user_id'];
therefore your user id field is not set and your Mysql command will fail.