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!
ChangePubKey sets the account's L2s signing key. On the L1, the contract verifies that the pubkey change uses the nonce from the pubdata. pub_nonce equality is NOT checked in the tx validity, but IS checked within the mutation validity. When handling the fees, the validity was checked via tx validity and not both of them.ChangePubKeyOffchain where the transaction checker believes it's valid but the mutation doesn't believe so. On the fee accrual chunk, the fee accounting adds more fees than it should without increasing the user debit/nonce. In practice, this attack could be repeated with a malicious proof to mint infinite funds in fees. It appears that this was permissioned because of the reliance on the prover/sequencer/operator though./view only succeeds if the header contains From-Fetch but contains an XSS sink within it via the HTML parameter. / performs a call to /view via a Fetch and places the contents within iframe without script execution. This is the setup for the challenge.From-Fetch header to an unintended request.cn_ prefix to prevent cache poisoning during mainframe navigation. In. Particularly, this is added when the top level of the page has its location.href modified.cn_ on the page. Notably, history.back() doesn't count as a cross-site main-frame navigation for whatever reason! window.open() to /?html=<XSS> to populate the cache. history.back()./view?html=<XSS>. history.back() to load the cached version of the page to get XSS.__cid and __user, an attacker can brute force the user ID of the Workplace community. If __user is correct, then an empty page with text/html is returned. If it's incorrect, the response in application/json, which will trigger CORB and block script execution. By observing onload and onerror events, it's possible to determine the user id of the logged-in user.__user is correct, everything renders as normal. If it's incorrect, then X-Frame-Options: Deny is returned, preventing the iframe from loading. This distinction allows brute-forcing the active sure or page ID by observing postMessage events rather than a timeout.https://www.facebook.com/signals/iwl.js?pixel_id=PIXEL_ID returns a JavaScript payload intended for internal Meta Pixel testing, including the Facebook user ID. This value is scoped inside a function. But by manipulating JavaScript prototypes before loading the script, it can still be extracted. Their PoC modifies the function prototype and prints the user ID of the object. Apparently, the script runs within the full context of your page, allowing for the reading of the data still. Neat!facebook.com or its subdomains. graph.facebook.com send. This includes location.href and document.referrer, which can contain OAuth codes and other sensitive values.postMessage to a target Facebook domain specified by the attacker. This appears to be a classic confused deputy problem, where the data is passed through without any checks from a trusted domain.fbevents.js code receives messages originating from facebook.com. By using the primitive from above with an arbitrary message send and including an attacker's access_token for GraphQL, requests can be tricked into exposing OAuth code/tokens to the attacker. By doing this, an account takeover may be possible. developers.facebook.com. developers.facebook.com, contains the fbevent.js file and has the message listener. To prevent the page from consuming the token, an invalid nonce must be used.https://auth.meta.com/fxauth/, a signed token and blob are returned for using the website. The base_uri contains where to redirect back to. base_uri had no restrictions on the value that was set. By exploiting this, it was possible to redirect to an arbitrary domain and extract the token. This made by an account takeover possible. The fix was to restrict it to Meta-owned domains, assuming that the path could not be controlled either.https://apps.facebook.com/{app_namespace}. If an attacker owns an application, they can read parameters from the URL even if they do not control the path directly.ACTOR_ID for validity when a PR is made. The validation is as follows: 16024985|755743|.... The | symbol is an OR operation in regex. ^ and $. Practically, this means that any account that contains these values would be approved by the filter. So, is it possible for a GitHub user ID to contain one of the values in the regex? 0x80000000. So, KASLR is effectively useless on these values. But why? .data entries of the kernel as R/W permissions. The offset0xffffff8001ff2398 will always map to modprobe_path, for instance; 0xffffff8000010000 is effectively the kernel base.www.facebook.com and designed for use in iFrames. Communication between the host website and Facebook is implemented using postMessage. Math.random(). This is insufficient for cryptographically random data and leaves a hole. The seed for randomness appears to be unique per page, so we need to leak the randomness somehow. The window.name() also uses Math.random(). If this could be leaked, it could be extracted.init:post will reinitialize the iframe, generating a new ID. Since the name of a window can be public, it's possible to leak the name and reverse the random number generator to find the seed. From there, it's possible to calculate the callback string to trigger the DOM XSS on the website. frame-ancestors set to any domain would place it in the XFO header with ALLOW-FROM. Since this isn't supported by modern browsers, this was a bypass of the iframe protection, but required frame-ancestors to be on the page. Math.random() seed.