
lighttpd 1.4.85 - High - Remote - Path - native Win32 GET /..%20/ 문서 루트 외부 읽기
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · lighttpd-win32-dotdot-space
분류: 파일 읽기 도달 범위: 원격
lighttpd 1.4.85 (4852959) - lighttpd
네이티브 _WIN32 staticfile은 buffer_path_simplify 이후 document-root에 rel_path를 결합한다. Simplify는 세 번째 바이트가 /일 때만 ../를 접는다. http_response_prepare_physical은 전체 경로에서만 후행 공백과 점을 제거한다. 따라서 GET /..%20/windows/win.ini는 /.. /windows/win.ini로 남는다. \\?\ 접두사 없이 _wstati64 / _wopen을 호출하면 Win32가 컴포넌트별로 공백을 제거하고 해당 세그먼트를 ..로 취급한다.
네이티브 Windows lighttpd에서 인증되지 않은 GET/HEAD는 워커 계정이 열 수 있는 document-root 외부의 일반 파일을 읽는다. Unix/Linux는 이 잔여물이 아니다. 파일 읽기이며, RCE가 아니다.
이 랩은 해당 핀 함수들의 가젯이다. 실제 네이티브 Win32 워커가 아니다. 마지막 줄은 how=gadget을 사용한다.
| ID | 아직 CVE 없음 |
| 분류 | 파일 읽기 (경로 순회, 네이티브 Win32 ..%20/) |
| 도달 범위 | 원격 (인증되지 않은 GET/HEAD) |
| CWE | CWE-22 |
| CVSS | 높음: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 제품 | lighttpd1.4 |
| 영향받음 | 1.4.85 (4852959e67ef51ea68084984400d3264b854c97d) 네이티브 _WIN32 |
| 인증 | 없음. 기본 mod_staticfile |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용, how=gadget |
정적 파일을 제공하는 네이티브 Windows lighttpd가 필요하다. 워커 계정이 대상 일반 파일을 열 수 있어야 한다.
| 권한 | 메서드 / 싱크 | 랩 입증 또는 추론 |
|---|---|---|
document-root 외부 파일 읽기 | 인증 없는 GET /..%20/<name> | 랩 입증 (가젯). HTTP 200 본문이 상위 비밀 파일 |
비최종 .. 컴포넌트의 다른 후행 ASCII 공백/점에 대한 동일 클래스 | url-decode 후 simplify가 .. 유지 | %20에 대해 랩 입증. 다른 후행 공백/점에 대해서는 추론 |
| 동일 경로에 HEAD | staticfile HEAD | 추론. 랩은 GET 사용 |
부정: 실제 /../ | buffer_path_simplify가 ../를 접음 | 랩 입증. 404, 단순화된 /windows/win.ini, 증거 없음 |
| 부정: 단순화되지 않은 물리적 문자열의 Unix POSIX open | open("/srv/htdocs/.. /windows/win.ini") | 랩 입증. ENOENT |
이 잔여물에서 제외됨: Unix/Linux staticfile; Cygwin (동일 strip, POSIX open); 1.4.85 %5C parseopt; CVE-2018-19052 alias; CVE-2014-2324 Host. RCE 아님. 쓰기 아님.
태그 lighttpd-1.4.85를 고정했다. 스무 번의 탐색. 기본 Unix/Linux staticfile, FastCGI, proxy, TLS, auth, HTTP/2, alias/rewrite: 이 기준에서는 없음. 1.4.81-1.4.85 파서 웨이브는 이미 trailers, CGI 헤더 충돌, 잘못된 백엔드 Content-Length를 닫았다.
buffer_path_simplify는 walk[2] == '/'일 때만 ../를 접는다. http_response_prepare_physical (src/response.c 334-360)의 WIN32 strip은 전체 경로 꼬리다. _wstati64 / _wopen (src/fs_win32.c 24-77)은 \\?\ 없이 UTF-16을 전달하므로 Win32가 컴포넌트별로 후행 공백을 제거하고 .. 가 ..가 된다. 물리적 결합은 doc_root + rel_path이며 stat 이후 basedir 검사가 없다.
이미 기록된 잘못된 방향: Unix ENOENT를 "버그 아님"으로 취급 (이는 부정 통제); Cygwin을 네이티브 Win32로 부름; 1.4.85 %5C가 이 잔여물이라고 주장; 파일 읽기를 RCE로 과장. 연극: 리버스 셸. 오라클은 document-root의 상위에서 오는 200 본문이다.
python3 lighttpd-win32-dotdot-space-Abraxas-Labs.py
또는
cd lab
./run.sh
이 랩은 buffer_urldecode_path, buffer_path_simplify (Win32 '\\' 매핑), response.c 꼬리 strip, 그리고 \\?\ 없는 _wstati64의 충실한 가젯이다. Unix POSIX open은 부정 통제다. Win32 resolve는 동일한 컴포넌트별 후행 공백 strip, 그다음 . / .., 그다음 해석된 경로의 POSIX open으로 구현된다. 루프백 HTTP 127.0.0.1:19400.
/index.html -> 200 public-index, 증거 없음./../windows/win.ini -> 404, 단순화된 /windows/win.ini./..%20/windows/win.ini -> 디코딩된 /.. /windows/win.ini, simplify가 공백 유지, Unix ENOENT, Win32가 /srv/windows/win.ini로 해석, 200 증거.SUCCESS lighttpd-win32-dotdot-space how=gadget win32-get=200 unix-open=enoent simplify-kept-dotdot-space=yes LIGHTTPD-WIN32-DOTDOT-SPACE-WITNESS
simplify 전에 경로 컴포넌트별로 후행 공백과 점을 제거하거나, Win32 open에 \\?\ 접두사를 붙이고 document-root 아래에 머물지 않는 물리적 경로를 거부하라.
4852959e67ef51ea68084984400d3264b854c97d)src/buffer.c · src/response.c · src/fs_win32.c%5C parseopt · CVE-2018-19052 alias · CVE-2014-2324 HostGNU Affero GPL v3.0. LICENSE 참조. 루프백 랩 전용. 보증 없음.