亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何讓 PHP 包含數據 URI(不打開 allow_url_include)?

如何讓 PHP 包含數據 URI(不打開 allow_url_include)?

PHP
揚帆大魚 2023-04-28 15:13:13
在我的 PHP 設置中,出于安全原因,我已經allow_url_include設置FALSE并且很樂意保持這種狀態。當我想include 'https://example.com/path/to/include.php'; // <= THIS WON'T WORK我可以用:include $_SERVER['DOCUMENT_ROOT'].'/path/to/include.php'; // <= BUT THIS WILL到目前為止,一切都很好。然而,現在,我正在嘗試在運行時在 PHP 中創建include 虛擬文件的方法。我想知道 PHP 中是否有等同于 javascript 的東西URL.createObjectURL(),之后我發現 PHP 可以讀取data:URI。這聽起來很有希望......但是因為我已經allow_url_include設置為FALSE,PHP 告訴我它不能include以以下開頭的 URI data::警告:包裝器在服務器配置中被禁用 include(): data://allow_url_include=0所以,而不是:include 'data:application/x-php;base64,ZnVuY3Rpb24gdGVzdDIoKSB7ZWNobyAnVGhpcyB0ZXN0IGZ1bmN0aW9uIDIgaXMgd29ya2luZy4nO30gdGVzdDIoKTs=';我必須file_get_contents像eval這樣使用:$Test_Function = file_get_contents('data:application/x-php;base64,ZnVuY3Rpb24gdGVzdDIoKSB7ZWNobyAnVGhpcyB0ZXN0IGZ1bmN0aW9uIDIgaXMgd29ya2luZy4nO30gdGVzdDIoKTs='); eval("$Test_Function");后一種方法有效eval(),但(尤其是因為它很慢)除非絕對必要,否則我不想使用。有什么方法可以讓 PHP 訪問includeURI data:,而無需打開allow_url_include?注一:您可能對我在這里使用 base-64 編碼的內容感到好奇:ZnVuY3Rpb24gdGVzdDIoKSB7ZWNobyAnVGhpcyB0ZXN0IGZ1bmN0aW9uIDIgaXMgd29ya2luZy4nO30gdGVzdDIoKTs=它只是以下內容:function test2() {echo 'This test function 2 is working.';} test2();筆記2:當我第一次嘗試創建一個數據 URI 時(很久之前我在這里發布)我在百分比編碼上犯了一個錯誤,使數據 URI 無效。我嘗試對 Data URI 進行 base-64 編碼(這有效),之后我沒有返回到原始百分比編碼的 Data URI 來找出我哪里出錯了。但是,重要的是要注意(除了混淆)根本沒有理由在數據 URI 中使用 base-64 編碼。以下百分比編碼的數據 URI 在功能上是相同的:data:application/x-php,function%20test2%28%29%20%7Becho%20%27This%20test%20function%202%20is%20working.%27%3B%7D%20test2%28%29%3B注3:雖然,到目前為止,我還沒有成功使用includeData URI while allow_url_includeremains set to FALSE,但我想我會比較一下:編寫一個字符串并eval()在該字符串上運行以執行它創建文件并include在該文件上運行測試包括運行其中一個進程超過 10,000 次。我沒有運行一次單個測試,而是連續運行了一組 6 個測試。總的來說,我跑了 5 組。這就涉及到 10,000 個流程的 5 組 6 次測試。綜上所述:運行eval()(通常但不總是)比簡單地聲明和執行一個函數慢 10 多倍。創建、寫入和保存文件,然后include在該文件上運行比聲明和執行函數慢 1000 多倍。聲明和執行一個簡單函數的平均時間(來自 60,000 個樣本)是 0.000002194s運行相同簡單函數的平均時間eval()(來自 60,000 個樣本)是 0.00009262s因此,任何花費eval()100 倍的時間來解析和執行的字符串,仍然只需要不到百分之一秒( < 0.01s) 的時間即可完成。
查看完整描述

3 回答

?
呼如林

TA貢獻1798條經驗 獲得超3個贊

我想到的一個想法是將生成的代碼保存在一個臨時文件中(在tmpfs中),然后include對其進行處理。


$Test_Function = file_get_contents('data:application/x-php;base64,ZnVuY3Rpb24gdGVzdCgpe2VjaG8nVGhpcyB0ZXN0IGRhdGEgdXJsIGZ1bmN0aW9uIDEgaXMgd29ya2luZy4nO30gdGVzdCgpOw==');


file_put_contents("/mnt/tempfs/<name>.php", "<?php\n$Test_Function");


include "/mnt/tempfs/<name>.php";

關于性能:


tmpfs 工具允許創建內容駐留在虛擬內存中的文件系統。由于此類文件系統上的文件通常駐留在 RAM 中,因此文件訪問速度非??臁?/p>


查看完整回答
反對 回復 2023-04-28
?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

我聞到了X/Y 問題的味道——您已經將URIevaldata:URI 視為特定問題的可能解決方案,并發現了兩者的缺點,但沒有回到最初的問題陳述。

從各種評論中,我們可以將問題定義為找到一種機制:

  1. 可以執行任意動態代碼

  2. 具有與正常相似的解析性能include

  3. 將允許代碼緩存在 OpCache 中

  4. 不需要在其他地方放松安全

你說eval在第 2 點(因為它啟動了一個新的解析器)和第 3 點(因為沒有可供 OpCache 使用的密鑰)失敗。

您已經確定data:URI 在第 4 點失?。ㄒ驗樗鼈冃枰?code>allow_url_include),但我懷疑它們在第 2 點(因為 base64 解碼是一項重要的開銷)和第 3 點(因為 OpCache 不支持緩存任意流;我相信它只支持文件路徑和 PHAR 內容)

更好的整體解決方案是將代碼寫入“真實”文件,使用內存文件系統(例如tmpfs提高性能)。這符合上述所有四個標準,因為就 PHP 而言,它與任何其他源文件相同;唯一的額外開銷是將文件寫入虛擬文件系統的 I/O 速度。

關鍵優化將確保您跟蹤動態內容何時更改,從某種修訂 ID 或字符串的哈希生成唯一的文件路徑。這可以實現兩件事:

  1. 您可以跳過寫入磁盤上已存在的文件,從而節省 I/O 時間

  2. OpCache 將能夠緩存此文件的內容并重新使用它,即使您設置opcache.validate_timestamps為 false ,您也可以確信正確的代碼會運行


查看完整回答
反對 回復 2023-04-28
?
一只甜甜圈

TA貢獻1836條經驗 獲得超5個贊

您可以嘗試編寫您的data:php://memory。因為它在那里就像普通文件一樣,你可以包括它嗎?



查看完整回答
反對 回復 2023-04-28
  • 3 回答
  • 0 關注
  • 223 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號