SubSonic: Case sensitive test? - subsonic

I'm curious if there's a way to do a case sensitive string comparison in SubSonic? I have the following statement:
return new Select()
.From<Account>()
.Where("email").IsEqualTo(email)
.And("password").IsEqualTo(password)
.ExecuteSingle<Account>();
However, it does not test against case for the password (which is what I need to do). Ideally, the password would be encrypted before storing, so this wouldn't be an issue. But, aside from using straight SQL, is there a way to do a case sensitive comparison (BINARY)?

SubSonic just creates the query - it doesn't handle the actual comparison, your DB does. You can set your DB to be case-sensitive if you want to (it's in the settings of just about every DB provider out there). I would recommend this.
If this isn't an option, then you can pull all records with the supplied email and then run a string comparison in code using String.Equals().
Encrypting isn't a good idea - salt/hash the password to do a one-way thing. If you can pull passwords and decrypt your system isn't secure.
You're still stuck with the same issue though - so set the case stuff in the DB or compare in code.

Not a good way but you can do your authentication on application level. You can get account with email and then compare password on application level. Performance killer but, it will do the trick.

Related

Hashing of api keys in Phoenix/Elixir and using comeonin for this

In my system each user can have multiple api keys. I want to hash api keys and store in a database their hashes. I'm using comeonin for this.
1) is it sensible to store hashes of api keys rather than their plain, original values?
2) when an api request comes in, there's only a plain api key value in it and no user email along with it -- this is my system is designed.
How should I check if an api key is valid? Will I have to do this -- recalculate a hash?
given_api_plain_key = get_key_from_request()
# re-hash it again
# but how about the original salt???
given_api_hash_key = Comeonin.Bcrypt.hashpwsalt(given_api_plain_key)
case Repo.get_by(ApiKey, key_hash: given_api_hash_key) do
nil -> IO.puts("not found")
a -> IO.puts("gooood")
end
Or is there a better way?
(1) is it sensible to store hashes of api keys rather than their plain, original values?
Your goal seems to be to protect against grand compromises that might happen if somebody gets access to your database (for example, via SQL injection, command injection, or reverse shell on your system). In this case, yes it is sensible, especially if each user has a different API key. However this link is worth reading for other considerations that might affect your decision.
(2) How should I check if an api key is valid?
It is clear that you need to hash the input and see if matches to something in your database.
(3) Implementation.
You do not want to apply the same protection that you use for passwords. Passwords tend to have low entropy by nature, and therefore we need tools like bcrypt to process them. Bcrypt is slow by design (to prevent brute force attacks), and uses salts to help the security of poorly chosen passwords.
API keys should not have low entropy, and therefore you do not need slow functions to process them. In fact, slow functions bring DoS risks, so you definitely do not want to do a bcrypt every request that comes in. Salting also complicates your use case (salts work when you know who is providing the input, but in your case you do not know who it is coming from beforehand).
Short answer: Just use SHA256, no salt needed.

SQL Injection assistance required

I am trying to understand the below injection and what it is trying to do. What is it trying to get? The only portion I understand is the union and select part, but the full injection I am unsure of and need help understanding.
action=&aid=1&_FILES%5Btype%5D%5Btmp_name%5D=%5C%27%20or%20mid=#%60%5C%27%60%20/!50000union//!50000select/1,2,3,(select%20CONCAT(0x7c,userid,0x7c,pwd)+from+%60%23#__admin%60%20limit+0,1),5,6,7,8,9%23#%60%5C%27%60+&_FILES%5Btype%5D%5Bname%5D=1.jpg&_FILES%5Btype%5D%5Btype%5D=application/octet-stream&_FILES%5Btype%5D%5Bsize%5D=4294
Well, first we can url decode the string:
action=
&aid=1
&_FILES[type][tmp_name]=\' or mid=#`\'`/!50000union//!50000select/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from `##__admin` limit 0,1),5,6,7,8,9##`\'`
&_FILES[type][name]=1.jpg
&_FILES[type][type]=application/octet-stream
&_FILES[type][size]=4294
One of these parameters sticks out as pretty suspicious.
[tmp_name]=\' OR mid=#`\'`
/!50000union/
/!50000select/1,2,3,
(select CONCAT(0x7c,userid,0x7c,pwd)
from `##__admin`
limit 0,1)
,5,6,7,8,9##`\'`
In plain english, it's injecting a select query to get usernames and passwords in a format like 0x7c<user>0x7c<password> from the ##__admin table (which, according to #DCoder is likely a placeholder for the actual table where these values would be kept) and appending it to your original select.
The !50000 stuff is for bypassing your web application firewall (if you have one). If you don't, then it may just be a bot or automated attempt. Or someone following a script to see what works. The numbers aren't really useful - it may be for evading a firewall or just for debugging purposes for the attacker to see how the output looks. It's hard to tell without being able to run it.
Here's what the SQL the attacker is trying to run would look like in 'plain SQL':
select
userid,
pwd
from
`##__admin`
Do you have a table like this? When you go to this url for your site, does it dump the user table? If not, then you may not even have a problem and it is just an automated scan. You may still have issues with SQL injection, even if it doesn't work, but having this in your logs is not evidence of a breach... it's definitely a red flag though.
It's adding extra columns to the result recordset, with user/pwd information. So in essence, the user wants to collect user accounts he or she wants to abuse.
It have to be noted that SQL injection (if any) is made possible by another vulnerability.
It is clear that this application is depending (or at least it is believed by the malicious user) on the some sort of homebrewed implementation of register_globals. A worst implementation ever.
To make this code work, the application have to take GET variables, and blindly convert them in global variables, making $_FILE array to appear not from internal process but from mere GET request.

