복붙노트

PHP에서는 디렉토리 탐색을 방지하지만 경로는 허용합니다.

PHP

PHP에서는 디렉토리 탐색을 방지하지만 경로는 허용합니다.

나는 기본 경로 / whatever / foo /

과 $ _GET [ '경로']는 그 경로와 관련이 있어야합니다.

그러나 어떻게하면 디렉터리 트래버 설을 허용하지 않고이 작업을 수행 할 수 있습니까?

예.

/\.\.|\.\./

제대로 필터링되지 않습니다.

해결법

  1. ==============================

    1.글쎄, 하나의 옵션은 실제 경로를 비교하는 것입니다 :

    글쎄, 하나의 옵션은 실제 경로를 비교하는 것입니다 :

    $basepath = '/foo/bar/baz/';
    $realBase = realpath($basepath);
    
    $userpath = $basepath . $_GET['path'];
    $realUserPath = realpath($userpath);
    
    if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) {
        //Directory Traversal!
    } else {
        //Good path!
    }
    

    기본적으로 realpath ()는 제공되는 경로를 실제 하드 실제 경로 (symlinks, .., /, /, // 등등)를 해결합니다 ... 그래서 실제 사용자 경로가 실제 기본 경로로 시작하지 않으면, 그것은 순회하는 것을 시도하고있다. realpath의 출력에는와 같은 "가상 디렉토리"가 없습니다. 또는 .....

  2. ==============================

    2.ircmaxell의 대답이 정확하지 않았습니다. 나는 그 해결책을 여러 발췌 문장에서 보았지만 realpath ()의 출력과 관련된 버그가있다. realpath () 함수는 뒤에 오는 디렉토리 분리자를 제거하므로 다음과 같은 연속 된 두 개의 디렉토리를 상상해보십시오.

    ircmaxell의 대답이 정확하지 않았습니다. 나는 그 해결책을 여러 발췌 문장에서 보았지만 realpath ()의 출력과 관련된 버그가있다. realpath () 함수는 뒤에 오는 디렉토리 분리자를 제거하므로 다음과 같은 연속 된 두 개의 디렉토리를 상상해보십시오.

    /foo/bar/baz/
    
    /foo/bar/baz_baz/
    

    realpath ()가 마지막 디렉토리 분리자를 제거하므로 $ _GET [ 'path']가 "../baz_baz"와 같으면 메서드가 "good path"를 반환합니다.

    strpos("/foo/bar/baz_baz", "/foo/bar/baz")
    

    아마도:

    $basepath = '/foo/bar/baz/';
    $realBase = realpath($basepath);
    
    $userpath = $basepath . $_GET['path'];
    $realUserPath = realpath($userpath);
    
    if ($realUserPath === false || strcmp($realUserPath, $realBase) !== 0 || strpos($realUserPath, $realBase . DIRECTORY_SEPARATOR) !== 0) {
        //Directory Traversal!
    } else {
        //Good path!
    }
    
  3. ==============================

    3.../ 또는 likes와 같은 패턴을 확인하는 것으로는 충분하지 않습니다. 예를 들어 "% 2e % 2e % 2f"로 인코딩되는 "../"을 가져옵니다. 디코드 전에 패턴 검사가 발생하면이 통과 시도를 놓치게됩니다. 해커가 특히 인코딩 된 문자열을 사용할 때 패턴 검사기를 우회 할 수있는 몇 가지 다른 트릭이 있습니다.

    ../ 또는 likes와 같은 패턴을 확인하는 것으로는 충분하지 않습니다. 예를 들어 "% 2e % 2e % 2f"로 인코딩되는 "../"을 가져옵니다. 디코드 전에 패턴 검사가 발생하면이 통과 시도를 놓치게됩니다. 해커가 특히 인코딩 된 문자열을 사용할 때 패턴 검사기를 우회 할 수있는 몇 가지 다른 트릭이 있습니다.

    필자는 ircmaxwell에서 제시하는 것처럼 realpath ()와 같은 것을 사용하여 절대 경로로 모든 경로 문자열을 정규화하여 이들을 중지시키는 데 가장 성공했습니다. 그래야만 미리 정의한 기본 경로와 일치시켜 순회 공격을 검사하기 시작합니다.

  4. ==============================

    4.당신은 모든 정규식을 제거하기 위해 정규 표현식을 사용하려고 시도 할 수 있습니다. 그러나 훨씬 좋은 일을 할 수있는 PHP에 내장 된 멋진 함수가 있습니다 :

    당신은 모든 정규식을 제거하기 위해 정규 표현식을 사용하려고 시도 할 수 있습니다. 그러나 훨씬 좋은 일을 할 수있는 PHP에 내장 된 멋진 함수가 있습니다 :

    $ page = basename (realpath ($ _ GET));

    basename - 경로에서 모든 디렉토리 정보를 제거합니다. ../pages/about.php는 about.php가됩니다.

    realpath - 파일에 대한 전체 경로를 반환합니다. about.php는 파일이 존재하는 경우에만 /home/www/pages/about.php가됩니다.

    결합하면 파일 이름 만 반환하지만 파일이있는 경우에만 반환됩니다.

  5. ==============================

    5.사용자가 디렉토리를 가로 질러 통과하지 못하게한다는 뜻인가요?

    사용자가 디렉토리를 가로 질러 통과하지 못하게한다는 뜻인가요?

    자신의 PHP가 디렉토리를 탐색하는 것을 막으려면 PHP를 제대로 작동시켜야합니다.

    사용자를 멈추게하려면 .htaccess 파일을 수정해야합니다.

    Options -Indexes
    

    (이 모든 것은 사용자에 대해 말하는 것으로 가정합니다)

  6. from https://stackoverflow.com/questions/4205141/preventing-directory-traversal-in-php-but-allowing-paths by cc-by-sa and MIT license