A friend challenged me in a programming question: You have a list of paths, make the paths a multidimensional associative array of paths.
Sample input:
$paths = [
"a/a/a",
"a/a/b",
"a/b/a"
];
Sample output:
array(1) {
["a"]=>
array(2) {
["a"]=>
array(2) {
["a"]=>
string(4) "file"
["b"]=>
string(4) "file"
}
["b"]=>
array(1) {
["a"]=>
string(4) "file"
}
}
}
Of course I could've used recursion or a simple loop and references, but a lazier solution crossed my mind, making PHP engine do all the work.
foreach($paths as $path) {
$filtered = addslashes($path);
$arrid = "['".str_replace("/", "']['", $filtered)."']";
eval("\$out$arrid = 'file';");
}
So, each path a/a/a
gets converted to $out['a']['a']['a'] = 'file';
, and then evalled. Since PHP doesn't require creating the array before using it, this solution works. The key names are inside a single quote, not a double quote, so you can't include a local variable, and '
and other characters are backslashed, so I'm thinking you can't escape from the key with a bad pathname. This usage of addslashes()
is even used as an example in the language documentation:
An example use of addslashes() is when you're entering data into string that is evaluated by PHP.
However, I immediately thought that this solution was unsecure because eval()
is evil. I wouldn't run this code in production, because eval()
is just unnecessary and always risky, a single error can lead to RCE, there are better solutions without it, and it's slow, 2x slower than the recursive solution I wrote, I just wanted to solve the challenge in a weird way, and know what to do if I see a similiar code during a code analysis. I tried breaking it with no luck. I know of multi-byte and encoding attacks on addslashes, but I feel like it isn't applicable here.
So, can you really exploit this code?