오늘은 CodeQL에 대해 알아볼 것입니다.
CodeQL 개념
CodeQL은 GitHub에서 개발한 정적 코드 분석 엔진이다. 코드를 실행하지 않고도 보안 취약점과 안티 패턴을 자동으로 탐지해 코드 품질을 높이는 데 도움을 준다. 또한 GitHub CI/CD 파이프라인과 연동하여 코드 변경 시마다 자동으로 보안 검사를 수행할 수 있다.
또한 CodeQL은 이미 알려진 취약점을 기준으로, 유사한 형태의 취약 코드가 존재하는지 분석할 수 있다.
CI/CD는 소프트웨어 개발 과정에서 빌드, 테스트, 배포를 자동화하는 방식이다.
- CI (Continuous Integration) - 코드를 push할 때마다 자동으로 빌드와 테스트를 돌려주는 것으로 여러 사람이 작업해도 코드가 깨지지 않게 유지해 준다.
- CD (Continuous Deployment/Delivery) - 테스트를 통과한 코드를 배포 가능한 상태로 만들거나, 자동으로 배포하는 과정을 의미한다.
즉, 코드를 push하면 테스트를 수행하고 자동으로 배포까지 진행하는 자동화 파이프라인이다.
CodeQL 원리
CodeQL의 핵심 아이디어는 소스코드를 데이터베이스처럼 다루는 것이다. 함수, 변수, 클래스 등 요소들을 관계형 데이터베이스의 테이블처럼 추상화하고, QL이라는 쿼리 언어를 사용해 원하는 패턴이나 취약점을 질의한다.
즉, CodeQL은 소스코드를 분석해 데이터베이스 형태로 변환한 뒤, 그 위에서 쿼리를 실행하여 취약점이나 코드 패턴을 탐지하는 방식으로 동작한다.
단순 패턴 매칭과 달리, CodeQL은 코드 전체의 데이터 흐름을 추적할 수 있다. 그래서 단순히 위험한 함수가 있는지만 탐지하는 것이 아니라, 실제로 외부 입력이 어떤 경로를 거쳐 위험한 지점까지 도달하는지 분석할 수 있다.
CodeQL에서 중요한 개념은 Source, Sink, Data Flow이다. CodeQL은 외부로부터 들어온 신뢰할 수 없는 입력이 어떤 경로를 따라 이동하는지 추적하고, 그 값이 적절한 검증 없이 위험한 실행 지점에 도달하는지를 분석하여 취약점을 탐지한다.
Source / Sink / Data Flow
- Source는 사용자 입력이 애플리케이션으로 들어오는 지점이다. HTTP GET/POST 파라미터, 커맨드라인 인자 등 외부에서 들어오는 신뢰할 수 없는 데이터가 여기에 해당한다.
- Sink는 해당 데이터가 검증 없이 도달하면 안되는 위험한 지점이다. 대표적으로 SQL 쿼리 실행 함수, 명령어 실행 함수 등이 있다.
- Data Flow는 Source에서 Sink까지 데이터가 흐르는 경로다. CodeQL은 이 경로가 존재하는지 분석하며, Source에서 Sink 사이에 입력값 검증이 없는 경로가 존재하면 취약점으로 판정한다.
CodeQL 실습
CodeQL Bundle 다운로드 : https://github.com/github/codeql-action/releases
해당 번들을 다운로드 후 압축 해제하고 환경변수에 등록한다.
그 후, VS Code 확장에서 CodeQL 확장 프로그램을 설치한다.
@app.route("/login", methods=["GET", "POST"])
def login():
result = ""
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
sql = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
con = sqlite3.connect("users.db")
row = con.execute(sql).fetchone()
con.close()
result = f"로그인 성공: {row}" if row else "로그인 실패"
return render_template_string("""
<h2>로그인 (SQLi 실습)</h2>
<form method="POST">
<input name="username" placeholder="username"><br>
<input type="password" name="password" placeholder="password"><br>
<button type="submit">로그인</button>
</form>
<p>{{ result }}</p>
""", result=result)
다음은 SQL Injection이 가능한 Flask 코드 중 일부이다.
분석할 코드가 있는 디렉토리에서 아래 명령어를 실행하여 CodeQL 데이터베이스를 생성한다.
codeql database create db --language=python --source-root=.
그 후, SQL Injection을 탐지하기 위한 쿼리 파일을 작성한다.
import python
import semmle.python.security.dataflow.SqlInjectionQuery
from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
where SqlInjectionFlow::flowPath(source, sink)
select sink.getNode(),
"SQL injection: $@ flows into SQL query.", source.getNode(), "user input"
해당 쿼리를 실행한다.
codeql query run --database=db queries-python/find_sqli.ql

실행 결과는 쿼리 파일의 select문에서 반환한 값이 순서대로 출력된 것이다.
순서대로 sink 위치, 경고 메시지, source 위치, source 설명 문자열을 의미한다.

VS Code 확장에서 CodeQL 쿼리를 돌려보면 동일한 결과가 나온다.
여기서 sink 위치를 클릭하면 취약한 코드를 보여준다.

이를 통해 CodeQL이 SQL Injection 취약점을 정상적으로 탐지하는 것을 확인할 수 있다.
'Knights Frontier_1st > 기술문서 | 블로그' 카테고리의 다른 글
| [ Knights Frontier ] EDR 환경 구축 후 실습 (0) | 2026.04.01 |
|---|---|
| [ Knights Frontier ] PAC 보호 기법 (0) | 2026.03.25 |
| [ Knights Frontier ] CVE-2026-20841 1-day 분석 (0) | 2026.03.13 |
| [ Knights Frontier ] 블록체인 기반의 공급망 공격 탐지 툴 제작 (0) | 2025.10.16 |
| [ Knights Frontier ] 쿼드콥터(드론)를 이용한 무선AP 모의해킹 (0) | 2025.10.14 |