Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
codeql-workshop-cve-2021-21380 — CVE-2021-21380을 다루는 CodeQL 워크숍 | Kitploit
도구/GitHubGitHub/rvermeulen/codeql-workshop-cve-2021-21380
Static AnalysisVulnerability AnalysisCode AnalysisWeb SecurityLearning & EducationLabs & Practice
GitHubrvermeulen/codeql-workshop-cve-2021-21380

codeql-workshop-cve-2021-21380

CVE-2021-21380을 다루는 CodeQL 워크숍

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기
1251년 전아직 검토되지 않음

Java용 CodeQL 워크숍: SQL 인젝션 찾기

이 워크숍에서는 구문적 및 의미적 추론을 사용하여 CVE-2021-21380에 문서화된 XWiki 플랫폼의 평점 컴포넌트에서 SQL 인젝션을 찾아보겠습니다.

목차

  • Java용 CodeQL 워크숍: SQL 인젝션 찾기
    • 목차
    • 사전 요구 사항 및 설정 지침
      • 로컬 머신에서
        • 설치
        • 설정 단계
    • 워크숍
      • 학습 내용
      • 문제 설명
      • 연습 문제
        • 연습 문제 1
        • 인터메조 1
        • 연습 문제 2
        • 인터메조 2
        • 연습 문제 3
        • 인터메조 3
        • 연습 문제 4
        • 연습 문제 5
        • 연습 문제 6
        • 연습 문제 7
        • 연습 문제 8
    • 다음 단계

사전 요구 사항 및 설정 지침

로컬 머신에서

가능하면 워크숍 전에 이 섹션을 완료하세요.

설치

  • Visual Studio Code를 설치합니다.

  • Visual Studio Code용 CodeQL 확장을 설치합니다.

  • CodeQL CLI를 설치할 필요는 없습니다: 확장이 이 작업을 대신 처리해 줍니다.

  • 이 저장소를 클론합니다:

    root@kitploit:~
    git clone https://github.com/advanced-security/codeql-workshop-cve-2021-21380.git
    

설정 단계

  • 워크숍에서 사용할 CodeQL 데이터베이스를 가져옵니다:
    • Explorer 보기에서 xwiki-platform-CVE-2021-21380.zip 파일을 마우스 오른쪽 버튼으로 클릭하고 CodeQL: Set Current Database 명령을 선택합니다.
    • 데이터베이스는 활동 막대(Activity Bar)의 QL 아이콘에서 접근할 수 있는 CodeQL 데이터베이스 보기에 표시됩니다.
  • Java 코드 분석과 연습 문제 및 솔루션의 테스트 실행에 필요한 종속성을 설치합니다.
    • 명령 팔레트(Cmd/Ctrl+Shift+P)에서 CodeQL: Install Pack Dependencies 명령을 검색하여 실행합니다.
    • VS Code 창 상단의 입력란에 github를 입력하여 목록을 필터링합니다.
    • cve-2021-21380-exercises, cve-2021-21380-exercises-tests, cve-2021-21380-solutions, cve-2021-21380-solutions-tests 옆의 확인란을 선택합니다.
    • OK/Enter를 클릭합니다.
  • 솔루션에 대한 테스트를 실행하여 모든 것이 예상대로 작동하는지 확인합니다.
    • 테스트 보기를 열고 트리의 솔루션 항목 옆에서 테스트 실행(솔루션에 마우스를 올리면 재생 아이콘이 표시됨)을 누릅니다.

워크숍

학습 내용

이 워크숍은 Java에 대한 QL 언어 지원을 소개하는 여러 연습 문제로 구성되어 있으며, 알려진 SQL 인젝션을 찾는 최종 쿼리로 끝납니다. 이 연습 문제들을 통해 다음을 배우게 됩니다:

  • 구문 정보에 대해 추론하는 방법.
  • 의미 정보에 대해 추론하는 방법.
  • 패턴을 표현하기 위해 Java에 대한 QL 언어 지원을 살펴봅니다.
  • 기존 모델링을 재사용하고 확장하는 방법을 살펴봅니다.
  • 여러 구성 요소를 사용하여 최종 쿼리를 구성합니다.

