Content Management Systems always end up suffering, at least a little, from the Inner Platform Effect. There’s the additional problem that, unlike say, a big ol’ enterprise HR system or similar, CMSes are useful for just about everyone. It’s a quick and easy way to put together a site which anyone can maintain. But it never has enough features for your content. So you always install plugins- plugins of wildly varying quality and compatibility.
Lucio Crusca was doing a security audit of a Joomla site, found this block inside an installed plugin:
<?php if(!empty($MyForm->formrow->scriptcode)){
echo "<script type='text/javascript'>\n";
echo "//<![CDATA[\n";
eval("?>".$MyForm->formrow->scriptcode);
echo "//]]>\n";
echo "</script>\n";
}
?>
Let’s just focus on the echo
s to start. We’re directly outputting a <script>
tag into the body of the page, and doing the bonus CDATA
wrapper, ensuring compatibility with XHTML, which is nice if if your code ever slips into the mirror universe where people thought mashing up HTML’s formatting and XML’s formality into a single document standard was a good idea.
But that, of course, is not the WTF. The WTF is the body of the script, which is output into the document via this line:
eval("?>".$MyForm->formrow->scriptcode);
$MyForm
is submitted from a client-side form. It, ostensibly, contains some executable PHP code, which outputs some JavaScript into the body of the document. eval
, of course, just executes that code. Blindly. Hoping for the best. With full access to the current executable scope.
Now, there’s one important thing to note about PHP’s eval
compared to other languages. Note the opening ?>
. The eval
block implicitly assumes an opening <?php
tag, which you can exit with a ?>
. This lets you, in your eval
, mix straight PHP and HTML content together:
eval("if (foo) { ?> <p>This is just pure HTML</p> <?php }");
So you see, the developer responsible for this was being “smart”. They knew just enough to understand how to use eval
to inject HTML content, and just went on to assume that no one would ever think about tossing a <?php
in there to get back into a server-side execution context.
In any case, something about the phrasing of the PHP docs on eval
makes me chuckle:
Caution The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
“Its use thus is discouraged” should be the new “considered harmful”.