How to sanitize data coming out of a database

This is my first question on stack overflow and I have taken a lot of time to search for the similar question but surprisingly could not find one.
So I read that no data should be trusted, whether from a client or that which is coming out of a database. Now while there are lots of examples that show how to sanitize data from a user ($_POST or $_GET), I could not find one that shows how the data from a database should be sanitized.
Now maybe it's the same as the data coming from a user / client (that's what I think it should be) but I found no example of it. So I am asking it just to make sure.
So for example if the result of a query yields as follows:-
$row=mysqli_fetch_assoc($result);
$pw = $row['Password'];
$id = $row['ID'];
$user = $row['Username'];
then do the variables $pw, $id and $user have to be sanitized before they should be used in the program? If so, then how ?
Thanks to all.
Your thinking is back to front here. By the time you are able to sanitise inputs using php, it's probably too late. The data is already in php. You don't sanitise inputs. You:
validate input & sanitise output
Normally a database is wrapped by the application tier. So the only data in there should have been filtered and escaped by your code. You should be able to trust it. But even then, in a relational database the data is fairly strongly typed. Hence there is little scope for attacking php from the data tier.
But you should be sanitising (escaping or encoding) any output. How you do that depends on where and how you are sending the data, hence it should be done at the point where it leaves php, not the point where it enters php. And the method you use (mysqli_escape, HTMLentities, base64, urlencode.....) Should be appropriate to where the data is going. Indeed it is better practice to change the representation of a copy of the data (and discard it after use) rather than the original.
It depends... How are you accessing this database? Who works on / maintains it? Going in is definitely a far bigger concern. However, if you wanted to sanitize it coming out of a database you need to know what you are sanitizing for. If you want to sanitize web traffic against XSS you'd probably want to remove all url's not on a whitelist, perhaps script tags and a few other things as well. Are you sanitizing data going into a C/C++ program? Then you probably want to make sure you're protecting yourself against buffer overflow issues as this is a legitimate avenue of attack.
I'm drawing some assumptions about your design here but I'm going to assume you're just working on the model aspect of an MVC application using PHP. PHP, in this case, has been most vulnerable to SQL Injection attacks on the backend, and XSS (cross site scripting) attacks on the front end. (NOTE: This isn't a PHP problem exclusively, this is a problem in all programming and different languages provide different solutions to different problems. Remember - you need to know what you're sanitizing for what reason. There is no one size fits all.
So really, unless you are sanitizing against something universal in all the code this model will sanitize for, you probably don't want to sanitize here. XSS would be a bigger concern to you now than sql injection... the way out is too late to stop an injection attack.
To take some liberty just to get the juices flowing - From a security standpoint, given your code seems to revolve around authentication, I would be much more immediately concerned around how you are storing and processing your credentialing data. A few things should definitely be doing:
Running the password through a secure, 1-way hash BEFORE storage (such as BCrypt).
Salting these hashes (with a different salt for EACH user) before storing them in the database to protect your user's data from things such as rainbow table attacks.
Using TLS for all communications.
Establishing and maintaining a secure session (track user-login without exposing password data with every single request sent, amongst other things).

Should one salt & hash the response to the challenge question used for lost pw?

