Disclaimer: I'm a computer programmer, not a security analyst or anything to do with security. I have zero experience in the world of cryptography, so bear with me please.
Situation: I was given the task to integrate a client's site with a data hosting site. While working on that, I stumbled upon a query that dumps all users' data. To make this query, the user has to 'authenticate' to get a session and use that session code to make this query, which then checks that the user has admin privileges before completing the query and responding.
But still... that seems sort of horrible to me. Especially since this is some of the data that is sent back if the query is successfully run:
"username": "email@example.com", "firstname": "Test", "lastname": "Name", "userpassword": "$1$te000000$qMpAriadAHuRyDkK58YKS0"
There is more data returned that is horrible to expose, but that's not my primary concern.
Clearly no person has ever been named "Test Name", and "testemail.blerg" is not a registered domain, let alone "blerg" being a possible top-level domain. Even if it were, that account has been deleted from the data hosting site and cannot log in. The password that was used is a weak, test-case one, and is not in-use by anyone.
Is is possible for me to brute-force/rainbow-table (while I don't have experience, I know some flash-words :P) or something to get the password from that? What little (I think) I know is that the first part of the
userpassword is the MD5 salt, but I don't know anything else.
If anyone can explain how easy it is, I can prove to my boss that this site is completely horrible and convince our client to migrate from this data hosting site.
There is more that I do know about the salting (i.e. how it gets the salt, what language/function it's using, etc), but I'd like to see how easily someone who doesn't have access to that information can figure it out. Another thing for me to go to my boss with, hopefully.
EDIT: There seems to a little confusion related to my intentionally being vague in the description, partially for the purpose of preventing any indication of which CRM this is, for legal/etc reasons. I also realize that my calling it 'data hosting' was potentially misleading, so my bad. Hopefully this clarifies:
The work our team is doing is creating a basic website for a company to show off their products. The only interaction I have with the CRM is:
- When a person fills out the Contact Us form, we
POSTto the CRM a
Contactsobject with the user's information.
- Do a
GETon a list of
Dealersthat sell their products to display.
I started with #2, the
GET API call, where I found out that I can query the
Users table. I have not created the API, I have only been making requests of it.
GET call requires a param
query= where the value is a
SELECT statement in the system's query language, which is then translated to SQL (presumably preventing SQLI attacks, but I don't know how it interprets/translates to SQL, so I'm not touching that with a 10ft pole). By changing
SELECT * FROM Dealers; to
SELECT * FROM Users; in the query I was able to see every user's data.
The way the CRM handles users is with a portal on their site. A user is created in the portal, where there is an "Is Admin" checkbox. This can be edited at any time through the portal. This is the process to making API requests:
A user makes a request to the CRM, containing the username, for a token.
The token is concatenated with the "secret" access key for that user, the resulting string is MD5 hashed and then sent back to request a session token.
This session token is included with every request, as a querystring param, to "verify" that the request is "authorized".
One of the problems is that if an 'admin' user makes a request of the
Users table, the response is a list of every user with the information I listed above as well as the user's "secret" access token (and other information). So it's even worse than just exposing a password, it's practically granting access to anyone by impersonating anyone.