
Apache Tomcat 11.0.27 - 높음 - 원격 - DoS - RewriteValve [NS] worker pin
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · tomcat-rewrite-ns-loop
분류: DoS 도달 범위: 원격
Apache Tomcat 11.0.27 (52f3b364) - tomcat.apache.org
RewriteValve.parseRuleFlag는 접두사로 매칭한다. NC/NE 이후에 남은 플래그 중 startsWith("N")인 것이 다음을 활성화한다. httpd에서 복사한 [NS](nosubreq)와 [NV](novary)는 [N]이 된다. 치환 -는 substitution을 null로 남기고, 이어서 RewriteRule.evaluate가 원래 URL을 반환한다. isNext()와 null이 아닌 newtest가 결합되면 라운드 상한 없이 i = -1을 설정하므로, 규칙에 매칭되는 인증되지 않은 GET 하나가 클라이언트가 연결을 끊거나 프로세스가 재시작될 때까지 HTTP 커넥터 스레드를 고정한다. 명시적 [N]과 [S=-1]도 동일한 고정을 일으킨다. [L,NS]는 isLast()가 먼저 중단하므로 안전하다.
CVE-2026-65927(Important, 11.0.25)은 [N]이 두 번째 규칙에서 재시작되는 문제를 수정했다. 이 고정 문제에는 여전히 라운드 상한이 없다. 11.0.27 이후 같은 날의 main에는 보안 권고 없이 MAX_REWRITE_ROUNDS=1000과 정확한 플래그 매칭(2da9fddb, 8992dbdd)이 추가되었다.
| ID | 아직 CVE 없음 |
| 분류 | DoS |
| 도달 범위 | 원격 (인증되지 않은 HTTP) |
| CWE | CWE-835 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| 제품 | Apache Tomcat |
| 영향받음 | 11.0.27 (52f3b364e5882a5dbcfc42cb8313a7c2ae532c64) RewriteValve |
| 인증 | 인증되지 않은 HTTP |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
태그 11.0.27을 고정하고 RewriteValve.invoke를 읽었다. 이 밸브는 기본 conf/server.xml에 없다. 기본 Host 경로는 conf/Catalina/localhost/rewrite.config이다. 랩은 127.0.0.1:18910의 루프백 HTTP이다. 공식 11.0.27 tarball. RCE는 아니다.
| 방법 | 싱크 | 권한 |
|---|---|---|
Host rewrite.config의 RewriteRule ^/loop$ - [NS]에 매칭되는 인증되지 않은 GET /loop | 토큰 NS에 대한 startsWith("N") 때문에 RewriteValve.invoke의 i = -1 | 가용성 (랩에서 입증): 클라이언트가 연결을 끊거나 프로세스가 재시작될 때까지 HTTP 커넥터 스레드 하나를 고정. 랩: /loop가 4.002초에 타임아웃. |
명시적 [N]을 사용한 인증되지 않은 GET /next | 동일한 isNext() 재시작 | 가용성 (랩에서 입증): 동일한 고정. 랩: /next가 4.003초에 타임아웃. |
[S=-1]을 사용한 인증되지 않은 GET /skip | i += -1 이후 for 증가 | 가용성 (랩에서 입증): 동일한 고정. 랩: /skip이 4.002초에 타임아웃. |
| 워커당 매칭 요청 하나 | 동일한 싱크, maxThreads개의 동시 매칭 URL | 가용성 (추론): 커넥터 풀을 채움(랩은 32 사용, 기본값은 200). 이후 새 요청은 대기하거나 거부됨. 하나의 /loop가 진행 중일 때도 형제 /ok는 계속 응답. |
/ok의 13ms 404 대비 행 | next/skip과 [L]의 타이밍 | 정찰 (랩에서 입증): next/skip 규칙이 매칭되었음을 판별. 랩: 4.002초 행 vs 0.013초 404. |
랩에서 입증 vs 추론: /loop [NS] 행, /next [N] 행, /skip [S=-1] 행, /ok [L] 13ms 내 404, /safe [L,NS] 5ms 내 404, 그리고 /loop가 진행 중일 때 형제 /ok 404는 랩에서 입증되었다. 풀 고갈은 스레드 하나 고정과 maxThreads로부터 추론된다.
요구 사항: Host 또는 Context에 RewriteValve가 있고 매칭되는 rewrite.config 규칙이 있어야 한다. 밸브는 옵트인이며, 주석 처리된 AJP와 같은 부류이다. httpd에서 복사한 [NS]는 매칭 규칙이지 의도적인 무한 [N] 루프가 아니다.
| 표면 | 랩 |
|---|---|
[L,NS] (httpd last+nosubreq) | /safe 5ms 내 404 (L-ns-safe=yes) |
| 스레드 하나가 고정된 동안 다른 진행 중 요청 | /loop 중 /ok 13ms 내 404 (sibling-alive=yes) |
RewriteValve가 없는 기본 server.xml | 밸브 부재; 잔여물이 발동하지 않음 |
| CVE-2026-65927의 RCE / WEB-INF 읽기 / 제약 우회 | [N]은 이제 규칙 0에서 재시작; 이 잔여물은 가용성에만 해당 |
| Manager / JMX / AJP / DefaultServlet PUT | 변경 없음; PUT은 여전히 readonly |
Tomcat 사용자로서의 코드 실행 없음. conf/ 또는 WEB-INF 읽기 없음. 세션 탈취 없음. Manager 배포 없음. JVM은 계속 살아 있고, 풀이 채워질 때까지 다른 워커는 계속 응답한다.
cd lab
./run.sh
루프백 127.0.0.1:18910이 컨테이너 8080에 매핑된다. Compose 프로젝트 tomcat-rewrite-ns-loop. 이미지 태그 tomcat-rewrite-ns-loop:11.0.27. 공식 apache-tomcat-11.0.27.tar.gz SHA512 a617896307cada4884b24f80c4e977ddad8b3e0f88ce0e2a6eea29d5f332498e276ae5976c227a9c8daecf05c7c90def684a3766dd5a81f47a56d8b1adf43dc3. 증인 TOMCAT-REWRITE-NS-LOOP-WITNESS. 마지막 줄:
SUCCESS TOMCAT-REWRITE-NS-LOOP control-ok=yes ns-hang=yes L-ns-safe=yes n-hang=yes skip-hang=yes sibling-alive=yes TOMCAT-REWRITE-NS-LOOP-WITNESS
랩 rewrite.config:
RewriteRule ^/loop$ - [NS]
RewriteRule ^/next$ - [N]
RewriteRule ^/skip$ - [S=-1]
RewriteRule ^/ok$ - [L]
RewriteRule ^/safe$ - [L,NS]
재작성 라운드에 상한을 둔다(이 태그 이후 main의 MAX_REWRITE_ROUNDS=1000, 커밋 2da9fddb). 정확히 일치하는 플래그를 사용하여 [NS]가 파싱에 실패하게 한다(커밋 8992dbdd). skip < 0을 거부한다. 이것들이 릴리스에 반영될 때까지: 매칭 규칙에서 [NS]/[NV]/[N]/[S=-1]을 피하거나 RewriteValve를 제거한다.
52f3b364e5882a5dbcfc42cb8313a7c2ae532c64)RewriteValve.java isNext() 재시작 및 startsWith("N")RewriteRule.java 치환 -가 원래 URL을 반환