国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

PHP中Mkdir函數如何使用

發(fā)布時(shí)間:2021-09-14 11:25 來(lái)源:億速云 閱讀:0 作者:Leah 欄目: 網(wǎng)絡(luò )安全

本篇文章給大家分享的是有關(guān)PHP中Mkdir函數如何使用,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習,希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著(zhù)小編一起來(lái)看看吧。

此過(guò)程中例如需要寫(xiě)入目標文件為:

首先需要先寫(xiě)一張

為什么會(huì )這樣?假設直接寫(xiě)目標文件,過(guò)程中會(huì )首先創(chuàng )建目錄:    

其實(shí)這個(gè)過(guò)程是沒(méi)有創(chuàng )建任何目錄的,因為判斷是directoryalready ,到下一步寫(xiě)入圖片這里是Imagick::writeImage,在這里就會(huì )出問(wèn)題。invaildfile path.報錯。因為這里不存在 /var/www/html/wordpress/wp-content/uploads/2019/03/1.jpg?    這個(gè)目錄,這涉及到系統調用,因系統的不同相對于的系統處理函數處理的方式也不同。        

列如在kali 下 Imagick::writeImage寫(xiě)入 ./1?/../1.png     , ./1? 這個(gè)目錄是會(huì )報錯的。具體系統調用如下:

首先判斷了這個(gè)文件的狀態(tài),而后調用openat 打開(kāi)這個(gè)文件并不存在。AT_FDCWD    表示打開(kāi)的文件位置相對于當前目錄。這是我在做的時(shí)候遇到的情況。

但是在 WORDPRESS IMAGE 遠程代碼執行漏洞分析    一文中,甚至其他另一篇。都沒(méi)提到兩次寫(xiě)圖片。難道因為window和linux的不同嗎?就這個(gè)問(wèn)題我進(jìn)行了一次對mkdir的探究。發(fā)現其實(shí)有很有趣。

二、PHP內核 && 系統差異 之mkdir()

2.1 Linux &&PHP 7.3.2-3

mkdir('./1?/../1',777    ,true);

mkdir('./1?/../1',777    ,false);

當第三參數為$recursivetrue     時(shí)可以寫(xiě)目錄,先說(shuō)一下這個(gè)參數的含義$recursive用來(lái)循環(huán)創(chuàng )建目錄。什么意思呢,當false時(shí)只能創(chuàng )建1級目錄,即目錄連接符最后的一個(gè)目錄。而當true        時(shí)是可以創(chuàng )建多級目錄至到最后一個(gè)目錄。列如./a/b/c當abc都不存在時(shí),會(huì )通過(guò)系統函數mkdir循環(huán)創(chuàng )建目錄,abc都會(huì )被創(chuàng )建,但若為false            會(huì )因為走到a處目錄不存在,則不回去創(chuàng )建最后一個(gè)c。

但是第一個(gè)mkdir即使為true卻也沒(méi)有創(chuàng )建1?    目錄,這里我們從php內部mkdir執行情況和 系統 mkdir         執行情況來(lái)探究。

2.1.1PHP_FUNTCION(mkdir)

PHP內調過(guò)程如下圖:

   

我們在出現分支的地方細分 
/php-src/main/streams/plain_wrapper.c

2.1.1.1 $recursive =fasle

其中出現的分支的地方在判斷$recursive 若是不需要循環(huán)創(chuàng )建則直接進(jìn)入php_mkdir

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

跟進(jìn)php_mkdir_ex

首先會(huì )檢查open_basedir,接著(zhù)會(huì )進(jìn)入VCWD_MKDIR    ,VCWD_MKDIR是個(gè)宏命令,有三種不同定義:

在這里我剛開(kāi)始并沒(méi)有考慮太多,跟著(zhù)gdb的流程走,直接執行mkdir(),會(huì )直接調用系統的_mkdir()    . mkdir("./1?/../1",         01411) = -            1 ENOENT (No such file or directory)

會(huì )直接報錯。在預料之類(lèi),linux系統下mkdir是不允許這樣創(chuàng )建目錄的,會(huì )效驗每一層目錄的有效性?;氐降谝淮纬霈F分叉的時(shí)候。

2.1.1.2 $recursive =true

這里會(huì )進(jìn)入expand_filepath_with_mode,這里其實(shí)很熟悉,之前也是在看路徑處理的時(shí)候看到過(guò)這個(gè)函數,它是一個(gè)展開(kāi)函數,會(huì )通過(guò)遞歸的方式展開(kāi)需要被創(chuàng )建的目錄。在其過(guò)程會(huì )先把相對目錄和當前腳本執行目錄評價(jià)起來(lái),若是絕對目錄則忽略. 
其中我們的相對目錄為 ./1?/../1    會(huì )變成 /var/www/html/WordPress/wp-content/themes/4/5/6/./1?/../1 
當前我所在的目錄為 /var/www/html/WordPress/wp-content/themes/4/5/6                     
           然后通過(guò)遞歸的方式 去掉 .././             ,//.并且對應目錄前移,會(huì )變成 /var/www/html/WordPress/wp-content/themes/4/5/6/1                                     
                   然后在傳遞給系統的mkdir函數。

