Đã đăng vào thg 11 18, 2019 8:41 SA 10 phút đọc 10 phút đọc
Quá trình Serialization và Deserialization đối tượng
- Serialization là quá trình chuyển đổi trạng thái thông tin của một đối tượng thành một hình thức có thể được lưu trữ hoặc truyền đi. Các thông tin chuyển đổi có thể được lưu trữ trên một đĩa. Trong quá trình truyền qua mạng, nó có thể ở dạng byte, XML, JSON,…
- Deserialization là quá trình ngược lại của quá trình serialization, thực hiện lấy dữ liệu từ các định dạng có cấu trúc, khôi phục thông tin theo byte, XML, JSON,... thành các đối tượng .
- Trong ngôn ngữ PHP, hàm hỗ trợ Serialization đối tượng là
serialize[ ]
. Input của hàm này là một object và output của hàm sẽ là một chuỗi lưu object đó, cụ thể sẽ lưu class của object và các thuộc tính của object.
- Ở đây, khỏi tạo một class Student với các thuộc tính $name và $age, cùng với những phương thức
setName[ ]
,getName[ ]
,setAge[ ]
, getAge[ ], và hai magic method__sleep[ ]
,__wakeup[ ]
. Tiếp theo khởi tạo một object $student và khởi tạo giá trị thuộc tính cho object $student thông qua hai phương thứcsetName[ ]
, vàsetAge[ ]
. - Dạng của object trước khi được serialize:
- Tiếp theo, gọi hàm serialize[ ], tham số truyền vào phương thức là một object, ở truyền vào object $student. Hàm serialize[ ] sẽ trả về một chuỗi lưu object được truyền vào. Chuỗi này sẽ được lưu vào $serializeStudent. Dạng của object sau khi được serialize:
Quá trình Deserialization đối tượng
- Trong ngôn ngữ PHP, hàm hỗ trợ Deserialization đối tượng là
unserialize[ ]
. Input của phương thức này là một chuỗi đại diện cho object. Output là object được xây dựng lại từ chuỗi truyền vào hàmunserialize[ ]
.
- Ở đây, sử dụng biến $serializeStudent truyền vào hàm
unserialize[ ]
để xây dựng lại object từsetName[ ]
1 và lưu vào biếnsetName[ ]
2. Sau đây là kết quả:
- Kết quả nhận được sau khi
setName[ ]
3 từ biếnsetName[ ]
1 giống với dạng object trước khi đượcsetName[ ]
5.
Giới thiệu về lỗ hổng Deserialization
- Trong TOP10 OWASP 2017, OWASP xếp lỗ hổng này ở vị trí thứ 8: Top 10-2017 A8- Insecure Deserialization. Ứng dụng mắc phải lỗ hổng này khi không kiểm tra dữ liệu đầu vào trước khi thực hiện deserialize. Dữ liệu không đúng định dạng hoặc dữ liệu không mong muốn có thể bị lợi dụng để thay đổi luồng xử lý của ứng dụng, gây ra hậu quả có thể là tấn công từ chối dịch vụ hoặc thực thi mã tùy ý.
- Lỗ hổng Deserialization trong PHP hay với một tên gọi khác là PHP Object Injection có thể giúp kẻ tấn công thực hiện các loại tấn công khác nhau, chẳng hạn như
setName[ ]
6,setName[ ]
7,setName[ ]
8 ,setName[ ]
9, tùy thuộc vào ngữ cảnh. Lỗ hổng này xảy ra khi dữ liệu đầu vào không được kiểm tra đúng cách trước khi được chuyển đến hàm PHPgetName[ ]
0. Với các lớp phương thức Magic methodgetName[ ]
1 ,getName[ ]
2,getName[ ]
3 cùng với cácgetName[ ]
4 giúp cho đối tượng tấn công thực thi lỗi này. - Năm 2010, Stefan Ess có bài thuyết trình của tại hội nghị BlackHat đã đề cập đến những nguy cơ tận dụng lỗi
getName[ ]
5 với nền tảng được xây dựng trên ngôn ngữ PHP là WordPress sử dụnggetName[ ]
6 vàgetName[ ]
0. Dựa vào đó, năm 2013, Tom Van Goethem, tiến sỹ tại Bỉ đã tìm được lỗ hổnggetName[ ]
5 trên nền tảnggetName[ ]
9 [version 3.6.1].Cũng trong năm 2013, một nền tảng khác làsetAge[ ]
0cũng bị lỗ hổng tương tựsetAge[ ]
1 Đến năm 2015, Johannes Dahse , tiến sĩ người Đức đã tìm ra lỗ hổnggetName[ ]
5 ở một phần mềm thương mại điện tử được xây dựng trên ngôn ngữsetAge[ ]
3 làsetAge[ ]
4 . Theo sau đó, chứng kiến sự gia tăng về lỗ hổngsetAge[ ]
5 trên nhiều ứng dụng web cho phép cả tấn công thi mã từ xasetAge[ ]
6và quản lý máy tính của nạn nhân từ xa. Trong những năm gần đây có khoảng 60 lỗ hổngsetAge[ ]
5 có thể thực thi mã từ xa, hơn 80 lỗ hổng đã được báo cáo. Năm 2017,setAge[ ]
8 xếp lỗ hổngsetAge[ ]
5 ở vị trí thứ__sleep[ ]
0 trong top__sleep[ ]
1. Những số liệu thống kê trên cho thấy sự nguy hiểm cũng như phổ biến của lỗ hổng trên nền tảngsetAge[ ]
3.
Kỹ thuật Property Oriented Programming
- Các lỗ hổng liên quan đến bộ nhớ như tràn bộ đệm, lỗi sai định dạng, đã được biết đến từ lâu. Các phương pháp bảo vệ như
__sleep[ ]
3 và__sleep[ ]
4 được triển khai rộng rãi để chống lại việc khai thác các lỗ hổng trên. Tuy nhiên, kẻ tấn công có thể sử dụng các kỹ thuật khác để vượt qua lớp phòng thủ trên, ví dụ như kỹ thuật__sleep[ ]
5. Các kỹ thuật__sleep[ ]
5 như__sleep[ ]
7,__sleep[ ]
8và__sleep[ ]
9 có thể vượt qua một số biện pháp phòng thủ trên. Với__wakeup[ ]
0và__wakeup[ ]
1, kẻ tấn công có thể sử dụng lại các đoạn mã nguồn trong chương trình [được gọi là__wakeup[ ]
2] và kết hợp chúng lại với nhau để xây dựng thành__wakeup[ ]
3__wakeup[ ]
4]. - Vào năm 2009, Esser đã trình diễn kỹ thuật
__sleep[ ]
5 tồn tại trên ứng dụngsetAge[ ]
3. Cụ thể, anh đã giới thiệu khả năng tấn công chèn đối tượng__wakeup[ ]
7 mà kẻ tấn công có thể sửa đổi các thuộc tính của đối tượng. Do đó, dữ liệu và luồng điều khiển của ứng dụng có thể bị thay đổi. Và anh cũng là người đã đặt ra thuật ngữ__wakeup[ ]
8[__wakeup[ ]
9]. __wakeup[ ]
8 [__wakeup[ ]
9] là khi chúng ta có thể điều khiển thuộc tính của đối tượng và có thể làm ảnh hưởng đến luồng thực thi của chương trình. MộtsetName[ ]
2 là đoạn mã mà chúng ta có thể làm ảnh hưởng đến thuộc tính của một số đối tượng. Đây chính là một__wakeup[ ]
0 cấp cao [một kỹ thuật được sử dụng trong khai thác tham nhũng bộ nhớ]. Thay vìsetName[ ]
4 đẩy giá trị lên ngăn xếp, thìsetName[ ]
2 cho phép chúng ta ghi một số dữ liệu vàosetName[ ]
6. Tấn công__sleep[ ]
5 cũng có thể xảy ra dựa trên các đoạn mã đã có sẵn, được gọi làsetName[ ]
8t, được thực thi để thực hiện một hành động không mong muốn như thực thi lệnh hệ thống tùy ý. Quá trìnhsetAge[ ]
5 có thể đặt các giá trị của biến tùy ý, cho phép kẻ tấn công có thể kiểm soát một số dữ liệu. Điều này cũng cho phép kẻ tấn công sử dụng mộtsetAge[ ]
0 để gọi mộtsetAge[ ]
0 thứ hai, vì các phương thức thường được gọi trên các đối tượng và được lưu trữ cho các biến của thực thể. Khi một loại cácsetAge[ ]
0 liên kết với nhau, nó được làsetAge[ ]
3.- Một điểm quan trọng ở đây là khai thác lỗ hổng
setAge[ ]
4 không phải là gửi các đoạnsetAge[ ]
5 lên chương trình để thực thi. Chúng ta chỉ đơn giản là gửi thuộc tính của các lớp mà máy chủ đã có biết để thực hiện tác thao tác mã đã có, liên quan đến các thuộc tính đó. Để khai thác thành công lỗ hổngsetAge[ ]
5 cần có 2 điều kiện:- Điểm đầu vào, là nơi mà kẻ tấn công gửi các dữ liệu đã được
setName[ ]
5 đến mục tiêu và mục tiêu sẽ thực hiệnsetName[ ]
3 đoạn dữ liệu này. - Kẻ tấn công có thể thao túng được một hoặc nhiều đoạn mã thông qua quá trình
setName[ ]
3.
- Điểm đầu vào, là nơi mà kẻ tấn công gửi các dữ liệu đã được
- Ví dụ, có hai điều kiện tiên quyết mà một ứng dụng
setAge[ ]
3 cần phải đáp ứng để có thể sử dụng__wakeup[ ]
9 để khai thác lỗ hổnggetName[ ]
5. Đầu tiên, có ít nhất mộtunserialize[ ]
3 được gọi lúc ứng dụng đang chạy, được xác định đúng trong lớp thuộc đối tượng mà kẻ tấn công muốnunserialize[ ]
4. Thứ hai, lớp được chọn cần phải được load trong phạm vi của lệnh gọigetName[ ]
0, và kẻ tấn công có thể điều khiển được đầu vào của hàmgetName[ ]
0. - Trong kịch bản dưới đây, Có 3
__wakeup[ ]
2 được kết hợp để tạo thành lỗ hổng xoá file tuỳ ý.
- Lỗ hổng
unserialize[ ]
8tồn tại ở dòngunserialize[ ]
9, nơi mà người dùng có thể nhập dữ liệu đầu vào và chương trình thực hiệnsetName[ ]
3. Ở dòngunserialize[ ]
1,unserialize[ ]
2 kẻ tấn công đã chèn một đối tượngunserialize[ ]
3 với thuộc tínhunserialize[ ]
4 được đặt là một đối tượng của lớpunserialize[ ]
5. Thuộc tínhunserialize[ ]
6 được đặt với nội dung làunserialize[ ]
7. - Khi ứng dụng kết thúc, đối tượng database đã được chèn sẽ được thực thi nhờ hàm
getName[ ]
2 tự động gọi. Bởi vì thuộc tính handle đã được chèn thành đối tượng lớpunserialize[ ]
5, gọi đến hàmsetName[ ]
00 của lớpsetName[ ]
01. Trong hàmsetName[ ]
00 sẽ gọi đến phương thứcsetName[ ]
03 được kế thừa ở lớpunserialize[ ]
5. Ở đây, vớiunserialize[ ]
6 màsetName[ ]
06truyền vào sẽ được chương trình xoá file đó. Kết quả là filesetName[ ]
07đã bị xoá.
Tobe continue...
All rights reserved