Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use the Mkdir function in PHP

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

This article is to share with you about how to use the Mkdir function in PHP, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

During this process, for example, the target file needs to be written as follows:

First of all, you need to write one.

Why is this? Suppose you write the target file directly, and the directory is created first in the process:

In fact, this process does not create any directory, because it is judged to be directoryalready, to the next step to write the image here is Imagick::writeImage, there will be a problem here. Invaildfile path. Report an error. Because / var/www/html/wordpress/wp-content/uploads/2019/03/1.jpg doesn't exist here? This directory, which involves system calls, varies from system to system relative to the way the function is handled.

As listed in kali, Imagick::writeImage writes. / 1?/../1.png,. / 1? This catalog will report an error. The specific system calls are as follows:

First determine the status of the file, and then call openat to open the file does not exist. AT_FDCWD indicates that the location of the open file is relative to the current directory. This is what happened to me when I was doing it.

But in WORDPRESS IMAGE remote code execution vulnerability analysis, or even another article. There is no mention of writing pictures twice. Is it because window is different from linux? I made an inquiry into mkdir on this issue. I found it very interesting.

2. PHP kernel & & system differences mkdir () 2.1 Linux & & PHP 7.3.2-3

Mkdir ('. / 1 hammer hammer... 1 pound pound 777, true)

Mkdir (. / 1? /.. / 1 false 777)

You can write a directory when the third parameter is $recursive and true. Let's first talk about the meaning of this parameter. $recursive is used to create directories in a loop. What do you mean, when false, you can only create a level 1 directory, that is, the last directory of the directory connector. When true, you can create a multi-level directory to the last directory. Column such as. / a/b/c when the abc does not exist, the directory will be created through the system function mkdir loop, and the abc will be created, but if the false will go to a because the directory does not exist, it will not go back to create the last c.

But the first mkdir, even for true, did not create a 1? Directory, here we explore from the php internal mkdir implementation and system mkdir implementation.

2.1.1PHP_FUNTCION (mkdir)

The internal adjustment process of PHP is shown below:

We subdivide where the branches appear.

/ php-src/main/streams/plain_wrapper.c

2.1.1.1$ recursive = fasle

The place where the branch appears is to judge $recursive. If you do not need to create a loop, go directly to php_mkdir.

/ php-src/ext/standard/file.c

Follow up php_mkdir_ex

Open_basedir is checked first, and then VCWD_MKDIR is entered. VCWD_MKDIR is a macro command with three different definitions:

I didn't think too much about it at the beginning. If I follow the gdb process and directly execute mkdir (), I will directly call the system's _ mkdir (). Mkdir (". / 1 ENOENT No such file or directory) 1", 01411)

Will report the wrong message directly. In anticipation, mkdir in linux systems does not allow the creation of directories in this way, and will verify the validity of each layer of directories. Go back to the first time there were bifurcations.

2.1.1.2$ recursive = true

Here you will enter expand_filepath_with_mode, which is actually very familiar here. I have seen this function before when looking at path processing. It is an expansion function that expands the directory that needs to be created recursively. In the process, the relative directory and the current script execution directory are evaluated, and if the absolute directory is ignored.

Where our relative catalog is. / 1 hammer.. 1 will become / var/www/html/WordPress/wp-content/themes/4/5/6/./1?/../1

My current directory is / var/www/html/WordPress/wp-content/themes/4/5/6

Then remove.. /,. /, / / by recursive method. And the corresponding directory moves forward, it will become / var/www/html/WordPress/wp-content/themes/4/5/6/1

Then the mkdir function passed to the system.

There are different branches of win32 and linux in this function, but before the specific processing, win32 determines that the directory name cannot exist.

Pay attention here!

Strace is attached to verify the appeal analysis process.

1. Mkdir ("/ var/www/html/WordPress/wp-content/themes/4/5/6/1", 01411) = 0

2.1.2 Mkdir In Linux

In linux, simple mkdir validates directories layer by layer, and then creates first-level directories. Mkdir can also take the parameter-p, which represents the creation directory of the system-level loop.

When executing mkdir-p:

Strace-f-e trace = mkdir mkdir-p. / 1? /.. / 1

Mkdir ("1?", 0777) = 0

Mkdir ("1", 0777) = 0

We can see that it doesn't unfold and then process as it does inside php. It is created layer by layer according to the directory entered.

2.2 window&& PHP 7.0.12

Here is an important question why I want to explore. In the article I mentioned earlier, the author experimented under window when $recursive was false to create successfully, just the opposite. The author's interpretation of the false will not go to layers of judgment, but is it really the case?

Then I did a confirmatory experiment with php 5.6on window, but the result made me wonder that neither false nor true would create a directory. And the error report is also very interesting, in the case of false error no error but can not be created. Error invaild path in the case of true.

Is it the php-cli problem? I tested it again with cgi and found that it was the same. Interesting, then I contacted the author of the article by e-mail and asked for its version number. Soon, I got his reply, php-7.0.12.

So download php-7.0.12 source code recompile plus debug, omit 1000 words here.

I couldn't wait to try it after the compilation was completed, and just like my php5.6, I couldn't reproduce the situation in the author's article in either cli mode or cgi mode. What is the problem with this?

After adjusting first, there is basically no detailed introduction to VS debugging php on the Internet, some of which are Vscode. I didn't know how to start and debug, so I had to think of a way to attach. Write sleep (10) in front of the mkdir, but this is actually a bit of a chicken. You can't actually catch the initialization process of the php kernel, but it's enough to use it here, or break it in the php_plain_files_mkdir place, refresh the page, and attach to the startup php-cgi.

2.2.1PHP_FUNCTION (mkdir)

2.2.1.1$ recursive== false

It is the same as before to analyze the situation of false first, except that the function called by VCWD_MKDIR in php_mkdir_ex is different.

This time we go to a different call.

Follow up virtual_mkdir

Virtual_file_ex () is also called. There is one point not mentioned above. In fact, this function is entered at the end of the process of expanding the path by expand. As mentioned earlier, if the case of win32 is in the process of processing, it will determine whether the path exists or not. If it exists, it will directly return 1 and will not enter the subsequent write path. Why did the author of that article succeed in the case of false?

2.2.1.1$ recursive== true

As mentioned earlier, the expand process will take place here, but it will also determine whether there is *,? in the pathname, and will report an error Invaild Path.

2.2.2 mkdir inwindow

Here because none of them are executed to the write directory. We can't explore how the mkdir function of the window system is executed here.

III. Program safety and non-thread safety

To sort it out, there are three different situations:

Linux / true writable

Window/7.0.12:

1. False is writable

2. True/false is not writable.

There are two things that happen to window. Go through the window/false situation carefully, and now the only thing I don't think about is the VCWD_MKDIR choice. The previous steps follow the debugging process, which is the only place where bifurcations can occur. Take a fresh look at its two macro definitions:

If it hadn't been for the author of that article, it was the second define, so I commented out the first define, replaced it with the second define, and then recompiled it, and it turned out to be the same as the author. But there is a small difference here. The directory written is relative to the php-cgi.exe interpreter, not to the root directory of the WWW website. When you read the following analysis, it should give you an answer. Then it is obvious that the problem now appears in the case of VIRTUAL_DIR definition. When it is not defined, it will go to the second define. Let me take a look at VIRTUAL_DIR.

Where is it defined?

/ php-src/Zend/zend_virtual_cwd.h

Friends who are familiar with the php kernel are no stranger to ZTS, which is a sign of php thread safety. Used to deal with Web servers that use threads to handle concurrent requests, such as apahce in IIS,worker_mpm mode under window. Php living in threads needs to consider inter-thread reading and writing while ensuring inter-thread security, so php needs to provide its own ZTS layer to manage inter-thread operations. When ZTS is defined, a virtual directory (VIRTUAL_DIR) is also defined. Why there is a virtual directory is actually very simple, as you can see from the corresponding virtual_file_ex (). The purpose of this function is to replace the complete absolute path for the relative path. To take a very simple example, the relative path written in the php script must be specific to the script. In the process of executing the script, you will enter php_execute_script () in the corresponding php kernel. One step is VCWD_CHDIR_FILE (filename), which is used to switch the current directory according to the location of the script to be executed. Similarly, this macro definition has two different functions, one is to switch directories under the virtual directory, the other is to switch directories in a non-thread-safe environment, and the difference is to switch directories under thread safety. Instead of directly calling the system's _ chdir (), the directory where the script is executed is stored in TSRMG, given a cwd_globals_id, and then fetched when you want to use it, such as creating a directory and writing files. Because the directory of the current process cannot be directly modified in a multithreaded environment, only one variable can be predefined to hold the current directory of each thread. You can see that in thread-safe mode, if the relative path is given, the splicing of the current directory and the relative directory will appear. And all environments in win32 will check whether the directory contains *,?.

IV. Summary of conclusions

I have noticed that the author of that article uses phpstudy on window. I also went to see if there is a 7.0.12 version of phpstudy, and the existence of a php-7.0.12-nts+Apache is indeed non-thread safe. Also confirm the above I modified the results of php7.0.12 recompilation, but a very interesting thing is that window's system call API _ mkdir () is the same path expansion function as php, that is, it is allowed to write like this. / 1 scratch pedigree 1 can be written in the current directory to folder 1, which is different from linux, the system function of linux is judged layer by layer. After php7.1, the API of the directory created by the system is changed from _ mkdir to CreateDirectoryW, but the same thing is that path expansion can still exist. Even if you write: @ @ # @ $@ ^% $& & * * / @! # @! $!% /.. /.. / evil can also create a directory evil, which can be regarded as a trick. But the condition is that the directory can be written in this way if php is in non-thread safe mode under window and the third parameter of PHP_FUNCTION (mkdir) is false. It can be regarded as a little tips. Combined with the corresponding application characteristics, it can be used, and php versions are generally non-thread-safe, in nginx are multi-process processing php, that is, non-thread-safe. Apache is multithreaded only in worker_mpm and is not commonly used. It is usually prefork_mpm + php_mod, and even fastcgi is multi-process. It is quite common to take advantage of the environment.

The above is how to use the Mkdir function in PHP. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report