Nginxのalias traversalについて

Nginxのalias traversalとは

Nginxではaliasディレクティブを使って locationディレクティブで指定したURIのパスをファイルシステム上のパスに対応させることができます。 以下の例のようにconfigを書くと、/var/www/app/static/以下にあるファイルに/static/ファイル名のようなパスでアクセスできます。

location /static {
    alias /var/www/app/static/;
}

しかし、このようにlocationのパスの末尾が/で終わっていない場合、..を使うことで、開発者が意図していない上位のディレクトリへのアクセスが可能になってしまいます。 このケースだと、/static../setting.pyのようにパスを指定することで、aliasで指定したディレクトリより上位のディレクトリである/var/www/app以下のsetting.pyにアクセスすることができます。これがNginxのalias traversalです。

以下のようにlocationで指定するパスの末尾に/を書いておくことで防ぐことができます。

location /static/ {
    alias /var/www/app/static/;
}

Nginxは、alias traversalを脆弱性として扱っておらず、Nginx側で修正されることはありません。

初出は2016年のHCTFの問題のようです。 http://momomoxiaoxi.com/2016/11/29/HCTF2016/#10%E4%BD%A0%E6%B2%A1%E8%B5%B0%E8%BF%87%E7%9A%84%E5%A5%97%E8%B7%AF

ぼくはCODEBLUE 2018でorangeさんのBreaking Parser Logic - Take Your Path Normalization Off and Pop 0days Outを聞いて知りました。 ちなみに、この発表はDEFCON26やBlack Hat 2018やHack.lu 2018でも行われています。ぼくもつよいexploit手法を見つけたら海外カンファレンス巡業したい。

実例

hackeroneでは以下のようなものが見つかっていました。

やってみる

alias traversalの問題があるNginxサーバーを立てることができるDockerfileを書きました。

github.com

このリポジトリは以下のファイルから構成されています。

nginx-alias-traversal-sample$ tree .
.
├── Dockerfile
├── LICENSE.md
├── README.md
├── index.html
├── screenshots
│   ├── flag.png
│   └── top.png
└── vulnerable.conf

1 directory, 7 files
$ docker build -t nginx-traversal .
$ docker run -d -p 3000:80 nginx-traversal:latest

上のコマンドでdocker runすると、http://localhost:3000でNginxサーバーが動きます。

f:id:TAKEmaru:20190306124807p:plain

http://localhost:3000/static/がalias traversal可能なパスになっています。

f:id:TAKEmaru:20190306124826p:plain

alias traversalを利用して、aliasで指定されたディレクトリの一つ上の階層にあるflagを読み出すことができました。

f:id:TAKEmaru:20190306124902p:plain

発見するのに使えるツール

Nginxのconfigにアクセスすることができる開発者側であれば、 gixyというNginxのconfigの静的解析ツールを使って、alias traversalを検出することができます。

github.com

$ gixy vulnerable.conf 

==================== Results ===================

>> Problem: [alias_traversal] Path traversal via misconfigured alias.
Description: Using alias in a prefixed location that doesn't ends with directory separator could lead to path traversal vulnerability. 
Additional info: https://github.com/yandex/gixy/blob/master/docs/en/plugins/aliastraversal.md
Pseudo config:

server {
    server_name localhost;

    location /static {
        alias /var/www/app/static/;
    }
}

==================== Summary ===================
Total issues:
    Unspecified: 0
    Low: 0
    Medium: 0
    High: 1

また、脆弱性を発見するペンテスターはBurpの拡張を使って検出することができます。

github.com