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!
pull_request_target
, it was checking out the user's PR from the Pull Request. By placing in a malicious pom.xml
file, RCE could be gained in the context of the PR. Since the action can have secrets, this is a serious security issue. Using the secrets and ACCESS_TOKEN, it may have been possible to edit the repository itself.Metadata-Flavor: Google
header. http://169.254.169.254/computeMetadata<</>>/v1/instance/
with a single extra slash did the trick. Sometimes, fuzzing and trying weird things is the way to go! Our systems are just so complex nowadays that it's hard to understand how they work.__Host-
can be used here instead.SameSite
cookie flag can be used to prevent CSRF at a browser level. This has three modes: none, lax and strict. Some browsers default to none because it would break many SSO flows otherwise but others default to lax, breaking many CSRF attacks. Some browsers even default to just two minutes after the cookies were set. This is a very good protection but does have some integration issues.Origin
header is a surprising safeguard as well. Since this cannot be spoofed, if the backend application knows its domain, it can reject based on the Origin very effectively. This creates some edge cases around the header being removed by Referrer-Policy
and by Chrome extensions though.Fetch Metadata
. On a request, the Set-Fetch-Site
header will set it to cross-site, same-site, same-origin or none. Since the browser sets this, it provides excellent CSRF protection by checking this header on the backend. According to some articles, it is now the recommended way to prevent CSRF attacks. duration
: it must be a divisor of CALCULATION_INTERVAL_SECONDS
. This is checked by doing duration % CALCULATION_INTERVAL_SECONDS == 0
. Technically, zero satisfies this requirement.// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.25; contract A { function a() public pure returns (uint256) { return 1 ** 2; } }
overloading
where the compiler can choose implementations for operations like equality. A member function has priority over a non-member function to overwrite this. G++ doesn't always follow this rule though. Clang would choose the member function and the G++ issue was reported 12 years ago.a=b
and code>b=a. This rewrite becomes recursive to do the comparison over and over again if you're not careful.operator==
. Under C++17, this was safe because of the member vs. non member bug was fixed. However, with C++20 and G++ < 14, G++ would incorrectly choose the non-member operation first. This leads to an infinite recursion bug!boost::rational
to represent some compile-time constant expressions. Because of this, Solidity inherited the bug mentioned above. To have this happen you had to be using G++ < 14, Boost < 1.75 and C++ enabled for Solidity builds. This crash occurs with any compile-time rational comparisons.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!