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!
Control bitfield in SepMediumDaclSd, it will skip the integrity check. Next, get the token of the renderer process via NtQueryInformationSystem. These steps are the same for the Chrome sandbox escape, but there are a few additional steps to take.NtQuerySystemInformation to get a token, they got an access denied error because the renderprocess runs at a low privilege level. To fix this issue, they used the previous OOB write to overwrite the SE_SACL_PRESENT field to skip the integrity control check. Since this was a 32-byte write, they had to be clever at the byte offset to do this at though.CreateProcess. The solution? Inject the code from the renderer process into another process (winlogon.exe) and have it call CreateProcess instead. This gives them code execution as a privileged user from Chrome! cargo-fuzz, but this was slow and didn't make any internal calls. secp256k1 0.27.0 version is not compatible with cargo-fuzz because it fails all the time. So, they had to use a different version for fuzzing. Secondly, they ended up modifying the FuelVM somewhat to add the offset into the execution data to have this within the context of the program. %command to execute arbitrary commands in the environment. The author points out that it works sometimes and is like a child. After some time, though, it becomes more and more consistent in execution. I am guessing that it sees its past actions and is more likely to perform the actions as a result. pgrep with non-dropped privileges AND with an absolute path. By changing the PATH variables, it's possible to change the binary being used and execute it as root. ANYNOEOF is defined as [\001-\377]. When adding a null byte and a question mark - ?\0 - it will see this as a SPECIAL and note a literal now. Naturally, this error occurs because it's trying to bind two things in the query. However, adding a comment - code>?#\0 - can easily remediate this problem. So, are we done? Nope! Still some more trickery for this to work.'x'#\0, where the x is a controllable parameter and the parameterization adds the single quotes around the query because it thinks it's a string. There's another issue now: a null byte cannot be in a comment. The problem can be solved by adding a semicolon between the comment and nullbyte to make it a new line. With the stolen parameter x`;# and the same column name, this problem is solved.'x does not exist, though. What now? PDO still thinks that our injection point is in a string! Placing a \ as the first character in the string causes some MAJOR havoc. It will escape the single quote to allow for a context escape. The column name \?#\0 and the stolen parameter with x` FROM... allows us to create a legitimate query to perform SQL injection. Neat! GET request to create the API keys. This ALSO worked with the admin user. By itself, this doesn't have much impact, though. CORS was misconfigured. In this case, the origin was simply reflected, and credentials were sent. The combination of these two meant that the generated key from above could be stolen. Pretty good impact!Perl::Tidy to make it prettier to read, they still wanted some help reading it. Naturally, they used AI to deobfuscate the code. It had some missing issues, but much of it was correct. eval. The subroutine _fop implemented a primitive templating engine. If something had [%...%], then it was evaluated as Perl code. ciwweb.pl input hid_Random_ACARAT that plugged into this sink with [%257*7%25] to return 49. By adding backticks, this turns into pretty easy code injection.call() to a function. It has some Yul code that is worth discussing further:
calldata of the program into EVM memory.swapAmount in the calldata via a user controlled index. This is where the fun begins!swapAmountInDataIndex is a 32 bit integer.
ptr + 36 (0x24) + swapAmountInDataIndex * 32 (0x20).
swapAmountInDataIndex variable is a uin256. Unfortantely, there's an integer overflow in this calculation. When performing the multiplication on the index, this can overflow. With a specially crafted value, it's possible to wrap back around to modify the function selector that had previously been verified. An arbitrary call in the context of a Solidity smart contract is effectively game over.account.data point directly to the hosts buffer for the Solana memory region. Because everything is now using a shared pointer instead of a personal pointer, the validation must happen on each write called copy-on-write. This changes a key invariant of the system. Originally, all of the data was directly read from the underlying DB implementation. So, a copy was added to memory and updated once it was written to.MemoryRegions structure for the previous call still points to the old buffer. To do this, it grabs the vm-data_addr to find the memory region of the original mapping to eventually update it.CallerAccount.vm_data_addr is stored completely in the VM's heap memory. By modifying the AccountInfo.data pointer in VM memory before triggering a CPI call, an attacker can forge an arbitrary vm_data_addr value. This causes the wrong memory region to have its host address updated, being mapped to an arbitrary location in virtual memory.MemoryRegion. By setting a simple value on the account data, we can locate it after some searching.host_addr and set its state to writable.tar implementation. This article describes a lot of reverse engineering of the device and a firmware downgrade vulnerability they found in the process. /opt/cookey.txt is found to contain the encryption key. After some reviewing of a customized kernel driver, they are able to decrypt locally, but cannot modify it because the data is signed. cs.tar and the second partition contains recipes, cloud settings, and a recovery firmware image.version section is what we're after. This contains three values: date, comment and force_flag, with the first two being arrays. The original usage of this contained a security issue: the firmware could be downgraded by swapping firmware update file sections between versions. A classic replay issue, but this was the past, and we needed a new vulnerability by swapping these individual sections around. AES-EAX mode. This combines AES-CTR for encryption and OMAC-based tag for integrity. Each section is RSA-signed, but the nonce and tag are excluded from the signature so that they can be tampered with. We know the encryption algorithm in this case, but we're unable to modify anything because of the signature. Or can we?PT = C0 XOR K0 in most cases. This can be rearranged to K0' = C0 XOR P0'. If we XOR our plaintext with the ciphertext, we can know what key (nonce starting value) it can be generated with. Since we control the nonce and know the key, we can reverse the encryption process to find a nonce that will match this. Neat!force_flag is something that we want to be set to 1 though. By brute forcing enough keys, it's possible to set this to 1. All of this works because A) the nonce is not verified and B) the header information with the date, comment, and force_flag is a singular encrypted piece of data with nothing else in it. I find it weird that the signature is unique per section, personally.