Good morning,
I had some problems yesterday and got help, unfortunately, my app still not does 100% does what I want it to do, although only a small detail is missing.
Given a scenario where I want to do an SQL injection to drop a database, and when it happens, render a PHP page. Everything works fine until I want the render to happen - even though the injection executes and the DB is dropped when I check it MySQL, still no rendering. The problem is probably due to the incorrect usage of multi_query. More details in comments in the code.
<?php
include("/../../connection.php");
if(isset($_POST["button_one"])){
$username = $_POST['username'];
$password = $_POST['password'];
if($conn->multi_query("SELECT id FROM users WHERE username = '$username' OR password = '$password'")) // IF THE USER HAS A VALID USERNAME OR PASSWORD,
{
do {
if ($result = $conn->store_result()) {
while ($row = $result->fetch_row()) { // THEN ENABLE BUTTON TWO, WHICH HAS TO BE CLICKED TO DROP THE DATABASE
echo "
<script type=\"text/javascript\">
document.getElementById('button_two').disabled=false;
</script>
";
}
$result->free();
}
} while ($conn->next_result());
}
}
if(isset($_POST["button_two"])){
$username = $_POST['username']; // SQL INJECTION TO DROP THE DB HAPPENS HERE
$password = $_POST['password'];
if($conn->multi_query("SELECT id FROM users WHERE username = '$username' OR password = '$password'")) // SQL INJECTION SUCCEEDED
{
do {
if ($result = $conn->store_result()) {
while ($row = $result->fetch_row()) {
if ($result = $conn->query("SHOW DATABASES LIKE 'mydatabase'")) { // NO MORE DATABASE LIKE THAT, IT HAS BEEN DROPPED DUE TO THE INJECTION
if($result->num_rows == 0) {
include("another.php"); // THE PROBLEM IS HERE. EVEN THOUGH THE DB IS DROPPED, THIS PAGE IS NOT RENDERING
}
}
}
$result->free();
}
} while ($conn->next_result());
}
}
?>
Any helpful idea would be appreciated!
The code block to include another.php never runs, because the SHOW DATABASES query fails.
I tested your code and added some error reporting:
if ($result = $conn->query("SHOW DATABASES LIKE 'mydatabase'")) {
if($result->num_rows == 0) {
include("another.php");
}
} else {
echo "Error: {$conn->error}\n";
}
I got this:
Error: Commands out of sync; you can't run this command now
You can't run another SQL query while the one you already have executed still has results to fetch. Even though you have used store_result() to fetch the result set, that only fetches the current result set. You used mulit_query() which produces multiple result sets. You have to process all result sets until the end of the next_result() loop before you can start a new query.
Another lesson here is that you should always check for and report errors after you try to query() or multi_query() or prepare() or execute().
Here's an example: You have to wait until after the last result has been processed before you can run another query. This means after the loop on $conn->next_result() is done.
if(isset($_POST["button_two"])){
$username = $_POST['username'];
$password = $_POST['password'];
if($conn->multi_query("SELECT id FROM users WHERE username = '$username' OR password = '$password'"))
{
do {
if ($result = $conn->store_result()) {
while ($row = $result->fetch_row()) {
// DISPLAY RESULTS FROM QUERY
}
}
$result->free();
} while ($conn->next_result());
// CAN'T START ANOTHER QUERY UNTIL AFTER THE NEXT_RESULT LOOP IS DONE
if ($result = $conn->query("SHOW DATABASES LIKE 'mydatabase'")) {
if($result->num_rows == 0) {
include("another.php");
}
}
}
Related
I have a form with only a username that will allow for access to two pages depending an users authority level in an MS SQL database.
If their authority level is 10 then they will log into the 'normal' page, however anything more and they will be logged into an admin page with more functionality. This all works fine, however It's letting anything typed into the username to log in.
I'm struggling to prevent it logging in any username that isn't in the database. This is what I have so far...
$conn = odbc_connect(database connection stuff here);
$login = $_POST['login'];
$sqlquery = "SELECT u.authorityLevel, u.employeeNo, e.knownAs FROM common.dbo.users as u JOIN
common.dbo.employees AS e on e.employeeNo = u.employeeNo WHERE u.employeeNo = '".$login."'";
$result = odbc_exec($conn, $sqlquery);
$user = odbc_fetch_array($result);
$userExists = odbc_num_rows($sqlquery);
if((isset($_SESSION['login']['logged_in']) && $_SESSION['login']
['logged_in'])==true){
if(isset($_POST)){
if ((int)$user['authorityLevel'] > 10) {
header("location: indexAdmin.php");
$row = $user;
$_SESSION['sessionUserName'] = $row['knownAs'];
} elseif ((int)$user['authorityLevel'] = 10) {
header("location: confirmedJobs.php");
$row = $user;
$_SESSION['sessionUserName'] = $row['knownAs'];
} else ((int)$user['authorityLevel'] < 10){
header("location: loginPage.php");
}
}
}
You're only declaring this variable:
$userExists = odbc_num_rows($sqlquery);
but not using it.
This is the syntax to check if a record exists:
if($userExists >0) {...}
Edit: (I overlooked something).
This line is using the wrong variable for it:
$userExists = odbc_num_rows($sqlquery);
In conjunction with:
$result = odbc_exec($conn, $sqlquery);
Therefore it should read as:
$userExists = odbc_num_rows($result);
odbc_num_rows() is used against the executed query, not the raw query.
You are also open to an SQL injection, use a prepared statement:
https://www.php.net/manual/en/function.odbc-prepare.php
Convert ODBC SQL query to use prepared statements
anything you fill in will make isset($_POST) return true.
Once you're in that if-then block, any choice leads to a page.
How about :
if(isset($_POST) && $userExists)
{
...
}
public function getLoginInfo($username,$password){
$conn=DB::connect();
session_start();
$sql="select * from owner where o_email='".mysql_real_escape_string($username)."' and o_password='".mysql_real_escape_string($password)."'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$_SESSION['email']=$username;
$_SESSION['password']=$password;
}
header("location:../owner/owner_dashboard.php");
} else {
header("location:../owner/owner_login.php");
}
$conn->close();
}
i have added username and password to my session array but i also want to save id into session array which is stored into databse as "o_id"
You are over complicate the process than necessary. mysql_ extensions are also deprecated.Therefore, you should not use them. use prepare statements which prevent against sql injections. In additional, there is no need for you to store the password in the session. Your password should be stored in the database as hashed so storing it in session wont be reliable to you. Once you find a match against the username and password you searched for, you only need to store the username in the session. In your application, you can compare against the username of logged in area. I modified your code to a much cleaner solution. I had to made few assumptions such as your conn is a PDO.
public function getLoginInfo($username,$password)
{
//start the session only if it has not started somewhere else
if (session_status() == PHP_SESSION_NONE)
{
session_start();
}
//try to query the database
try {
$conn = DB::connect();
$sql = 'Select * from owner where o_email= :email and o_password = :password';
$conn->prepare($sql);
$res = $conn->execute(array(':email' => $username, ':password' => $password));
//check if the data exist. only true if result set is greater than 0
if ($res->rowCount() > 0)
{
$_SESSION['email']=$username;
header("location:../owner/owner_dashboard.php");
exit("login success, redirecting to dashboard...");
}
//doesnt exit so go back to login
header("location:../owner/owner_login.php");
exit('Invalid username or password. Redirecting back to lgoin...');
}
//Error is only output for debugging purpose. I would encourage turn this off in production
catch(Exception $e)
{
print_r($e->getMessage());
}
}
First of all, it must be clear that if you are querying for logging
in, then query will return only one row, so using while is
meaningless.
public function getLoginInfo($username,$password){
$conn=DB::connect();
session_start();
$sql="select * from owner where o_email='".mysql_real_escape_string($username)."' and o_password='".mysql_real_escape_string($password)."'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// Edited from here
// output data of each row
$row = $result->fetch_assoc();
$arraydata[$row['id']] = $row;
$_SESSION['user_info']=$arraydata;
$_SESSION['current_loggedin_id']=$row['id'];
header("location:../owner/owner_dashboard.php");
} else {
header("location:../owner/owner_login.php");
}
$conn->close();
}
I am developing a website for testing with logging page with different access levels for users, the site is connected with MySQL db which have 3 columns
user | password | level(1/2)
code is filter out the particular entry from db but it didn't redirected to particular page. i tested with echo but at the $count it shows 0 . please help me to sort this out, I am going to use mysqli instead at the launching phase.
session_start();
if($_SERVER["REQUEST_METHOD"] == "POST"){
$username = $_POST['username'];
$password = $_POST['password'];
$conn = mysql_connect('localhost','root','');
$db = mysql_select_db('udb',$conn);
$sql = "SELECT * FROM logins WHERE user ='".$username."' AND password = '".$password."'";
$result = mysql_query($sql,$conn);
echo $result;
$count = mysql_num_rows($result);
if ($count==1) {
$_SESSION['login_user']=$username;
while ($row = mysql_fetch_array($result)){
if ($row['level'] == '2') {
header("home2.php");
} else {
header("home1.php");
}
}
}
Your echo $result; will prevent any further redirect down in the code. It is due to the fact that redirects are managed using headers... but since you output some data ... headers can not be managed.
no need to give connection variable in mysql_query() and in header function u forgot to pass location
$sql = "SELECT * FROM logins WHERE user ='".$username."' AND password = '".$password."'";
$result = mysql_query($sql);
//echo $result;
$count = mysql_num_rows($result);
if ($count==1) {
$_SESSION['login_user']=$username;
while ($row = mysql_fetch_array($result))
{
if ($row['level'] == '2')
{
header("location:home2.php");
} else {
header("location:home1.php");
}
}
}
You need to use location if you want your redirects to work.
if ($row['level'] == '2') {
header("location: home2.php");
} else {
header("location: home1.php");
}
Your script is at risk for SQL Injection.
If you can, you should stop using mysql_* functions. They are no longer maintained and are officially deprecated. Learn about prepared statements instead, and consider using PDO, it's really not hard.
Finally, you should use the proper methods to hash passwords with PHP. The way that you're handling login is extremely insecure.
Place the user and password into back ticks (apostrophe marks on the left of key 1)
i have looked at the other results for what i'm trying to do, none of them do what i need them to. What i am trying to do is something like this:
myfunction(){
require('./connect.php'); //connect to database
$query = mysql_query("SELECT * FROM users WHERE username='$user'"); //user is defined outside the function but it works in my login function which i use the same way.
$numrows = mysql_num_rows($query);
if($numrows == 1){
$row = mysql_fetch_assoc($query);
$value = row['value'];
mysql_close();
return $value;
} else {
$errmsg = "connection failed.";
$value = 0;
return $value;
}
}
In my php file i would do something like this at the top.
$value = myfunction();
This does not work.
Ultimately what i'm trying to accomplish is getting a value from the database and output it from the function in another file.
(this is my first post on stackoverflow so if i need to change this feel free to tell me and i shall)
Your code has several syntax error. Check this, and read my comments:
function myfunction() {
//connect to database
require('./connect.php');
//user is defined outside the function but it works in my login function which i use the same way.
$query = mysql_query("SELECT * FROM users WHERE username='" . mysql_real_escape_string($user) . "'");
$numrows = mysql_num_rows($query);
if ($numrows == 1) {
$row = mysql_fetch_assoc($query);
return $row['value']; //Missing $ sign
//No need to create $value if you just return with that.
//mysql_close();
//return $value;
} else {
//Where do you use this errmsg????
$errmsg = "connection failed.";
return 0;
// These 2 lines are unnecessary.
//$value = 0;
//return $value;
}
} //Missing function close
In my example, I've just leave the mysql functions, but please do not use them, they are deprecated. Use mysqli or PDO instead. Also, avoid sql injections by escapeing your variables!
$row = mysql_fetch_assoc($query);
$value = row['value']; // <-------- you forgot the $
and most probably, the correct way to extract the result is,
$row[0]['value'];
Note:
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
i'm thinking you forgot a dot here.
require('./connect.php');
And a bit of function improvement
myfunction(){
require_once('../connect.php'); //connect to database
$query = mysql_query("SELECT * FROM users WHERE username='".$user."'"); //user is defined outside the function but it works in my login function which i use the
$numrows = mysql_num_rows($query);
if($numrows == 1){
$row = mysql_fetch_assoc($query);
$value = $row['value'];
mysql_close();
}
else{
$errmsg = "connection failed.";
$value = 0;
}
return $value;
}
I am new in PHP and need help with my below code. When I am entering wrong userid instead of giving the message "userid does not exist" it is showing "password/id mismatch. Please guide me where I am wrong.
<?php
session_start();
$id = $_POST['userid'];
$pwd = $_POST['paswd'];
$con = mysqli_connect("localhost", "????", "????", "??????");
if ($con) {
$result = mysqli_query($con, "SELECT * FROM users WHERE userid=$id");
if ($result) {
$row = mysql_fetch_array($result);
if ($row["userid"] == $id && $row["paswd"] == $pwd) {
echo "Welcome! You are a authenticate user";
if ($id == $pwd)
//my default login id and password are same
{
header("Location: changepwd.html");
} else {
header("Location: dataentry.html");
}
} else {
echo "ID/Password Mismatch";
}
} else {
echo "User does not Exist !!!";
}
} else {
echo "Connection failed - ".mysqli_error()." -- ".mysqli_errno();
}
?>
The main problem you have is that you're mixing up between the mysqli and mysql functions. These two libraries are not compatible with each other; you must only use one or the other.
In other words, the following line is wrong:
$row=mysql_fetch_array($result);
It needs to be changed to use mysqli_.
While I'm here, going off-topic for a moment I would also point out a few other mistakes you're making:
You aren't escaping your SQL input. It would be extremely easy to hack your code simply by posting a malicious value to $_POST['userid']. You must use proper escaping or parameter binding. (since you're using mysqli, I recommend the latter; it's a better technique).
Your password checking is poor -- you don't appear to be doing any kind of hashing, so I guess your passwords are stored as plain text in the database. If this is the case, then your database is extremely vulnerable. You should always hash your passwords, and never store the actual password value in the database.
I've gone off topic, so I won't go any further into explaining those points; if you need help with either of these points I suggest asking separate questions (or searching here; I'm sure there's plenty of existing advice available too).
else
{
echo "ID/Password Mismatch";
}
is connected with the
if($row["userid"]==$id && $row["paswd"]==$pwd)
{
So since you are giving a wrong id. It echo's: ID/Password Mismatch
Also the else at if ($result) { wont ever show since
$result = mysqli_query($con, "SELECT * FROM users WHERE userid=$id");
You need some additionnal checks:
select * return 1 row (not 0, and not more)
you need to protect the datas entered by the html form (for example someone could enter 1 or 1 to return all rows
<?php
session_start();
$con = mysqli_connect("localhost", "????", "????", "??????");
$id = mysqli_real_escape_string($_POST['userid']);
$pwd = mysqli_real_escape_string($_POST['paswd']);
if ($con) {
// don't even do the query if data are incomplete
if (empty($id) || empty($pwd)
$result = false;
else
{
// optionnal : if userid is supposed to be a number
// $id = (int)$id;
$result = mysqli_query($con, "SELECT * FROM users WHERE userid='$id'");
}
if (mysqli_num_rows($result) != 1)
$result = false;
if ($result) {
$row = mysqli_fetch_assoc($result);
if ($row["userid"] == $id && $row["paswd"] == $pwd) {
echo "Welcome! You are a authenticate user";
if ($id == $pwd)
//my default login id and password are same
{
header("Location: changepwd.html");
} else {
header("Location: dataentry.html");
}
} else {
echo "ID/Password Mismatch";
}
} else {
echo "User does not Exist, or incomplete input";
}
} else {
echo "Connection failed - " . mysqli_error() . " -- " . mysqli_errno();
}
?>
Try with isset() method while you are checking if $result empty or not.
that is in line
if ($result) {.......}
use
if (isset($result)) { .......}
$result is always true, because mysqli_query() only returns false if query failed.
You could check if $result has actual content with empty() for example.
You can use this sql compare password as well with userid
$sql= "SELECT * FROM users WHERE userid='".$id.", and password='".$pwd."'";