문제 설명

이 워크숍에서는 XWiki Platform의 평점 API 컴포넌트에서 알려진 _SQL 인젝션 취약점_을 찾아보겠습니다. 이러한 취약점은 외부 사용자가 제어하는 정보가 SQL 쿼리를 안전하지 않게 구성하고 실행하는 애플리케이션 코드에 도달할 때 애플리케이션에서 발생할 수 있습니다.

이 워크숍에서 다루는 알려진 SQL 인젝션은 GitHub Advisory Database의 GHSA-79rg-7mv3-jrr5에서 검토됩니다. SQL 인젝션과 가능한 변형을 찾기 위해 다음 하위 문제들을 다룰 것입니다:

  • 신뢰할 수 없는 정보의 소스를 식별하고 QL로 모델링합니다.
  • 싱크, 즉 SQL 쿼리를 실행하는 메서드를 식별하고 QL로 모델링합니다.
  • 위 솔루션들을 결합하여 오염 추적(taint tracking)을 사용해 소스와 싱크 사이에 정보 흐름이 있는지 확인합니다.

연습 문제

처음 몇 개의 연습 문제에서는 추상 구문 트리(AST)를 사용하여 구문 정보를 추론하고 다음을 식별합니다:

  • 취약점 이해를 위해 보안 권고에 설명된 메서드
  • 신뢰할 수 없는 데이터를 포함하는 매개변수, 즉 소스
  • SQL 문을 받아들이는 메서드 호출, 즉 싱크

연습 문제 1

쿼리 exercise1.ql을 완성하여 프로그램에서 이름이 getAverageRating인 모든 메서드와 해당 선언 타입을 찾으세요.

힌트
  • java 모듈은 프로그램의 메서드를 추론하기 위한 Method 클래스를 제공합니다.
  • Method 클래스는 메서드의 이름을 추론하기 위한 멤버 조건자 getName과 hasName을 제공합니다.
  • Method 클래스는 메서드를 선언하는 타입을 추론하기 위한 멤버 getDeclaringType을 제공합니다.

솔루션은 쿼리 exercise1.ql에서 찾을 수 있습니다.

인터메조 1

연습 문제 1의 솔루션은 메서드 목록을 반환합니다. 그중 일부는 RatingsManager라는 인터페이스에 정의되어 있고, 일부는 AbstractRatingsManager 및 RatingsScriptService 클래스에 정의되어 있습니다.

쿼리가 반환한 정보와 XWiki 컴포넌트 문서를 통해 다음을 추론할 수 있습니다:

  • XWiki는 확장과 사용자 지정을 허용하기 위해 컴포넌트 지향 설계를 사용합니다.
  • 취약한 메서드는 컴포넌트의 일부입니다.
  • 컴포넌트는 Role 어노테이션이 달린 인터페이스와 Component 어노테이션이 달린 구현체로 구성됩니다.
  • ScriptService를 확장하는 컴포넌트는 스크립팅을 통해 위키 페이지에서 접근할 수 있게 됩니다.

연습 문제 2

쿼리 exercise2.ql을 완성하여 Component 어노테이션이 달린 모든 클래스를 찾으세요. 해당 어노테이션 타입의 정규화된 이름(fully qualified name)은 org.xwiki.component.annotation.Component입니다.

힌트
  • /클래스 도메인 타입/, 즉 그 슈퍼 타입들의 교집합은 /특성 조건자/에서 this 키워드를 사용하여 접근할 수 있습니다.
  • Class 클래스는 연관된 어노테이션을 가져오기 위한 getAnAnnotation 메서드를 제공합니다.
  • Annotation 클래스는 해당 타입을 추론하기 위한 getType 멤버 조건자를 제공합니다.
  • Type 클래스는 타입의 이름을 추론하기 위한 멤버 조건자 getName과 hasName을 제공합니다.
  • 클래스와 인터페이스를 나타내는 RefType 클래스는 RefType의 정규화된 이름을 추론하기 위한 멤버 조건자 getQualifiedName과 hasQualifiedName을 제공합니다.

