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!
PublicKey used in the exploit, can be created with user code. So, the attacker declared a value as a PublicKey and then encoded a resource-containing structure as a value in its place. This allowed for smuggling a resource inside a struct context.add(), the static types being used on the call were not validated to match the contract itself. This allowed turning a static public key into a resource. An absolutely crazy chain of three bugs!constructor directly, the runtime denies access to this during React rendering. This broke the exploit path. Even with a WAF bypass, this runtime check would remove all exploitation. :constructor with a colon. By finding another gadget for property access that used property access and string interpolation, it was possible to use constructor instead. This shows the power of slight deviations in the original exploit.$@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.status to be resolved_model, an attacker can express the internal state of the application for React..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. 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.eval() and os.system().init and init_if_needed. init requires for account creation to occur otherwise it exists. init_if_needed will always run but will create the account if it doesn't already exist.init is required? Associated Token Accounts (ATAs) are 100% permissionless to create. So, using init with ATAs is a bad idea. callback() parameter in the encrypted payload that triggered an eval(). So, if you could somehow get valid data to be decrypted, you'd get an RCE.AES-256-CBC under the hood, where the key is a value known as the salt. Despite a change several years ago to fix this, legacy salt generation was kept around via the uniqid() command, which simply returns the machine's microseconds since installation. This timestamp can be leaked by inspecting the default categories in the setup.hashId that is computed via md5(salt). Since all the information is public except the salt, we can compute hashes with different salts until we find the matching one. This allows us to leak salt.encrypt_decrypt() function uses the system root path as the IV. Either via educated guesses or using the the leaked posterPortraitPath from another API, this can be figured out. With the salt known and the RCE path identified, we can execute RCE on the machine. Pretty neat!eval() callback remained. CVE-2023-46746 by directly calling a PATCH request to store the endpoint used for a webhook. There's also a TOCTOU bug in the verification. Now, we can set the domain to be localhost.'posthog_table' into 'posthog_table\'', but the backslash is a literal here. So, we now have SQL injection on the incoming query that can be used to write on a GET request as well.;END, which makes it read-only. Next, execute a command using cmd_exec and put the results into a payload. An important trick is to use $$ instead of single quotes within the payload. Otherwise, the single quotes would have been escaped once again.State parameter on the OAuth Authorization flow contained an origin key. This key was used to verify the target origin of post messages, ensuring that only authorized domains request information via post messages. So, a very security-sensitive value.https://attacker.com/codeassist.google.com.origin was treated as a URL with strict validation. Overall, a solid bug in a weird section of code..css to an endpoint that returned an authentication token. Unfortunately, this API had to include the X-Auth-Token header, which wouldn't be automatically added to the request. This is issue number 1.../ can be used to make the client-side execute an arbitrary API call that is authenticated. They weren't able to do anything useful with this by itself..css at the end of it. This would cache the API token! The exploit is just the user clicking on the following link: https://example.com/user?id=../../../v1/token.css.