The <cross-domain-policy> mangling in OutputHandler.php (see bug 66776) poses a potentially severe security problem for API clients written in PHP, in that format=php is affected.
Let's look at the body of wfMangleFlashPolicy():
Avoid weird excessive memory usage in PCRE on big articles
if ( preg_match( '/\<\s*cross-domain-policy\s*\>/i', $s ) ) {
return preg_replace( '/\<\s*cross-domain-policy\s*\>/i', '<NOT-cross-domain-policy>', $s );
} else {
return $s;
}
The problem is that the regex can match strings of various lengths (different numbers of whitespace characters) yet replace them with a fixed string of constant, possibly differing length. This is done after PHP serialization and allows an attacker who can control just two string fields in an API response to inject arbitrary serialized values (including objects, for which the security concerns are well-known).
Here's an example of a serialize()'d string:
s:54:"And he said, "Are you my son Esau?"; and said, "I am":";
serialize() does not have to escape syntactically important characters, including '"' and ';', because the string's length has already been encoded in the data stream.
In the first string, the attacker would add a <cross-domain-policy> tag with enough whitespace to push the expected location of the end-of-string delimiter into the body of the second string, swallowing all bytes up until that point. Then a fake end-of-string delimiter would be added, followed by an arbitrary serialized object, and the well-known exploitation techniques for unserialization of attacker-controlled data would apply.
An example attack:
- The attacker makes a single edit to "Wikitest:Sandbox":
Edit summary: <cross-domain-policy[95 spaces]>
Content: ";O:3:"Foo":0:{}
- A bot requests the URL http://www.mediawiki.test/w/api.php?action=query&format=php&prop=revisions&rvprop=comment|content&titles=Wikitest:Sandbox.
- The API generates and outputs the response, which is then predictably and insecurely mangled (in the name of security!).
- The bot tries to unserialize the response, and Foo::wakeup() is called, followed by Foo::destruct(). With some additional work on the "Content" part of his edit, the attacker may be able to overwrite arbitrary files or execute arbitrary shell commands or PHP code.
One major limitation: if I'm not mistaken, null bytes are not allowed. That would interfere with attempts to manipulate protected and private properties.
Version: unspecified
Severity: normal