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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/sylwia-budzynska/codeql-workshop
التحليل الثابتتحليل الثغرات الأمنيةتحليل الكودالتعلم والتعليمموارد منسقةمسارات ودورات التعلممختبرات وتدريب عملي
GitHubsylwia-budzynska/codeql-workshop

codeql-workshop

اتخذ الخطوات الأولى في CodeQL لـ Python بكتابة استعلام للعثور على CVE-2024-32022

عرض المستودع
128منذ شهر واحدلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

البحث عن الثغرات باستخدام CodeQL

ورشة عمل أصلية من Sylwia Budzynska

المتطلبات الأساسية • الموارد • ورشة العمل

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

📣 المتطلبات الأساسية

يمكنك الاختيار بين خيارين لتشغيل تمارين ورشة العمل:

  • الخيار أ: التثبيت المحلي (باستخدام VS Code - يتم تشغيل CodeQL محلياً على جهازك)
  • الخيار ب: GitHub Codespace (باستخدام متصفح أو VS Code - يتم تشغيل CodeQL عن بُعد على GitHub Codespace قائم على Linux في السحابة)

الخيار أ: التثبيت المحلي

استخدم تثبيت CodeQL محلياً للعمل على تمارين ورشة العمل.

المتطلبات الأساسية

  • Visual Studio Code (VS Code) و git مثبتان على جهازك المحلي.

