LosFormatter - ViewState deserialize
Bài này sẽ là một số note của mình về LosFormatter và exploit ViewState deserialize
Demo LosFormatter
Theo như docs Microsoft thì LosFormatter sinh ra để serialize ViewState dùng trong các trang Web Forms. Và theo như docs nói thì LosFormatter cũng không an toàn nếu sử dụng không đúng cách. Vậy thì cụ thể nó không an toàn như thế nào thì ta sẽ tìm hiểu ở phần sau.
Đầu tiên ta có code minh họa sử dụng LosFormatter như sau
Kết quả
Ta sẽ thấy kết quả khi dùng LosFormatter để seri là một chuỗi base64 bắt đầu bằng /wEyt.
Thực chất quá trình seri và deser của LosFormatter là gọi đến hàm seri và deser của ObjectStateFormatter
Ví dụ khi gọi LosFormatter deser
Giá trị của this._formatter
Tại ObjectStateFormatter
sẽ base64 decode giá trị nhận vào rồi tiến hành quá trình deser thật sự
Demo exploit với chain TextFormattingRunProperties
ViewState
Demo ViewState
Theo mình hiểu ViewState tương tự như cơ chế cache của web thông thường nhưng được dùng trong các ứng dụng Web Forms giúp lưu trạng thái người dùng. Giá trị của ViewState sẽ nằm trong các filed ẩn của form và được serialize bởi LosFormatter. Để tiện demo thì ta sẽ tạo một trang dùng web forms như sau:
Chọn new project trong Visual Studio với options là ASP.NET Web Application
Nếu không có options này thì mở Visual Studio Installer rồi chọn Modify -> Individual components
và tick vào .Net Framework project and item templates
để tải về
Sau khi đặt tên project xong thì ta chọn Web Forms
Sau đó mình tạo một file Form.aspx
để demo như sau
Run Web và truy cập /Form ta sẽ thấy giá trị Viewstate
Ta có thể decode để xem value của viewstate bằng extension ViewStateDecoder
Đi sơ qua quá trình handle __VIEWSTATE
tại package System.Web.dll. Ta sẽ thấy, giá trị __VIEWSTATE
được lấy ra từ method Page.RequestViewStateString
Trace ngược về ta biết được tại method Load
của HiddenFieldPageStatePersister
sẽ gọi đến Page.RequestViewState
và giá trị ViewState được deser bằng Util.DeserializeWithAssert
Hàm Util.DeserializeWithAssert
sẽ deser string với formatter truyền vào
Trace một hồi thì ta biết được formatter được sử dụng là ObjectStateFormatter
. Do đó nếu attacker kiểm soát được giá trị ViewState (điều này là hiển nhiên) có thể trigger RCE với các chain dùng được của ObjectStateFormatter
Vì thế Microsoft cũng cung cấp một số tính năng để secure ViewState như:
ViewStateEncryptionMode: cho phép Viewstate hiển thị ở client dạng được encrypt -> việc này chỉ để phòng chống việc lộ lọt thông tin trong viewstate còn khi exploit thì ta có thể đấm như bình thường
EnableViewStateMac: Dùng MacKey trong quá trình deser viewstate để xác thực -> tránh việc attacker dễ dàng lợi dụng viewstate. Từ bản .NET framework 4.5.2 trở đi thì EnableViewStateMac được enable mặc định luôn, còn các phiên bản thấp hơn thì mặc định không có hành vi này mà ta phải tự config. Extension ViewStateDecoder mình đề cập ở trên cũng cho ta biết viewstate có đang được bảo vệ bởi MAC key hay không, nếu có thì ViewStateDecoder return enable còn nếu không thì return unknow
Do đó ta sẽ có bảng sau ứng với từng case khi exploit Viewstate
1.
Any
false
false/true
No
2.
<4.5
false (default)
false/true
No
3.
<4.5
true
false/true
MAC Key
4.
>4.5
true (default)
false/true
MAC Key
Case 1 và 2: .NET any version and MAC disable
Vì 2 trường hợp exploit này đều dựa trên việc MAC encrypt disable nên mình gộp chung luôn.
Như đã đề cập thì từ sau bản .NET 4.5 EnableViewStateMac mặc định là bật. Nhìn lại vào hàm deser tại ObjectStateFormatter ta sẽ thấy trước khi deser sẽ có đoạn check EnableViewStateMac
EnableViewStateMac
sẽ gọi đến EnableViewStateMacRegistryHelper
EnableViewStateMacRegistryHelper
gọi đến method IsMacEnforcementEnabledViaRegistry
để check
Đúng như tên gọi thì IsMacEnforcementEnabledViaRegistry
check reg xem Mac có Enable hay không
Mặc định thì reg này cũng có value là true
Khi này ta có thể setup MAC Key trong phần web.conf, nếu không setup thì mặc định sẽ gen ngẫu nhiên với alg là HMACSHA256
Khi setup Mac key trong web.conf thì ta setup như sau
Lúc này thì ta sẽ có được giá trị validationKey và decryptionKey như setup
Code để get infor key trên web
Ta có thể config on/off EnableViewStateMac ngay trong file aspx bằng options EnableViewStateMac="false"
hoặc EnableViewStateMac="true"
. Tuy nhiên với các bản .NET ≥ 4.5 cho dù ta có set EnableViewStateMac="false"
thì config cũng sẽ ăn theo reg do đó ta cần phải config thêm trong file web.conf giá trị như sau để allow insecure deser
Ta dùng ysoserial để gen payload
Case 3: .NET version <4.5 and MAC enable
Đối với case 3 ta sẽ có 2 trường hợp nhỏ hơn là khi Encryption true và Encryption false.
Nói sơ qua một chút các on/off Encryption. Ta có thể on/off thông qua options ViewStateEncryptionMode
. Các giá trị của ViewStateEncryptionMode
Giá trị của ViewState khi Encryption enable
Cho dù Encryption enable thì cũng không ảnh hưởng đến payload exploit của ta, nên trong trường hợp Mac disable và Encryption enable ta vẫn có thể exploit như bình thường với payload gen từ yso.
A. Encryption false
Để dễ demo thì mình sẽ thêm mac key vào web.conf như sau:
Khi này nếu muốn exploit ta cần phải biết giá trị của validationKey. Quay trở lại một chút đoạn deser của ObjectFormatter
. Ta sẽ thấy trong trường hợp EnableViewStateMac
là true (1) ta sẽ nhảy vào hàm MachineKeySection.GetDecodedData
(2) trước khi deser giá trị (3)
Hàm GetDecodedData có nhiệm vụ check xem data đưa vào có legit hay không dựa vào MacKey
Nói tóm lại là khi EnableViewStateMac
là true ta cần biết được validationKey để exploit. Việc có được validationKey có thể là thông qua việc ta exploit read file -> read web.conf -> có được validate key.
Lúc này ta gen payload với ysoserial như sau
Với giá trị generator
là __VIEWSTATEGENERATOR
của mỗi form. Ta chỉ cần Ctrl+U
lên là thấy
Kết quả:
Đối với trường hợp không exploit được gì để có được MAC Key ta cũng có thể brute force với Blacklist3r
Ta chỉ cần cung cấp giá trị __VIEWSTATE
với option -c
và __VIEWSTATEGENERATOR
với option -m
như sau
Kết quả
Khi có key rồi thì ta gen payload như trên
B. Encryption true
Đối với trường hợp này dù Encryption là true mà ta có được MAC key thì vẫn gen payload và exploit như thường.
....<TODO>....
Case 4: .NET version >4.5 and MAC enable
Hiện tại mình khá bận không có nhiều thời gian test phần này nên chỉ note cách gen payload. Đối với .NET version >4.5 thì ngoài MAC key ta cần biết thêm application path để exploit
Với --path
là full path đến endpoint exploit còn --apppath
là IIS dirpath tức là application name.
Ở case 3 nếu ta không biết value __VIEWSTATEGENERATOR
thì cũng có thể cung cấp application path để gen payload
Ta cũng có thể dùng Blacklist3r để brute key
Thamn khảo thêm: https://soroush.me/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/
Bonus
Bonus một trường hợp là khi viewstate bị disable với options EnableViewState="false"
. Dấu hiệu của trường hợp này là khi ta F5 nhiều lần nhưng giá trị ViewState không thay đổi. Mặc dù mang tiếng là đã off nhưng param __VIEWSTATE
vẫn được handle và deser do đó ta vẫn có thể exploit như bình thường.
Refer
Last updated