Within this update, TYPO3 team fixed a vulnerability that I've discovered a few weeks ago. In detail, this discovery pertains to a previous vulnerability fixed in TYPO3-SA-2010-020 and discovered by Gregor Kopf.
TYP03 decided to follow a policy of least disclosure. Although it's an Open Source project, no technical details are available in the wild besides these (1,2). As I strongly believe that this practice does not improve the overall security (as mentioned in a previous post), I've decided to briefly explain this interesting flaw.
From the advisory, we can actually deduce two important concepts:
A Remote File Disclosure vulnerability in the jumpUrl mechanism [..] Because of a non-typesafe comparison between the submitted and the calculated hash, it is possible [..]In a nutshell, the JumpUrl mechanism allows to track access on web pages and provided files (e.g. /index.php?id=2&type=0&jumpurl=/etc/passwd&juSecure=1&locationData=2%3a&juHash=2b1928bfab)
The patch (see this shell script) simply replaces the two equal signs with three (loose vs strict comparisons).
That's the affected code:
Having this knowledge, it is probably clear to the reader that the overall goal is to bypass the comparison between $juHash and $calcJuHash. While the former is user supplied (string or array), the latter is derived from a substr(md5_value,10) (string).
In PHP, comparisons involving numerical strings result in unexpected behaviors (at least for me before studying this chapter).
If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically
If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.For instance, the following comparisons are always TRUE:
if(0=="php")-> TRUEAnd again, also the following comparisons are TRUE:
if(12=="12php")-> TRUE
if(110=="110")-> TRUE
if(100=="10E1")-> TRUE
if(array()==NULL) -> TRUE
[..]
If("0"=="0E19280311"){}Consequently, we can pad and wait till the substring of an md5 hash resembles this form. If you do the math, you will discover that the combined probability of having such calculated hash is considerably less than pure bruteforcing.
If("0"=="0E00106552"){}
If("0"=="0E81046233"){}
~37037037 max trials (worth case) VS 3656158440062976 all possibilitiesIn practice, the number of iterations is even less as "0000E13131" and similar strings are also accepted.
To further improve this attack, I've discovered another bypass (TYPO3-SA-2010-022) which allows the disclosure of TYPO3_CONF_VARS['SYS']['encryptionKey']. In this way, it is possible to retrieve the key once and download multiple files without repeating the entire process. Using multiple requests, this attack takes a few minutes (8-20 minutes in a local network). A real coder can surely enhance it.
As you can see from the exploit (posted on The Exploit Database), the fileDenyPattern mechanism bypass is pretty trivial. A demonstration video is also available here (slow connection, sorry).
Keep your TYPO3 installation updated! A patch is already available from the vendor's site.
@_ikki
Hello,
ReplyDeleteVery nice summary. The weak typing of php is very comfortable from a developers point of view.
But this example illustrates undoubtfully, that without strong input validation small mistakes may lead to serious security vulnerabilities.
Regards,
Marc
This comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete