Questions de sécurité des comptes Windows stockées dans la LSA

Table des matières :

Questions de sécurité des comptes Windows stockées dans la LSA

Introduction

Les questions de sécurité ont été introduites dans Windows 10 1803 (en avril 2018). Ces questions permettent de fournir un moyen de récupération de mot de passe aux utilisateurs d’une machine.

Stockage et format

Ce secret est stocké dans la Local Security Authority (LSA) et est nommé selon le format L$_SQSA_<SID>, avec:

  • L$ - Local Secret
  • SQSA - Security Questions Security Answers
  • SID - Security identifier

Le format de ce secret est une chaine de caractères encodée en UTF-16-LE contenant un dictionnaire JSON:

{
  "version":1,
  "questions": [
    {
      "question":"What was your childhood nickname",
      "answer":"John"
    },
    {
      "question":"What is the first name of your oldest cousin?",
      "answer":"Jack"
    },
    {
      "question":"What was your first pet’s name?",
      "answer":"Fluffy"
    }
  ]
}

Implémentation dans les outils

Secretsdump de la suite Impacket

Dans le fichier impacket/examples/secretsdump.py j’ai rajouté ces quelques lignes de python pour automatiquement parser et mettre en forme les questions de sécurité dans la sortie de l’outil secretsdump :

elif re.match('^L\$_SQSA_(S-[0-9]-[0-9]-([0-9])+-([0-9])+-([0-9])+-([0-9])+-([0-9])+)$', upperName) is not None:
    # Decode stored security questions
    sid = re.search('^L\$_SQSA_(S-[0-9]-[0-9]-([0-9])+-([0-9])+-([0-9])+-([0-9])+-([0-9])+)$', upperName).group(1)
    try:
        strDecoded = secretItem.decode('utf-16le').replace('\xa0',' ')
        strDecoded = json.loads(strDecoded)
    except:
        pass
    else:
        output = []
        if strDecoded['version'] == 2:
            output.append(" - Version : %d" % strDecoded['version'])
            for qk in strDecoded['questions']:
                output.append(" | Question: %s" % qk['question'])
                output.append(" | └──> Answer: %s" % qk['answer'])
            output = '\n'.join(output)
            secret = 'Security Questions for user %s: \n%s' % (sid, output)
        else:
            LOG.warning("Unknown SQSA version (%s), please open an issue with the following data so we can add a parser for it." % str(strDecoded['version']))
            LOG.warning("Don't forget to remove sensitive content before sending the data in a Github issue.")
            secret = json.dumps(strDecoded, indent=4)

En sortie de l’outil secretsdump nous avons maintenant :

J’ai proposé une pull request pour l’intégrer dans impacket.

Références