솔루션은 쿼리 exercise2.ql에서 찾을 수 있습니다.

연습 문제 3

쿼리 excercise3.ql을 완성하여 ScriptService 인터페이스를 구현하는 모든 컴포넌트를 찾으세요.

힌트
  • Class 타입은 클래스의 슈퍼 타입, 즉 extends하거나 implements하는 타입을 추론하기 위한 멤버 조건자 getASuperType을 제공합니다.

솔루션은 쿼리 exercise3.ql에서 찾을 수 있습니다.

인터메조 2

이 시점에서 우리는 사용자가 호출할 수 있는 메서드를 구문적으로 식별했으며, 해당 메서드의 매개변수는 워크숍 후반에 신뢰할 수 없는 데이터의 소스로 간주할 것입니다.

다음 연습 문제에서는 가능한 싱크를 조사하고 식별할 것입니다. 연습 문제 1의 결과를 통해 구현 중 하나가 getAverageRatingFromQuery 메서드를 호출한다는 것을 추론할 수 있습니다. 유사한 쿼리를 사용하여 getAverageRatingFromQuery의 선언 타입을 찾을 수 있으며, 이를 통해 AbstractRatingsManager 클래스의 구현이 search 메서드로 전달되는 SQL 문을 구성한다는 것을 확인할 수 있습니다.

search 메서드는 의존성에 구현되어 있으므로 해당 구현을 사용할 수 없습니다. 다음 연습 문제에서는 사용 가능한 타입 정보를 사용하여 이 search 메서드 호출과 해당 선언 타입을 식별할 것입니다.

연습 문제 4

쿼리 exercise4.ql을 완성하여 search 메서드에 대한 모든 메서드 호출을 찾고 해당 선언 타입을 식별하세요.

힌트
  • MethodCall 타입은 메서드 호출에 대해 추론할 수 있는 수단을 제공합니다.
  • MethodAcccess 타입은 메서드 호출의 대상을 추론하기 위한 멤버 조건자 getMethod를 제공합니다.

솔루션은 쿼리 exercise4.ql에서 찾을 수 있습니다.

연습 문제 5

쿼리 exercise5.ql을 완성하여 XWikiStorageInterface 인터페이스(정규화된 이름은 com.xpn.xwiki.store.XWikiStoreInterface)에 선언된 메서드에 대한 모든 메서드 호출을 찾으세요.

힌트
  • instanceof 키워드는 값이 타입으로 표현되는 값의 집합에 속한다는 것을 명시하는 데 사용할 수 있습니다. 예를 들어, 인터페이스 메서드에 대한 모든 호출을 식별하려면:

    root@kitploit:~
    import java
    
    from MethodCall ma
    where ma.getMethod.getDeclaringType() instanceof Interface
    select ma
    

솔루션은 쿼리 exercise5.ql에서 찾을 수 있습니다.

인터메조 3

이 시점에서 우리는 QL을 사용하여 가능한 소스와 싱크를 구문적으로 설명했습니다. 프로그램에서 이 지점들 사이에 정보 흐름이 있는지 확인하기 위해 오염 추적(taint tracking)을 사용하여 프로그램을 의미적으로 분석할 것입니다. 지원하는 언어의 표준 라이브러리는 두 가지 데이터 흐름 메커니즘을 제공합니다:

  1. DataFlow 모듈은 값을 보존하는 정보 흐름을 지원합니다.
  2. TaintTracking 모듈은 값이 수정되더라도 정보 흐름을 지원합니다.

후자가 중요한 이유는 SQL 인젝션과 같은 인젝션 취약점에서는 신뢰할 수 없는 데이터가 실행되는 더 큰 문장의 일부가 되는 것이 일반적이기 때문입니다.

이 워크숍에서는 기존 SQL 인젝션 오염 추적 구성을 재사용하고, 모델링한 소스와 싱크로 확장하여 SQL 인젝션을 찾을 것입니다. 구성을 확장하는 방법을 이해하기 위해 아래 구성 정의를 살펴보는 것부터 시작하겠습니다.

