I have the following issue: I am currently working on a ASP .net core entity framework backend and have the problem that I need to use a Custom Method in LINQ Query and getting a error when doing this. I
researched and found out that it is possible to write custom functions, that will be translated to sql, but I think that there is not a big scope for doing this. (e.g: SQL will not be able to use Libaries and hash strings).
Another way that I have heard of ist to convert my Database to a Enumberale and then apply my Custom Methods on it, which works, but is not that performant, because I am saving my whole Database in my memory, which gets very slow when having a huge amount of data. So my question is, if there is a performant solution to perform custom methods in LINQ queries?
My detailed problem is, that I have saved my salted passwords hashed in my database and when someone want s to log in to his account I have to compare the password in the database with the salt + user password input, that has to get hashed in my where clause. It would work if I wouldnt use salts, because then, I would only have to hash the user input, which is not column of the database.
What you should do is - calculate the hash and salt in the backend, and use the computed hash in your WHERE statement. In this case you don't need to call your methods from SQL equally you don't need to pull entire db (or table) into memory to compute hash.
As I don't know your code, the pseudo-code approach would be:
var user = service.GetUserByEmail(email);
if (user == null) {
//Invalid User
}
var hash = ComputeHash(user.Salt, inputPwd);
if(user.PasswordHash == hash) {
//User is logged in
} else {
//Invalid Password or email
}
Related
I was reading this article about hashing passwords when I came to this part:
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same
hash function.
Compare the hash of the given password with the hash from the
database. If they match, the password is correct. Otherwise, the
password is incorrect.
But I am a little confused with the flow this would follow, for example lets assume I have a database with a user table with id,name,password and email and in order to login to some app I need to input my email and password.
Following the the steps above, I first need to get the salt+hashed password of said user stored in the database.
Question:
Assuming I am using a simple stored procedure would the only way be to do it like this...
CREATE PROCEDURE [dbo].[sp_validate_user]
#us_email VARCHAR (MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT us_id,
us_name,
us_pass,
us_email
FROM Users
WHERE us_email = #us_email
END
Then following step two and three:
public static bool ValidatePassword(string inputPassword, string storedPassword)
{
// Extract the parameters from the hash
char[] delimiter = { ':' };
string[] split = storedPassword.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(inputPassword, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
My concern comes from the fact that if I am creating objects with the data pulled from the table, doesn't that make the information within vulnerable somehow?
Also does that mean that the only way to use this validation is pulling all the user's information based only on a username/email just to check in runtime if the input password and the hashed one match and then letting said user access the information?
I'm sorry if this sounds confusing but any insight would be great.
It looks like you may be thinking of it backwards. The salt is added to the cleartext password before passing to the hash function. Store the end result in the database.
Commonly, the salt is the username. Something unique to each user to thwart dictionary attacks. (A dictionary attack relies on the economy of scale by cracking one password and then looking for other instances of the same crypto-text. It used to work especially well on very large user databases like well known sites that have millions of users, but hopefully those sites use proper salting and key derivation nowadays).
So for username u, password p, assume SHA2 is hash function. Concatenate u + p to get a salted value, then hash it.
hashtext = SHA2(u + p) // in this case, + is concatenate
hashtext is what you store in the database.
For the login, user enters his username u2 and password p2:
tryhash = SHA2(u2 + p2)
Query database for a user record matching u2, with password hashtext of tryhash
Lets say you have an MVC action receiving loginViewModel which is populated with cleartext email or username as well as cleartext password, entered from the page:
var loginUser = new User(loginViewModel);
CalcHash(loginUser);
var realUser = users.Find(loginUser.username);
if(realUser.HashPassword == loginUser.HashPassword)
// success
While it is also possible to add the hashed password as a second argument to your Data Access method, ie. users.Find(username, hashPass), it is usually not done this way, because you need to access the user record even if the password fails, in order to increment password failure count and lockout the account.
The article covers ASP.NET (C#) Password Hashing Code but you seem to want to use a database?
You have three things to worry about; the unique key for the user (username), your chosen hashing algorithm and adding a salt to the password attempt (prevents rainbow table attacks).
To validate a password you should create a sql stored procedure that accepts the username and password attempt as parameters. This data is in plain text and has been entered into the web form, passed to the web server and will be passed into the database server via the stored procedure.
The stored procedure will do the following;
Lookup the data row for user based on matching the username parameter with the username field and
select the stored salt field
Append the salt from (1) to the password parameter and hash the result
Lookup the data row for the user based on matching the username parameter with the username field
and the hash result from (2) with the hashed password field.
If there is no row found the password hashes don't match and are wrong so return a suitable error code
If there is a row found return the useful user data i.e. First Name, Address
If the stored procedure handles all this then the web server never needs to know what the salt is or the hashing algorithm. At no point does the hash result or the salt get transmitted out of the database server.
I think you understood it correctly, this is the usual workflow:
Get the password-hash by username SELECT password_hash FROM user WHERE email=?.
Extract the salt from the password_hash, or get the salt from a separate field.
Calculate the hash of the entered password with the extracted salt and compare the hashes.
Validating the password cannot be done in a single query, because you first have to extract the salt. Appropriate hash functions like PBKDF2, BCrypt or SCrypt are often not supported by the database system, so you have to do the validation in your code. Additionally to the salt you also have to store other parameters like the cost factor and the algorithm (to be future-proof), so it is a good idea to store all these parameters in the same database field.
The salt should be a random string of at least 20 characters, so it is not safe to use the username as salt, or to derrive the salt from other information.
I have spent the past hour reading up on salting and still don't understand how it is achieved. Forgive me if im wrong, but the way I am thinking of salting is, storing an ArrayList of random strings for example 100 strings. Now when a user registers, a method gets a random string from the array list and retrieves the index of the string within the array to insert into my DB, it then applies this random string to the password the user entered and then hashes the whole string and stores into the DB.
Now when the user logs in it will retrieve the index for the ArrayList of random strings, then applies it to the entered password to then hash the whole string and compare the 2 passwords.
Is this a good way of salting? Is this classed as salting?
It's better to have unique salts for each user/password hash instead of reusing a limited set of 100 salts.
The reason is because of the way hackers attempt to compromise a database full of passwords once they get a hold of it, in particular using rainbow tables to find known values shared between multiple users.
For example (pseudo-code):
This is bad because once a hacker cracks the first password hash, both users are compromised.
//BAD WAY
var nonUniqueSalt = "some salt value";
var userPass1 = "P#ssword!";
var userPass2 = "P#ssword!";
//Bad! This will be true!
var isSame = (DoHash(userPass1 + nonUniqueSalt) == DoHash(userPass2 + nonUniqueSalt));
This way is better, because the salts are different even if the passwords are the same, so the hacker can't use rainbow tables and is forced to compromise each user's password individually.
//BETTER WAY
var uniqueSalt1 = "unique salt 1";
var userPass1 = "P#ssword!";
var uniqueSalt2 = "unique salt 2";
var userPass2 = "P#ssword!";
//Better! This will be false.
var isSame = (DoHash(userPass1 + uniqueSalt1) == DoHash(userPass2 + uniqueSalt2));
As far as the salting "algorithm" some users mentioned in comments, you don't REALLY need to worry about it too much aside from trying to make the salt unique to each user (because of the reasons described above).
In practice, whatever salt you use will need to be stored in the DB alongside the password hash, so once a hacker has the database, he'll have the value you used for a salt no matter how you go about deriving it.
As such, using a salt based on something like Guid.NewGuid().ToString() is sufficient for simply having unique values for each login.
I'm fairly new to C# and RavenDB, so please excuse my lack of understanding.
I currently have a Windows Form Application. In one of the forms, I have two text boxes and one button. These two text boxes serve as the username and password inputs and the button is obviously there so that the user can login. When the user clicks on the button, a method is called and saves the content of the two inputs in two string variables.
At the moment, in my RavenDB Database, I have created two samples of username and password.
How do I appropriately check whether the username and password given from the user exists in the database.
Any help is really appreciated.
There are two ways to answer this question.
a) You can query for multiple properties using the Linq provider
session.Query<User>().Where(user=> user.Name = username && user.Password = pass).ToList();
b) The problem with this is that this assumes that you are storing the password as plain text in the database, which you should never do.
You can see how we implemented that in RaccoonBlog's RavenDB's sample application:
https://github.com/ayende/RaccoonBlog/blob/master/src/RaccoonBlog.Web/Models/User.cs
https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Areas/Admin/Controllers/LoginController.cs
As a matter of good security practice you don't store passwords at all, rather you you store the password's hash.
To store your password
Read the values on the server and generate a hashcode of the password. You should use crypto functions to generate hash (such as via SHA256)
Store a document in Raven DB of type User with his username and hashed password
To check if the user with the passed credentials is in the database
Query Raven DB and look for the user with the given name and password hash.
Sample code
var user = session.Query<User>()
.Where(u => u.UserName == "Alice" && u.HashedPassword == "hashPwd");
In MySQL i can do
SELECT * FROM table WHERE MD5(column) = 'blablabla';
But how do i do that with NHibernate and Criteria functions?
I got a value alrady as md5 but the column in the database is not md5 hashed...
I working in C#.
Some ideas?
In Java, you can use Expression.Sql, the same should work in C#, something like:
var table = session.CreateCriteria(typeof(Table))
.Add(Expression.Sql("MD5(column)= ?", value, NHibernateUtil.String))
.UniqueResult<Table>();
where value is the hex-encoded value of your MD5 hash.
Although, one word of caution - if the value stored in the database is the user's password, then your design is flawed and insecure. You should only store salted, hashed passwords in the database. No, you shouldn't even do that, you should right away use bcrypt, scrypt or PBKDF2 for that.
I know how to execute queries from C# but I want to provide a dropdown list in which people can write a query and it will execute and populate the list.
A problem is that I want to forbid all queries that modify the database in any way. I have not managed to find a way to do this and I did my best with google.
The solution I can think of is that I will scan the query for INSERT, DELETE, UPDATE and only allow SELECT statements. However, I want to be able to allow users to call stored procedures as well. This means I need to get the body of the stored procedure and scan it before I execute it. How do I download a stored procedure then?
If anyone knows a way to only execute read only queries do share please! I have the feeling scanning the text for INSERT, DELETE, UPDATE doesn't prevent SQL injections.
The easiest way to do this might be to offload this job to the database. Just make sure that the database user that will be running the queries has read-access only. Then, any queries that do anything other than SELECT will fail, and you can report that failure back to the users.
If you don't go this route, the complexity becomes quite enormous, since you basically have to be prepared to parse an arbitrary SQL statement, not to mention arbitrary sequences of SQL statements if you allow stored procs to be run.
Even then, take care to ensure that you aren't leaking sensitive data through your queries. Directly input queries from site users can be dangerous if you're not careful. Even if you are, allowing these queries on anything but a specifically constructed sandbox database is a "whoops, I accidentally changed the user's permissions" away from becoming a security nightmare.
Another option is to write a "query creator" page, where users can pick the table and columns they'd like to see. You can then a) only show tables and columns that are appropriate for a given user (possibly based on user roles etc.) and b) generate the SQL yourself, preferably using a parameterized query.
Update: As Yahia points out, if the user has execute privilege (so that they can execute stored procs,) then the permissions of the procedure itself are honoured. Given that, it might be better to not allow arbitrary stored proc execution, but rather offer the users a list of procedures that are known to be safe. That will probably be difficult to maintain and error-prone, though, so disallowing stored procs altogether might be best.
How about creating a user account on the database server which only has select (read-only) rights?
Perhaps you could set up a SQL user with read-only access to the database and issue the command using that user? Then you can catch the errors when/if they happen.
It seems to me that it's going to be very difficult and error-prone to try to parse the query to figure out if it modifies the database.
You can't parse SQL like that reliably.
Use permissions to
Allow only SELECT on tables and views
No permissions on stored procedures that change data (An end user by default won't be able to see stored procedure definition)
Best is to not allow users to enter SQL and use only prepared/parameterized queries...
The next best way to prevent that is to use a restricted user with pure read access
The above two can be combined...
BEWARE
To execute a Stored Procedure the user must have execute privilege... IF the Stored Procedure modifies data then this would happen without an error messages even with a restricted user since the permission to modify is granted to the Stored Procedure!
IF you absolutely must allow users to enter SQL and can't restrict the login then you would need to use a SQL parser - for example this...
As to how to download the body of a Stored Procedure - this is dependent on the DB you use (SQL Server, Oracle etc.).
EDIT:
Another option are so-called "Database Firewall" - you connect instead of directly to the DB to the Firewall... in the Firewall you configure several things like time-based restrictions (when specific users/statement are/art not allowed), SQL-based statement (which are allowed...), quantity-based restrictions (like you can get 100 records, but are not able to download the whole table/DB...) etc.
There are commercial and opensource DB Firewalls out there - though these are by nature very dependent on the DB you use etc.
Examples:
Oracle Firewall - works with Oracle / SQL Server / DB2 etc.
SecureSphere - several including Oracle / SQL Server / DB2 etc.
GreenSQL - opensource version support Postgres + MySQL, commercial MS SQL Server
Don't forget about things that are even worse than INSERT, UPDATE, and DELETE. Like TRUNCATE...that's some bad stuff.
i think SQL Trigger is the best way what you want to do.
Your first move should be to create a DB user for this specific task with only the needed permissions (basically SELECT only), and with the rights to see only the tables you need them to see (so they cannot SELECT sys tables or your users table).
More generally, it seems like a bad idea to let users execute code directly on your database. Even if you protect it against data modification, they will still be able to make ugly-looking joins to make your db run slow, for instance.
Maybe whichever language your programming the UI with, you could try to look online for a custom control that allows filtering on a database. Google it...
this is not perfect but might be what you want, this allows the keyword to appear if its a part of a bigger alphanumeric string:
public static bool ValidateQuery(string query)
{
return !ValidateRegex("delete", query) && !ValidateRegex("exec", query) && !ValidateRegex("insert", query) && !ValidateRegex("alter", query) &&
!ValidateRegex("create", query) && !ValidateRegex("drop", query) && !ValidateRegex("truncate", query);
}
public static bool ValidateRegex(string term, string query)
{
// this regex finds all keywords {0} that are not leading or trailing by alphanumeric
return new Regex(string.Format("([^0-9a-z]{0}[^0-9a-z])|(^{0}[^0-9a-z])", term), RegexOptions.IgnoreCase).IsMatch(query);
}
you can see how it works here: regexstorm
see regex cheat sheet: cheatsheet1, cheatsheet2
notice this is not perfect since it might block a query with one of the keywords as a quote, but if you write the queries and its just a precaution then this might do the trick.
you can also take a different approach, try the query, and if it affects the database do a rollback:
public static bool IsDbAffected(string query, string conn, List<SqlParameter> parameters = null)
{
var response = false;
using (var sqlConnection = new SqlConnection(conn))
{
sqlConnection.Open();
using (var transaction = sqlConnection.BeginTransaction("Test Transaction"))
using (var command = new SqlCommand(query, sqlConnection, transaction))
{
command.Connection = sqlConnection;
command.CommandType = CommandType.Text;
command.CommandText = query;
if (parameters != null)
command.Parameters.AddRange(parameters.ToArray());
// ExecuteNonQuery() does not return data at all: only the number of rows affected by an insert, update, or delete.
if (command.ExecuteNonQuery() > 0)
{
transaction.Rollback("Test Transaction");
response = true;
}
transaction.Dispose();
command.Dispose();
}
}
return response;
}
you can also combine the two.