
lighttpd 1.4.85 - Alta - Remota - Ruta - Win32 nativo GET /..%20/ lee fuera del document-root
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · lighttpd-win32-dotdot-space
Write-up: https://abraxaslabs.tech/research/lighttpd-win32-dotdot-space
Clase: Lectura de archivos Alcance: Remoto
lighttpd 1.4.85 (4852959) - lighttpd
El staticfile nativo _WIN32 une document-root con rel_path después de buffer_path_simplify. Simplify solo pliega ../ cuando el tercer byte es /. http_response_prepare_physical elimina los espacios y puntos finales de la ruta completa únicamente. Por lo tanto, GET /..%20/windows/win.ini permanece como /.. /windows/win.ini. _wstati64 / _wopen sin un prefijo \\?\ permiten entonces que Win32 elimine el espacio por componente y trate ese segmento como ...
Un GET/HEAD no autenticado en lighttpd nativo de Windows lee un archivo regular fuera de document-root que la cuenta del worker puede abrir. Unix/Linux no presenta este residuo. Lectura de archivos, no RCE.
El laboratorio es un gadget de esas funciones de pin. No es un worker nativo Win32 en vivo. La última línea usa how=gadget.
| ID | aún sin CVE |
| Clase | Lectura de archivos (path traversal, ..%20/ nativo de Win32) |
| Alcance | Remoto (GET/HEAD no autenticado) |
| CWE | CWE-22 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| Producto | lighttpd1.4 |
| Afectado | 1.4.85 (4852959e67ef51ea68084984400d3264b854c97d) _WIN32 nativo |
| Autenticación | ninguna. mod_staticfile por defecto |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1, how=gadget |
Requiere lighttpd nativo de Windows sirviendo archivos estáticos. La cuenta del worker debe poder abrir el archivo regular objetivo.
| Privilegio | Método / sink | Probado en laboratorio o inferido |
|---|---|---|
Leer un archivo fuera de document-root | GET /..%20/<name> sin autenticación | Probado en laboratorio (gadget). El cuerpo HTTP 200 es el secreto del directorio padre |
Misma clase para otro espacio/punto ASCII final en un componente .. no final | url-decode y luego simplify conserva .. | Probado en laboratorio para %20. Inferido para otro espacio/punto final |
| HEAD a la misma ruta | staticfile HEAD | Inferido. El laboratorio usó GET |
Negativo: /../ real | buffer_path_simplify pliega ../ | Probado en laboratorio. 404, /windows/win.ini simplificado, sin testigo |
| Negativo: apertura POSIX de Unix de la cadena física no simplificada | open("/srv/htdocs/.. /windows/win.ini") | Probado en laboratorio. ENOENT |
Cerrado en este residuo: staticfile de Unix/Linux; Cygwin (mismo strip, apertura POSIX); %5C parseopt de 1.4.85; alias de CVE-2018-19052; Host de CVE-2014-2324. No es RCE. No es una escritura.
Fijé el tag lighttpd-1.4.85. Veinte búsquedas. staticfile por defecto de Unix/Linux, FastCGI, proxy, TLS, auth, HTTP/2, alias/rewrite: ninguno a este nivel. La ola de parsers de 1.4.81-1.4.85 ya había cerrado trailers, conflictos de cabeceras CGI y Content-Length de backend inválido.
buffer_path_simplify solo pliega ../ cuando walk[2] == '/'. El strip de WIN32 en http_response_prepare_physical (src/response.c 334-360) es la cola de la ruta completa. _wstati64 / _wopen (src/fs_win32.c 24-77) pasan UTF-16 sin \\?\, por lo que Win32 elimina los espacios finales por componente y .. se convierte en ... La unión física es doc_root + rel_path sin comprobación de basedir posterior al stat.
Giros incorrectos ya registrados: tratar Unix ENOENT como "no es un bug" (es el control negativo); llamar a Cygwin nativo de Win32; afirmar que 1.4.85 %5C es este remanente; inflar la lectura de archivo a RCE. Teatro: una reverse shell. El oráculo es un cuerpo 200 del padre de document-root.
python3 lighttpd-win32-dotdot-space-Abraxas-Labs.py
o
cd lab
./run.sh
El laboratorio es una reproducción fiel de buffer_urldecode_path, buffer_path_simplify (mapa de '\\' en Win32), el recorte final de response.c y _wstati64 sin \\?\. La apertura POSIX de Unix es el control negativo. La resolución de Win32 se implementa como el mismo recorte de espacios finales por componente, luego . / .., y después una apertura POSIX de la ruta resuelta. HTTP en loopback 127.0.0.1:19400.
/index.html -> 200 public-index, sin testigo./../windows/win.ini -> 404, simplificado a /windows/win.ini./..%20/windows/win.ini -> decodificado a /.. /windows/win.ini, la simplificación conservó el espacio, ENOENT en Unix, Win32 resolvió /srv/windows/win.ini, 200 testigo.SUCCESS lighttpd-win32-dotdot-space how=gadget win32-get=200 unix-open=enoent simplify-kept-dotdot-space=yes LIGHTTPD-WIN32-DOTDOT-SPACE-WITNESS
Eliminar los espacios y puntos finales por componente de ruta antes de simplify, o prefijar las aperturas Win32 con \\?\ y rechazar una ruta física que no permanezca bajo 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. Consulte LICENSE. Solo laboratorio de loopback. Sin garantía.