15

Our developers left a surprise in handling user login. Namely:

// java
List users = hibernate.find("from Users where username = '"+formUsername+"'";
if (users.length==0) { return BAD_USER; }
if (!checkPassword(users.get(0).getPassword(), formPassword)) {
  return BAD_USERNAME_PASSWORD_COMBO;
}
// continue to mark session as authenticated

Now, obviously, it's possible to inject into the query. But that is HQL language. If it was SQL, and I knew the structure of the database, I could hang a "union" operation, and could log in into any account. But I don't quite see what kind of malicious HQL I can hang on here, to really make something bad happen.

Yes, we've already replaced this code to use parameters, but I'm just curious as to what can be done in that situation. The HQL examples I've seen are about adding 'OR' operator, which will not help in this case.

Also, the underlying database is postgres, so any postgres functions are fair game.

P.S.

There was a question as to how the union would help. Given the table structure of (id,username,password), and SQL query of:

select id, username, password from users where username = ...

I can inject:

' union select 1, 'root', 'synthetic_password

and the complete executed SQL will become:

select id, username, password from users where username = '' union select 1, 'root', 'synthetic_password'

First select would not return any records, and the second will return a record that JAVA code will read and populate its beans from it. It will then compare the password, but since I provided the password data in both the injected SQL, and in the form, they will check out.

Pawel Veselov
  • 561
  • 5
  • 11

1 Answers1

7

You could for example enumerate any users hash/password:

insert the following as the username:

admin' AND substring(password,0,1) == char(64) AND '1' = '1

Checks if first character in column 'password' is a lower case a.

Chris Dale
  • 16,149
  • 10
  • 57
  • 97
  • nice! Still would only enumerate hashes for us, and there is no interface to use hash as a password directly. – Pawel Veselov Nov 20 '12 at 23:22
  • It's worth mentioning that this technique is called Blind Injection. – Polynomial Nov 21 '12 at 06:56
  • @PawelVeselov, Yes, but you could use this scenario for every other piece of data in your database. There is tools that automate this for your, such as Havji and SQLMap. – Chris Dale Nov 21 '12 at 08:30
  • 1
    Are you _sure_ the passwords are hashed? The naming of stuff up there makes it seem otherwise... And at minimum, you don't appear to be using salts. – Clockwork-Muse Nov 21 '12 at 21:04
  • Agree with @Clockwork-Muse . Unless you modify formPassword by applying the hashing algorithm on it, it looks like it is not hashed. – Chris Dale Nov 22 '12 at 09:55
  • The code I put together was just to show general algorithm of how the password is checked. The logic to hash and compare is all inside checkPassword(). Yes, we are not using salts, but it's an MD5 hash. – Pawel Veselov Nov 23 '12 at 01:38
  • Sorry, without a salt (and even [apparently with](http://security.stackexchange.com/questions/19906/is-md5-considered-insecure)), MD5 is considered a broken hash. Just have a look around (for example, [this question](http://security.stackexchange.com/questions/17968/logic-for-generating-strong-password)) – Clockwork-Muse Nov 23 '12 at 16:56
  • @Clockwork-Muse I agree to all that. But it's outside the scope of the original question, and is a separate discussion all together. For the record, I do acknowledge the weakness of MD5 (there are better hashes), but I don't so much believe in usefulness of salts (because salts are stored alongside hashes, if I got my hands on a hash, I got my hands on the salt) – Pawel Veselov Nov 25 '12 at 23:38
  • 1
    @PawelVeselov, you have misunderstood the function of the salt :) I recommend reading up on it and learning about its function. – Chris Dale Nov 26 '12 at 07:00
  • @ChrisAndrèDale IMHO, I'm not misunderstanding it. for either hash=f(pt) or hash=f(pt,salt), the only component that's not stored by db is pt. If the db is stolen, salt makes it harder to find the pt from hash in pre-computed databases. I don't believe that brute-forcing with salt, or without salt is any different (unless you somehow make salt application REALLY slow). For a pre-computed database, how hard it is to traverse it, with a given salt value? – Pawel Veselov Nov 26 '12 at 07:43
  • 1
    @PawelVeselov, Yes!This is when it gets interesting, and also this is explained in several questions already on sec.se. Being able to thwart rainbow tables and make the attacker recompute hashes for every password he is trying are some serious benefits of salts. Again, I recommend reading up on it, as the subject is too big to answer in a comment :) Best of luck. PS:You should use a slow password algorithm such as PBKDF#2, Bcrypt or Scrypt. They are designed to hash passwords, which MD5 is not. – Chris Dale Nov 26 '12 at 09:17