2017.W27 - Path Traversal - 資安

Table of Contents

2017.W27 - Path Traversal
> 重新設計輪子當然可以 只要妳開的車裝上你的輪子

## 前言 ##
最近在處理公司上的事情 一直覺得重新造輪子是個不錯的概念

但是也不要在公司產品上用你設計輪子啊 QQ

## 內容 ##
Path Traversal 或者稱為 Directory Travelsal 是一系列安全性的漏洞概念

主要是處理檔案路徑時不正確 造成存取的檔案超出設計者的預期

從 CWE 列表中可以從 CWE-21 - Pathname Traversal and Equivalence Errors[0] 開始

引起各種 Path Travelsal 的問題

主要的問題都會回歸到所謂的 CWE-20 Improper Input Validateion[1]

也就是不正確的使用者輸入驗證


簡單的例子:有一個 web service 會提供 上傳檔案 與 自動轉檔 功能

轉檔功能操作時 需要指定檔案的路徑

一個基本的驗證則是快速判斷檔案路徑中是否包含 . 跟 .. (Linux-Based)

但是這樣的假設也不盡正確 原因是這樣就代表不允許使用 ..abc 這樣的名稱

因此一個聰明的概念就是利用 / 來切割檔案名稱

並且逐一檢查是否包含 . 或者 ..



然而一個優秀的 c/c++ programmer 應該會知道 glibc 會提供 realpath 這個函數

根據 man realpath 可以得到他的主要描述

returns the canonicalized absolute pathname

在下面的描述中的第一段話更明確的表示他的主要功能

The realpath() function resolves all symbolic links, extra ``/'' characters,
and references to /./ and /../ in file_name.

這代表用 realpath 處理過後的檔案已經不會包含任何 . .. 跟 symbolic link

這些有機會跳轉的符號



從 glibc 的 realpath 的 source code[2] 來看

可以看到 __realpath 主要有以下幾個判斷

1. 輸入的檔名是否為空
2. 當下路徑不存在則報錯
3. 相對路徑則自動帶入當下路徑 getcwd
4. 依序處理每一個 / 切割的元素
4.1 無視連續的 /
4.2 無視 . 的元素
4.3 .. 則跳到上一個資料夾 已經是 / 則無視
4.4 透過 stat 判斷檔案是否檔案、資料夾是否存在
4.5 如果是 symbolic link 則透過 readlink 獲得真實路徑


透過 realpath 的好處在於你可以獲得一個乾淨的絕對路徑

之後就能透過這個路徑 判斷目的地是否在允許的路徑之下



至於為什麼不需要重新造輪子 原因在於這個問題不是第一天發現

因此在這個平台下這個方式會經過各種優化

像是在這篇文章中[3] 提到的 GNU 的 yes 指令快到突破天際 (12.8 GB/s)

這就是針對平台已經特殊優化的結果了

再重新設計一個 yes 除非有特殊的需求

不然還是乖乖用經過千錘百鍊的版本吧!




[0]: https://cwe.mitre.org/data/definitions/21.html
[1]: https://cwe.mitre.org/data/definitions/20.html
[2]: https://github.com/lattera/glibc/blob/master/stdlib/canonicalize.c
[3]: https://www.reddit.com/r/unix/comments/6gxduc/how_is_gnu_yes_so_fast/

--

All Comments

Emily avatarEmily2017-07-09
12.8GB/S AS FUK