50 Shades of SolarWinds Orion Deserialization (Part 1: CVE-2021–35215)

Jang
6 min readOct 22, 2021

--

Cách đây không lâu, mình bắt tay vào phân tích một vài bug deserialize của SolarWinds và cũng đã note lại tại đây

Trong vòng 1 tuần đọc code, mình cũng đã phát hiện thêm ít nhất 4 bug deserialize với đủ thể loại khác nhau trên product này,

Hôm vừa rồi có check lại trên trang chủ thì đã thấy có bản vá cho mấy bug này, hơi bất ngờ một chút khi thấy mấy ae người Việt cũng tìm ra cùng thời điểm mình report cho SolarWinds:

Những bug mình tìm ra và được đánh số là:

  • CVE-2021–35215: SolarWinds Orion Platform ActionPluginBaseView Deserialization of Untrusted Data RCE Vulnerability
  • CVE-2021–35216: Patch Manager Orion Platform Module: Edit Research Controls Deserialization of Untrusted Data Remote Code Execution Vulnerability
  • CVE-2021–35217: Patch Manager Orion Platform Module: WSAsyncExecuteTasks Deserialization of Untrusted Data Remote Code Execution Vulnerability
  • CVE-2021–35218: Patch Manager Orion Platform Module: Chart Endpoint Deserialization of Untrusted Data Remote Code Execution Vulnerability => (Thực ra bug này là Pre-Auth RCE)

Trong 4 bug mình report cho SolarWinds, mỗi bug đều có 1 điểm hay riêng, cho nên blog này vừa để phân tích cũng như note lại về quá trình mình tìm ra các bug trên!

#CVE-2021–35215: SolarWinds Orion Platform ActionPluginBaseView Deserialization of Untrusted Data RCE Vulnerability

Bug này tồn tại ở ngay bản Core của SolarWinds Orion, cho nên tất cả các product của SolarWinds có giao diện web dựa trên Orion (NPM, PM, SAM, SEM, …) đều bị ảnh hưởng. Hơi buồn một chút là để trigger bug này, cần ít nhất 1 account hợp lệ của target :<.

Entrypoint của lỗ hổng này nằm ở Orion/RenderControl.aspx.cs:

Khi gọi tới page, method Orion_RenderControl.OnInit() sẽ gọi tới PropertySetter.LoadJsonData() để parse data từ body của request, nội dung của method này như sau:

JavaScriptSerializer.Deserialize() được gọi để deserialize json data, tuy nhiên JavaScriptSerializer cần phải đi kèm với một TypeResolver thì mới có thể bị abuse và RCE từ đó.

Cho nên ở đây JsonData sau khi được deserialize sẽ chỉ có dạng map string => string.

Tiếp tục theo dõi xuống phía dưới, giá trị biến “Control” được lấy từ phía người dùng rồi truyền vào TemplateControl.LoadControl() để khởi tạo Template cho phiên này:

Template vừa khởi tạo sẽ tiếp tục được truyền vào Orion_RenderControl.ApplyPropertiesAndAttributes() để khởi tạo lại các attributes, properties:

Logic của đoạn này như sau:

Nếu “JsonData” (đã parse đầu method OnInit) có chứa key với tên “config” thì sẽ tiếp tục gọi vào PropertySetter.SetProperties() -> SetProperty() để set các property có trong JsonData:

PropertySetter. SetProperty() sẽ tiếp tục invoke PropertyInfo.SetValue() với “obj ”chính là Template vừa được tạo, cùng với “converted” là giá tị lấy ra từ JsonData

Tại PropertyInfo.SetValue(), Setter Method của Template sẽ được invoke để khởi tạo lại giá trị:

Như vậy, dựa vào các dữ kiện trên, mình hoàn toàn có thể trigger một Setter Method của một Template bất kỳ, chain attack có dạng như sau:

Nếu đã từng làm về Deserialization, bạn đọc có thể nhận ra sự quen thuộc này. Vì rất nhiều phương thức Attack Deser trên .Net nói riêng hoặc rộng hơn là Java đều lợi dụng việc invoke Setter Method để RCE (☞゚ヮ゚)☞.

Hơi khác một chút, trong context này chúng ta mới chỉ có thể invoke Setter Method của một Template, các Template này có đặc trưng là nó kế thừa từ class System.Web.UI.Control:

Trong ví dụ trên, mình có thể invoke được Setter Method của property BaseViewGroupControl.View, và gọi tới được method RebuidUI() sau đó.

Để có thể trigger RCE, cần tìm một gadgetchain thỏa mãn các điều kiện sau:

  • Source là một Setter Method
  • Có thừa kế class System.Web.UI.Control
  • Sink có thể RCE hoặc write file gì đó

Cũng khá là may mắn cho mình, chỉ trong vài giờ đồng hồ đào bới đã tìm thấy được 1 gadgetchain khá tiềm năng, (chứ nếu đen thì ko biết đào bới bằng tay bao giờ mới ra được cái chain này=)) )

Chain này bắt đầu từ ActionPluginBaseView.set_ViewContextJsonString() -> ParseViewContext()

Nội dung của method ParseViewContext():

Rất rõ ràng, ở đây ta có thể thấy method này trực tiếp gọi tới Newtonsoft.Json.JsonConvert.DeserializeObject() với TypeNameHandling != null

Từ đó có thể lợi dụng để tiếp tục Deserialize dữ liệu lần 2, và trigger RCE thông qua JsonConvert.DeserializeObject().

Ở đây cũng vẫn là may mắn, nếu đã đọc bài viết trước của mình về SolarWinds Deser, có thể bạn đã biết rằng SolarWinds đã sửa đổi lại cái JsonConvert này => SolarWinds.Newtonsoft.Json.JsonConvert, với rất nhiều hạn chế khi load Class, gần như không thể RCE nếu server sử dụng phiên bản custom này. ¯\_(ツ)_/¯ Hacker hệ thắp hương thật mà, các cụ phù hộ đến tận đây nữa.

Với phần Deserialize = JsonConvert, mình tiếp tục sử dụng lại GadgetChain trong bài trước (các bạn có thể tham khảo tại đây):

Để tổng hợp lại, chain attack của CVE-2021–35215 có dạng như sau:

Trong payload của mình có sử dụng “~/Orion/Actions/Controls/CustomPropertyView.ascx”, đương nhiên Template này có thừa kế từ ActionPluginBaseView

.

.

Còn 3 bug nữa cũng về Deserialize, nhưng sau khi xem xét mình thấy nội dung ko thể nhồi nhét đủ vào 1 bài được cho nên tạm thời Part 1 sẽ dừng lại tại đây,

Phần tiếp theo về 3 bug này sẽ được viết vào tuần sau,

Cảm ơn các bạn đã theo dõi tới đây!

PoC Video: https://www.youtube.com/watch?v=a73rq5zxJYA

--

--