
Python के लिए CodeQL में पहला कदम उठाएँ, 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 में: File -> **Open Workspace from File...** `vscode-codeql-starter.code-workspace`
4. [CodeQL डेटाबेस चुनने](#select-codeql-database) पर आगे बढ़ें
5. फिर [अपनी इंस्टॉलेशन का परीक्षण करें](#test-your-installation)
### विकल्प B: 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) एक्सटेंशन स्थापित हो।
नोट: Codespace उपयोग के पहले 120 घंटे प्रति कोर प्रति माह निःशुल्क हैं, हम इस कार्यशाला के लिए 4 कोर वाले codespace का उपयोग करते हैं क्योंकि मुफ्त खातों के लिए 4 कोर वर्तमान अधिकतम है। (यदि आपके पास Pro खाता है, तो हम 8-कोर मशीन पर स्विच करने की सलाह देते हैं।)
#### निर्देश
1. अपने [GitHub](https://github.com/login) खाते में लॉग इन करें
2. रेपो पर जाएँ https://github.com/sylwia-budzynska/codeql-workshop
3. Code -> Codespaces पर क्लिक करें
4. नया codespace बनाने के लिए प्लस चिह्न (+) पर क्लिक करें।
<img src="https://assets.kitploit.com/production/public/readmes/33098/c86e537f9e7891fb6bdb5da727cae5b6ad0b2c9ac94f67854d48296f2dad89cb.png" width="439" alt="स्क्रीनशॉट: Codespace बनाएँ, प्लस पर क्लिक करें">
VS Code आपके ब्राउज़र में शुरू होगा और एक दूरस्थ Codespace बनाया जाएगा। इसमें कुछ मिनट लग सकते हैं।
यदि आपसे `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)
आप अपने codespaces को [github.com/codespaces](https://github.com/codespaces) पर देख सकते हैं। कुछ घंटों तक उपयोग न करने पर codespace अपने आप बंद हो जाएगा, लेकिन यह सुनिश्चित करने के लिए कि आप 120h मुफ्त घंटों में से अतिरिक्त घंटों का उपयोग नहीं कर रहे हैं, कार्यशाला के बाद [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. सुनिश्चित करें कि VS Code में `vscode-codeql-starter.code-workspace` कार्यस्थान खुला है।
2. CodeQL दृश्य पर जाने के लिए बाएँ टैब फलक में "QL" आइकन पर क्लिक करें।
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="स्क्रीनशॉट: CodeQL के संबंध में VSCode त्रुटि संदेश">
<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/)
- [Python के लिए CodeQL भाषा गाइड](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/)
- [Python के लिए CodeQL लाइब्रेरी](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 zero to hero भाग 1: भेद्यता अनुसंधान के लिए स्थैतिक विश्लेषण की मूल बातें](https://github.blog/2023-03-31-codeql-zero-to-hero-part-1-the-fundamentals-of-static-analysis-for-vulnerability-research/)
- [CodeQL zero to hero भाग 2: CodeQL के साथ शुरुआत](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/)
- [CodeQL zero to hero भाग 3: सुरक्षा अनुसंधान](https://github.blog/2024-04-29-codeql-zero-to-hero-part-3-security-research-with-codeql/)
- [CodeQL zero to hero भाग 4: Gradio केस स्टडी](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-4-gradio-framework-case-study/)
- [CodeQL zero to hero भाग 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` हो सकता है। इन खतरनाक कार्यों को “**सिंक**” कहा जाता है। ध्यान दें कि केवल इसलिए कि कोई फ़ंक्शन संभावित रूप से खतरनाक है, इसका मतलब यह नहीं है कि यह तुरंत एक शोषण योग्य भेद्यता है और इसे हटाना होगा। कई सिंक में उन्हें सुरक्षित रूप से उपयोग करने के तरीके होते हैं। सिंक के अन्य उदाहरण, जिन्हें उपयोगकर्ता इनपुट के साथ उपयोग नहीं किया जाना चाहिए, Python में MySQLdb लाइब्रेरी से MySQLCursor.execute() (जो 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
Find references to os.system() calls```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() कॉल्स के संदर्भ खोजें, इस बार एक क्लास के साथ```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 कॉल में जाकर समाप्त होता है।
कार्यशाला के पहले भाग में, हम स्रोतों (sources) और सिंक (sinks), os.system कॉल्स को खोजने के लिए CodeQL क्वेरी लिखेंगे, एक जानबूझकर कमज़ोर कोडबेस पर। कार्यशाला के दूसरे भाग में, हम उन क्वेरी का उपयोग करके एक ओपन सोर्स सॉफ़्टवेयर, kohya_ss v22.6.1 में स्रोत से सिंक तक एक कमांड इंजेक्शन खोजने जा रहे हैं।
हमारे द्वारा लिखी गई CodeQL क्वेरी से, हम नीचे दिए गए जैसे कमांड इंजेक्शन खोजने में सक्षम होंगे।
उपयोगकर्ता इनपुट #1 पर एक इंटरैक्टिव Gradio (मशीन लर्निंग अनुप्रयोगों के लिए वेब फ्रेमवर्क) घटक gr.Textbox से आता है। #2 पर gr.Button.click बटन क्लिक को execute_cmd फ़ंक्शन से बांधता है, folder से मानों को पास करते हुए। इसका मतलब है कि जब gr.Button क्लिक किया जाता है, folder को execute_cmd में पास किया जाता है, जहाँ folder को एक कमांड में जोड़ा जाता है, और #3 पर os.system कॉल में सिस्टम पर निष्पादित किया जाता है।```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` फ्रेमवर्क का उपयोग करके बनाए गए ऐप में है। इस मामले में, उपयोगकर्ता इनपुट Flask (पायथन का लोकप्रिय वेब फ्रेमवर्क) अनुरोध के GET पैरामीटर से आता है, जिसे वेरिएबल `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 कॉल्स का पता लगाने के लिए एक क्वेरी बनाना शुरू करेंगे और बाद में स्रोतों के लिए एक क्वेरी बनाएँगे।
हम CodeQL के ApiGraphs मॉड्यूल का उपयोग करके बाहरी लाइब्रेरीज़ (जो कोडबेस में परिभाषित नहीं हैं) से फ़ंक्शनों के सभी कॉल पा सकते हैं।
नीचे दिए गए टेम्पलेट का उपयोग करें:```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::` से शुरू करें और API Graphs मॉड्यूल में उपलब्ध प्रकारों को देखने के लिए `Ctrl + Space` दबाएँ।
- एक कॉल को `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.system के सभी कॉल खोजेंfrom क्लॉज़ में, API::CallNode प्रकार का एक call वेरिएबल बनाएँ।where क्लॉज़ में, समानता ऑपरेटर = का उपयोग करके यह सुनिश्चित करें कि call os.system कॉल्स के बराबर है। कई शर्तों को निर्दिष्ट करने के लिए लॉजिकल ऑपरेटर and का उपयोग करें।os लाइब्रेरी के अनुरूप नोड्स खोजने के लिए, API::moduleImport() मेथड का उपयोग करें, जिसमें तर्क के रूप में os हो। os लाइब्रेरी के system फ़ंक्शन तक पहुँचने के लिए, 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 में classes का उपयोग पुन: प्रयोज्य लॉजिक के हिस्सों को समाहित करने के लिए किया जा सकता है। क्लासेस मानों के एकल समुच्चयों का प्रतिनिधित्व करती हैं, और वे उन मानों के समुच्चय के लिए विशिष्ट संक्रियाएँ (जिन्हें member predicates कहा जाता है) भी शामिल कर सकती हैं। आप पहले से ही CodeQL क्लास (API::CallNode) और member predicates (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` वेरिएबल आपकी नई `OsSystemSink` क्लास का `instanceof` बन जाए।
</details>
<details>
<summary>समाधान</summary>```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"
अब हम sources खोजने की ओर बढ़ते हैं।
अधिकांश sources पहले से CodeQL में modeled हैं, और उनके पास RemoteFlowSource type होता है। हम इस type का उपयोग किसी codebase में किसी भी source को खोजने के लिए कर सकते हैं।
RemoteFlowSource type का उपयोग करने के लिए semmle.python.dataflow.new.RemoteFlowSources import करें।from clause में, सभी उपलब्ध types देखने के लिए 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
</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 के Stable Diffusion प्रशिक्षण, जनरेशन और उपयोगिताओं हेतु स्क्रिप्ट के लिए एक GUI है।
कार्यशाला के दूसरे भाग में, हम जिस कोडबेस पर क्वेरी कर रहे हैं उसे kohya_ss पर स्विच करेंगे और kohya_ss में स्रोतों से सिंक तक के डेटा फ्लो खोजेंगे, जो कमांड इंजेक्शन की ओर ले जाते हैं: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027
अगला अभ्यास शुरू करने से पहले:
Databases सेक्शन में, "आर्काइव से डेटाबेस चुनें" पर क्लिक करें और रिपॉजिटरी के रूट में स्थित kohya_ss-db.zip फ़ाइल का चयन करें। एक चेकमार्क दिखना चाहिए। यह उस CodeQL डेटाबेस का चयन करेगा जिस पर आप काम कर रहे हैं।os.system कॉल के पहले तर्क तक डेटा फ्लो खोजेंisSource प्रेडिकेट में, source वेरिएबल को RemoteFlowSource प्रकार का बनाने के लिए परिष्कृत करें।isSink प्रेडिकेट में, sink वेरिएबल को os.system कॉल के पहले तर्क के रूप में परिष्कृत करें। इसे exists तंत्र और अपनी OsSystemSink क्लास का उपयोग करके करें।
exists अस्थायी वेरिएबल्स को सीमित दायरे के साथ प्रस्तुत करने का एक तंत्र है। आप उन्हें अपने स्वयं के from-where-select के रूप में सोच सकते हैं। इस मामले में, exists का उपयोग करके call नामक वेरिएबल को OsSystemSink प्रकार के साथ प्रस्तुत करें और फिर sink को के पहले तर्क के रूप में परिष्कृत करें।```codeql
/**Python के लिए CodeQL क्वेरीज़ ql/python/ql/src/Security फ़ोल्डर में स्थित हैं। सबसे लोकप्रिय भेद्यताओं के लिए क्वेरीज़ पहले से मौजूद हैं: SQL injection, command injection, code injection, आदि। टेस्ट डेटाबेस पर SQL injection क्वेरी (CWE-089) चलाएँ (आपको इसे CodeQL एक्सटेंशन > Databases में चुनना होगा। चेकमार्क पर ध्यान दें)।
💡 यह सुरक्षा शोधकर्ताओं के लिए बहुत दिलचस्प है - डिफ़ॉल्ट क्वेरीज़ का उपयोग करके, हम एक सामान्य अंदाज़ा लगा सकते हैं कि किसी दिए गए प्रोजेक्ट में संभावित भेद्यताएँ क्या हो सकती हैं।
CodeQL की शक्ति इस बात में निहित है कि CodeQL क्वेरीज़ और मॉडल को पुनः उपयोग करके उन्हें उसी भाषा के किसी भी कोडबेस पर चलाया जा सकता है। हम multi-repository variant analysis (MRVA) का उपयोग करके एक साथ 1000 तक रिपॉजिटरीज़ पर CodeQL क्वेरीज़ चला सकते हैं। प्रोजेक्ट GitHub पर होस्ट किए जाने चाहिए।
💡 यह सुरक्षा शोधकर्ताओं के लिए बहुत दिलचस्प है - यदि आपको कोई संभावित खतरनाक sink या source मिला है, तो आप उसे CodeQL में जोड़ सकते हैं (या एक क्वेरी के रूप में चला सकते हैं) और एक साथ एक हजार रिपॉजिटरीज़ के विरुद्ध अपना शोध कर सकते हैं।
आज, आपने सीखा है कि CodeQL का उपयोग करके कोडबेस का अन्वेषण कैसे करें और अपने स्वयं के सुरक्षा अनुसंधान कार्यप्रवाह में CodeQL का उपयोग कैसे करें।
यदि आप इनके बारे में अधिक जानना चाहते हैं तो इन संसाधनों को देखें:
यदि आप CodeQL का उपयोग करके कोई भेद्यता खोज लेते हैं, तो बेझिझक उसे CodeQL Wall of Fame में जोड़ें।
getMember()getACall()os.systemटेम्पलेट भरें:```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`"
callimport 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"