Hướng dẫn why is php insecure - tại sao php không an toàn

Hướng dẫn why is php insecure - tại sao php không an toàn

Đã đă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 .

Hướng dẫn why is php insecure - tại sao php không an toàn

Quá trình Serialization đố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.

Hướng dẫn why is php insecure - tại sao php không an toàn

Hướng dẫn why is php insecure - tại sao php không an toàn

  • Ở đâ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ức setName( ), và setAge( ).
  • Dạng của object trước khi được serialize:

Hướng dẫn why is php insecure - tại sao php không an toàn

  • 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:

Hướng dẫn why is php insecure - tại sao php không an toàn

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àm unserialize( ).

Hướng dẫn why is php insecure - tại sao php không an toàn

  • Ở đâ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ến setName( )2. Sau đây là kết quả:

Hướng dẫn why is php insecure - tại sao php không an toàn

  • Kết quả nhận được sau khi setName( )3 từ biến setName( )1 giống với dạng object trước khi được setName( )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 PHP getName( )0. Với các lớp phương thức Magic method getName( )1 , getName( )2, getName( )3 cùng với các getName( )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ụng getName( )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ổng getName( )5 trên nền tảng getName( )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ổng getName( )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ổng setAge( )5 trên nhiều ứng dụng web cho phép cả tấn công thi mã từ xa setAge( )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ổng setAge( )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ổng setAge( )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ảng setAge( )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ột setName( )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ào setName( )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ình setAge( )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ột setAge( )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ác setAge( )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ạn setAge( )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ổng setAge( )5 cần có 2 điều kiện:
    1. Đ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ện setName( )3 đoạn dữ liệu này.
    2. 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.
  • 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ổng getName( )5. Đầu tiên, có ít nhất một unserialize( )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ốn unserialize( )4. Thứ hai, lớp được chọn cần phải được load trong phạm vi của lệnh gọi getName( )0, và kẻ tấn công có thể điều khiển được đầu vào của hàm getName( )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ỳ ý.

Hướng dẫn why is php insecure - tại sao php không an toàn

Hướng dẫn why is php insecure - tại sao php không an toàn

  • Lỗ hổng unserialize( )8tồn tại ở dòng unserialize( )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ện setName( )3. Ở dòng unserialize( )1, unserialize( )2 kẻ tấn công đã chèn một đối tượng unserialize( )3 với thuộc tính unserialize( )4 được đặt là một đối tượng của lớpunserialize( )5. Thuộc tính unserialize( )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ớp unserialize( )5, gọi đến hàm setName( )00 của lớp setName( )01. Trong hàm setName( )00 sẽ gọi đến phương thức setName( )03 được kế thừa ở lớp unserialize( )5. Ở đây, với unserialize( )6 mà setName( )06truyền vào sẽ được chương trình xoá file đó. Kết quả là file setName( )07đã bị xoá.

Tobe continue...

All rights reserved