Big Fish: Exploiting a 37-Year-Old Kernel Bug in OpenBSD
🇬🇧 English
Calif, a security research firm, has published details of a vulnerability in OpenBSD that traces back roughly 37 years to the original BSD sources. A shared memory attachment counter was defined as a signed 16-bit short. Repeatedly forking a process with shared memory attachment records could push that counter past its maximum value of 32,767, causing it to wrap to a negative value. This integer overflow could lead to a use-after-free via a race condition. Combined with a separate out-of-bounds write in the kernel, it allowed local privilege escalation to root. The issues were addressed in errata 026 and 018.
The researchers described an exploit path that achieved local root on OpenBSD with KARL, SMAP and SMEP enabled, without using an information disclosure vulnerability. The method involved mapping 127 System V shared memory segments, unmapping them, and forking 259 processes to wrap the attach count. Heap grooming and a race condition were then used to align allocations, corrupt a multicast structure, and ultimately gain kernel code execution by overwriting a predictable kernel pointer.
The exploit relied on a write-what-where primitive, where the write came from a TAILQ_REMOVE operation, the target was userland memory made supervisor-accessible, and the location was a predictable kernel pointer. OpenBSD's KARL randomizes function and data addresses, but the kernel's memory allocators remain deterministic, which made certain early boot allocations reliable targets.
To reduce the risk of similar attacks, the authors suggest measures such as safe-unlinking, which checks doubly linked list invariants before performing unlink writes and aborts or panics if they are violated. Calif said it regularly reports vulnerabilities to open source projects, often with suggested patches.
🇸🇦 العربية
ثغرة نواة عمرها 37 عامًا في OpenBSD تتيح استغلالًا للحصول على صلاحيات الجذر
نشرت Calif، وهي شركة أبحاث أمنية، تفاصيل ثغرة في OpenBSD تعود جذورها إلى نحو 37 عامًا في مصادر BSD الأصلية. كان عداد إرفاق الذاكرة المشتركة معرّفًا كعدد قصير موقّع بسعة 16 بتًا. ويمكن لتكرار تفريع عملية تحمل سجلات إرفاق ذاكرة مشتركة أن يدفع هذا العداد إلى ما بعد حده الأقصى البالغ 32,767، فيلتف إلى قيمة سالبة. ويمكن لهذا الفيض الصحيح أن يؤدي إلى استخدام بعد التحرير عبر حالة سباق. وعند اقترانه بكتابة منفصلة خارج الحدود داخل النواة، سمح بتصعيد الامتيازات المحلية إلى الجذر. وقد عُولجت المشكلات في errata 026 و018.
وصف الباحثون مسار استغلال حقق صلاحيات الجذر المحلية على OpenBSD مع تفعيل KARL وSMAP وSMEP، دون استخدام ثغرة كشف معلومات. تضمنت الطريقة ربط 127 قطعة ذاكرة مشتركة من نوع System V وفك ربطها، وتفريع 259 عملية لجعل عداد الإرفاق يلتف. ثم استُخدم تهيئة الكومة وحالة السباق لمحاذاة التخصيصات، وإفساد بنية multicast، وصولًا إلى تنفيذ شيفرة في النواة عبر الكتابة فوق مؤشر نواة قابل للتنبؤ.
اعتمد الاستغلال على أداة كتابة من نوع write-what-where: جاءت الكتابة من عملية TAILQ_REMOVE، وكان الهدف ذاكرة userland جُعلت متاحة لوضع المشرف، وكان الموقع مؤشرًا قابلًا للتنبؤ داخل النواة. تقوم آلية KARL في OpenBSD بعشوائية عناوين الدوال والبيانات، لكن مخصصات الذاكرة في النواة تبقى حتمية، ما جعل بعض تخصيصات مرحلة الإقلاع المبكرة أهدافًا موثوقة.
ولتقليل خطر هجمات مشابهة، يقترح المؤلفون إجراءات مثل safe-unlinking، الذي يتحقق من ثوابت القوائم المرتبطة ثنائيًا قبل إجراء كتابات الفصل، ويوقف التنفيذ عبر abort أو panic إذا انتُهكت هذه الثوابت. وقالت Calif إنها تُبلغ بانتظام مشاريع المصادر المفتوحة عن الثغرات، وغالبًا مع اقتراح التصحيحات.
كيف أمكن تنفيذ استغلال الجذر في OpenBSD؟
يمكن لعداد إرفاق الذاكرة المشتركة الموقّع بسعة 16 بتًا أن يفيض بعد تكرار التفريع فيلتف إلى قيمة سالبة. أتاح ذلك استخدامًا بعد التحرير عبر حالة سباق، وعند اقترانه بكتابة خارج الحدود داخل النواة أمكن التصعيد المحلي إلى الجذر. وقد أُصلحت المشكلات في errata 026 و018.
🇧🇩 বাংলা
OpenBSD-এর ৩৭ বছরের পুরনো কার্নেল বাগ রুট এক্সপ্লয়েটের সুযোগ তৈরি করে
নিরাপত্তা গবেষণা প্রতিষ্ঠান Calif মূল BSD সোর্স পর্যন্ত প্রায় ৩৭ বছর আগের একটি OpenBSD দুর্বলতার বিস্তারিত প্রকাশ করেছে। একটি শেয়ার্ড মেমোরি অ্যাটাচমেন্ট কাউন্টারকে সাইনড ১৬-বিট short হিসেবে সংজ্ঞায়িত করা হয়েছিল। শেয়ার্ড মেমোরি অ্যাটাচমেন্ট রেকর্ড থাকা একটি প্রক্রিয়াকে বারবার fork করলে কাউন্টারটি তার সর্বোচ্চ মান ৩২,৭৬৭ ছাড়িয়ে যেতে পারত এবং ঋণাত্মক মানে ঘুরে যেত। এই ইন্টিজার ওভারফ্লো একটি রেস কন্ডিশনের মাধ্যমে use-after-free-এর দিকে নিয়ে যেতে পারত। কার্নেলে আলাদা একটি out-of-bounds write-এর সঙ্গে মিলিত হয়ে এটি স্থানীয়ভাবে রুট পর্যন্ত সুবিধা বৃদ্ধির সুযোগ দিত। সমস্যাগুলো errata 026 ও 018-এ সমাধান করা হয়েছে।
গবেষকরা এমন একটি এক্সপ্লয়েট পথের বর্ণনা দিয়েছেন যা KARL, SMAP ও SMEP সক্রিয় থাকা অবস্থায় OpenBSD-তে স্থানীয় রুট অর্জন করেছে, কোনো information disclosure দুর্বলতা ব্যবহার না করেই। পদ্ধতিতে ১২৭টি System V শেয়ার্ড মেমোরি সেগমেন্ট ম্যাপ ও আনম্যাপ করা এবং অ্যাটাচ কাউন্ট ঘোরাতে ২৫৯টি প্রক্রিয়া fork করা হয়েছিল। এরপর heap grooming ও রেস কন্ডিশন ব্যবহার করে বরাদ্দগুলো সারিবদ্ধ করা হয়, একটি multicast কাঠামো নষ্ট করা হয় এবং শেষ পর্যন্ত একটি পূর্বানুমেয় কার্নেল পয়েন্টার ওভাররাইট করে কার্নেল কোড এক্সিকিউশন অর্জন করা হয়।
এই এক্সপ্লয়েট একটি write-what-where প্রিমিটিভের উপর নির্ভর করেছিল: লেখাটি এসেছিল TAILQ_REMOVE অপারেশন থেকে, লক্ষ্য ছিল supervisor-accessible করা userland মেমোরি, আর অবস্থান ছিল একটি পূর্বানুমেয় কার্নেল পয়েন্টার। OpenBSD-এর KARL ফাংশন ও ডেটার ঠিকানা র্যান্ডমাইজ করে, তবে কার্নেলের মেমোরি অ্যালোকেটর এখনো নির্ধারিত, তাই বুটের প্রাথমিক কিছু বরাদ্দ নির্ভরযোগ্য লক্ষ্যে পরিণত হয়েছিল।
এ ধরনের আক্রমণের ঝুঁকি কমাতে লেখকেরা safe-unlinking-এর মতো ব্যবস্থার পরামর্শ দিয়েছেন, যা unlink লেখার আগে doubly linked list-এর invariant যাচাই করে এবং লঙ্ঘিত হলে abort বা panic করে। Calif জানিয়েছে, তারা নিয়মিত ওপেন সোর্স প্রকল্পগুলোতে দুর্বলতা রিপোর্ট করে, প্রায়ই প্রস্তাবিত প্যাচসহ।
OpenBSD-এর রুট এক্সপ্লয়েট কীভাবে সম্ভব হলো?
একটি সাইনড ১৬-বিট শেয়ার্ড মেমোরি অ্যাটাচ কাউন্টার বারবার fork করলে ওভারফ্লো হয়ে ঋণাত্মক মানে ঘুরে যেতে পারত। এটি রেস কন্ডিশনের মাধ্যমে use-after-free সম্ভব করে, যা কার্নেলের out-of-bounds write-এর সঙ্গে মিলে স্থানীয়ভাবে রুট পর্যন্ত সুবিধা বৃদ্ধির সুযোগ দেয়। সমস্যাগুলো errata 026 ও 018-এ ঠিক করা হয়েছে।
🇩🇪 Deutsch
37 Jahre alter Kernel-Bug in OpenBSD ermöglicht Root-Exploit
Calif, eine Sicherheitsforschungsfirma, hat Details zu einer Schwachstelle in OpenBSD veröffentlicht, die rund 37 Jahre zurück bis zu den ursprünglichen BSD-Quellen reicht. Ein Zähler für Shared-Memory-Anhänge war als vorzeichenbehafteter 16-Bit-Short definiert. Wiederholtes Forken eines Prozesses mit Shared-Memory-Anhangseinträgen konnte den Zähler über seinen Maximalwert von 32.767 hinaus treiben, sodass er in einen negativen Wert umschlug. Dieser Integer-Überlauf konnte über eine Race Condition zu einem Use-after-free führen. In Kombination mit einem separaten Out-of-bounds-Schreibzugriff im Kernel ermöglichte er eine lokale Rechteausweitung zu Root. Die Probleme wurden in den Errata 026 und 018 behoben.
Die Forscher beschrieben einen Exploit-Pfad, der lokalen Root-Zugriff auf OpenBSD mit aktiviertem KARL, SMAP und SMEP erreichte, ohne eine Schwachstelle zur Informationsoffenlegung zu nutzen. Die Methode umfasste das Mappen von 127 System-V-Shared-Memory-Segmenten, deren Unmapping und das Forken von 259 Prozessen, um den Anhangszähler umschlagen zu lassen. Anschließend wurden Heap-Grooming und eine Race Condition genutzt, um Allokationen auszurichten, eine Multicast-Struktur zu korrumpieren und schließlich durch Überschreiben eines vorhersagbaren Kernel-Zeigers Codeausführung im Kernel zu erlangen.
Der Exploit beruhte auf einem Write-what-where-Primitive: Der Schreibvorgang stammte aus einer TAILQ_REMOVE-Operation, das Ziel war Userland-Speicher, der für den Supervisor-Modus zugänglich gemacht wurde, und der Ort war ein vorhersagbarer Kernel-Zeiger. KARL in OpenBSD randomisiert Funktions- und Datenadressen, doch die Speicherallokatoren des Kernels bleiben deterministisch, weshalb bestimmte frühe Boot-Allokationen verlässliche Ziele wurden.
Um ähnliche Angriffe zu erschweren, schlagen die Autoren Maßnahmen wie Safe-Unlinking vor. Dabei werden die Invarianten doppelt verketteter Listen vor dem Unlink-Schreibvorgang geprüft, und bei einer Verletzung wird über abort() oder panic() abgebrochen. Calif erklärte, dass man Schwachstellen regelmäßig an Open-Source-Projekte melde, oft zusammen mit vorgeschlagenen Patches.
Wie war der Root-Exploit in OpenBSD möglich?
Ein vorzeichenbehafteter 16-Bit-Zähler für Shared-Memory-Anhänge konnte nach wiederholtem Forken überlaufen und in einen negativen Wert umschlagen. Dies ermöglichte ein Use-after-free über eine Race Condition, das zusammen mit einem Out-of-bounds-Schreibzugriff im Kernel eine lokale Rechteausweitung zu Root erlaubte. Die Probleme wurden in den Errata 026 und 018 behoben.
🇪🇸 Español
Un fallo del kernel de OpenBSD de 37 años permite un exploit para obtener root
Calif, una firma de investigación en seguridad, ha publicado los detalles de una vulnerabilidad en OpenBSD que se remonta aproximadamente 37 años a las fuentes originales de BSD. Un contador de adjuntos de memoria compartida estaba definido como un short de 16 bits con signo. Bifurcar repetidamente un proceso con registros de adjuntos de memoria compartida podía hacer que el contador superara su valor máximo de 32.767, provocando que diera la vuelta a un valor negativo. Este desbordamiento de enteros podía derivar en un uso tras liberación mediante una condición de carrera. Combinado con una escritura fuera de límites independiente en el kernel, permitía la escalada de privilegios locales a root. Los problemas se corrigieron en las erratas 026 y 018.
Los investigadores describieron una ruta de explotación que logró root local en OpenBSD con KARL, SMAP y SMEP habilitados, sin usar una vulnerabilidad de divulgación de información. El método consistió en mapear 127 segmentos de memoria compartida System V, desmapearlos y bifurcar 259 procesos para hacer que el contador de adjuntos diera la vuelta. Después se usaron el grooming del heap y una condición de carrera para alinear asignaciones, corromper una estructura multicast y, finalmente, obtener ejecución de código en el kernel sobrescribiendo un puntero del kernel predecible.
La explotación se basó en una primitiva de escritura en un lugar arbitrario (write-what-where): la escritura provenía de una operación TAILQ_REMOVE, el objetivo era memoria de userland hecha accesible en modo supervisor y la ubicación era un puntero del kernel predecible. KARL de OpenBSD aleatoriza las direcciones de funciones y datos, pero los asignadores de memoria del kernel siguen siendo deterministas, lo que convirtió ciertas asignaciones tempranas del arranque en objetivos fiables.
Para reducir el riesgo de ataques similares, los autores sugieren medidas como el safe-unlinking, que verifica los invariantes de las listas doblemente enlazadas antes de realizar las escrituras de desenlazado y aborta o provoca un panic si se violan. Calif afirmó que informa regularmente de vulnerabilidades a proyectos de código abierto, a menudo con parches sugeridos.
¿Cómo fue posible el exploit de root en OpenBSD?
Un contador de adjuntos de memoria compartida con signo de 16 bits podía desbordarse tras bifurcaciones repetidas, dando la vuelta a un valor negativo. Esto permitió un uso tras liberación mediante una condición de carrera que, combinado con una escritura fuera de límites en el kernel, dio lugar a la escalada de privilegios locales a root. Los problemas se corrigieron en las erratas 026 y 018.
🇫🇷 Français
Un bogue du noyau vieux de 37 ans dans OpenBSD permet une élévation vers root
Calif, une société de recherche en sécurité, a publié les détails d'une vulnérabilité dans OpenBSD qui remonte à environ 37 ans, jusqu'aux sources originales de BSD. Un compteur d'attachements de mémoire partagée était défini comme un short signé de 16 bits. En créant de façon répétée des processus fils ayant des enregistrements d'attachement de mémoire partagée, il était possible de faire dépasser à ce compteur sa valeur maximale de 32 767, le faisant basculer vers une valeur négative. Ce dépassement d'entier pouvait mener à une utilisation après libération via une condition de course. Combiné à une écriture hors limites distincte dans le noyau, il permettait une élévation locale de privilèges jusqu'à root. Les problèmes ont été corrigés dans les errata 026 et 018.
Les chercheurs ont décrit une voie d'exploitation qui a permis d'obtenir un accès root local sur OpenBSD avec KARL, SMAP et SMEP activés, sans recourir à une vulnérabilité de divulgation d'informations. La méthode consistait à mapper 127 segments de mémoire partagée System V, à les démapper, puis à créer 259 processus pour faire basculer le compteur d'attachements. Un grooming du tas et une condition de course ont ensuite servi à aligner les allocations, corrompre une structure multicast et, finalement, obtenir l'exécution de code noyau en écrasant un pointeur noyau prévisible.
L'exploit reposait sur une primitive d'écriture write-what-where : l'écriture provenait d'une opération TAILQ_REMOVE, la cible était une mémoire userland rendue accessible en mode superviseur, et l'emplacement était un pointeur noyau prévisible. KARL d'OpenBSD randomise les adresses des fonctions et des données, mais les allocateurs mémoire du noyau restent déterministes, ce qui a fait de certaines allocations de démarrage précoce des cibles fiables.
Pour réduire le risque d'attaques similaires, les auteurs suggèrent des mesures comme le safe-unlinking, qui vérifie les invariants des listes doublement chaînées avant d'effectuer les écritures de déchaînage et interrompt l'exécution par abort ou panic en cas de violation. Calif indique qu'elle signale régulièrement des vulnérabilités aux projets open source, souvent accompagnées de correctifs suggérés.
Comment l'exploit root sur OpenBSD a-t-il été possible ?
Un compteur d'attachements de mémoire partagée signé de 16 bits pouvait déborder après des créations répétées de processus fils, basculant vers une valeur négative. Cela a permis une utilisation après libération via une condition de course qui, combinée à une écriture hors limites dans le noyau, a donné une élévation locale de privilèges jusqu'à root. Les problèmes ont été corrigés dans les errata 026 et 018.
🇮🇳 हिन्दी
OpenBSD में 37 साल पुराना कर्नल बग रूट एक्सप्लॉइट को संभव बनाता है
सुरक्षा शोध फर्म Calif ने OpenBSD में एक कमजोरी का विवरण प्रकाशित किया है, जो मूल BSD स्रोतों तक लगभग 37 साल पुरानी है। एक साझा मेमोरी अटैचमेंट काउंटर को साइन्ड 16-बिट short के रूप में परिभाषित किया गया था। साझा मेमोरी अटैचमेंट रिकॉर्ड वाली प्रक्रिया को बार-बार fork करने पर यह काउंटर अपनी अधिकतम सीमा 32,767 से आगे बढ़ सकता था, जिससे वह ऋणात्मक मान में घूम जाता था। यह इंटीजर ओवरफ्लो एक रेस कंडीशन के जरिए use-after-free की ओर ले जा सकता था। कर्नल में एक अलग out-of-bounds write के साथ मिलकर, इससे स्थानीय विशेषाधिकार वृद्धि के जरिए रूट मिल सकता था। ये समस्याएँ errata 026 और 018 में दूर की गई थीं।
शोधकर्ताओं ने एक एक्सप्लॉइट मार्ग का वर्णन किया जिससे KARL, SMAP और SMEP सक्षम होने पर भी OpenBSD पर स्थानीय रूट प्राप्त हुआ, और इसके लिए किसी information disclosure कमजोरी का उपयोग नहीं हुआ। इस विधि में 127 System V साझा मेमोरी सेगमेंट को map और फिर unmap करना, तथा अटैच काउंट को घुमाने के लिए 259 प्रक्रियाएँ fork करना शामिल था। फिर heap grooming और रेस कंडीशन का उपयोग करके आवंटनों को संरेखित किया गया, एक multicast संरचना को दूषित किया गया, और अंततः एक पूर्वानुमेय कर्नल पॉइंटर को overwrite करके कर्नल कोड निष्पादन प्राप्त किया गया।
यह एक्सप्लॉइट एक write-what-where प्रिमिटिव पर आधारित था: लिखने की क्रिया TAILQ_REMOVE से आई, लक्ष्य वह userland मेमोरी थी जिसे supervisor-accessible बनाया गया था, और स्थान एक पूर्वानुमेय कर्नल पॉइंटर था। OpenBSD का KARL फ़ंक्शन और डेटा पतों को रैंडमाइज़ करता है, लेकिन कर्नल के मेमोरी एलोकेटर अब भी निर्धारक हैं, जिससे बूट के शुरुआती कुछ आवंटन भरोसेमंद लक्ष्य बन गए।
ऐसे हमलों का जोखिम कम करने के लिए लेखकों ने safe-unlinking जैसे उपाय सुझाए हैं, जो unlink लिखने से पहले doubly linked list की invariants जाँचता है और उल्लंघन होने पर abort या panic करता है। Calif ने कहा कि वह नियमित रूप से ओपन सोर्स परियोजनाओं को कमजोरियों की रिपोर्ट करता है, अक्सर सुझाए गए पैच के साथ।
OpenBSD रूट एक्सप्लॉइट कैसे संभव हुआ?
एक साइन्ड 16-बिट साझा मेमोरी अटैच काउंटर बार-बार fork करने के बाद ओवरफ्लो होकर ऋणात्मक हो सकता था। इससे रेस कंडीशन के जरिए use-after-free संभव हुआ, जो कर्नल के out-of-bounds write के साथ मिलकर स्थानीय विशेषाधिकार वृद्धि की ओर ले गया। ये समस्याएँ errata 026 और 018 में ठीक की गईं।
🇮🇩 Bahasa Indonesia
Bug Kernel Berusia 37 Tahun di OpenBSD Memungkinkan Eksploitasi Root
Calif, sebuah perusahaan riset keamanan, telah merilis rincian kerentanan di OpenBSD yang berakar sekitar 37 tahun lalu, hingga ke sumber BSD asli. Penghitung lampiran memori bersama didefinisikan sebagai short 16-bit bertanda. Membuat proses fork berulang kali dengan catatan lampiran memori bersama dapat mendorong penghitung itu melewati nilai maksimumnya, 32.767, sehingga berputar menjadi nilai negatif. Integer overflow ini dapat mengarah ke use-after-free melalui race condition. Digabungkan dengan penulisan out-of-bounds terpisah di kernel, kerentanan ini memungkinkan eskalasi hak akses lokal menjadi root. Masalah ini ditangani dalam errata 026 dan 018.
Peneliti menjelaskan jalur eksploitasi yang berhasil memperoleh root lokal di OpenBSD dengan KARL, SMAP, dan SMEP aktif, tanpa memanfaatkan kerentanan pengungkapan informasi. Metodenya meliputi pemetaan 127 segmen memori bersama System V, pelepasan pemetaannya, dan fork 259 proses untuk membuat penghitung lampiran berputar. Selanjutnya, heap grooming dan race condition digunakan untuk menyelaraskan alokasi, merusak struktur multicast, dan akhirnya memperoleh eksekusi kode kernel dengan menimpa pointer kernel yang dapat diprediksi.
Eksploitasi ini bergantung pada primitif write-what-where: penulisan berasal dari operasi TAILQ_REMOVE, targetnya adalah memori userland yang dibuat dapat diakses mode supervisor, dan lokasinya adalah pointer kernel yang dapat diprediksi. KARL pada OpenBSD mengacak alamat fungsi dan data, tetapi alokator memori kernel tetap deterministik, sehingga beberapa alokasi pada tahap awal boot menjadi target yang andal.
Untuk mengurangi risiko serangan serupa, penulis menyarankan langkah seperti safe-unlinking, yang memeriksa invarian daftar tertaut ganda sebelum melakukan penulisan unlink dan menghentikan proses dengan abort atau panic jika invarian dilanggar. Calif menyatakan bahwa mereka secara rutin melaporkan kerentanan kepada proyek sumber terbuka, sering disertai usulan patch.
Bagaimana eksploitasi root di OpenBSD bisa terjadi?
Penghitung lampiran memori bersama 16-bit bertanda dapat meluap setelah fork berulang kali, berputar menjadi nilai negatif. Hal ini memungkinkan use-after-free melalui race condition yang, dikombinasikan dengan penulisan out-of-bounds di kernel, memberikan eskalasi hak akses lokal menjadi root. Masalah ini diperbaiki di errata 026 dan 018.
🇯🇵 日本語
OpenBSDの37年前のカーネルバグでroot権限を奪うエクスプロイトが可能に
セキュリティ研究企業のCalifは、元のBSDソースにまで遡る約37年前のOpenBSDの脆弱性の詳細を公表しました。共有メモリのアタッチカウンタは、符号付き16ビットのshortとして定義されていました。共有メモリのアタッチ記録を持つプロセスを繰り返しforkすると、このカウンタが最大値32,767を超えて負の値に折り返す可能性がありました。この整数オーバーフローは、競合状態を介したuse-after-freeにつながる恐れがありました。カーネル内の別の範囲外書き込みと組み合わさることで、ローカルでの権限昇格によりrootを取得できました。問題はerrata 026と018で対処されています。
研究者らは、KARL、SMAP、SMEPを有効にしたOpenBSD上で、情報漏えいの脆弱性を使わずにローカルrootを取得した攻撃経路を説明しました。その方法は、127個のSystem V共有メモリセグメントをマッピングして解除し、259個のプロセスをforkしてアタッチカウントを折り返させるものでした。その後、ヒープのグルーミングと競合状態を利用して割り当てを整え、マルチキャスト構造を破壊し、最終的に予測可能なカーネルポインタを上書きしてカーネルコードの実行を得ました。
このエクスプロイトは、write-what-where型のプリミティブに依存していました。書き込みはTAILQ_REMOVEの操作から生じ、対象はスーパーバイザモードからアクセス可能にされたユーザランドのメモリで、場所は予測可能なカーネルポインタでした。OpenBSDのKARLは関数やデータのアドレスをランダム化しますが、カーネルのメモリアロケータは依然として決定的であるため、起動初期の特定の割り当てが確実な標的になりました。
同様の攻撃のリスクを減らすため、著者らはsafe-unlinkingなどの対策を提案しています。これは、unlinkの書き込みを行う前に二重連結リストの不変条件を検査し、違反があればabortまたはpanicで停止させる仕組みです。Califは、オープンソースプロジェクトに脆弱性を定期的に報告しており、多くの場合は修正パッチも併せて提案していると述べています。
OpenBSDのrootエクスプロイトはどのように可能になったのですか?
符号付き16ビットの共有メモリアタッチカウンタは、プロセスを繰り返しforkすると、オーバーフローして負の値に折り返す可能性がありました。これにより競合状態を介したuse-after-freeが生じ、カーネルの範囲外書き込みと組み合わさることでローカルでの権限昇格によりrootを取得できました。問題はerrata 026と018で修正されています。
🇧🇷 Português
Falha no kernel do OpenBSD com 37 anos permite exploit para obter root
A Calif, uma empresa de pesquisa em segurança, publicou detalhes de uma vulnerabilidade no OpenBSD que remonta a aproximadamente 37 anos, até as fontes originais do BSD. Um contador de anexos de memória compartilhada foi definido como um short de 16 bits com sinal. Criar repetidamente um processo com registros de anexo de memória compartilhada podia fazer o contador ultrapassar seu valor máximo de 32.767, fazendo-o dar a volta para um valor negativo. Esse estouro de inteiro podia levar a um use-after-free por meio de uma condição de corrida. Combinado com uma escrita fora dos limites separada no kernel, permitia a escalada local de privilégios até root. As falhas foram corrigidas nas errata 026 e 018.
Os pesquisadores descreveram um caminho de exploração que obteve root local no OpenBSD com KARL, SMAP e SMEP habilitados, sem usar uma vulnerabilidade de divulgação de informações. O método consistiu em mapear 127 segmentos de memória compartilhada System V, desmapeá-los e criar 259 processos para fazer o contador de anexos dar a volta. Em seguida, foram usados o heap grooming e uma condição de corrida para alinhar alocações, corromper uma estrutura multicast e, por fim, obter execução de código no kernel sobrescrevendo um ponteiro previsível do kernel.
A exploração dependeu de uma primitiva de escrita write-what-where: a escrita veio de uma operação TAILQ_REMOVE, o alvo era memória userland tornada acessível em modo supervisor, e a localização era um ponteiro previsível do kernel. O KARL do OpenBSD randomiza endereços de funções e dados, mas os alocadores de memória do kernel continuam determinísticos, o que tornou certas alocações do início do boot alvos confiáveis.
Para reduzir o risco de ataques semelhantes, os autores sugerem medidas como o safe-unlinking, que verifica os invariantes das listas duplamente encadeadas antes de executar as escritas de desvinculação e interrompe a execução com abort ou panic se forem violados. A Calif afirmou que reporta regularmente vulnerabilidades a projetos de código aberto, muitas vezes com patches sugeridos.
Como foi possível o exploit de root no OpenBSD?
Um contador de anexos de memória compartilhada com sinal de 16 bits podia estourar após criações repetidas de processos, dando a volta para um valor negativo. Isso permitiu um use-after-free por meio de uma condição de corrida que, combinado com uma escrita fora dos limites no kernel, possibilitou a escalada local de privilégios até root. As falhas foram corrigidas nas errata 026 e 018.
🇷🇺 Русский
Ошибка ядра OpenBSD возрастом 37 лет позволяет получить root
Компания Calif, специализирующаяся на исследованиях в области безопасности, опубликовала подробности уязвимости в OpenBSD, которая восходит примерно к 37 годам назад, к исходным кодам BSD. Счётчик подключений разделяемой памяти был определён как знаковое 16-битное short. Многократный fork процесса с записями подключения разделяемой памяти мог вывести этот счётчик за максимальное значение 32 767, из-за чего он переполнялся и принимал отрицательное значение. Это целочисленное переполнение могло привести к использованию после освобождения через состояние гонки. В сочетании с отдельной записью за границами буфера в ядре оно позволяло локально повысить привилегии до root. Проблемы были устранены в errata 026 и 018.
Исследователи описали путь эксплуатации, который обеспечил локальный root в OpenBSD при включённых KARL, SMAP и SMEP, без использования уязвимости раскрытия информации. Метод включал отображение 127 сегментов разделяемой памяти System V, их отключение и создание 259 процессов через fork для переполнения счётчика подключений. Затем с помощью grooming кучи и состояния гонки выравнивались выделения памяти, повреждалась структура multicast и в конечном итоге получалось выполнение кода ядра путём перезаписи предсказуемого указателя ядра.
Эксплуатация опиралась на примитив write-what-where: запись выполнялась операцией TAILQ_REMOVE, целью была пользовательская память, сделанная доступной в режиме супервизора, а местом записи был предсказуемый указатель ядра. KARL в OpenBSD рандомизирует адреса функций и данных, однако аллокаторы памяти ядра остаются детерминированными, поэтому некоторые выделения на раннем этапе загрузки стали надёжными целями.
Чтобы снизить риск подобных атак, авторы предлагают такие меры, как safe-unlinking: проверку инвариантов двусвязных списков перед операциями отвязывания с последующим аварийным завершением через abort или panic при их нарушении. Компания Calif заявила, что регулярно сообщает об уязвимостях разработчикам проектов с открытым исходным кодом, часто с предлагаемыми исправлениями.
Как стал возможен эксплойт root в OpenBSD?
Знаковый 16-битный счётчик подключений разделяемой памяти мог переполниться после многократных fork и принять отрицательное значение. Это позволило использовать память после освобождения через состояние гонки, а в сочетании с записью за границами буфера в ядре обеспечило локальное повышение привилегий до root. Проблемы исправлены в errata 026 и 018.
🇨🇳 简体中文
OpenBSD 存在长达37年的内核漏洞,可被用于获取root权限
安全研究机构 Calif 发布了 OpenBSD 中一个漏洞的详细信息,该漏洞可追溯到约37年前的原始 BSD 源代码。共享内存附加计数器被定义为有符号16位短整型。反复派生携带共享内存附加记录的进程,可使该计数器超过其最大值32,767,从而回绕为负值。这种整数溢出可通过竞争条件导致释放后使用。结合内核中另一处越界写入,攻击者可实现本地权限提升至root。相关问题已在勘误026和018中修复。
研究人员描述了一条攻击路径,可在启用 KARL、SMAP 和 SMEP 的 OpenBSD 上实现本地root,且无需利用信息泄露漏洞。该方法包括映射127个System V共享内存段,将其解除映射,并派生259个进程以使附加计数回绕。随后利用堆整理和竞争条件来对齐分配、破坏一个组播结构,最终通过覆写一个可预测的内核指针获得内核代码执行权限。
该攻击依赖于一个写入任意地址(write-what-where)原语:写入操作来自 TAILQ_REMOVE,写入内容为被设为内核态可访问的用户空间内存,写入位置为可预测的内核指针。OpenBSD 的 KARL 会随机化函数和数据地址,但内核内存分配器仍然是确定性的,这使得某些早期启动阶段的分配成为可靠目标。
为降低类似攻击风险,作者建议采取安全断链(safe-unlinking)等措施,即在执行断链写入前检查双向链表的不变量,若不变量被破坏则中止或触发panic。Calif 表示,其会定期向开源项目报告漏洞,并通常附带建议的补丁。
OpenBSD 的 root 提权漏洞是如何产生的?
有符号16位共享内存附加计数器在反复派生进程后可能溢出并回绕为负值。这导致通过竞争条件产生释放后使用,再结合内核越界写入,攻击者可实现本地权限提升至root。相关问题已在勘误026和018中修复。