CVE-2021-27076: A Replay-Style Deserialization Attack Against SharePoint

March 17, 2021 | Simon Zuckerbraun

An attacker is frequently in the position of having to find a technique to evade some data integrity measure implemented by a target. One instructive example of a data integrity measure is a message authentication check. Generally, message authentication is achieved by appending some form of a cryptographic tag to a message. Calculating the correct value for the tag is possible only with knowledge of a secret key held by the legitimate sender. When the target receives a message, the target can check that the tag has been calculated correctly. A correct calculation proves that the message was authorized by the legitimate sender.

An attacker who wishes to concoct some other message and convince the target that it was authorized by the sender faces a challenge. Typically, the attacker cannot calculate the proper tag that must be appended, because the attacker is not in possession of the secret key.

In such a circumstance, what are the attacker’s options? An important realization is this: While the attacker herself does not know the secret key, there is at least one actor in the picture who does, namely, the legitimate sender. Perhaps the attacker can interact with the sender in such a way that the sender will be influenced to authorize the very message that the attacker wishes to send to the target (or one close enough).

Naturally, a system will not be designed in such a way that an attacker can ask directly to have an arbitrary message authorized. That would defeat the entire purpose of including an authorization code in the system’s design. On the contrary, the sender is presumably designed to authorize only those messages that it intends the target to accept as authentic. Nevertheless, there is an insidious and underappreciated danger lurking within this very common security design pattern we have just described.

The essence of the problem is centered on the word “intends” in the previous paragraph. For a secure system, what we really need is for the recipient to be able to prove that the sender has a particular intent. In reality, what we have is a cryptographic scheme that proves that the sender has emitted a message consisting of a particular sequence of bits. Is this good enough? The answer depends upon how precisely the sender’s intent can be inferred from the binary message.

Let us make this clear with a concrete example. Here, “Bob” and “Alice” are two legitimate actors. They could be automated systems, or they could be humans communicating over an electronic medium. Suppose that, in the course of an exchange, Bob asks Alice whether Alice wishes to proceed with a particular transaction. Alice replies “YES” and appends a cryptographic tag, proving that Alice authorizes the message that says “YES”. Bob receives the “YES” message together with the tag, verifies that the tag has been calculated correctly, and concludes that Alice has authorized proceeding with the transaction.

This conclusion is on shaky ground, though. When we look a bit more closely, we can easily see that all that Bob can really conclude is that Alice has said “YES” to someone, sometime, in regard to something. Bob is not really justified in concluding anything about Alice’s intent.

An attacker can exploit this as follows. First, the attacker records Alice’s “YES” response, in some context, perhaps an inconsequential one. Alice’s “YES” is accompanied by a valid message authorization code, calculated by Alice herself (or Alice’s equipment). Later, the attacker replays Alice’s “YES” response, together with the valid code, convincing Bob that Alice has said “YES” in an entirely different context (or perhaps simply at a later date). The essential problem is that Alice’s “YES” response does not contain enough information to uniquely identify her intent.

Interestingly, the FCC has warned that scammers have been executing an attack following this exact pattern, by eliciting a verbal “yes” from human victims over the phone. In this instance, no cryptographic authenticators are in use. Rather, an individual’s unique voice is the basis for authenticating messages.

For an example of an attack of this nature against an automated system using cryptographic message authentication, see Michal Zalewski’s ASP.NET VIEWSTATE bug CVE-2005-1664 (variant 1a).

Attacks of this sort are known as replay attacks since they involve replaying a response generated by a legitimate actor in a context not intended by that actor. The different context might simply be a later time, or it might involve taking the message out of its intended context in some more sophisticated fashion.

Attacking SharePoint Session

The above introduction will help us appreciate the nature of a rather amazing attack against SharePoint, submitted to us by an anonymous researcher and given the identifiers ZDI-21-276 / CVE-2021-27076.

In the implementation of SharePoint’s InfoPath functionality, documents are serialized and stored in session state. From there, they may be retrieved by key (editingSessionId) and deserialized. Relevant code outtakes are as follows:

Data read from session state is ultimately passed to BinaryFormatter.Deserialize. If an attacker can specify arbitrary data here, code execution can result.

