
CodeQL for 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)
### 옵션 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코어 코드스페이스를 사용합니다. (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="스크린샷: Codespace 생성, 더하기 클릭">
VS Code가 브라우저에서 시작되고 원격 코드스페이스가 빌드됩니다. 몇 분 정도 걸릴 수 있습니다.
`vscode-codeql-starter.code-workspace` 작업 영역을 열 것인지 묻는 메시지가 나타나면 "작업 영역 열기"를 클릭합니다.
5. 로컬 VS Code를 사용하려면 왼쪽 위 모서리의 세 줄 버튼을 누르고 "Open VS Code Desktop"을 선택합니다. 이 옵션이 나타나는 데 최대 몇 분이 걸릴 수 있습니다.
<img src="https://assets.kitploit.com/production/public/readmes/33098/f2c8c2fe6da80142344b17c208da31a23c3fa68a3917a124f0e2f7871b6a20f7.png" width="300" alt="스크린샷: 세 줄 버튼을 누르고 'Open in 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. VS Code에서 `vscode-codeql-starter.code-workspace` 작업 영역이 열려 있는지 확인합니다.
2. 왼쪽 탭 창에서 "QL" 아이콘을 클릭하여 CodeQL 보기로 이동합니다.
3. "Choose Database from Archive"를 클릭하고 저장소 루트에 있는 `test-app-db.zip` 파일을 선택합니다.
참고: 이 시점에 VS Code에서 CodeQL CLI를 설치하라는 팝업 메시지가 나타날 수 있습니다. 수락하면 문제가 해결됩니다. CLI 설치가 완료되면 위의 데이터베이스 선택을 완료할 수 있습니다.
<img src="https://assets.kitploit.com/production/public/readmes/33098/65cc5790b8b49113623bc9a9b34a1be61575b05bea2428c46f83115e2271148b.png" alt="스크린샷: CodeQL 관련 VS Code 오류 메시지">
<img src="https://assets.kitploit.com/production/public/readmes/33098/c3bf9c304d9c1f6199f591c9bcbf6e446ee4f5388ab209e30887326698129f84.png" alt="스크린샷: VS Code에서 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 for 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/)
- [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 제로부터 히어로까지 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) 명령을 실행할 수 있으며, 일반적으로 애플리케이션과 그 데이터를 완전히 손상시킬 수 있습니다.
삽입 취약점의 주요 원인은 신뢰할 수 없는 사용자 제어 입력이 프로그램의 민감하거나 위험한 함수에 사용되는 것입니다. 정적 분석에서 이를 나타내기 위해 데이터 흐름, 소스, 싱크와 같은 용어를 사용합니다.
사용자 입력은 일반적으로 애플리케이션의 진입점, 즉 데이터의 출처에서 비롯됩니다. 여기에는 GET 및 POST와 같은 HTTP 메서드의 매개변수 또는 프로그램의 명령줄 인수가 포함됩니다. 이를 "**소스**"라고 합니다.
명령 삽입의 예를 계속 들자면, 무해화되지 않은 신뢰할 수 없는 데이터와 함께 호출되어서는 안 되는 위험한 함수의 예로는 `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
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()` 호출에 대한 참조를 찾되, 이번에는 조건자를 포함합니다.```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 호출에 포함되는 명령어 주입을 찾아볼 것입니다.
워크숍의 첫 번째 부분에서는 의도적으로 취약한 코드베이스에서 소스와 싱크, 즉 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(Python의 인기 웹 프레임워크) 요청의 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
Right click in the file area and choose "CodeQL: Run Query on Selected Database" to run the query.
<details>
<summary>지침</summary>
- `from` 절에서 `API::`로 시작하고 `Ctrl + Space`를 눌러 API 그래프 모듈에서 사용 가능한 유형을 확인합니다.
- 호출은 `API::CallNode` 유형으로 표현됩니다. 이 유형의 변수를 생성하고 이름을 `call`로 지정합니다.
- 애플리케이션의 루트 폴더(이름: `test-app`)에 있는 호출로만 결과를 제한하려면 `where` 절을 추가하고 조건 `where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")`를 사용합니다.
</details>
<details>
<summary>해결 방법</summary>
</details>```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()에 getMember() 술어를 사용합니다. 마지막으로 술어로 호출을 가져옵니다.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)의 인스턴스를 나타냅니다. 이전에 `API::moduleImport`에서 했던 것과 같은 방식으로 `this`를 사용하여 `os.system` 호출을 찾으세요.
- `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"
RemoteFlowSource 클래스로 모든 소스 찾기이제 소스 찾기로 전환합니다.
대부분의 소스는 이미 CodeQL에 모델링되어 있으며 RemoteFlowSource 타입을 가지고 있습니다. 이 타입을 사용하여 코드베이스에서 모든 소스를 찾을 수 있습니다.
RemoteFlowSource 타입을 사용하려면 semmle.python.dataflow.new.RemoteFlowSources를 가져옵니다.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
</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 섹션으로 이동하여 "Choose Database from Archive"를 클릭하고 리포지토리 루트에 있는 kohya_ss-db.zip 파일을 선택합니다. 체크 표시가 나타나야 합니다. 이렇게 하면 작업 중인 CodeQL 데이터베이스가 선택됩니다.os.system 호출의 첫 번째 인수로의 데이터 흐름 찾기isSource 조건자에서 source 변수를 RemoteFlowSource 유형으로 세분화하세요.isSink 조건자에서 sink 변수를 os.system 호출의 첫 번째 인수로 세분화하세요. exists 메커니즘과 OsSystemSink 클래스를 사용하여 수행합니다.
exists는 제한된 범위를 가진 임시 변수를 도입하는 메커니즘입니다. from-where-select와 유사하다고 생각할 수 있습니다. 이 경우 exists를 사용하여 call 변수를 OsSystemSink 유형으로 도입한 다음 sink를 call의 첫 번째 인수로 세분화하세요.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"
Python용 CodeQL 쿼리는 ql/python/ql/src/Security 폴더에 있습니다. SQL 인젝션, 명령어 인젝션, 코드 인젝션 등 가장 흔한 취약점에 대한 쿼리가 이미 존재합니다. 테스트 데이터베이스에서 SQL 인젝션 쿼리(CWE-089)를 실행하세요(CodeQL 확장 > 데이터베이스에서 선택해야 하며, 체크 표시가 있는지 확인하세요).
💡 보안 연구자에게 매우 흥미로운 점입니다. 기본 쿼리를 사용하면 특정 프로젝트에 존재할 수 있는 잠재적 취약점의 일반적인 개요를 파악할 수 있습니다.
CodeQL의 강점은 CodeQL 쿼리와 모델을 재사용하여 동일한 언어의 모든 코드베이스에 대해 실행할 수 있다는 데 있습니다. 다중 저장소 변형 분석(MRVA)을 사용하면 한 번에 최대 1000개의 저장소에서 CodeQL 쿼리를 실행할 수 있습니다. 프로젝트는 GitHub에 호스팅되어야 합니다.
💡 보안 연구자에게 매우 흥미로운 점입니다. 잠재적으로 위험한 sink 또는 source를 발견했다면, 해당 항목을 CodeQL에 추가하거나 쿼리로 실행하여 수천 개의 저장소를 대상으로 한 번에 연구할 수 있습니다.
오늘 여러분은 CodeQL을 사용하여 코드베이스를 탐색하는 방법과 보안 연구 워크플로에 CodeQL을 활용하는 방법을 배웠습니다.
더 자세한 내용을 알고 싶다면 다음 리소스를 확인하세요:
CodeQL을 사용하여 취약점을 발견했다면 CodeQL Wall of Fame에 추가해 주세요.
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`"