0x01 bypass Introduction
We know that PHP query strings (in the text or URL) into an internal $_GET
or associative array $_POST
. For example: /?foo=bar
to become Array([foo] => “bar”)
. It is worth noting that, delete or replace the query string parsing underlined in the process of turning some characters. For example, /?%20news[id%00=42
it will be converted to Array([news_id] => 42)
. If one IDS/IPS
or WAF
there is a rule that when the news_id
value of the parameter is a non-numeric value of the interception, then we can bypass with the following statement:
/news.php?%20news[id%00=42"+AND+1=0--
0x02 php parsing features introduced
PHP need to convert all the parameters to a valid variable name, so when parsing the query string, it will do two things:
-
Delete whitespace
-
To convert some characters to underscore (including spaces)
E.g:
User input | Decoded PHP | variable name |
---|---|---|
20foo_bar% 00% | foo_bar | foo_bar |
foo%20bar%00 | foo bar | foo_bar |
foo%5bbar | foo[bar | foo_bar |
The above results we can fuzz up
script as follows:
<?php
foreach(
[
"{chr}foo_bar",
"foo{chr}bar",
"foo_bar{chr}"
] as $k => $arg) {
for($i=0;$i<=255;$i++) {
echo "\033[999D\033[K\r";
echo "[".$arg."] check ".bin2hex(chr($i))."";
parse_str(str_replace("{chr}",chr($i),$arg)."=bla",$o);
/* yes... I've added a sleep time on each loop just for
the scenic effect :)
like that movie with unrealistic
brute-force where the password are obtained
one byte at a time (∩`-´)⊃━☆゚.*・。゚
*/
usleep(5000);
if(isset($o["foo_bar"])) {
echo "\033[999D\033[K\r";
echo $arg." -> ".bin2hex(chr($i))." (".chr($i).")\n";
}
}
echo "\033[999D\033[K\r";
echo "\n";
}