التعليمات

  1. تثبيت إضافة VS Code لـ CodeQL
  2. شغّل في الطرفية:```bash git clone https://github.com/sylwia-budzynska/codeql-workshop cd codeql-workshop git submodule init git submodule update --recursive --depth 1

Download CodeQL databases

curl -L -O "https://github.com/sylwia-budzynska/codeql-workshop/releases/download/v1/test-app-db.zip" curl -L -O "https://github.com/sylwia-budzynska/codeql-workshop/releases/download/v1/kohya_ss-db.zip"

root@kitploit:~
3. في VS Code: ملف -> **فتح مساحة العمل من ملف...** `vscode-codeql-starter.code-workspace`
4. تابع مع [اختيار قاعدة بيانات CodeQL](#select-codeql-database)
5. ثم [اختبر تثبيتك](#test-your-installation)

### الخيار ب: GitHub Codespace

استخدم مساحة عمل عن بُعد من GitHub Codespace للعمل على تمارين الورشة.

#### المتطلبات الأساسية

* حساب GitHub ([سجّل](https://github.com/) مجانًا)
* متصفح (يمكنك إجراء الورشة بأكملها في متصفح - هذه هي أسرع طريقة) أو [Visual Studio Code](https://code.visualstudio.com/download) (VS Code) مع تثبيت إضافة [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) على جهازك المحلي.

ملاحظة: أول 120 ساعة لكل نواة من استخدام Codespace مجانية شهريًا، نستخدم مساحة عمل مع 4 أنوية لهذه الورشة نظرًا لأن 4 أنوية هو الحد الأقصى الحالي للحسابات المجانية. (إذا كان لديك حساب Pro، ننصح بالتبديل إلى جهاز بـ 8 أنوية.)

#### التعليمات

1. سجّل الدخول إلى حساب [GitHub](https://github.com/login) الخاص بك
2. اذهب إلى المستودع https://github.com/sylwia-budzynska/codeql-workshop
3. انقر على Code -> Codespaces
4. انقر على علامة الجمع (+) لإنشاء مساحة عمل جديدة.

<img src="https://assets.kitploit.com/production/public/readmes/33098/c86e537f9e7891fb6bdb5da727cae5b6ad0b2c9ac94f67854d48296f2dad89cb.png"  width="439" alt="لقطة شاشة: إنشاء مساحة عمل، انقر على الجمع">

سيبدأ VS Code في متصفحك وسيتم بناء مساحة عمل عن بُعد. قد يستغرق هذا بضع دقائق.
إذا طُلب منك فتح مساحة العمل `vscode-codeql-starter.code-workspace`، انقر على "Open Workspace".

5. إذا كنت تريد استخدام VS Code محليًا، اضغط على زر الخطوط الثلاثة في الزاوية اليسرى العليا واختر "Open VS Code Desktop". قد يستغرق ظهور هذا الخيار بضع دقائق.

<img src="https://assets.kitploit.com/production/public/readmes/33098/f2c8c2fe6da80142344b17c208da31a23c3fa68a3917a124f0e2f7871b6a20f7.png" width="300" alt="لقطة شاشة: اضغط على زر الخطوط الثلاثة واختر فتح في VS Code Desktop">

6. تابع مع [اختيار قاعدة بيانات CodeQL](#select-codeql-database)
7. ثم [اختبر تثبيتك](#test-your-installation)

يمكنك رؤية مساحات العمل الخاصة بك على [github.com/codespaces](https://github.com/codespaces). سيتم إيقاف تشغيل مساحة العمل تلقائيًا بعد بضع ساعات من عدم استخدامها، ولكن لضمان عدم استخدام ساعات إضافية من الـ 120 ساعة المجانية، تذكر الانتقال إلى [github.com/codespaces](https://github.com/codespaces) > النقاط الثلاث > "Stop codespace" بعد الورشة.

#### استكشاف أخطاء التثبيت وإصلاحها

في حال ظهرت أخطاء مثل:
* `Failed to run query: Could not resolve library path for [..]`
* `Could not resolve module [..]`
* `Could not resolve type [..]`

من المحتمل جدًا أنك نسيت استنساخ الوحدات الفرعية git (أي مستودع ql). لإصلاح ذلك، قم بتشغيل `git submodule init && git submodule update --recursive`.

### اختيار قاعدة بيانات CodeQL

1. تأكد من أن مساحة العمل `vscode-codeql-starter.code-workspace` مفتوحة في VS Code.
2. انقر على أيقونة "QL" في اللوحة اليسرى للانتقال إلى عرض CodeQL.
3. انقر على "Choose Database from Archive" واختر ملف `test-app-db.zip` في جذر المستودع.
   ملاحظة: في هذه المرحلة قد تواجه خطأ في VSCode مع رسالة منبثقة تطلب تثبيت CodeQL CLI. قبول هذا التثبيت يجب أن يحل المشكلة. بعد انتهاء تثبيت CLI، يجب أن تكون قادرًا على إكمال اختيار قاعدة البيانات أعلاه.
   <img src="https://assets.kitploit.com/production/public/readmes/33098/65cc5790b8b49113623bc9a9b34a1be61575b05bea2428c46f83115e2271148b.png"  alt="لقطة شاشة: رسالة خطأ VSCode بخصوص CodeQL">
   <img src="https://assets.kitploit.com/production/public/readmes/33098/c3bf9c304d9c1f6199f591c9bcbf6e446ee4f5388ab209e30887326698129f84.png"  alt="لقطة شاشة: VSCode يقوم بتثبيت CodeQL CLI">

### اختبر تثبيتك

#### المتطلبات الأساسية

تأكد من أن قاعدة بيانات CodeQL المختارة سابقًا محددة في عرض CodeQL. (انقر على "Select" إذا لم تكن كذلك)

عند تحديد قاعدة البيانات، يجب أن تبدو هكذا (لاحظ علامة الاختيار):

<img src="https://assets.kitploit.com/production/public/readmes/33098/fee6e47c0d9b0754c7ac9e29e2f0b3a721093aa5ce882615b3839a99f4862506.png"  alt="لقطة شاشة: تم تحديد قاعدة بيانات CodeQL">

#### التعليمات

1. في VS Code: اذهب إلى مجلد مساحة العمل: `codeql-custom-queries-python`
2. أنشئ ملفًا جديدًا `test.ql`
3. أضف المحتوى التالي: `select "Hello World!"`
4. احفظ الملف، انقر بزر الماوس الأيمن في منطقة الملف واختر "CodeQL: Run Query on Selected Database"
5. يجب أن ترى علامة تبويب جديدة تفتح مع النتيجة "Hello World!"

## :books: الموارد

- [دروس QL](https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/)
- [دليل لغة CodeQL للغة Python](https://codeql.github.com/docs/codeql-language-guides/codeql-for-python/)
- [توثيق CodeQL](https://codeql.github.com/docs/)
- [مرجع لغة QL](https://codeql.github.com/docs/ql-language-reference/)
- [مكتبة CodeQL للغة Python](https://codeql.github.com/codeql-standard-libraries/python/)
- [الاستعلام الأساسي لرمز Python](https://codeql.github.com/docs/codeql-language-guides/basic-query-for-python-code/)
- [فئات QL](https://codeql.github.com/docs/ql-language-reference/types/#classes)
- [CodeQL من الصفر إلى الاحتراف الجزء 1: أساسيات التحليل الثابت لأبحاث الثغرات](https://github.blog/2023-03-31-codeql-zero-to-hero-part-1-the-fundamentals-of-static-analysis-for-vulnerability-research/)
- [CodeQL من الصفر إلى الاحتراف الجزء 2: البدء مع CodeQL](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/)
- [CodeQL من الصفر إلى الاحتراف الجزء 3: أبحاث الأمان](https://github.blog/2024-04-29-codeql-zero-to-hero-part-3-security-research-with-codeql/)
- [CodeQL من الصفر إلى الاحتراف الجزء 4: دراسة حالة Gradio](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-4-gradio-framework-case-study/)
- [CodeQL من الصفر إلى الاحتراف الجزء 5: تصحيح أخطاء الاستعلامات](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-5-debugging-queries/)

## ورشة العمل

مرحبًا بكم في ورشة العمل "العثور على الثغرات باستخدام CodeQL"!

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

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

تنقسم ورشة العمل إلى أقسام متعددة، ويتكون كل قسم من تمارين تؤدي إلى الاستعلام النهائي.
لكل قسم نقدم *إرشادات* تساعدك في إنهاء التمرين من خلال تزويدك بمراجع لفئات QL والمسندات الأعضاء التي يمكنك استخدامها.

### نظرة عامة

في هذه الورشة سنبحث عن *ثغرات حقن الأوامر* المعروفة في [kohya_ss](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/). يمكن أن تحدث مثل هذه الثغرات عندما تنتقل المعلومات التي يتحكم فيها المستخدم إلى كود التطبيق الذي يقوم ببناء أمر غير آمن وتنفيذه. يمكن إعادة كتابة الأمر المبني بشكل غير آمن من إدخال المستخدم لتنفيذ إجراءات غير مقصودة مثل تنفيذ أوامر عشوائية، أو الكشف عن معلومات حساسة.

حقن الأوامر التي تمت مناقشتها في هذه الورشة هي [CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/).

## النظرية

### المصادر والمصارف

فكر في واحدة من أشهر الثغرات—حقن الأوامر. تحدث إذا تم استخدام إدخال المستخدم في دوال تسمح بتشغيل أوامر في شل مباشرة على الخادم. يسمح للمهاجم بتنفيذ أوامر نظام التشغيل (OS) على الخادم الذي يدير التطبيق، وعادة ما يؤدي إلى اختراق كامل للتطبيق وبياناته.

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

تأتي إدخالات المستخدم عمومًا من نقاط الدخول إلى التطبيق—أصل البيانات. تشمل هذه المعلمات في طرق HTTP، مثل GET و POST، أو وسائط سطر الأوامر لبرنامج. تسمى هذه "**المصادر**."

باستمرار مع مثال حقن الأوامر، مثال على دالة خطيرة لا ينبغي استدعاؤها ببيانات غير موثوقة وغير معقمة يمكن أن تكون `os.system`. تسمى هذه الدوال الخطيرة "**المصارف**." لاحظ أن مجرد كون الدالة خطيرة محتملة لا يعني أنها ثغرة قابلة للاستغلال فورًا ويجب إزالتها. العديد من المصارف لديها طرق لاستخدامها بأمان. أمثلة أخرى للمصارف التي لا ينبغي استخدامها مع إدخال المستخدم هي MySQLCursor.execute() من مكتبة MySQLdb في Python (مسببة لحقن SQL) أو دالة Python المدمجة eval() التي تقيم تعابير عشوائية (مسببة لحقن كود).

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

<img src="https://assets.kitploit.com/production/public/readmes/33098/ff60a1649737805a71bd27710209dba66203a77159cc72ae435c165353e56491.png">

### ورقة الغش CodeQL
هيكل الاستعلام الأساسي```codeql
import python

