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!
WrapperTokenSwappgerImpl. When doing this, the development team had a mixup on which version was should be deployed - a pre-review vs post-review. For whatever reason, the pre-view module got added and attached to the contract. address being called and the data, such as the selector, could be set. As a result, an attacker called transferFrom() on all of the token contracts that had large approvals from users. This is a good example on why approvals on tokens should NOT be infinite.y2=x3 + Ax + B. Because of the y2, the entire curve is reflected over the x axis perfectly. As a result, there are always two valid points or two valid signatures. The math to generate the other point is trivial to do.k value. Any knowledge of the random can makes it trivial to find the private key. Additionally, if two signatures have the same k from a user then it's also trivial to recover the private key using similar techniques. Permit() function. This removes the burden of paying for gas on a call to approve(). Instead, a user can sign offline a permit signature, give it to a user and make it usable for them to transfer funds from their account. Good idea that saves lots of gas!msg.sender of the call does NOT need to be validated. This is a known limitation but was brushed off, as "The end result is the same for the Permit signer..." The authors of this post asked themselves if this is true or not. Permit() is in the middle of lots of other code. So, if an attacker frontruns the call to the other function, extracts the signature and uses this signature directly on the call to Permit(), they would lose the ability to use the functionality after that point. The authors went around and starting looking for cases of this being true.deposit() functions. With these, there's a permit, a transfer then some custom logic. In the example, the logic called _creditUser(). Since we can frontrun this call, the final step will never happen, losing the user some value.<svg> and replace them with <proton-svg>. It may be possible to use this to break the parsing of the HTML!<style> tag, the parsing is different when seeing a closing tag. In HTML, the text in the next closing style tag will end. In SVG, it can contain child elements. Seeing the code in different contexts can cause major issues. <style><a alt="</style><img..."> and changing the context will cause the style to get parsed differently. Originally, the text was kept in for svg, since it was valid. But, the transformation leads to issues with the context, potentially leading to XSS.<onerror="javascript..."> will now lead to XSS! But, we still have two more lines of defense. First, there's an iframe. Second, there's a CSP. For the iFrame on Safari, it adds the directive allow-scripts directive, which allows attackers to execute JS to access the top frame.allow-popups-to-escape-sandbox element allows JS to access the other page that popped the iFrame. For other browsers, the attacker needs a victim to click on a link that opens in a new tab, which will then access the rest of the content on the website.blob URi was allowed for scripts. They are temporary URLs that can be dynamically created at a link then used. If we can convince the browser to load our blob, we'd be able to execute arbitrary JS.https:// @evil.com/, with the space being the important thing here.data-injected-id=last-email-quote. So, what's the big deal with this small change?div is invalid within an svg tag. So, if the browser sees this it will move the entire div element outside of the svg. Many of the elements within the svg that are safe there are unsafe in the normal context. Using some weirdness with style tags closing within double quotes in the HTML context but not the SVG context allows for the smuggling of an image tag with a onerror event! This gives us XSS within the iFrame.allow-same-origin, allow-popups and allow-popups-to-escape-sandbox. The goal is to get code that we can execute on the page. To do this, they first noticed that images are rendered as inline blobs. Since blobs inherit the origin they are on, we can create an attachment with the necessary information in a blob. The blobs have a random UUID though. So, using a technique in a previous post, they use CSS to leak the UUID to themselves.target="_blank", this will be opened in another tab with the content being controlled by us.script-src 'unsafe-eval' http://hcaptcha.com. This is known to have an XSS gadget. So, an attacker can simply use one of these existing functions to get the XSS working.createConnection event handler! So, the SSRF mitigation strategy doesn't work since the hook is never called. navigation.entries() function is used to access a list of the history for a given windows session. Ideally, this will only given history entries for pages that have the same origin as the current page. Each history entry contains the full URL including fragments, making it ripe for attack.about:blank. Upon doing this, they history array was returned!codesandbox.io hosts code that can be executed by others on subdomains. If a user was logged in to the site via an SSO provider like Github or Google, an attacker could access the history information with the OAuth codes from the history! Damn, that's real bad. It should be noted that a window reference is all that is needed; either through opening a tab or an iFrame.about:blank navigation, the developer did not consider a cross-origin request could be made. Luckily enough, site isolation (which isolates processes for different origins) prevents leaks cross origin.pash appears to be a small shell that was used for handling SCM operations for hg.mozilla.org. One function allows users to clone private repos of a given user.user is completely user controlled. When checking to see if the user exists via ldap, the author thought they had LDAP injection at first. However, characters necessary for this were being filtered out. So, what can we do?fetch() in the background then update the UI without reloading the page. This overwrites the default functionality of just making a GET request.fetch() request being made. For instance, you can change the method being used, the headers and more. The functionality is only intercepted from the browser if the origin of the path is the same as an internal meta tag. turbo-root is can be set in a meta tag. According to the author, they've seen cases where it's possible for control this location as an attacker. Since the application thinks this is a trusted link, it will send the CSRF token alongside it.