PHP contains a library for prepared statements with PDO and contains prepared statements. In most languages, this is sufficient for preventing SQL injection. However, PDO in PHP isn't a true prepared statement. PDO attempts to do the escaping itself instead of binding the information, like many other languages do, which requires their own custom SQL parser. There's a great quote that sums up the whole challenge: "if we can trick the PDO parser into parsing our input as a bound parameter where it shouldn’t, we can get an SQLi in a situation that would otherwise be impossible." They created this as a CTF challenge that contains a potential injection point within a column name; this is because column names cannot be bound. So, the parameter should be escaped adequately with backticks, but this isn't enough! The parser contains a nice specification for how it parses the data. The type 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. Now, the first parameterized item in the query is used with OUR question mark and has to have a value. The substitution turns this into '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. The column '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! Older versions of PHP are much more susceptible to these types of attacks. This is because the lack of usage of backticks allowed for any injection of a question mark or semicolon, leading to SQL injection. There are numerous other ways to exploit this by creating a desync between the parameterization data. Overall, a pretty slick blog post on a fun SQL injection technique.