from <type> <name> 		//variables used in the query

where <conditions for variables>

select <output>			//results, referring to the variables

ابحث عن مراجع لاستدعاءات `os.system()````codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call = API::moduleImport("os") .getMember("system") .getACall() select call, "Call to os.system"

root@kitploit:~
ابحث عن مراجع إلى استدعاءات `os.system()`، هذه المرة مع predicate```codeql
predicate isOsSystemSink(API::CallNode call) {
	call = API::moduleImport("os")
	.getMember("system").getACall()
  }


from API::CallNode call
where isOsSystemSink(call)
select call, "Call to os.system"

ابحث عن المراجع إلى استدعاءات os.system()، هذه المرة مع class```codeql class OsSystemSink extends API::CallNode { OsSystemSink() { this = API::moduleImport("os") .getMember("system").getACall() } }

from API::CallNode call where call instanceof OsSystemSink select call, "Call to os.system"

root@kitploit:~
ابحث عن مراجع لاستدعاءات `os.system()`، هذه المرة مع فئة. حدد أن النوع الذي نبدأ به هو `OsSystemSink````codeql
class OsSystemSink extends API::CallNode {
  OsSystemSink() {
    this = API::moduleImport("os")
    .getMember("system").getACall()
	}
}


from OsSystemSink s
select s, "Call to os.system"

