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!
successfulMessages mapping prevents the same withdrawal from being executed more than once.0xDEAD. The variable is xDomainMsgSender. On a cross-chain message, this is set to the calling user. In effect, this acts as a reentrancy protection as well. At the end of the call, the storage value is set back to the default.initialize() instead of using reinitializer modifier. Such a small line of code seems so simple. So, what's wrong?0xDEAD at all times except during the withdrawal process. Within the initialization code (which gets retriggered), this value is set to 0xDEAD but actually defaults to zero. Normally, this would be fine (since it should be a NOP) but that's NOT true in the context of the withdrawal code!failedMessages mapping.
0xDEAD.
relayMessage passing in the withdrawal request. This will succeed because the DEFAULT 0xDEAD address was set back.
xDomainMsgSender global variable doesn't seem important until you have the better context of what it does and why it's important. It's crazy how this reentrancy/replay protection was touched by this simple upgrade code. What an awesome find!keep[index] that actually perform the access. The author compares this bug to reviewing JIT compilers. They try to enforce invariants early on in the program then the rest of the code assumes that this invariant is true. If the invariant is ever violated, then you have a memory corruption bug. {{7 * 7}} will be evaluated as 49 when returned, which is how the author found it. Range header. In HTTP, the Range Header is used for returning only changes to the content of a page by requesting partial information on the request by a portion of the header. For instance, you can ask for bytes 2-6 from the request.206 Partial Content queries. To me, this is fairly surprising, since it should be made to get the data only and not be rendered.Range header, the reflected input can be used to get XSS! The post focuses on getting a header injection vulnerability on the request in order to exploit this.'abc' == 0. However, there are some that still remain. In the case of Craft CMS, a popular PHP based CMS, there are still some footguns lurking.$_SERVER['argc'] and $_SERVER['argv']. If you run this as a web server then PHP will take argv from the query string, if you have enabled this! In the case of PHP, this functionality was on in the default Docker container.$_SERVER['argv'] can be controlled from web! This allows an attacker to control the configurations of the running website. For example, --configPath=/aaa will set the configuration path to a non-existent location, remotely.file_exists check before this that prevented using HTTP, PHP or other many other types of files.ftp:// URI supports file existence checks. Using a file here is blocked by the allow_url_include security feature. But, a template CAN be included! So, they created an FTP server with anonymous access and a file called index.twig with {{7*7}} in it. When craft loads the file, it gets evaluated! system are denied. They found that using {{ ['system', 'id'] | sort('call_user_func') }} bypassed the verification, which I don't really understand how it works.arc://boost/v2/js and arc://boost/v2/css./play endpoint. This was base64 encoded data that was being converted to JSON. This was used for configuring the boosts.LaunchAgent plist files that are run whenever a user logs in or the system starts. By adding a file to this location, arbitrary commands will be executed. When the system restarts after the file write, the attacker has arbitrary command execution on the system./play endpoint was not mentioned anyway. To the author, this indicated that functionality was never meant for public use. To patch this, the functionality for the legacy boost builder was removed. They got a nice 10K bounty for reporting the vulnerability.Makefile that is used to build the router firmware. The make command will expand shell variables before executing a command. Since the package name is controlled by the user and set as an environment variable, this can be used to execute arbitrary bash commands on the server.