Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

React2Shell- 1851

raunchgPosted 2 Months Ago
  • The React Flight protocol is used to encode inputs/outputs for React Server Functions and Server Components (RSC). This is a Backend For Frontend, similar to GraphQL. When requirements for complex UIs are made quickly, Flight enables data to be transmitted back and forth. By using streaming like this, the UI can render as soon as it receives requests from the backend with promises.
  • In the Flight protocol, data is sent in Chunks. These chunks are labeled as integers for the keys of a JavaScript object, and the values are streamable data sent. Using $@0 allows for data to be streamed later on an as-needed basis, which is a promise. The twitter post linked is great but the wiz article has a little bit of an easier payload to follow.
  • The Flight protocol is only intended to transport user objects. By setting the status to be resolved_model, an attacker can express the internal state of the application for React.
  • In JavaScript, anything that has the function .then() is considered a Promise. Adding then to the internal object treats it as a promise and executes the provided then function. This gets executed as a promise because of the previously used $@0. So, chunk 1 triggers the resolution process for the promise in chunk 0, which causes the vulnerability. The then contains $1:then.
  • The vulnerable code that we're trying to trigger is this: response._formData.get(response._prefix + obj). By overwriting the get function of the response objects with another function and controlling the prefix, we can make an arbitrary function call within the context of React. By using the constructor() as the get and JavaScript code as the parameter, we get arbitrary execution.
  • The reason for the specific payload is to trigger deserialization. This deserialization occurs because of the type of object inserted into the flow. It's crazy to me that it's possible to overwrite a field on an object that will eventually execute a function in JavaScript. This is why the payload is recursive: to make this possible. They needed the internal reference to a chunk object in order to be able to access the prototype information. This is described here.
  • Overall, an absolutely crazy exploit that took hours to craft I'm sure. RCE in a large percentage of websites is a huge deal. Great find!