
اتخذ الخطوات الأولى في CodeQL لـ Python بكتابة استعلام للعثور على CVE-2024-32022
المتطلبات الأساسية • الموارد • ورشة العمل
يمكنك الاختيار بين خيارين لتشغيل تمارين ورشة العمل:
استخدم تثبيت CodeQL محلياً للعمل على تمارين ورشة العمل.
git مثبتان على جهازك المحلي.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"
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"
ابحث عن مراجع إلى استدعاءات `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"
ابحث عن مراجع لاستدعاءات `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")
btn = gr.Button("Run")
btn.click(fn=execute_cmd, inputs=[folder]) #2
if name == "main": demo.launch(debug=True)
ستلاحظ أيضًا مثالًا آخر لحقن الأوامر في الورشة، في تطبيق تم إنشاؤه باستخدام إطار العمل `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 ثم بعد ذلك استعلامًا للمصادر.
يمكننا العثور على جميع الاستدعاءات للدوال من المكتبات الخارجية (غير المعرفة في قاعدة الشيفرة) باستخدام وحدة 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
انقر بزر الماوس الأيمن في منطقة الملف واختر "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"
os.systemfrom، أنشئ متغير call من نوع API::CallNode.where، استخدم عامل المساواة = لتأكيد أن call يساوي استدعاءات os.system. استخدم العامل المنطقي and لتحديد عدة شروط.os، استخدم طريقة API::moduleImport() مع os كوسيط. للوصول إلى دالة system من مكتبة os، استخدم المسند getMember() على API::moduleImport(). وأخيرًا، احصل على أي استدعاءات باستخدام المسند .os.systemنريد البحث عن الوسائط الأولى لاستدعاءات os.system، لنتحقق لاحقًا مما إذا كان أي إدخال من المستخدم يتدفق إلى الوسائط الأولى (أي إلى الأمر الذي سيتم تنفيذه).
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.
</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"
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"
- استخدم الكلمة المفتاحية `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"
ننتقل الآن إلى البحث عن المصادر.
معظم المصادر مُنمذجة بالفعل في CodeQL، وتحمل النوع RemoteFlowSource. يمكننا استخدام هذا النوع للعثور على أي مصادر في قاعدة الشيفرة.
semmle.python.dataflow.new.RemoteFlowSources لاستخدام النوع RemoteFlowSource.from، اضغط على Ctrl + Space لعرض جميع الأنواع المتاحة.املأ القالب:
from //TODO: fill me in where //TODO: fill me in select //TODO: fill me in
</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 هي واجهة مستخدم رسومية لـ نصوص كوهيا الخاصة بـ Stable Diffusion للتدريب والتوليد والأدوات المساعدة لـ Stable Diffusion.
في الجزء الثاني من ورشة العمل، سنقوم بتبديل قاعدة الكود التي نستعلم عنها إلى kohya_ss وإيجاد تدفقات البيانات من المصادر إلى المستقبلات في kohya_ss، والتي تؤدي إلى حقن الأوامر: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027
قبل أن تبدأ بالتمرين التالي:
Databases، انقر على "Choose Database from Archive" واختر الملف kohya_ss-db.zip في جذر المستودع. يجب أن تظهر علامة اختيار. سيؤدي هذا إلى تحديد قاعدة بيانات CodeQL التي تعمل عليها.os.systemisSource، قم بتحديد المتغير 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 > قواعد البيانات. لاحظ علامة الاختيار).
💡 هذا مثير جدًا للاهتمام لباحثي الأمن - باستخدام الاستعلامات الافتراضية، يمكننا الحصول على فكرة عامة عن الثغرات المحتملة التي قد توجد في مشروع معين.
تكمن قوة CodeQL في القدرة على إعادة استخدام استعلامات ونماذج CodeQL لتشغيلها على أي قاعدة شيفرة بنفس اللغة. يمكننا تشغيل استعلامات CodeQL على ما يصل إلى ١٠٠٠ مستودع في وقت واحد باستخدام تحليل المتغيرات متعدد المستودعات (MRVA). يجب أن تكون المشاريع مستضافة على GitHub.
💡 هذا مثير جدًا للاهتمام لباحثي الأمن - إذا وجدت مصدرًا أو مصرفًا خطيرًا محتملًا، يمكنك إضافته إلى CodeQL (أو تشغيله كاستعلام) وإجراء أبحاثك ضد ألف مستودع في وقت واحد.
اليوم، تعلمت كيفية استكشاف قاعدة شيفرة باستخدام CodeQL وكيفية استخدام CodeQL في سير عمل أبحاث الأمن الخاصة بك.
تفقد هذه الموارد إذا كنت ترغب في معرفة المزيد حول:
إذا انتهى بك الأمر إلى العثور على ثغرة باستخدام CodeQL، فلا تتردد في إضافتها إلى قاعة مشاهير CodeQL.
os.systemgetACall()املأ القالب:```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"
</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`"
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"
</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"