الجزء العملي الأول - قاعدة بيانات الاختبار

في هذا الجزء العملي، سنقوم بإيجاد حقن الأوامر، حيث ينتهي إدخال المستخدم في استدعاء os.system.

في الجزء الأول من الدورة العملية، سنكتب استعلامات CodeQL للعثور على المصادر والمصارف، استدعاءات os.system، على قاعدة بيانات ضعيفة عن قصد. في الجزء الثاني من الدورة العملية، سنستخدم تلك الاستعلامات للعثور على حقن أوامر من مصدر إلى مصرف في برنامج مفتوح المصدر، kohya_ss الإصدار 22.6.1.

مع استعلام CodeQL الذي نكتبه، سنكون قادرين على العثور على حقن الأوامر مثل الذي أدناه.

يأتي إدخال المستخدم من مكون Gradio تفاعلي (إطار ويب لتطبيقات التعلم الآلي) gr.Textbox في #1. gr.Button.click في #2 يربط النقر على الزر بالدالة execute_cmd، مررًا القيم من folder. وهذا يعني أنه عند النقر على gr.Button يتم تمرير folder إلى execute_cmd، حيث يتم دمج folder في أمر، وتنفيذه على النظام في استدعاء os.system في #3.```python import gradio as gr import os

def execute_cmd(folder): cmd = f"python caption.py --dir={folder}" os.system(cmd) #3

with gr.Blocks() as demo: gr.Markdown("Create caption files for images in a directory") with gr.Row(): folder = gr.Textbox(placeholder="Directory to caption") #1 logs = gr.Checkbox(label="Add verbose logs")

root@kitploit:~
btn = gr.Button("Run")
btn.click(fn=execute_cmd, inputs=[folder]) #2

if name == "main": demo.launch(debug=True)

