hacktricks/pentesting-web/file-inclusion/lfi2rce-via-eternal-waiting.md
2024-02-10 21:30:13 +00:00

8.3 KiB

LFI2RCE를 통한 Eternal waiting

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

기본 정보

기본적으로 PHP에 파일이 업로드되면 (php[a-zA-Z0-9]{6}와 같은 이름의 임시 파일이 /tmp에 생성됩니다. 그러나 일부 도커 이미지에서는 생성된 파일에 숫자가 포함되지 않습니다.

로컬 파일 포함에서 업로드된 파일을 포함시킬 경우 RCE를 얻을 수 있습니다.

기본적으로 PHP는 단일 요청에서 20개의 파일만 업로드 허용합니다 (/etc/php/<version>/apache2/php.ini에 설정됨):

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

또한, 잠재적인 파일 이름의 수는 62*62*62*62*62*62 = 56800235584입니다.

다른 기술들

다른 기술들은 PHP 프로토콜을 공격하는 데에 의존합니다 (경로의 마지막 부분만 제어할 수 있다면 불가능할 것입니다), 파일의 경로를 공개하는 것, 예상 파일을 악용하는 것, 또는 PHP가 세그멘테이션 오류를 일으켜 업로드된 임시 파일이 삭제되지 않도록 하는 것입니다.
이 기술은 제로데이를 찾을 필요 없이 마지막 기술과 매우 유사합니다.

Eternal wait 기술

이 기술에서는 상대 경로만 제어하면 됩니다. 파일을 업로드하고 LFI가 끝나지 않도록 만들면, 업로드된 파일 중 어떤 파일이든 "충분한 시간"을 가지고 브루트 포스를 사용하여 찾을 수 있습니다.

이 기술의 장점:

  • 인클루드 내부의 상대 경로만 제어하면 됩니다
  • nginx나 예상치 못한 수준의 로그 파일 접근이 필요하지 않습니다
  • 세그멘테이션 오류를 일으키기 위해 0데이가 필요하지 않습니다
  • 경로 공개가 필요하지 않습니다

이 기술의 주요 문제점은 다음과 같습니다:

  • 특정 파일이 존재해야 합니다 (더 많을 수도 있음)
  • 말도 안 되는 수의 잠재적인 파일 이름: 56800235584
  • 서버가 숫자를 사용하지 않는다면 총 잠재적인 수는: 19770609664
  • 기본적으로 단일 요청에서 최대 20개의 파일만 업로드할 수 있습니다.
  • 사용된 서버의 병렬 작업자 수의 최대 값
  • 이러한 제한들로 인해 이 공격이 너무 오래 지속될 수 있습니다
  • PHP 요청의 타임아웃. 이상적으로는 영원히 지속되거나 PHP 프로세스를 종료시키지만 업로드된 임시 파일을 삭제하지 않아야 합니다. 그렇지 않으면 이것도 골칫거리가 될 것입니다.

그렇다면, 어떻게 하면 PHP 인클루드를 끝나지 않게 할 수 있을까요? 단순히 파일 **/sys/kernel/security/apparmor/revision**을 인클루드하면 됩니다 (Docker 컨테이너에서는 사용할 수 없습니다 유감스럽게도...).

다음을 호출하여 시도해보세요:

php -a # open php cli
include("/sys/kernel/security/apparmor/revision");

Apache2

기본적으로, Apache는 150개의 동시 연결을 지원합니다. https://ubiq.co/tech-blog/increase-max-connections-apache/에서는 이 숫자를 최대 8000까지 늘릴 수 있다고 합니다. 이 링크를 따라가면 PHP를 사용할 수 있습니다: https://www.digitalocean.com/community/tutorials/how-to-configure-apache-http-with-mpm-event-and-php-fpm-on-ubuntu-18-04.

기본적으로 (내 테스트에서 확인한 대로), PHP 프로세스는 영원히 지속될 수 있습니다.

간단한 계산을 해보겠습니다:

  • 우리는 149개의 연결을 사용하여 웹쉘과 함께 149 * 20 = 2980개의 임시 파일을 생성할 수 있습니다.
  • 그런 다음, 마지막 연결을 사용하여 잠재적인 파일을 **무차별 대입(brute-force)**합니다.
  • 10개의 요청/초의 속도로 계산하면:
  • 56800235584 / 2980 / 10 / 3600 ~= 530시간 (50% 확률로 265시간)
  • (소수점을 제외하고) 19770609664 / 2980 / 10 / 3600 ~= 185시간 (50% 확률로 93시간)

{% hint style="warning" %} 이전 예제에서는 다른 클라이언트를 완전히 DoS 공격하고 있음을 유의하세요! {% endhint %}

Apache 서버가 개선되어 4000개의 연결을 악용할 수 있다면 (최대 연결 수의 절반까지), 3999*20 = 79980 파일을 생성할 수 있으며, 시간은 약 19.7시간 또는 6.9시간 (10시간, 3.5시간 50% 확률)으로 줄어들 것입니다.

PHP-FPM

만약 웹 페이지가 일반적인 Apache의 php 모듈 대신 PHP-FPM을 사용한다면 (웹 페이지의 효율성을 향상시키기 위해 일반적으로 사용됨), 기술을 개선하기 위해 추가로 할 수 있는 작업이 있습니다.

PHP-FPM은 **/etc/php/<php-version>/fpm/pool.d/www.conf**에 있는 request_terminate_timeout 매개변수를 구성할 수 있습니다.
이 매개변수는 PHP 요청이 종료되어야 하는 최대 시간을 나타냅니다 (기본적으로 무한하지만, 매개변수가 주석 처리되면 30초로 설정됨). PHP에 의해 처리되는 요청이 지정된 시간만큼 진행되면 강제로 종료됩니다. 이는 즉, 요청이 임시 파일을 업로드하고 있는 경우, php 처리가 중지되기 때문에 해당 파일이 삭제되지 않을 것입니다. 따라서 요청을 해당 시간 동안 지속시킬 수 있다면, 삭제되지 않는 수천 개의 임시 파일을 생성할 수 있으며, 이는 파일을 찾는 과정을 가속화시키고 모든 연결을 소비하여 플랫폼에 대한 DoS의 가능성을 줄입니다.

따라서, DoS를 피하기 위해, 공격자가 동시에 100개의 연결만 사용하고 php-fmp의 최대 처리 시간인 (request_terminate_timeout**)**이 30초라고 가정해 봅시다. 따라서 1초당 생성될 수 있는 임시 파일의 수100*20/30 = 66.67입니다.

그럼, 공격자가 10000개의 파일을 생성하기 위해 필요한 시간은: **10000/66.67 = 150초**입니다 (100000개의 파일을 생성하기 위한 시간은 25분입니다).

그런 다음, 공격자는 이러한 100개의 연결을 사용하여 무차별 대입(brute-force) 검색을 수행할 수 있습니다. 300개의 요청/초의 속도를 가정한다면, 이를 악용하기 위해 필요한 시간은 다음과 같습니다:

  • 56800235584 / 10000 / 300 / 3600 ~= 5.25시간 (50% 확률로 2.63시간)
  • (100000개의 파일로) 56800235584 / 100000 / 300 / 3600 ~= 0.525시간 (50% 확률로 0.263시간)

네, EC2 중간 크기 인스턴스에서 100000개의 임시 파일을 생성할 수 있습니다:

{% hint style="warning" %} 타임아웃을 트리거하기 위해서는 취약한 LFI 페이지를 포함시키면 충분합니다. 그러면 페이지가 영원한 포함 루프에 들어갑니다. {% endhint %}

Nginx

기본적으로 Nginx는 동시에 512개의 연결을 지원하는 것으로 보입니다 (이 숫자는 개선될 수 있습니다).