This is a short story about how a seemingly small logic bug can lead to a big security risk. I was testing an organization that utilized the CA Identity Manager as an identity management solution. This web application acted as a centralized place where users could request access to multiple systems, and most importantly, manage a single password that was synchronized across all systems they could access. This included credentials for the internal Windows network, as well as internal and external web applications. The CA Identity Manager application included a “Forgot Password” feature, which was configured to allow users to access their account by answers security questions. It was in this feature that I discovered a bug that allowed me to continuously guess answers against a user’s security questions.
My opinion on security questions
Before I go into details about triggering the bug and how I took advantage of it, I need to mention a few reasons about why I don’t like security questions as a means for account or password recovery:
- For an attacker, they are easy to guess (if a user answers them honestly).
- For a user, the answers are sometimes hard to remember (and even harder when they provide false answers) because they don’t frequently use them, and/or they don’t remember exactly how they answered the question the first time (Favorite Author: Tolkien or JRR Tolkien).
- The questions/answers are often stored in plain text in the database or even in the user’s profile. This means that if an attacker gains access to the database (or a user’s profile) then they also have access to the security questions and answers.
- If the questions are answered honestly then they can’t be changed as easy as changing a password (you can’t change your grandmother’s maiden name).
Back to the story…
That being said, this application did have good intentions for keeping the security questions/answers safe. The system was configured to disable the user account after 3 failed attempts to answer the security questions, which is usually a very effective control. Additionally, the security questions were variable; the user provided answers to 5 questions (chosen from a pool of 17 questions) and password recovery required the user to correctly answer 3 of their questions. Unfortunately, the account disablement was able to be bypassed, allowing unlimited guesses against the security questions. Here is a rundown of how the account disablement was supposed to work.
The intended account disablement feature
A user clicks on the ‘Forgot Password’ link and enters a valid user name:
They are presented with a security question:
An incorrect answer gives immediate feedback, but offers a chance to try again:
If a second incorrect answer is entered, no error message is given but another question is presented:
The same thing happens for this question. An incorrect answer gives an error, but on the second incorrect answer you are given this error:
At this point, clicking the ‘OK’ button takes you back to the login screen, where you can click the ‘Forgot Password’ link, enter a valid username, and try to again. If you go through this process three times, then your user account will be disabled and you will no longer be able to guess answers to security questions or log in to the site.
As mentioned, it takes three times going through this process before the account is disabled. So imagine a server-side variable that acts as a counter for the failed guessing attempts. The flaw comes about because that server-side counter variable doesn’t increment unless you go through all the steps (two incorrect guesses on the first question, and two incorrect guesses on the second question). The way to take advantage of this flaw is to make one guess, click the cancel button and visit the login page (which starts a new session), and repeat.
Each time the system returns a question to be answered, it randomly chooses the question from one of the 5 configured questions, so an attacker will have the opportunity to cycle through and guess each question.
When I found this logic bug, I was super excited and immediately reported a critical finding to the client and contacted CA about the issue. Neither of them seemed very impressed. The client thought it was too much theory, and CA didn’t really seem convinced as they couldn’t reproduce it (turns out we were miscommunicating about versions). So, I started writing code to automate the guessing process so I could show the client the impact.
Here is a short demo of the tool in action. It takes a list of users (which have been anonymized in this video) and immediately starts guessing answers. Each correct answer is written to the screen along with the question and username.
This tool was able to guess correct answers (for 3 or more questions) for ~40% of the users from the user list I had gathered. After an initial small sample group (100 users), I decided to target important accounts. I went after the C-suite, domain administrators, and infosec personnel. For those groups I had ~50% success rate for answering at least 3 of their questions.
Admittedly, a contributing factor for the success of this attack was due to the some of the questions. As mentioned, the site allowed the user to provide answers for 5 questions from a pool of 17 questions. However, the problem with many of the questions is that the probable answer set was relatively small. Example:
Who is your favorite super hero? Probably less than 100 possible answers. Most people chose batman, superman, or spiderman.
If you were a car, what kind of a car would you be? Probably less than 50 answers. Nobody has ever wanted to be a Nissan Sentra or Ford focus. They want to be a Porsche, Shelby, Jaguar, or the Batmobile
How much did you weigh your last year of high school? Probably less than 200 answers (75-250).
There were similar questions about books, favorite authors, the last word of favorite movie quote, among others.
There were also questions dealing with things such as Grandmother’s maiden name, spouse’s mother’s last name, and favorite teacher’s name. While these could have many answers, I just compiled a list of the most common 200 last names. Worked pretty well.
What I learned about users
I was always taught to lie when answering my security questions, and my expectation was that most IT and IT security people would probably have unguessable answers. It turns out I was wrong. Knowing what I know now, I would say there are four types of users when it comes to answering security questions:
- Truth tellers: They answer the questions honestly, and it was easy to guess the answers to their questions.
- Liars who still provide a possible answer: These people lie. If the question was “What was your favorite children’s book”, they may answer ‘The Cat in the Hat’ even though their real favorite children’s book is ‘Green eggs and ham’. Maybe that will confuse a targeted attack, but be assured both books will be on an attacker’s list. It was easy to guess the answers to their questions.
- Complete liars: These people provide answers that are infeasible to categorize. The answer to ‘What is your favorite movie?’ might be correcthorsebatterystaple. I probably didn’t guess any of these people’s answers to their questions.
- ‘Clever’ people: These people answer the questions in a strange but often predictable way. They may answer the question with the last word of the question (Q: What is your favorite animal? A: animal). They may answer with ‘none’ or ‘nothing’ or ‘nobody’ or something like that. They may answer the questions with answer1, answer2, answer3, etc. It was hit or miss with these ‘clever’ people.
All sorts of people, including IT and IT security people, fell into each of these categories. Executives, SOC analysts, Domain Administrators; all types.
Advice to users
It’s tough to give advice on answering questions. If you tell outlandish lies, you’ll likely have to write the answers down somewhere to remember them. If you tell the truth or half-truths, then you’ll likely be guessable. Another approach may be a combination of the truth and a secret. There are many ways you could do this; perhaps an answer and its reverse:
Q: What is your favorite animal? A: wolfflow
Or maybe the truth and a secret word you can reuse (submarine will be my secret word):
Q: What’s you’re favorite color? greensubmarine
Personally, I tell outrageous lies and store the answers in a password safe.
Advice to systems that want to use security questions
First and foremost, the account disablement feature must work. After that, I can think of two other things you could do to make a safer system, but there will be a tradeoff between security and user experience.
- Require all security questions to be answered at the same time, rather than one by one, and if an answer is incorrect do not specify which one. For example:
Answering any of these questions incorrectly would result in the following error:
This provides an added degree of difficulty and would greatly increase the time and number of guesses it would take to get all three questions correct.
- Allow users to write their own security questions. This increases the work for an attacker, as it takes time to come up with potential answers to questions. Making an automated tool would prove difficult if you there were an infinite number of questions.
After I wrote the exploit, the organization paid much more attention, and immediately started to see things my way. They acted quickly to disable the feature until a fix could be implemented. CA later got back to me and confirmed the bug affected Identity Manager versions 12.6.8 CR1 and 14.0 GA with the fixes dated from April and June 2017. What was interesting was that the fix was not filed as a security bug. Even after seeing a proof of concept, CA decided to not send out any security notice.
Overall I thought it was a pretty cool bug. It serves as a good example about how a simple logic flaw could allow an external attacker to compromise 40-50% of an organization’s accounts, including those with high privileges. Don’t overlook the small stuff.