The challenge facing the attacker here is somewhat similar to the scenario described above in regard to message authentication. The difference is that, in this case, what stands in the attacker’s way is not a cryptographic authentication code, but rather the fact that the attacker has no access to session state and cannot place arbitrary data there at will.

As above, though, the attacker still has an available option. While the attacker has no direct control over the contents of session state, there is another actor present that does: namely, the SharePoint application itself. Perhaps the SharePoint application can be influenced to place the attacker’s chosen data into session state?

Surely there is no direct way to accomplish this, as it would be folly to design an application in such a way that an untrusted user can make arbitrary modifications to session state. Rather, all edits to session state are moderated through the application itself, so that anything that ends up in session state is, in effect, authorized by the application to reside there.

This is the point where the thorny problem of intent rears its head. Though the SharePoint application would not place into session state arbitrary user-supplied data with the intent of that data being read back by the deserialization mechanism, it remains within the realm of possibility that SharePoint could be influenced to place such data there with some alternative intent. In fact, that turns out to be the case. SharePoint also uses the session state mechanism to store arbitrary user-supplied files during attachment upload operations. This is at the core of the vulnerability, though there is still more for us to explain.

Under normal operating conditions, these two different types of data in session state never mix. Each blob added to session state is stored under a unique key (as in the editingSessionId variable discussed above). During attachment upload operations, data is normally retrieved from session state using the key corresponding to a data item that was placed there with the intent of it being used in attachment upload operations. Similarly, during DocumentSessionState deserialization operations, data is normally retrieved using a key that corresponds to a data item that was placed into session state with the intent of it being used in DocumentSessionState deserialization. Hence nothing untoward happens during typical operations.

The next piece of the vulnerability is that the editingSessionId can be influenced from the client side. By replacing one key value for another on the client side, it becomes possible to influence the server to retrieve data from session state placed there with one intent (attachment upload), and replay it in a different context, so that it enters the DocumentSessionState deserialization code path.

There is one final difficulty for the attacker. When uploading an attachment, the corresponding session state key is not visible from the client side. It is present only on the server side, within the DocumentSessionState object. Our anonymous researcher solved this problem by performing an additional attack in the reverse direction: feeding the document’s state key into the attachment mechanism, so that the server replays a serialized DocumentSessionState as an attachment and returns it to the client. Within the serialized bytes, the state key of the attachment can be found.

The final exploit is highly reliable but has numerous steps. We present a simplified version below:

  1. Create an InfoPath list.
  2. Begin adding a new item to the list.
  3. Attach a file to the item. The file contains a fake InfoPath DocumentSessionState including arbitrary objects to be deserialized. The file’s extension can be set to anything InfoPath allows for extensions, for example, .png. After attaching this file, do not save the form.
  4. Scrape the document’s state key from the page’s HTML.
  5. Feed the document’s state key to the FormServerAttachments.aspx page, maliciously replaying the DocumentSessionState into the attachment mechanism. The entire serialized DocumentSessionState is returned to the client as if it were an attached file.
  6. From within the returned data, extract the state key of the attachment added in step 3.
  7. Feed the attachment’s state key into an undocumented client-side API, maliciously replaying the attachment into the deserialization mechanism. Remote code execution is achieved when the arbitrary objects present in the attachment are deserialized on the server.

Microsoft patched this vulnerability in March as CVE-2021-27076. All supported versions of SharePoint Server, including Microsoft Business Productivity Servers 2010 Service Pack 2, are affected by this vulnerability. We recommend applying the patch to affected systems.

Conclusion

Correct system design hinges upon the proper interchange of messages. It is well understood that cryptographic techniques such as message authentication codes are needed to assure the integrity of data in transit, and that access control is required to assure the integrity of data at rest, which we may think of as messages generated by a system to be consumed later by the same system. When applying these security techniques, however, it is also crucial to keep in mind the semantics of how the data will be consumed. Even where the integrity of binary data itself is assured by the application of appropriate security measures, the security of the system as a whole may nonetheless be compromised if an attacker can alter some context that affects how the data is ultimately interpreted.

You can find me on Twitter at @HexKitchen, and follow the team for the latest in exploit techniques and security patches.