在這個(gè)函數里面存在win32 和linux的不同分支,但在具體處理之前win32判斷了目錄名不能存在 *,?

注意一下此處!     

附上strace ,也是驗證上訴分析過(guò)程

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

2.1.2 Mkdir In Linux

在linux中單純的mkdir是會(huì )層層驗證目錄,而后在創(chuàng )建一級目錄。mkdir 也可以帶參 -p,代表系統層面循環(huán)的創(chuàng )建目錄。 
當執行mkdir -p 時(shí) :

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

 mkdir("1?", 0777        )  = 0

mkdir("1", 0777        )   = 0

我們能看到它并不像php內部那樣,展開(kāi)而后處理 。它會(huì )層層按照輸入的目錄創(chuàng )建。

2.2 window&& PHP 7.0.12

這里是我為什么要探究的一個(gè)重要問(wèn)題點(diǎn)所在,在前面我提到的那篇文章中作者在window下實(shí)驗當$recursivefalse        才能創(chuàng )建成功,正好是反著(zhù)的。作者的解釋的false的時(shí)候不會(huì )去層層判斷,但是真的是這樣嗎?

而后我也做了一個(gè)驗證性的實(shí)驗,在window 上用 php 5.6做了這個(gè)測試,但是結果讓我疑惑了,無(wú)論在false還是 true        的情況都不會(huì )創(chuàng )建目錄.而且報錯也很有意思,在false的情況下報錯 no error 但是就是無(wú)法創(chuàng )建。在true的情況下報錯 invaild path。

難道是php-cli 問(wèn)題?我又用cgi測了一遍,發(fā)現同樣是這樣。有意思,而后我通過(guò)郵件聯(lián)系了那篇文章作者,詢(xún)問(wèn)其版本號。很快,得到了他的答復,php-7.0.12。

于是下載php-7.0.12源碼 重新編譯加debug,此處省略1000字... 
在編譯完成后我迫不及待的試了一下,同樣如此和我的php5.6 一摸一樣,無(wú)論在cli 模式 或者 cgi 模式下都是無(wú)法復現作者文中的情況。這到底問(wèn)題出在哪呢?

先調了再說(shuō),VS調試php 網(wǎng)上基本上沒(méi)有詳細的介紹,有的都是Vscode。我不知道如何啟動(dòng)并調試,只好想了個(gè)attach的辦法。在mkdir前面寫(xiě)上sleep(10)        ,但是這樣做,其實(shí)是有一點(diǎn)雞肋的,php內核初始化過(guò)程你其實(shí)抓不到的,但是用在這里夠了,還是在php_plain_files_mkdir這個(gè)地方下斷,刷新頁(yè)面,attach到啟動(dòng)的php-cgi 上。

2.2.1PHP_FUNCTION(mkdir)

2.2.1.1 $recursive== false

還是先分析false的情況,前面都一樣,不同的是在php_mkdir_ex            中VCWD_MKDIR調用的函數不一樣

這次走到不一樣的調用上

跟進(jìn)virtual_mkdir

同樣調用了virtual_file_ex(),前面有一點(diǎn)沒(méi)提到,在expand展開(kāi)路徑的過(guò)程中最后其實(shí)也是進(jìn)入的這個(gè)函數,前面說(shuō)過(guò)在處理的過(guò)程中若是win32的情況會(huì )判斷路徑存不存在 *            , ?.若是存在則會(huì )直接返回1,不會(huì )進(jìn)入后面寫(xiě)路徑。為什么那篇文章的作者會(huì )在false的情況下寫(xiě)成功呢?

2.2.1.1 $recursive== true

這里前面說(shuō)過(guò)這里會(huì )進(jìn)行expand過(guò)程,但是同樣會(huì )判斷路徑名中存不存在*?            ,會(huì )報錯 Invaild Path。

2.2.2 mkdir inwindow

這里因為沒(méi)有都沒(méi)有執行到寫(xiě)目錄。此處我們還無(wú)法探究window系統mkdir 函數是如何執行的。

三、程安全與非線(xiàn)程安全

重新梳理一下,現在是三種不一樣的情況: 
 linux /true 可寫(xiě) 
 window/7.0.12 : 

 1. false 可寫(xiě) 
 2. true/false 都不可寫(xiě)

window 出現了兩種情況。仔細在走一遍window/false的情況,現在我唯一沒(méi)有考慮到是VCWD_MKDIR             選擇情況。前面都是跟著(zhù)調試流程走的,這是唯一可能出現分叉的地方,重新看一下它的兩種種宏定義:        

