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!
datr. https://www.facebook.com/recover/account/ is used to verify an account via email or phone number. In cases where requests originate from a trusted device an alternative flow canbe used to recover the account via uploading a document. This process is automated and is supposed to help legitimate users regain access easily. A core invariant of this flow is that trusted device cannot be easily impersonated. datr value. When a datr is in the fields for an application with Facebook login, the machine_id is the same as this cookie. Although this data cannot be queried directly, Facebook's GraphQL allows chaining GraphQL API requests. By having multiple requests reference earlier responses, it's possible to propagate the machine_id to attacker-viewable output.BATCH API to trigger the OAuth call that will return the machine_id and then post that to your own Facebook account.datr value. This should be easy to bypass with public information and fake documents.datr and the Batch API referencing previous values. Both of these require a lot of context, specifically on this target. They were awarded $24K for the bug, which is a solid payment. Another amazing write-up!gw.conversionsapigateway.com is Meta's own deployment of the application. The fbq JavaScript module includes the collection/processing module in a JavaScript file named capig-events.js. Any vulnerability in this script could inherit the privileges of the site it's on, such as business.facebook.com.capig-events.js only triggers when the page has an opener window. This event includes various pieces of data, such as the message type. If the type is IWL_BOOTSTRAP then the script will check if the pixel_id exists in the list. The event origin is never explicitly verified, meaning that this can be called from any origin.event.origin is used in order to dynamically load JavaScript via <origin>/sdk/<pixel_id>/iwl.js. Since an attacker can control the origin of arbitrary loaded JavaScript, this creates the opportunity for some nasty XSS. This is a classic case of not validating the origin data from a post message call and using the data anyway.same-origin-allow-popups. On the surface, this appears to prevent the issue. However, the security is not evaluated on a single page or a single policy; it is evaluated across all contexts where the code runs.window.name. They found a vulnerability in a third-party application that allowed them to hijack the iframe to interact with the page with a CSP allowed site. Here's the full exploit chain:
capig-events.js script."]} could be used to add attacker-controlled JavaScript in the generated output. In practice, this creates stored XSS within the capig-events.js file. Notably, the payload is served to every user, including Meta-owned domains. This isn't just stored XSS; this is a supply chain attack.map (known as a hidden class) that represents the memory layout of a object. A map holds an array of property descriptors that contain information about each property, as well as the elements and their types. These maps are shared between objects that have the same layout. If a map doesn't exist, then a new one is created. When this happens, the old and new map are related by a transition that occurs to go from one map to another.o1 and o2 having a as an integer, if o1 gets a set to a double then the map in o2 is set to deprecated. This is because SMI (internal small integer) can be represented by a more generalized value. Eventually, the o2 object will be updated to the map of o1 once a property is accessed.PrepareForDataProperty are safe, there are two locations where the type can be updated to a dictionary map instead of the original object map. In CreateDataProperty, it may result in a dictionary map after an update. There are multiple routes to this but the usage of the spread syntax ended up being the most interesting....obj1) and the usage of a property accessor, the function CreateDataProperty will be called while it's being cloned. While this cloning is happening, it's possible to deprecate the map while it's being used for the clone. This allows for the updated map to be a fast map instead of a dictionary map! A type confusion in the JavaScript engine leads to memory corruption now.elements to a large value within the underlying data structure for NameDictionary. By doing this, we get an OOB read for property values that leads to improper object access. Creating a "fake object primitive" is one of the best primitives in JavaScript engine exploitation. So, just arrange the heap in a nice way to create a fake object. invoke or invoke_signed, you provide a set of accounts to be used. In raw Solana, you pass in AccountInfo directly, which is a handle to the in-memory runtime state. In Anchor, you pass in Account<'info, T>., which is a deserialized version of T and acts as a cached value.lamports, are read directly from the runtime state every time. If you reborrow the data, then the underlying bytes will also be updated.T on the AccountInfo is a deserialized snapshot of the account data bytes. At the start of the instruction, Anchor constructs the accounts by deserializing them in a generated handler from the info.data on the account. This means that the data is copied onto the stack/heap as a Rust value and is NOT a live reference to the runtime bytes. At the end of the instruction, Anchor will serialize the data structure and write it back to the runtime.balance on a token account, a token transfer would show the same balance before and after the CPI, regardless of whether the account balance changed.reload(). This will reload the data from storage via re-reading and deserializing the data within AccountInfo.data. The account data is now no longer stale.reload(). It's required when A) a CPI can be used to mutate account data, B) the account needs to be read/validated later and C) you are reading a cached struct. If lamports or native runtime fields are being read, then reloading isn't necessary.lamports didn't need to be reloaded but the data did; now I know!admin:admin. So, with access to a device, it's possible to login to it. Additionally, there is no key signing so it's trivial to reflash the firmware with arbitrary code.