WEB] PHP Serialization Vulnerability

노션으로 옮김·2020년 4월 8일
1

skills

목록 보기
20/37
post-thumbnail

개요

PHP serialization 취약점에 대해서 다시 접하게 되었다. 관련된 내용을 찾아보니 그 내용이 간단하지만은 않아 따로 정리하게 되었다.


PHP Serialization

PHP에는 serialize라는 기능이 존재한다.
데이터를 직렬화하여 저장하거나, 전달하는 등 관리측면에서 효율성을 얻기 위해 만들어졌다.

사용되는 함수를 확인해보자.

php document - serialize

serialize ( mixed $value ) : string

인자로 전달되는 값을 직렬화시켜 문자열 형태로 반환한다.

value

The value to be serialized. serialize() handles all types, except the resource-type and some objects (see note below).

인자는 일부 오브젝트, 리소스타입을 제외하고 모든 유형이 전달될 수 있다고 한다.

예제

데이터를 직렬화시킨 값들의 유형을 살펴보자.

String
s:size:value;

Integer
i:value;

Boolean
b:value; (does not store "true" or "false", does store '1' or '0')

Null
N;

Array
a:size:{key definition;value definition;(repeated per element)}

Object
O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}

Vulnerability

이런 직렬화 기능이 왜 문제가 되는 것일까?

직렬화 기능자체에는 문제가 없다.
직렬화 기능이 수행될 때 자동적으로 실행되는 magic method에서 취약점이 발생한다.

Magic Method

magic method란 특정 PHP events에 대응해 자동실행하여 기능을 수행하는 함수를 말한다.
__로 시작하며, 생성자나 소멸자의 기능을 하여 객체가 생성되고 소멸될 때 실행되는 __construct, __destruct 도 이에 해당한다.

https://lornajane.net/posts/2012/9-magic-methods-in-php
자세한 종류는 링크를 확인하자.

Object Injection

오브젝트는 클래스가 인스턴스화된 객체를 말한다.

안에는 그 오브젝트의 메소드, 변수 등 관련된 값이 포함되어있다.

serialize로 인해 이런 오브젝트 값을 직렬화시켜 외부에 전달하거나 전달받아 관련된 처리를 하는 형태의 코드를 작성할 수 있게 되었다.

하지만 이런 구조의 웹서버에 변조된 오브젝트를 전달한다면?

웹서버는 조작된 값을 그대로 받아 의도하지 않은 데이터나 코드를 실행할 것이다.

이게 바로 phpserialize에 의해 발생할 수 있는 Object Injection 취약점이다.

예제

오브젝트 인젝션을 활용해서 데이터 변조, 코드 인젝션 등 다양한 악의적인 행동을 유발할 수 있다.

OWASP에 나와있는 몇가지 예제를 이용해 살펴보겠다.

데이터 변조

class Example1
{
   public $cache_file;

   function __construct()
   {
      // some PHP code...
   }

   function __destruct()
   {
      $file = "/var/www/cache/tmp/{$this->cache_file}";
      if (file_exists($file)) @unlink($file);
   }
}

// some PHP code...

$user_data = unserialize($_GET['data']);

// some PHP code...

Example1이라는 클래스가 선언되어있고 GET파라미터로 데이터를 전달받아 unserialize()을 실행한다.

만약 다음의 데이터를 전달한다면

http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}

cache_file에 내가 설정한 ../../index.php라는 값이 저장될 것이다.

코드 인젝션

class Example2
{
   private $hook;

   function __construct()
   {
      // some PHP code...
   }

   function __wakeup()
   {
      if (isset($this->hook)) eval($this->hook);
   }
}

// some PHP code...

$user_data = unserialize($_COOKIE['data']);

// some PHP code...

hook 변수의 값이 __wakeup()이 실행될 때 코드로서 실행된다.
__wakeup()unserialize()가 실행될 때 trigger되는 magic method이다.

내가 조작된 hook이 포함되어있는 오브젝트를 인젝션 한다면 unserialize할 때 __wakeup()이 실행되면서 내가 조작한 코드가 실행될 것이다.

GET /vuln.php HTTP/1.0
Host: testsite.com
Cookie: data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
Connection: close

다른 예제들도 같은 방식을 이용하는 것이다.
또한, 위에서는 변수값만 변조했지만 대상을 함수로 바꾼다면 변조된 함수를 실행시킬 수 있을 것이다.


부록

phar

phar에서도 직렬화된 데이터를 사용하는 구간이 있고 같은 방식의 취약점을 확인할 수 있다고 한다.

https://www.hahwul.com/2018/11/phar-php-deserialization-vulnerability.html


참조

https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
: Object Injection 설명

https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection
: OWASP

0개의 댓글