Untrusted Deserialization in RadMultiSelect control for webForms.

1 Answer 42 Views
MultiSelect
Konstantin
Top achievements
Rank 1
Iron
Konstantin asked on 21 Aug 2023, 06:11 PM

Hi Telerik team,

the "Contrast Security" tool we use shows us a "Untrusted Deserialization" Vulnerability found on one of the ASPX (webForms) page where we utilize RadMultiSelect control. (Our current version is 2021.1.119.45). 

Could you please suggest any options now to fix it, please?  

Details:

Tracked the following data from "ctl00_Main_content_ddlMSelectMultipleStaff_ClientState...:

POST /vosnet/communications/scheduler/default.aspx

ctl00_Main_content_ddlMSelectMultipleStaff_ClientState={"enabled":true,"selectedItems":[],"deselectedItems":[],"value":[2613],"selectedDataItems":[{"text":"Skaggs","value":"2613","Lastname":"Skaggs","Userid":2613,"attributes":{"FullName":"Skaggs Kari","Color":"background-color:rgb(89,20,195);","ColorARGB":"5838019"}}]}&ctl00$textsize=.......SNIP...........

...which was accessed within the following code:
Telerik.Web.UI.RadMultiSelect.LoadPostData()

...and ended up being deserialized with code that looks like this:
m = serializer.Deserialize<M>("{"enabled":true,"selectedItems":[],"deselectedI...")

 

1 Answer, 1 is accepted

Sort by
0
Konstantin
Top achievements
Rank 1
Iron
answered on 22 Aug 2023, 01:43 PM | edited on 22 Aug 2023, 04:39 PM

The issue was addressed by overriding the LoadPostData event handler in derived class. The JS Type resolver code is not posted here, but could be found in MS recommendations (https://learn.microsoft.com/en-us/dotnet/api/system.web.script.serialization.javascripttyperesolver?view=netframework-4.8.1). 

 

Public Class MultiSelectApptStaff
        Inherits RadMultiSelect

        Protected Overrides Function LoadPostData(ByVal postDataKey As String, ByVal postCollection As NameValueCollection) As Boolean
            Dim errorMsg As String = "Selected Calendar Staff cannot be desirialized.  "
            Dim updatedPostCollection = New NameValueCollection(postCollection)

            If (Not String.IsNullOrWhiteSpace(postDataKey)) Then
                If (Not IsNothing(updatedPostCollection(postDataKey))) Then
                    Try
                        Dim multiSelectControlSeletedValue As String = updatedPostCollection.Get("ctl00_Main_content_ddlMSelectMultipleStaff_ClientState")
                        If (Not String.IsNullOrWhiteSpace(multiSelectControlSeletedValue)) Then
                            Dim jsCalendarResolver As CalendarJSTypeResolver = New CalendarJSTypeResolver(New Type() {
                                                                                                          GetType(StaffCalendarSelectDTO),
                                                                                                          GetType(StaffCalendarItemDTO),
                                                                                                          GetType(StaffCalendarDTO)}
                                                                                                          )
                            Dim jsCalendarSerializer As JavaScriptSerializer = New JavaScriptSerializer(jsCalendarResolver)

                            Dim selectedCalendarStaff As StaffCalendarSelectDTO = jsCalendarSerializer.Deserialize(Of StaffCalendarSelectDTO)(multiSelectControlSeletedValue)

                            If (IsNothing(selectedCalendarStaff)) Then
                                Logging.ErrorLogsManager.AddDebugLogEntry(errorMsg:=errorMsg, addContext:=True, refGUID:=System.Guid.Parse("f8fcd9d1-7396-4fac-a9e8-d7875a610001"), refOPC:=861046)
                                Throw New Exception(errorMsg)
                            Else
                                Dim serializedJsonCalendarSeleted As String = jsCalendarSerializer.Serialize(selectedCalendarStaff)
                                'update PostData with valid serialized data. Make sure to remove '__type' from json

                                updatedPostCollection("ctl00_Main_content_ddlMSelectMultipleStaff_ClientState") = serializedJsonCalendarSeleted 
                            End If
                        End If
                    Catch ex As Exception
                        Dim msg As String = ex.ToString()
                        Logging.ErrorLogsManager.AddDebugLogEntry(errorMsg:=errorMsg & ex.ToString(), addContext:=True, refGUID:=System.Guid.Parse("f8fcd9d1-7396-4fac-a9e8-d7875a610002"), refOPC:=861046)
                        Throw New Exception(ex.ToString())
                    End Try
                End If
            End If

            Return MyBase.LoadPostData(postDataKey, updatedPostCollection)
        End Function
    End Class

 

Rumen
Telerik team
commented on 30 Aug 2023, 12:36 PM

The _ClientState field indicated in the scan report is something standard for an IScriptControl instance. These hidden fields are a standard feature for controls based on the MS AJAX framework (such as ours) and their purpose is to store the state (that is, some key-value pairs of information) that the control has on the client, so they can be read and set accordingly on the server, in order to be returned to the client. It acts for the browser a little bit like the ViewState acts for the server.

So, what we do with the information in them is what every MS AJAX-based control does - we parse the JSON and set the properties of the control as necessary with the provided data. This is, in turn, returned to the browser, and this behavior is also expected. This does not indicate that an injection occurred, and it is not an XPATH or XSS attack either, because the framework encodes the JSON literal. 

  • We do not use these hidden fields for any data storage or user input, so there should be no vulnerability coming from it. 
  • We do not execute code based on these values, nor we do not send any debug information through them. Even if a malicious user changed the values, they could have either of the following outcomes:

    • They will get a server error that the data cannot be parsed - either because they put a string the framework will not allow in a POST query (such as HTML tags), or because our code will not expect the values they provide and will throw a generic exception (e.g., index out of range or something like that). Just make sure that RequestValidation is enabled, e.g. the validateRequest page attribute is set to true.
    • They will change the properties of the control and get the behavior they changed when the postback returns. This is, assuming the values they provide are valid.

We are not aware of a way to execute code on the server through those fields and, also considering the information above, we believe this report to be a false positive from a static code scan tool that adds this warning for any input it finds on the page.

We utilize the JavaScriptSerializer class from .NET to extract the contents of the ClientState fields. As of our current knowledge, there aren't any known vulnerabilities associated with the ClientState fields in our controls. Furthermore, when calling the Deserialize method of JavaScriptSerializer, we explicitly specify the object type as RadMultiSelectClientState using serializer.Deserialize<RadMultiSelectClientState>(clientStateValue). This ensures it will only deserialize to the known RadMultiSelectClientState type, further enhancing security.

That said, if you have managed to execute code or commands, or otherwise perform an attack through the _ClientState fields of our component, please provide the details on how this is accomplished - sample values, the necessary steps, and a sample reproducible would be appreciated. Having a concrete sample or information on the vulnerability will let us investigate it.

In relation to the solution shared by Konstantin on the Telerik forum at this link — which subclasses the multiselect and incorporates a custom deserializer — we recommend exercising your discretion when deciding to use it. We're currently unfamiliar with the inner workings of the custom jsCalendarSerializer class.

Tags
MultiSelect
Asked by
Konstantin
Top achievements
Rank 1
Iron
Answers by
Konstantin
Top achievements
Rank 1
Iron
Share this question
or