root@kitploit:~
ستلاحظ أيضًا مثالًا آخر لحقن الأوامر في الورشة، في تطبيق تم إنشاؤه باستخدام إطار العمل `Flask`. في هذه الحالة، يأتي إدخال المستخدم من معامل GET لطلب Flask (إطار ويب شائع في Python)، والذي يتم تخزينه في المتغير `files` (انظر #1). ثم يتم تمرير `files` إلى استدعاء `os.system` ويتم ربطها مع `ls`، مما يؤدي إلى حقن الأوامر (انظر #2).```python
import os
from flask import Flask, request

app = Flask(__name__)

@app.route("/command1")
def command_injection1():
    files = request.args.get('files', '')   #1
    os.system("ls " + files)                #2

سنبدأ ببناء استعلام تدريجيًا لكشف استدعاءات os.system ثم بعد ذلك استعلامًا للمصادر.

1. البحث عن جميع الاستدعاءات للدوال من المكتبات الخارجية

يمكننا العثور على جميع الاستدعاءات للدوال من المكتبات الخارجية (غير المعرفة في قاعدة الشيفرة) باستخدام وحدة ApiGraphs من CodeQL.

استخدم القالب أدناه:```codeql import python import semmle.python.ApiGraphs

from //TODO: fill me in. Start typing API:: and press Ctrl+Space to see a list of available types. Name your variable call select //TODO: fill me in

root@kitploit:~
انقر بزر الماوس الأيمن في منطقة الملف واختر "CodeQL: Run Query on Selected Database" لتشغيل الاستعلام.

<details>
<summary>إرشادات</summary>

- في جملة `from`، ابدأ بـ `API::` واضغط `Ctrl + Space` لرؤية الأنواع المتاحة في وحدة API Graphs.
- يتم تمثيل الاستدعاء بنوع `API::CallNode`. أنشئ متغيراً بهذا النوع واسمه `call`.
- لتحديد النتائج للاستدعاءات الموجودة فقط في المجلد الجذر للتطبيق (المسمى `test-app`) أضف جملة `where` مع الشرط `where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")`.

</details>
<details>
<summary>الحل</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call, "A call"

2. البحث عن جميع استدعاءات os.system

إرشادات
  • في جملة from، أنشئ متغير call من نوع API::CallNode.
  • في جملة where، استخدم عامل المساواة = لتأكيد أن call يساوي استدعاءات os.system. استخدم العامل المنطقي and لتحديد عدة شروط.
  • للعثور على العقد المطابقة لمكتبة os، استخدم طريقة API::moduleImport() مع os كوسيط. للوصول إلى دالة system من مكتبة os، استخدم المسند getMember() على API::moduleImport(). وأخيرًا، احصل على أي استدعاءات باستخدام المسند .

3. البحث عن الوسائط الأولى لاستدعاءات os.system

نريد البحث عن الوسائط الأولى لاستدعاءات os.system، لنتحقق لاحقًا مما إذا كان أي إدخال من المستخدم يتدفق إلى الوسائط الأولى (أي إلى الأمر الذي سيتم تنفيذه).

إرشادات
  • املأ القالب:```codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call = API::moduleImport("os").getMember("system").getACall() and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call // TODO: fill me in. Type a dot . right after call and press Ctrl+Space to see available predicates.

root@kitploit:~
</details>
<details>
<summary>الحل</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call = API::moduleImport("os").getMember("system").getACall() and
call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call.getArg(0), "First argument of an `os.system` call"

4. تحويل استعلامك الذي يبحث عن استدعاءات os.system إلى صنف CodeQL

يمكن استخدام الصنوف في CodeQL لتغليف أجزاء قابلة لإعادة الاستخدام من المنطق. تمثل الصنوف مجموعات مفردة من القيم، ويمكنها أيضًا تضمين عمليات (تُعرف بالمسندات الأعضاء) خاصة بتلك المجموعة من القيم. لقد رأيت بالفعل العديد من الأمثلة على صنوف CodeQL (API::CallNode) والمسندات الأعضاء (getLocation() وما إلى ذلك.)

إرشادات
  • لإنشاء نوع جديد، يجب علينا توسيع نوع فائق، هنا API::CallNode، وإعطائه اسمًا، و_مسندًا مميزًا_ بنفس الاسم. سنسمي صنفنا OsSystemSink.

املأ القالب:```codeql import python import semmle.python.ApiGraphs

class OsSystemSink extends API::CallNode { OsSystemSink() { //TODO: fill me in } }

from API::CallNode call where // TODO: fill me in and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call.getArg(0), "Call to os.system"

root@kitploit:~
- استخدم الكلمة المفتاحية `this`، التي تشير إلى حالات عُقد الاستدعاء (`API::CallNode`s) التي نصفها في الفئة. استخدم `this` للعثور على استدعاءات `os.system` بنفس الطريقة التي فعلتها سابقًا مع `API::moduleImport`.
- غيّر جملة `where` لتجعل متغير `call` الخاص بك `instanceof` لفئة `OsSystemSink` الجديدة.```codeql
import python
import semmle.python.ApiGraphs

class OsSystemSink extends API::CallNode {
	OsSystemSink() {
		this = API::moduleImport("os").getMember("system").getACall()
	}
}


from API::CallNode call
where call instanceof OsSystemSink
and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call.getArg(0), "First argument of an `os.system` call"

٥. العثور على جميع المصادر من فئة RemoteFlowSource

ننتقل الآن إلى البحث عن المصادر.

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

إرشادات
  • استورد semmle.python.dataflow.new.RemoteFlowSources لاستخدام النوع RemoteFlowSource.
  • في جملة from، اضغط على Ctrl + Space لعرض جميع الأنواع المتاحة.

املأ القالب:

```codeql import python import semmle.python.dataflow.new.RemoteFlowSources

from //TODO: fill me in where //TODO: fill me in select //TODO: fill me in

root@kitploit:~
</details>
<details>
<summary>الحل</summary>```codeql
import python
import semmle.python.dataflow.new.RemoteFlowSources

from RemoteFlowSource rfs
where rfs.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select rfs

ورشة العمل الجزء الثاني - البحث عن حقن الأوامر في kohya_ss

Kohya_ss هي واجهة مستخدم رسومية لـ نصوص كوهيا الخاصة بـ Stable Diffusion للتدريب والتوليد والأدوات المساعدة لـ Stable Diffusion.

في الجزء الثاني من ورشة العمل، سنقوم بتبديل قاعدة الكود التي نستعلم عنها إلى kohya_ss وإيجاد تدفقات البيانات من المصادر إلى المستقبلات في kohya_ss، والتي تؤدي إلى حقن الأوامر: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027

قبل أن تبدأ بالتمرين التالي:

  • اذهب إلى علامة التبويب CodeQL في VSCode، قسم Databases، انقر على "Choose Database from Archive" واختر الملف kohya_ss-db.zip في جذر المستودع. يجب أن تظهر علامة اختيار. سيؤدي هذا إلى تحديد قاعدة بيانات CodeQL التي تعمل عليها.

6. البحث عن تدفقات البيانات من المصادر إلى الوسيط الأول لاستدعاءات os.system

إرشادات
  • استخدم القالب أدناه ولاحظ:
  • في المسند isSource، قم بتحديد المتغير source ليكون من النوع RemoteFlowSource.
  • في المسند isSink، قم بتحديد المتغير sink ليكون الوسيط الأول لاستدعاء os.system. افعل ذلك باستخدام آلية exists وفئة OsSystemSink الخاصة بك.
    • exists هي آلية لتقديم متغيرات مؤقتة بنطاق محدود. يمكنك التفكير فيها على أنها من-where-select الخاصة بها. في هذه الحالة، استخدم exists لتقديم المتغير call من النوع OsSystemSink ثم قم بتحديد sink ليكون الوسيط الأول لـ call.```codeql /**

تمارين إضافية، إذا سمح الوقت

٧. الاستعلام عن قاعدة الشيفرة باستخدام الاستعلامات الافتراضية

توجد استعلامات CodeQL الخاصة بلغة Python في مجلد ql/python/ql/src/Security. هناك بالفعل استعلامات للثغرات الأكثر شيوعًا: حقن SQL، حقن الأوامر، حقن الشيفرة، إلخ. قم بتشغيل استعلام حقن SQL (CWE-089) على قاعدة البيانات الاختبارية (ستحتاج إلى تحديدها في إضافة CodeQL > قواعد البيانات. لاحظ علامة الاختيار).

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

٨. تشغيل استعلاماتك الخاصة باستخدام تحليل المتغيرات متعدد المستودعات (MRVA)

تكمن قوة CodeQL في القدرة على إعادة استخدام استعلامات ونماذج CodeQL لتشغيلها على أي قاعدة شيفرة بنفس اللغة. يمكننا تشغيل استعلامات CodeQL على ما يصل إلى ١٠٠٠ مستودع في وقت واحد باستخدام تحليل المتغيرات متعدد المستودعات (MRVA). يجب أن تكون المشاريع مستضافة على GitHub.

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

  • اتبع الإعداد في الوثائق.
  • لاحظ أن MRVA يعمل باستخدام مهام سير عمل GitHub Actions. مهام سير العمل مجانية على المستودعات العامة، ومدفوعة على الخاصة.
  • بعد الإعداد، انقر بزر الماوس الأيمن واختر "CodeQL: تشغيل تحليل المتغيرات"

ملاحظات ختامية

اليوم، تعلمت كيفية استكشاف قاعدة شيفرة باستخدام CodeQL وكيفية استخدام CodeQL في سير عمل أبحاث الأمن الخاصة بك.

تفقد هذه الموارد إذا كنت ترغب في معرفة المزيد حول:

  • التحليل الثابت وكيفية عمله:
    • CodeQL من الصفر إلى الاحتراف الجزء 1: أساسيات التحليل الثابت لأبحاث الثغرات.
  • أساسيات استخدام CodeQL ولغة الاستعلام الخاصة به:
    • CodeQL من الصفر إلى الاحتراف الجزء 2: البدء مع CodeQL.
  • أبحاث الأمن باستخدام CodeQL:
    • CodeQL من الصفر إلى الاحتراف الجزء 3: أبحاث الأمن.
  • كيفية نمذجة CodeQL لإطار ويب على مثال Gradio:
    • CodeQL من الصفر إلى الاحتراف الجزء 4: دراسة حالة Gradio.
  • تصحيح أخطاء سبب عدم عمل استعلام:
    • CodeQL من الصفر إلى الاحتراف الجزء 5: تصحيح أخطاء الاستعلامات

إذا انتهى بك الأمر إلى العثور على ثغرة باستخدام CodeQL، فلا تتردد في إضافتها إلى قاعة مشاهير CodeQL.

تنزيل الأداة
os.system
getACall()

املأ القالب:```codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call //TODO: fill me in and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call, "Call to os.system"

root@kitploit:~
</details>
<details>
<summary>الحل</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call = API::moduleImport("os").getMember("system").getACall() and
call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call, "Call to `os.system`"
  • @name Command injection in os.system sink
  • @kind path-problem
  • @id codeql-ws/dataflow-query */

import python import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.ApiGraphs import MyFlow::PathGraph import semmle.python.dataflow.new.RemoteFlowSources

//TODO: add previous class definition here

private module MyConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { // TODO: fill me in }

predicate isSink(DataFlow::Node sink) { // TODO: fill me in. Use the exists mechanism exists( | sink = ... ) } }

module MyFlow = TaintTracking::Global;

from MyFlow::PathNode source, MyFlow::PathNode sink where MyFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Command injection"

root@kitploit:~
</details>
<details>
<summary>الحل</summary>```codeql
/**
 * @name Command injection in os.system sink
 * @kind path-problem
 * @id codeql-ws/dataflow-query
 */

import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.ApiGraphs
import semmle.python.dataflow.new.RemoteFlowSources
import MyFlow::PathGraph

class OsSystemSink extends API::CallNode {
	OsSystemSink() {
		this = API::moduleImport("os").getMember("system").getACall()
	}
}

private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
	source instanceof RemoteFlowSource
}

predicate isSink(DataFlow::Node sink) {
	exists(OsSystemSink call |
	sink = call.getArg(0)
	)
}
}

module MyFlow = TaintTracking::Global<MyConfig>;

from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Command injection"