背景
Nginx是一个高性能的HTTP和反向代理服务器,经常被做为反向代理,动态的部分被proxy_pass传递给后端端口,而静态文件需要Nginx来处理。
而本次提及的漏洞是出现在服务器的静态文件中。
什么是 Nginx alias 目录穿越?
如果静态文件存储在
/home/
目录下,而该目录在url中名字为files,那么就需要用alias设置目录的别名。Nginx在配置别名(Alias)的时候,如果忘记加
/
,将造成一个目录穿越漏洞。
目的
- 目录穿越如何产生/复现/实现原理?
- 实现目录穿越后,对应的相对目录是什么?
- 如何修复?
环境描述
静态资源目录:
/data1/web_static/test_file
正常静态资源文件:
/data1/web_static/test_file/index.html
<html lang="zh-CN"><head> Hello. </head>
直接上层静态资源1(目录穿越后验证): /data1/web_static/test.html
<html lang="zh-CN"><head> Bravo! </head>
隔级上层静态资源2(目录穿越后验证): /data1/test2.html
<html lang="zh-CN"><head> Aloha! </head>
Nginx配置
server {
listen 80;
server_name alias-test.nestealin.com;
charset utf-8;
access_log logs/alias.nestealin.com.access.main.log main;
error_log logs/alias.nestealin.com.error.log error;
location /file {
alias /data1/web_static/test_file/ ;
}
location / {
add_header Content-Type application/json ;
return 200 '{"remote_addr":"$remote_addr","remote_port":"$remote_port","clientRealIp":"$clientRealIp","time_local":"$time_local"}';
}
}
Nginx进程运行用户
- 主进程为 root 用户
- worker进程为 www 用户
# ps -ef | grep nginx root 643 1 0 Jul07 ? 00:00:00 nginx: master process ../../sbin/nginx www 8513 643 0 12:45 ? 00:00:00 nginx: worker process www 8514 643 0 12:45 ? 00:00:00 nginx: worker process
场景复现
在如下配置中设置目录别名时 /file
配置为 /data1/web_static/test_file/ 的别名,那么当我们访问 /file../
时,nginx实际处理的路径时 /data1/web_static/test_file/../
,从而实现了穿越目录。
正常请求
访问 http://alias-test.nestealin.com/file/index.html
请求日志 $request
: GET /file/index.html HTTP/1.1
尝试穿越至直接上层
访问 http://alias-test.nestealin.com/file../test.html
成功
- 请求日志
$request
:"GET /file../test.html HTTP/1.1
尝试穿越至隔级上层
访问 http://alias-test.nestealin.com/file../../test.html
跳转至默认 location
- 请求日志
$request
:GET /test2.html HTTP/1.1
穿越后目录用户验证
将穿越后目标 html 文件 修改属主权限为 root 用户只读
chmod 400 /data1/web_static/test.html
chown root.root /data1/web_static/test.html
# 验证权限
# ll /data1/web_static/test.html
-r-------- 1 root root 45 Jul 7 12:51 /data1/web_static/test.html
尝试访问目录穿越文件 http://alias-test.nestealin.com/file../test.html
提示 403 。
修改属主权限为 www 用户只读
# chown www.www /data1/web_static/test.html
# ll /data1/web_static/test.html
-r-------- 1 www www 45 Jul 7 12:51 /data1/web_static/test.html
尝试访问目录穿越文件 http://alias-test.nestealin.com/file../test.html
访问成功 。
所以,执行目录文件读取的均为 Nginx 的 worker 进程,符合预期。
修复方式
将 /file
这个 location 指令闭环即可。
location /file/ {
alias /data1/web_static/test_file/ ;
}
验证常规页面访问 http://alias-test.nestealin.com/file/index.html
正常,常规页面访问未受影响。
验证穿越页面访问 http://alias-test.nestealin.com/file../test.html
符合预期,跳转至默认 location ,漏洞修复。
小结
1. 目录穿越如何产生/复现/实现原理?
由于 location 中目标路径未闭合导致相对路径穿越
location /file {
alias /data1/web_static/test_file/ ;
}
2. 实现目录穿越后,对应的相对目录是什么?
目录穿越后,是 Alias 目标目录的上一层,并且只能穿越一层目录。
3. 如何修复?
闭合 location 路径即可。
location /file/ {
alias /data1/web_static/test_file/ ;
}
4. 危害程度
- 目标路径是否有其它敏感资源
- 相对目录是否均为 Nginx worker 进程可读
- 如果开了
autoindex
会将目录结构直接暴露在他人之下 - 复杂用法下,同样要注意执行
rewrite
、try_files
时是否会触及该漏洞