i am a beginner in PHP & MySQL development, I am following a tutorial. I am trying to make login system, after inserting data to Mysql in registration. I want to validate the password from the database and the password from user in login page, if it is match, then login is successful.
here is the password from the database, as we can see, for username=admin the password is 3462623.....
The data type of this database is like this
as we can see, the data type for password and salt is Binary.
when I tried to var_dump the variable which stores the value from the database, the password and salt is different from what appears in the database.
the password should be : 3462623.....
but from var_dump, the password is : 4bb5d8229634bf5 .....
other data like id,username,email are correct. just password and salt are different.
I suspect this is because the return value data type from var_dump is String, but when i stored to database, the datatype is Binary, how do I fix that ? it seems that from tutorial I saw, the login system still OK even though the password in string data type.
to be honest I don't understand why it has to be Binary data type. but I guess it because it will be encrypted.
so what went wrong in here?
here is the code :
Registration Process
$username = htmlentities($_REQUEST["username"]);
$password = htmlentities($_REQUEST["password"]);
$fullname = htmlentities($_REQUEST["fullname"]);
$email = htmlentities($_REQUEST["email"]);
if (empty($username) || empty($password) || empty($fullname) || empty($email)) {
$returnArray = [
"status" => "400",
"message" => "missing required information"
];
echo json_encode($returnArray);
return;
}
//encrypt the password
$salt=openssl_random_pseudo_bytes(20);
$securedPassword = sha1($password.$salt);
// Create Connection
$file = parse_ini_file("../../../twitter.ini");
$dbhost = trim($file["host"]);
$dbusername = trim($file["username"]);
$dbpassword = trim($file["password"]);
$dbname = trim($file["dbname"]);
$access = new access($dbhost,$dbusername,$dbpassword,$dbname);
$access->connect();
function registerUser($username,$password,$salt,$email,$fullname) {
$query = "INSERT INTO users SET username=?, password=?,salt=?,email=?,fullname=?";
$statement = $this->conn->prepare($query);
if (!$statement) {
throw new Exception($statement->error);
}
$statement-> bind_param('sssss',$username,$password,$salt,$email,$fullname);
$returnValue = $statement -> execute();
return $returnValue;
}
// Insert data to database
$result = $access->registerUser($username,$securedPassword,$salt,$email,$fullname);
if ($result) {
// get data from database
$user = $access->selectUser($username);
$resultArray = [
"status" => "200",
"message" => "Sucessfully registered",
"id" => $user["id"],
"username" => $user["username"],
"email" => $user["email"],
"avatar" => $user["avatar"],
"fullname" => $user["fullname"]
];
login process
$username = htmlentities($_REQUEST["username"]);
$password = htmlentities($_REQUEST["password"]);
if (empty($username) || empty($password)) {
$returnArray = [
"status" => "400",
"message" => "missing required information"
];
echo json_encode($returnArray);
return;
}
// make connection
$file = parse_ini_file("../../../twitter.ini");
$dbhost = trim($file["host"]);
$dbusername = trim($file["username"]);
$dbpassword = trim($file["password"]);
$dbname = trim($file["dbname"]);
$access = new access($dbhost,$dbusername,$dbpassword,$dbname);
$access->connect();
$user = $access -> getUserData($username);
if (empty($user)) {
$returnArray = [
"status" => "403",
"message" => "User is not found"
];
echo json_encode($returnArray);
return;
} else {
// password validation
$securedPassword = $user["password"];
$salt = $user["salt"];
if ($securedPassword === sha1($password.$salt)) {
$resultArray = [
"status" => "200",
"message" => "Login Success!",
"id" => $user["id"],
"username" => $user["username"],
"email" => $user["email"],
"avatar" => $user["avatar"],
"fullname" => $user["fullname"]
];
} else {
$returnArray = [
"status" => "403",
"message" => "Password didn't match"
];
}
}
$access ->disconnect();
echo json_encode($returnArray);
As pointed out by other users, password and salt should be char or varchar or even text, but not binary.
The reason you see a difference between them is based on the method of access and character sets used in retrieval and display.
In one case you are retrieving using PHP and then displaying using (likely) a PRE tag and showing it on a web page. In the other case you are viewing it in phpMyAdmin or some other MySQL desk system. Each one of these requires several translations before viewing and as binary data they will not display the same way reliably when retrieved with two different pathways (phpMyAdmin will translate the character set differently, and then display the result differently).
A simple solution to this is to switch to a non-binary (TEXT/VARCHAR) field definition.
Alternately, you could attempt to retrieve them as HEX or some other Binary Friendly display method in both your MySQL desk (using a query, not just displaying in the table) and in the php/mysqli query as well. In essence, then, you'd be converting the binary to a known text display set.
Related
I'd like to know why OWASP ZAP detect potential SQL injection on my login page. I call an API to connect my users.
PHP slim API code:
$sql = "SELECT id, idGroup, idTeam,lastName, firstName, isLogged, login, phoneNumber, webrtc FROM users WHERE enable = 1 AND login = :login AND password = :password";
$db = new db();
$db = $db->connect();
$stmt = $db->prepare($sql);
$userPass = md5($password);
$stmt->bindParam(':login', $login);
$stmt->bindParam(':password', $userPass);
$stmt->execute();
$user = $stmt->fetchAll(PDO::FETCH_OBJ);
Login page:
$login = $_POST['username'];
$password = $_POST['password'];
$client = new GuzzleHttp\Client();
$response = $client->request('POST', $apiUrl . 'agent/login', [
'form_params' => [
'login' => $login,
'password' => $password,
'ipAddress' => $_SERVER['REMOTE_ADDR'],
]
]);
$data = json_decode($response->getBody(), true);
if (isset($data[0]['id']) && $data[0]['id'] > 0) {
$_SESSION['fullName'] = $data[0]['firstName'] . ' ' . $data[0]['lastName'];
$_SESSION['idGroup'] = $data[0]['idGroup'];
$_SESSION['idTeam'] = $data[0]['idTeam'];
$_SESSION['idUser'] = $data[0]['id'];
$_SESSION['login'] = $data[0]['login'];
$_SESSION['phoneNumber'] = $data[0]['phoneNumber'];
$_SESSION['webrtc'] = $data[0]['webrtc'];
//Get roles for user
$response = $client->request('GET', $apiUrl . 'web/permissions/' . $login);
$data = json_decode($response->getBody(),true);
foreach ($data as $roles) {
$_SESSION['roles'][$roles['bit']] = $roles['name'];
}
echo "<script>window.open('index.php','_self')</script>";
}
All my APIs use prepared statements and parameterized queries.
Here's the OWASP ZAP alert:
The page results were successfully manipulated using the boolean
conditions [ZAP" AND "1"="1" -- ] and [ZAP" AND "1"="2" -- ] The
parameter value being modified was NOT stripped from the HTML output
for the purposes of the comparison Data was returned for the original
parameter.
This may happen if the response page for the form submission contains the value of a form field as it was specified by a user. For instance if you are logging in your user and use the value of 'username' field to greet the user but pull it not from the DB but from the request variables. SQL injection does not take place but the scanning script assumes that you stored the value unsanitized in the DB while you just using the value provided by a user and not the value that you have stored in the DB. Hope this makes sense.
I'm having trouble creating a Custom Authentication! I'm using a free host from 000WebHost to test Photon's multiplayer on Unity, but I get the following error in Unity debug:
OperationResponse 230: ReturnCode: 32755 (Custom authentication deserialization failed: Unexpected character encountered while parsing value: U. Path '', line 0, position 0.).
Parameters: {} Server: NameServer Address: ns.exitgames.com:5058
UnityEngine.Debug:LogError(Object)
Photon.Realtime.LoadBalancingClient:DebugReturn(DebugLevel, String) (at Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:1835)
Photon.Realtime.LoadBalancingClient:OnOperationResponse(OperationResponse) (at Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:1909)
ExitGames.Client.Photon.PeerBase:DeserializeMessageAndCallback(StreamBuffer) (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/PeerBase.cs:616)
ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands() (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/EnetPeer.cs:545)
ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands() (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/PhotonPeer.cs:1473)
Photon.Pun.PhotonHandler:FixedUpdate() (at Assets/Photon/PhotonUnityNetworking/Code/PhotonHandler.cs:130)
My Unity authentication code:
using Photon.Pun;
using Photon;
public class Login : MonoBehaviour {
public InputField User_Input;
public InputField Pass_Input;
public Text Error_Text;
public string username;
public string password;
public void UserName(){
username = User_Input.text.ToString ();
}
public void UserPass(){
password = Pass_Input.text.ToString ();
}
public void SubmitLogin(){
PhotonNetwork.AuthValues = new AuthenticationValues ();
PhotonNetwork.AuthValues.AuthType = CustomAuthenticationType.Custom;
PhotonNetwork.AuthValues.AddAuthParameter ("username", username);
PhotonNetwork.AuthValues.AddAuthParameter ("password", password);
PhotonNetwork.ConnectUsingSettings();
}
void OnJoinedLooby(){
Debug.Log ("We did it");
}
void OnGUI(){
GUILayout.Label (PhotonNetwork.connectionStateDetailed.ToString ());
}
}
My server-side code:
<?php
include "db.php";
$username = $_GET['username'];
$password = $_GET['password'];
$check = mysqli_query($conn , "SELECT * FROM accounts WHERE `username`='".$username."'");
$numrows = mysqli_num_rows($check);
if ($numrows == 0){
die ("Username does not exist.");
}else{
$password = md5($password);
while($row = mysqli_fetch_assoc($check)){
if ($password == $row['password']){
$login_info = array(
"ResultCode" => 1,
"Message" => "You are connected!");
}else{
$login_info = array(
"ResultCode" => 2,
"Message" => "Wrong username or password");
}
}
}
$json = json_encode($login_info);
echo $json;
?>
In the photon panel I placed Url mydomain/auth.php and I did not put any optional Key/Value Pairs
I do not know what the problem is, if anyone knows
I replied on our forum. Posting the same here:
The letter "U" is a hint that it could be from "Username does not exist.".
Replace
die ("Username does not exist.");
with
$login_info = array(
"ResultCode" => 3,
"Message" => "Username does not exist."
);
If the issue persists, use postman and send an HTTP request with proper query string values to your server and see what it returns. Fix that.
I have tried creating a RESTful API service. I have generated a token by hashing a string (using a randomly generated secret key that is stored in the database) that is returned by the login script on successful login, to the client end as a part of a JSON object. The client passes the token (along with some other fields as a JSON object) as a GET/POST parameter to get access to the other API services. However, it seems that when the token string is passed around as a JSON object, the string gets altered somewhere in the middle, and dehashing it with the secret key at the verification endpoint does not yield the same string as the string that was hashed. Result is an unsuccessful attempt at getting the data secured by the token.
I am adding parts of the code that are relevant:
Login Script
$secret = newsecret($rand);
$token = newtoken($secret, $str);
$qry1 = "UPDATE user_master set user_secret='".$secret."' where user_code='".$uid."'";
$res1 = mysqli_query($conn, $qry1);
$outdata = array("status" => "success", "username" => $un, "uid" => $uid, "token" => $token);
header('Content-type: application/json');
echo json_encode($outdata);
Client JS
$.post("http://www.ckoysolutions.com/apis/login.php", inputs).done(function(data){
if(data.status=="success") {
var inputs = '{ '
+'"uid" : "'+data.uid+'" , '
+'"token" : "'+data.token+'"'
+' }';
window.location='http://hasconpanel.ckoysolutions.com/hasconpanel.php?inputs='+inputs;
}
else {
alert(data.message);
}
});
Redirected page (http://hasconpanel.ckoysolutions.com/hasconpanel.php) sending token as json as a curl postfield for verification
if(isset($inputs->uid) && isset($inputs->token)) {
$token = $inputs->token;
$uid = $inputs->uid;
$auth_data = array("uid" => $uid, "token" => $token);
$auth_json = json_encode($auth_data);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $auth_json,
CURLOPT_URL => "http://www.ckoysolutions.com/apis/authuser.php",
CURLOPT_HTTPHEADER => [
'Content-Type: application/json'
]
]);
$result = curl_exec($curl);
curl_close($curl);
echo $result;
}
Function used in http://www.ckoysolutions.com/apis/authuser.php to authenticate
$row = mysqli_fetch_array($res);
$secret = $row['user_secret'];
$token = $token;
$un = $row['user_name'];
$words = explode(" ",$un);
$fn = $words[0];
$udetails = $row['user_log'];
$udetails = json_decode($udetails);
$uip = $udetails->ip;
$date_time = $udetails->time;
$str = $date_time.$fn.$uip;
$chkstr = decrypt($secret, $token);
if($str == $chkstr) {
$outdata = array("status" => "success");
mysqli_close($conn);
}
else {
$outdata = array("status" => "failure");
mysqli_close($conn);
}
header('Content-type: application/json');
echo json_encode($outdata);
Please do suggest what might be going wrong here.
I had a similar issue to this and found that if the token is passed as a query string parameter and contains the + character it will get removed. I discovered the issue because the call wasn't always breaking. The easiest solution for me was to replace "+" with "P".
AJAX POST and Plus Sign ( + ) — How to Encode?
I am creating a simple login page for my application but my auth always says i'm failed?
$email = Input::get('email');
//echo = matchesmyemail
$password = Input::get('password');
//echo = matchesmydbpassword
$auth = Auth::attempt(array(
'email' => $email,
'password' => $password
));
if($auth){
die('logged in');
}else{
die('failed');
}
Any ideas what i'm doing incorrect?
Is your password hashed in the database?
$password = Hash::make('password');
If you have a plain text password in the database table than that is the problem. The password will be hashed and the hashes will be compared.
I'm having trouble getting the Authentication to work with laravel 4. This is my whole sign in function when a user enters their email and password into the form.
public function getSignin() {
$return_arr = array();
$email = Input::get('email');
$password = Input::get('password');
$validation = Validator::make(
array(
'Email' => $email,
'Password' => $password
), array(
'Email' => 'required|Email',
'Password' => 'required'
)
);
if ($validation->passes()) {
$pass = base64_encode($password);
$details = array ('email' => $email, 'password' => $pass);
if (Auth::attempt($details)) {
$return_arr['frm_check'] = 'success';
$return_arr['msg'] = 'logged in';
} else {
$return_arr['frm_check'] = 'error';
$return_arr['msg'] = 'log in failed';
}
} else {
$errors = $validation->messages();
$return_arr['frm_check'] = 'error';
$return_arr['msg'] = $errors->first();
}
echo json_encode($return_arr);
$this->layout = null;
return;
}
Even though the email and password are in the same row in the database, it still returns log in failed, was wondering if anyone could shed some light on to this situation?
If I've missed off any other crucial details let me know and I'll post them right away. Thanks in advance.
Based on your comments...
When you're creating your $user, use Hash::make($password) to hash the password using BCrypt, before saving it in your db.
Then, when the user's logging in just use Auth::attempt($credentials) as you are, but don't use base_64 to encrypt it, the Auth method does it all for you!
Much more on the excellent Laravel docs: http://laravel.com/docs/security
Unless you have base64 encoded your password on save(), remove this line from your code:
$pass = base64_encode($password);
And edit this one to:
$details = array ('email' => $email, 'password' => $password);
Auth::attempt() will hash it for you, using something safer than base64.
EDIT:
To correctly save your passwords you have to do something like this:
$user = new User;
$user->email = 'me#me.com';
$user->password = Hash::make('mySuperSecretPassword');
$user->save();
Then you can user attempt just passing it unhashed.
Here's a tutorial I wrote; which might help!
https://medium.com/on-coding/e8d93c9ce0e2