Formatter - một vài chain của BinaryFormatter
Ở bài này ta sẽ cùng phân tích một vài chain của BinaryFormatter
Last updated
Ở bài này ta sẽ cùng phân tích một vài chain của BinaryFormatter
Last updated
Đây là một chain đơn giản và cũng là tiền đề của các chain khác trong BinaryFormatter, nên mình sẽ phân tích trước
Điều kiện để exploit chain này:
Dùng BinaryFormatter
Target có dùng Microsoft.PowerShell.Editor.dll
(là một phần của Powershell, thường được cài đặt mặc định trong các bản windows server 2008/windows 7 trở lên)
Đầu tiên ta sẽ nhìn vào code gen payload của ysoserial để có cái nhìn tổng quát về chain
Ta thấy code này chủ yếu là chỉ tạo ra 1 object wrapper inplement lại ISerializable
để cho phép custome quá trình seri, trong quá trình seri sẽ gọi đến info.SetType
nhằm set object type khi object này được deser (tham khảo: https://stackoverflow.com/questions/42794732/customized-serialization#:~:text=4,table of sprites). Hiểu đơn giản là sau khi SetType
, nếu object được deser thì sẽ đi đến SetObjectData (do ta implement lại ISerializable) để tạo object có type tương ứng với object type được set, nghĩa là từ 1 object wrapper ta có thể tạo instace của bất kỳ object nào thông qua SetType
. Nguyên nhân của việc phải khai báo 1 cách gián tiếp như thế này là vì object ta muốn lợi dụng để exploit không thể khai báo trong code một cách bình thường do constructor của nó không được public, do đó ta phải thông qua SetType
Ta thấy chain này cực kỳ đơn giản chỉ set property ForegroundBrush
cho object type TextFormattingRunProperties
là một malicious xaml
Ta có đoạn code sau để demo lại chain và exploit trên local:
Nội dung file xml.txt
Kết quả khi thực thi sẽ quăng ra lỗi nhưng vẫn pop up calc
Note: như đã đề cập ở bài trước thì malicious xaml có thể thay bằng ResourceDictionary và cho hiệu quả tương tự
Sink nằm ở TextFormattingRunProperties
của Microsoft.PowerShell.Editor.dll
nên mình sẽ decomplie dll này để xem source (nếu không tìm thấy dll ở local thì có thể decomplie dll đi kèm khi tải ysoserial nằm ở đường dẫn ysoserial.net\ysoserial\dlls\Microsoft.PowerShell.Editor.dll)
Decomplie bằng dnspy ta được kết quả như sau:
Nhấn vào Microsoft.VisualStudio.Text.Formatting
để tìm TextFormattingRunProperties
Nhìn vào constructor của TextFormattingRunProperties ta để ý đoạn set ForegroundBrush
sẽ gọi đến GetObjectFromSerializationInfo
Nội dung hàm GetObjectFromSerializationInfo
Ta thấy giá trị malicious xaml mà ta truyền vào sẽ được lấy ra và đưa vào XamlReader.Parse
→ RCE
Vậy thì tóm tắt chain này sẽ như sau:
Mình thử debug để confirm lại
Để debug thì mình phải add file exe dùng để demo vào và run debug (lưu ý dùng dnspy bản 32-bit)
Break at set là Don’t Break
Code sẽ dừng ngay đây:
Nhấn F9
để đặt breakpoint tại đây và rundebug lại một lần nửa thì ta sẽ hit được breakpoint
Khi này chỉ cần Step Into
là ta sẽ đi đến constructor của TextFormattingRunProperties
Tiếp tục nhảy vào GetObjectFromSerializationInfo
Giá trị của biến string là xaml payload, khi đi qua hàm Parse thì calc popup
Chain tiếp theo sẽ là DataSet
, thật ra chain này có phần đầu là DataSet còn phần cuối lại gọi đến TextFormattingRunProperties
Tóm tắt chain
Điều kiện để exploit:
Target có sử dụng Microsoft.PowerShell.Editor.dll
package (tương tự chain trên vì DataSet thuộc package System.Data - mặc định)
Vì lười nên mình dùng yso gen payload và viết code load payload để build file exe demo dùng cho mục đích debug
Gen payload:
Code load đơn giản:
Khi chạy code thì sẽ quăng ra lỗi, kèm theo đó là calc pop up
Trước khi debug thì mình nhìn sơ qua cách yso gen payload
Ta thấy payload sẽ khai báo object type khi deser là DataSet
kèm theo một vài property, payload trigger RCE là _fakeTable
nằm trong property Tables_0
Khi kéo lên trên để nhìn code được gọi khi gen thì ta sẽ biết giá trị của _fakeTable
là binary của chain TextFormattingRunProperties
Vậy là chain TextFormattingRunProperties
được lồng vào trong chain DataSet
Tiếp theo mình sẽ attach file demo vào dnspy và tiến hành debug
Tương tự như chain trên, mình chạy lần đầu để dnspy tự nhảy đến điểm quăng lỗi, sau đó đặt breakpoint và chạy lại lần 2 để nhảy vào constructor của DataSet
Đoạn code trên tại constructor sẽ lặp qua từng giá trị ta set trong SerializationInfo
Nếu gặp phải DataSet.RemotingFormat
thì nó sẽ set serialize format thành giá trị mà ta cung cấp (nếu không có thì mặc định seralize format là xml)
Vì payload ta khai báo format là Binary
nên ta bỏ qua được 2 câu if và nhảy thẳng vào method DeserializeDataSet
Trong method này ta tiếp tục đi vào DeserializeDataSetSchema
Tại đây vì formatter là Binary
nên ta sẽ nhảy vào câu if thứ 2
Tiếp đến code gọi đến DeserializeDataSetProperties
, tại method này nếu ta muốn tiếp tục đi đến sink thì ta phải khai báo một số giá trị như DataSetName, Namespace,…
Đó cũng chính là lý do vì sao khi gen payload ta cần phải setup nhiều property đến vậy
Tiếp tục quay lại hàm DeserializeDataSetSchema
, vì ta setup DataSet.Tables.Count = 1
nên code nhảy vào vòng for và giá trị của DataSet.Tables_0
được gán vào bytes array và đem đi deser
Chain đến đây có thể coi như đã xong vì khi deser bytes array đó sẽ gọi đến constructor của TextFormattingRunProperties và flow code y hệt như mình phân tích ở phần đầu
Ta có thể thấy chain này chỉ đơn giản relay lại chain TextFormattingRunProperties, tuy điểm ban đầu là khác nhưng về bản chất thì sinks đều y như sau
Tóm tắt chain lại 1 lần nữa
Exploit code
Nguồn: https://testbnull.medium.com/deep-inside-typeconfusedelegate-gadgetchain-456915ed646a
Nếu muốn serialize một object mà ta không thể khởi tạo ví dụ như object internal của .net thì ta dùng phương pháp implement ISerializable
và thông qua info.SetType
để serialize được object mong muốn