VirtualPath
라이브러리는 파일 시스템을 쿼리하지 않고도 경로를 정규화하고 디렉터리 탐색 공격을 방지합니다.
rayne/virtual-path
설치하려면 종속성 관리자 Composer를 사용하는 것이 좋습니다.
composer require rayne/virtual-path
VirtualPath
클래스는 파일 시스템을 쿼리하지 않고 절대 virtual path 에 대한 입력을 정규화합니다. 또한 디렉터리 탐색 공격을 탐지하고 플래그를 지정합니다.
JailedPath
클래스는 VirtualPath
활용하여 실제 파일 작업에 사용할 수 있는 안전한 경로를 구축합니다. 정규화는 사용자가 입력한 모든 경로에 대한 가상 루트로 사용되는 path라는 jail
기준으로 수행됩니다. JailedPath
파일 시스템을 쿼리하지 않으므로 로컬, 원격 또는 가상 경로 작업에 적합합니다.
자세한 내용은 구현 세부정보 섹션을 읽어보세요.
TL;DR 의심스러운 경우 JailedPath
클래스를 사용하세요.
JailedPath
이 예에서 웹사이트 방문자는 상대 경로를 GET
매개변수로 지정하여 로컬 디렉터리 /test
에서 모든 파일을 다운로드할 수 있습니다. 사용자가 디렉토리 순회 공격으로 디렉토리를 떠나는 것을 방지하기 위해 JailedPath
/test
와 함께 가상 루트 디렉토리로 사용됩니다.
<?php
use Rayne VirtualPath JailedPath ;
$ jailedPath = new JailedPath ( ' /test ' , $ _GET [ ' path ' ] ?? '' );
if ( $ jailedPath -> hasJailbreakAttempt ()) {
// Log jailbreak attempt, ban user, …
return ;
}
if ( is_file ( $ jailedPath -> getAbsolutePath ())) {
@ readfile ( $ jailedPath -> getAbsolutePath ());
}
다음 표에서는 사용자 정의 경로가 정규화되는 방식과 가상 루트를 기준으로 해석되는 방식을 보여줍니다.
사용자 입력 | hasJailbreakAttempt() | getAbsolutePath() | getRelativePath() |
---|---|---|---|
빈 문자열 | false | /test | 빈 문자열 |
. | false | /test | 빈 문자열 |
a.png/../b.png | false | /test/b.png | b.png |
/a/./b | false | /test/a/b | a/b |
.. | true | /test | 빈 문자열 |
../example | true | /test/example | example |
../etc/passwd | true | /test/etc/passwd | etc/passwd |
정렬 | true | /test | 빈 문자열 |
VirtualPath
고정 접두사 또는 JailedPath
의 설탕 코팅이 필요하지 않은 경우 VirtualPath
경로 정규화에 사용되는 클래스이므로 충분합니다. VirtualPath
입력을 정규화하고 신뢰할 수 있는( /
로 시작하는 정규화된) 경로와 신뢰할 수 없는(아마도 악의적인 사용자 입력의 문자열 표현) 경로를 제공합니다.
이전 예제는 VirtualPath
인스턴스( (string)
캐스팅 가능)가 가상 루트 디렉터리에 추가될 때 VirtualPath
사용하여 쉽게 다시 만들 수 있습니다.
<?php
use Rayne VirtualPath VirtualPath ;
$ path = new VirtualPath ( $ _GET [ ' path ' ] ?? '' );
$ absolutePath = ' /test ' . $ path ;
사용 시나리오에 따라 원래 입력이 신뢰할 수 없는 경우에도 정규화된 신뢰할 수 있는 경로로 작업하는 것이 유용한 경우가 있습니다. 예를 들어 명시적으로 상대 경로를 지원하고 실수로 virtual path 외부의 파일에 액세스하려고 할 때 사용자에게 의심의 이점을 제공하는 경우입니다.
참고 : VirtualPath
앞에 /
붙은 정규화된 경로를 반환합니다. 파일 작업 시 신뢰할 수 있는 경로를 접두사로 추가하는 것이 좋습니다(현재 섹션의 코드 예제 참조). 그렇지 않으면 파일 시스템의 루트와 관련된 파일이 참조됩니다. 접두사를 추가하는 것을 잊지 않으려면 실제 파일로 작업할 때 대신 JailedPath
클래스를 사용하십시오.
입력 | isTrusted() | getTrustedPath() | getUntrustedPath() |
---|---|---|---|
정렬 | false | / | 빈 문자열 |
빈 문자열 | true | / | 빈 문자열 |
../articles | false | /articles | ../articles |
tags/../../articles | false | /articles | tags/../../articles |
tags/../articles | true | /articles | tags/../articles |
../etc/passwd | false | /etc/passwd | ../etc/passwd |
/etc/passwd | true | /etc/passwd | /etc/passwd |
etc/passwd | true | /etc/passwd | etc/passwd |
순수 가상 정규화된 경로를 사용하면 다음과 같은 다양한 이점이 있습니다.
파일 시스템을 쿼리하지 않고 경로 정규화가 수행됩니다.
virtual path 범위 밖의 파일에 대한 타이밍 공격을 위조하는 것은 불가능합니다.
디렉토리 순회를 특정 디렉토리와 그 하위 디렉토리로 제한하기 위해 복잡한 비교가 필요하지 않습니다.
오직 .
, ..
, (
/
로 정규화됨) 및 /
경로 정규화를 위해 해석됩니다.
예상치 못한 정보 유출 없음 ~
다른 라이브러리에서 볼 수 있는 확장
VirtualPath
구현은 제어 문자와 유니코드를 해석, 변경 또는 제거하지 않습니다.
일부 시스템에서는 디렉터리 및 파일 경로에 제어 문자가 포함될 수 있습니다.
제어 문자를 제거하는 것은 라이브러리의 범위를 벗어납니다.
저장소 복제
git clone https://github.com/rayne/virtual-path.git
개발 종속성 설치
composer install --dev
테스트 실행
composer test