小心Alias引发的静态资源目录穿越


背景

Nginx是一个高性能的HTTP和反向代理服务器,经常被做为反向代理,动态的部分被proxy_pass传递给后端端口,而静态文件需要Nginx来处理。

而本次提及的漏洞是出现在服务器的静态文件中。

  • 什么是 Nginx alias 目录穿越?

    如果静态文件存储在 /home/ 目录下,而该目录在url中名字为files,那么就需要用alias设置目录的别名。

    Nginx在配置别名(Alias)的时候,如果忘记加 / ,将造成一个目录穿越漏洞。


目的

  1. 目录穿越如何产生/复现/实现原理?
  2. 实现目录穿越后,对应的相对目录是什么?
  3. 如何修复?

环境描述

  • 静态资源目录: /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. 危害程度

  1. 目标路径是否有其它敏感资源
  2. 相对目录是否均为 Nginx worker 进程可读
  3. 如果开了 autoindex 会将目录结构直接暴露在他人之下
  4. 复杂用法下,同样要注意执行 rewritetry_files 时是否会触及该漏洞

文章作者: NesTeaLin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 NesTeaLin !
  目录