Monday, June 21, 2010

MS10-032, ou pourquoi c'est mal de changer de parent lors de la creation d'un enfant

Dans le bulletin MS10-032, trois vulnerabilites ont ete corrigees: CVE-2010-0485, CVE-2010-0484, CVE-2010-1255. Mais seule la premiere a un indice d'exploitabilite de 1. Il est interessant de constater que personne n'est credite pour la decouverte de cette vulnerabilite, decrite comme etant "Win32k Window Creation vulnerability". De plus, le bulletin specifie que la vulnerabilite a ete portee a la connaissance du public, mais il n'y a pas d'exploit circulant. Etrange.

Une rapide analyse differentielle du binaire (win32k.sys) mettra en evidence le rajout d'un "UnlinkWindow" dans une branche du code qui n'est atteinte que si WM_NCCREATE rate. Les fonctions "LinkWindow" et "UnlinkWindow" sont utilisees pour lier parents et enfants entre eux, pour la transmission de messages, le "Z-ordering", etc. Cependant, la liaison d'un enfant fraichement cree avec son parent n'a lieu qu'apres un WM_NCCREATE ayant reussi. Quel est donc l'interet de de-lier un enfant dont la creation a echoue, a un parent qu'il n'a pas? Tout simplement parceque dans le gestionnaire de WM_NCCREATE, il est possible de faire appel a SetParent() et donc de changer le parent d'un enfant en cours de creation.

Faire appel a SetParent() dans le gestionnaire de WM_NCCREATE et retourner 0, entrainera un cas singulier ou le parent pense qu'il a un enfant mais l'enfant a en fait ete detruit par un xxxFreeWindow(). Certains penseront de suite a un cas d'utilisation apres liberation, mais c'est en fait un chouillat plus complique. Le lien qui existe fait que lors de sa destruction, l'enfant est marque comme detruit mais pas libere. C'est moche, ca nous aurait facilite la tache. On se retrouve alors avec un enfant invisble, marque comme detruit, et qui ne repond a aucun message. Seule specificite de l'enfant, son parent est NULL. Il n'est pas facile de referencer le parent d'un enfant qui n'accepte aucun message. Il faut donc trouver un message a envoyer au parent, qui va etre diffuse a ses enfants, dont le traitement devra entrainer un referencement du parent. Il s'avere que deplacer le parent mettra en branle cette chaine d'evenements et se terminera en ecran bleu.

Quelques commentaires. Je pense que j'ai du rater quelque chose, parceque l'exploitation du chemin que j'ai trouve ne merite clairement pas un "1", c'est plus un 1.5 - 2. Certes on dipose de toutes les informations necessaires localement, mais la primitive que l'on obtient, une addition dans une boucle qui va finir par crasher, est difficilement exploitable. Je reviens maintenant sur le fait que cette vulnerabilite etait connue du public. Il faut remonter jusqu'en 2004 pour trouver une trace de ce bug:

http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.kernel/2004-03/0602.html

microsoft.public.win32.programmer.kernel n'etait probablement pas le bon endroit pour signaler une faille de securite. Neanmoins certaines personnes attentives auront pu beneficier d'une elevation de privileges dans TOUTES les versions de Windows pendant ces 6 dernieres annees...

Edit: Un lien envoye par ivanlef0u sur un doc de taviso sur les parents des fenetres: https://docs.google.com/View?id=dfqd62nk_228h28szgz. Interessant!