WCF (Windows Communication Foundation)
.NET Framework 4.7.1
WCF (Windows Communication Foundation) is a framework for building service-oriented applications. It is used in web services as well as inter process communication.
A weakness in this framework might expose applications that use it to DOS attacks.
WCF framework takes care of de-serializing the input to the application and of serializing the output that it returns. It supports both XML and JSON formats.
If a highly nested object is being returned by the application, a StackOverflowException is being throwed and the hosting process is terminated immediately (see our blog post).
If an attacker can build a highly nested object in the system and then use the API to get this object, s/he can remotely crashes the application.
For example, if the API provides a way to build a tree structure by adding nodes iteratively and it also provides a way to retrieve the entire tree, an attacker can build a deep tree and then crash the application by requesting the entire tree.
Applications that contain such a pattern, will be vulnerable to a DOS attack due to poor implementation of the serializer that is used by the framework.
I reported this issue to Microsoft on July 30 2018. A case was opened, but Microsoft closed it as “by design”.
I was surprised by this response. How can you design a framework that crash the process by design when handling a highly nested object? I would expect it to return an appropriate error message.
Here is an example of WCF service that crashes the application when being called with big depth (~2000):
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace TestService
{
[DataContract]
public class TreeNode
{
[DataMember]
public TreeNode[] Suns { get; set; }
}
[ServiceContract]
public interface ITreeService
{
[OperationContract]
TreeNode GetTree(int depth);
}
[ServiceBehavior]
public class TreeService : ITreeService
{
[WebGet(UriTemplate = "GetTree?depth={depth}")]
public TreeNode GetTree(int depth)
{
TreeNode root = new TreeNode();
TreeNode iNode = root;
for (int i = 0; i < depth; i++)
{
iNode.Suns = new TreeNode[] { new TreeNode() };
iNode = iNode.Suns[0];
}
return root;
}
}
}