root@kitploit:~
class QueryInjectionFlowConfig extends TaintTracking::Configuration {
  QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }

  override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }

  override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

  override predicate isSanitizer(DataFlow::Node node) {
    node.getType() instanceof PrimitiveType or
    node.getType() instanceof BoxedType or
    node.getType() instanceof NumberType
  }

  override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
    any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
  }
}

구성이 이러한 프로그램 위치를 식별하는 데 사용하는 isSource와 isSink 조건자는 둘 다 앞서 살펴본 instanceof 키워드를 사용합니다. RemoteFlowSource와 QueryInjectionSink 클래스는 둘 다 abstract 클래스입니다. 이것은 표준 라이브러리에서 자주 만나게 되는 일반적인 패턴이며, 이 패턴을 통해 RemoteFlowSource와 QueryInjectionSink 클래스가 나타내는 값의 집합을 확장할 수 있습니다.

abstract class를 확장하는 QL class는 슈퍼 클래스가 나타내는 값의 집합을 세분화하지 않지만, 서브클래스가 나타내는 값을 슈퍼클래스에 추가합니다. 다음 연습 문제에서는 이러한 서브클래스들을 구현하고 최종 쿼리를 구성할 것입니다.

연습 문제 6

쿼리 exercise6.ql을 완성하여 연습 문제 3에서 식별한 컴포넌트 클래스의 공용 메서드 매개변수로 RemoteFlowSource의 값 집합을 확장하세요.

힌트
  • instanceof 키워드는 값이 타입으로 표현되는 값의 집합에 속한다는 것을 명시하는 데 사용할 수 있습니다. 예를 들어, 인터페이스 메서드에 대한 모든 호출을 식별하려면:

    root@kitploit:~
    import java
    
    from MethodCall ma
    where ma.getMethod.getDeclaringType() instanceof Interface
    select ma
    

솔루션은 쿼리 exercise6.ql에서 찾을 수 있습니다.

연습 문제 7

쿼리 exercise7.ql을 완성하여 연습 문제 5에서 식별한 저장소 인터페이스의 메서드 호출 인자로 QueryInjectionSink의 값 집합을 확장하세요.

힌트
  • exists 수식은 exists의 범위 내에서 추론할 수 있는 임시 변수를 도입할 수 있게 해줍니다.

    다음 예제는 exists 표현식을 사용하여 메서드 집합을 호출되는 메서드로 줄입니다.

    root@kitploit:~
    from Method m
    where m.hasName("foo") and exists(MethodCall ma | ma.getMethod() = m)
    select m
    
  • MethodCall 클래스는 메서드 접근의 한정자(qualifier)를 추론하기 위한 멤버 조건자 getQualifer를 제공합니다.

솔루션은 쿼리 exercise7.ql에서 찾을 수 있습니다.

연습 문제 8

쿼리 exercise8.ql을 완성하여 이전 연습 문제들의 솔루션을 최종 솔루션으로 결합하세요.

솔루션은 쿼리 exercise8.ql에서 찾을 수 있습니다.

다음 단계

  • 쿼리에는 XWiki 프레임워크의 일부를 모델링하는 모듈이 포함되어 있습니다. 이를 별도의 모듈 파일로 리팩터링하고 쿼리에서 사용하세요.
  • 신뢰할 수 없는 데이터의 소스를 스크립트 서비스 컴포넌트로 한정했습니다. 다른 소스로 확장하는 방법을 살펴보세요.
  • 싱크에 대해서는 XWikiStoreInterface의 직접 사용으로 한정했습니다. 인터페이스 구현체의 직접 사용을 포함하도록 싱크를 확장하세요. Class 클래스는 extendsOrImplements 멤버 조건자를 제공하고, Method 클래스는 overridesOrInstantiates 멤버 조건자를 제공하므로 도움이 될 수 있습니다.
  • 소스 정의를 사용하여 쿼리 '외부 API로 전달된 신뢰할 수 없는 데이터 '
도구 다운로드