If you salt & hash a pw in a db, should you also do so for the response to the challenge question used during a temporary pw generation?
Thanks,
JDelage
It depends on what you want to do with the stored response. If you only want to compare it exactly to the response supplied by the user, storing it as a salted hash will be fine and is highly recommended.
But if you allow an answer that is almost correct (e.g. case-sensitivity or missed whitespaces), you will need the original string for comparison. Also if you have a helpdesk that supports users resetting their password, you might want them to be able to compare the answers. In such cases you will need the original string, the hash is useless. Your decision depends on what you might need the original string for during the password reset process.
In case you cannot avoid storing the information in clear text, you should enforce additional restrictions to password resets like a validated email address to send an authorization link to, before the password can be changed.
yes, you should.
There is no need to ever know what the challenge was, only if it was answered correctly.
If you're asking about password recovery questions & answers, then, good heavens, yes! You might be able to implement a bit more traceability around the processes of password recovery (to detect and prevent attempted cracking), but that part of your database is just as sensitive as your passwords, and would harm your users if leaked in plaintext.
Basically, password recovery challenges are just passwords by another name...

Encrypted passwords of not-encrypted passwords user base

Some time ago I joined new project. It was under development for quite a long time.
The thing that surprised me was that all users' passwords are stored in non-encrypted form.
I explained huge security vulnerabilities of this to our management - it looks like they agree with that and want to make project more secure. Team members agree too.
We have about 20K users in the system.
Actually it is quite stressful to make this work - migrate non-encrypted passwords to encrypted form. If something goes wrong it can lead to project's disaster.
How can I lower this stress?
Backup?
Unit-tests(integrational tests)?
Well, be careful with your backup because it will contain unencrypted user passwords :-)
Assuming that the passwords are stored in a database, an easy solution would go something like this:
1) Make a secure backup of the entire table data
2) Create new column (PasswordEncrypted or similar name)
3) Use an UPDATE query to update each row's new column with an MD5 of the unencrypted password while using a 32 byte or larger salt. Pretty much every database system today has an MD5 function so you won't even have to leave your SQL prompt
4) Keep the plaintext column in the interim and update your application/scripts accordingly to work with the salted password.
5) Rename the plaintext old password column to temporarily take it out of play and test your application- if there are any problems then go back to step 4 and fix your mistakes.
6) When everything is working properly drop the plaintext password column
7) Encourage users to pick a new password now that you have some level of security in place to mitigate the effects of any previous attacks which may have been successful.
What sort of project is this? A web application, desktop application?
If you're going down the refactoring road, is there a reason that the passwords need to be stored in something reversible like encryption? In general, it's good practice to hash your passwords with something like SHA then hash the input with the same algorithm and compare the results. You only store the hashed values, not the actual passwords. This gives you the ability to check that someone has entered the correct password without exposing your users to the possibility of your encryption being broken and their passwords exposed.
Specific information about your approach isn't something I can provide (since I don't know how it works), but your best bet is to create an additional column to store the hashed passwords, hash the existing passwords, then keep them up to date with any password changes. Use this new column for all new development, then once the move is complete and tested, delete the column with the plaintext passwords.
Write lots of tests, that test lots of corner cases (upper and lower case, numbers, symbols, Unicode characters, long passwords, etc). When you're developing and testing, create a system to move back to the old system (by providing the old password list, of course, since once the passwords are hashed you won't be able to convert them back directly). Save a copy of the current password list. Convert the passwords over in a test file or test database, and then use the saved copied of the passwords to test that everything worked. Now move the system into production, and make sure it works for your users. If it does not, you have already tested the plan for migrating back to the old system. Once it has been demonstrated to work for a couple of weeks, you can delete the cleartext password list and you're all set.
I would just hash the current passwords, store them in a new database field, and begin using that field while deleting the password field. I would then notify my users that now would be a good time to change passwords as you've implemented more security mechanisms to keep their data safe.
To have a backup, just do SELECT * INTO Backup FROM UserData
You can get extra confidence by running both authentication methods (encrypted and unencrypted) for each login attempt, and if they yield a different outcome, get an alert e-mail sent to you. This change is not visible to your users, so it can run for weeks and even months. Once you see that the old and the new authentication works for a high enough percentage of your users, deactivate the old one.
If possible you can try this: Send out an email to all your users to update their passwords with a time-out period, after which they cannot work if they do not change their passwords. Hash these new passwords and store the hash. This would require some changes on the frontend (i.e. the data it sends back).

Resources