若非那片文章作者,是走的第二個(gè)define,于是我把第一個(gè)define先注釋掉了,換上了第二個(gè)define,再重新編譯一邊,結果竟然出現了和那篇作者一樣的情況。但是這里有一個(gè)小小不同,寫(xiě)入的目錄是相對于php-cgi.exe解釋器的,不是相對于WWW的網(wǎng)站根目錄下的,當你看了下面的分析以后,應該會(huì )給你一個(gè)答案,那么很顯然問(wèn)題現在出現在 VIRTUAL_DIR             定義的情況,在它沒(méi)有定義的情況下,才會(huì )走到第二個(gè)define,我看看VIRTUAL_DIR 

是在哪被定義的

/php-src/Zend/zend_virtual_cwd.h

熟悉php內核的朋友不會(huì )陌生ZTS,這是php 線(xiàn)程安全的標志。用來(lái)應對那些使用線(xiàn)程來(lái)處理并發(fā)請求的Web,列如window下的IIS,worker_mpm模式下的apahce,生活在線(xiàn)程里面的php需要考慮線(xiàn)程間的讀寫(xiě)同時(shí)也要保證線(xiàn)程間是安全,所以php需要自己提供ZTS層來(lái)管理線(xiàn)程間的操作。當定義了ZTS時(shí)候,就也同時(shí)定義了虛擬目錄(VIRTUAL_DIR)。為什么會(huì )存在虛擬目錄這一說(shuō)法呢,其實(shí)很簡(jiǎn)單你通過(guò)對應virtual_file_ex()            可以看出來(lái),這個(gè)函數的目的在于針對相對路徑替換出完整的絕對路徑。舉很簡(jiǎn)單的例子,php腳本中寫(xiě)的相對路徑,其相對路徑一定是針對于該腳本的。在執行腳本的過(guò)程中,會(huì )進(jìn)入相應的php 內核里面的php_execute_script(),其中有一步是VCWD_CHDIR_FILE(filename)                ,這是用來(lái)根據要執行的腳本位置去切換當前目錄,同樣這個(gè)宏定義有兩個(gè)不同的函數,一個(gè)是在虛擬目錄下切換目錄,一個(gè)是非線(xiàn)程安全環(huán)境下單線(xiàn)程切換目錄,不同是在線(xiàn)程安全下切換目錄,并不是直接調用系統的_chdir(),                    而是將執行腳本的目錄存儲在TSRMG中,并給定一個(gè)cwd_globals_id,要用的時(shí)候再去取,比如創(chuàng )建目錄,寫(xiě)文件。因為在多線(xiàn)程環(huán)境不能直接修改當前進(jìn)程的目錄,只能預定義一個(gè)變量保存各線(xiàn)程的當前目錄。                        可以看到在線(xiàn)程安全的模式下,若是給的相對路徑,都會(huì )出現當前目錄和相對目錄的拼接。且都在win32的環(huán)境都會(huì )檢測目錄是否包含* ,?                            .        

四、結論匯總

我有注意到那篇的文章作者是在window 上用的phpstudy,我也去看了一下phpstudy的是否有7.0.12的版本,存在一個(gè) php-7.0.12-nts+Apache             確實(shí)也是非線(xiàn)程安全。也印證上面我修改php7.0.12 重新編譯的結果,但是一個(gè)很有趣的東西是,window的系統調用API _mkdir() 是存在和php內部一樣的路徑展開(kāi)功能,即他是允許這樣寫(xiě)的./1?/../1                 可以在當前目錄下寫(xiě)入文件夾1的,這和linux不一樣,linux的系統函數是逐層判斷。在php7.1之后,改變了系統創(chuàng )建目錄的API,從_mkdir                     變成了CreateDirectoryW,但是不變的是還是可以存在路徑展開(kāi)的功能。即便你這樣寫(xiě):@@#@$@#$^%$&&**/@!#@!$!%/../../evil                        也是可以創(chuàng )建目錄evil的,可以算是一個(gè)小技巧。但是條件是在windowphp非線(xiàn)程安全模式和PHP_FUNCTION(mkdir)                            第三個(gè)參數為false的情況下是可以這樣寫(xiě)目錄的??梢运闶且粋€(gè)小tips吧。結合相應的應用特點(diǎn),是可以用到的,而且php版本一般都是非線(xiàn)程安全的,在nginx下都是多進(jìn)程處理php,即非線(xiàn)程安全。apache只有在worker_mpm才是多線(xiàn)程的,一般也不常用。一般都是prefork_mpm + php_mod,即便是fastcgi也是多進(jìn)程。利用環(huán)境還是比較常見(jiàn)的。

        

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

欧美精品亚洲精品日韩专区一乛方| 亚洲AV无码专区国产乱码京东传媒| 成人午夜亚洲精品无码区| 免费A级猛片在线观看| 午夜A级理论片在线播放不卡| 蜜桃视频无码区在线观看|