摘要:第行通過類提供的方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個類對象。
前言
上個星期碰到個客戶使用Swoole Compiler加密Drupal導致Drupal項目無法運行的問題,逐步排查后總結問題是Drupal中有部分代碼直接通過file_get_contents獲取PHP源碼導致的,因為項目代碼是加密過后的,所以直接獲取PHP源碼解析是獲取不到想要的內容的。
注:
Swoole Compiler:https://www.swoole-cloud.com/compiler.html
Drupal是使用PHP語言編寫的開源內容管理框架(CMF),它由內容管理系統(CMS)和PHP開發框架(Framework)共同構成。
加密后的影響Drupal運行的主要代碼 代碼路徑drupal/vendor/doctrine/common/lib/Doctrine/Common/Reflection/StaticReflectionParser.php:126
//代碼內容 protected function parse() { if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) { return; } $this->parsed = true; $contents = file_get_contents($fileName); if ($this->classAnnotationOptimize) { if (preg_match("/A.*^s*((abstract|final)s+)?classs+{$this->shortClassName}s+/sm", $contents, $matches)) { $contents = $matches[0]; } } $tokenParser = new TokenParser($contents); ...... }
其中部分代碼如上,通過class名獲取文件路徑,然后通過file_get_contents獲取PHP文件的內容,其中TokenParser類中構造函數如下
public function __construct($contents) { $this->tokens = token_get_all($contents); token_get_all("numTokens = count($this->tokens); }
傳入獲取到的源碼通過token_get_all進行解析,然后后續分析代碼獲取PHP文件的類、屬性、方法的注釋 ,父類的命名空間 和class名 ,本類的use信息等,因為文件已經加密,所以file_get_contents獲取到的內容是加密后的內容,token_get_all就解析不到正確的信息,從而導致程序無法運行。
解決方案本次使用的2.1.1版本的加密器,通過Swoole Compiler加密器加密的代碼,在配置文件中save_doc配置選項必須設置為1,如果設置為0則不會保存注釋,并且在2.1.3版本swoole_loader.so擴展中新增加的函數naloinwenraswwww也無法獲取到類中use的相關信息,具體函數使用在后面會詳細說明。
1 $ref = new ReflectionClass($this->className); 2 3 $parent_ref = $ref->getParentClass(); 4 5 ...... 6 7 if (is_file($fileName)) { 8 $php_file_info = unserialize(naloinwenraswwww(realpath($fileName))); 9 foreach ($php_file_info as $key => $info) { 10 if ($key == "swoole_namespaces" || $key == "swoole_class_name") { 11 continue; 12 } 13 $this->useStatements[$key] = $info; 14 } 15 } 16 17 $this->parentClassName = $parent_ref->getName(); 18 19 if (strpos($this->parentClassName, "")!==0) { 20 $this->parentClassName = "".$this->parentClassName; 21 } 22 23 $static_properties = []; 24 25 $properties = $ref->getProperties(); 26 27 $parent_properties = $this->createNewArrKey($parent_ref->getProperties()); 28 29 ...... 30 31 $static_methods = []; 32 33 $methods = $ref->getMethods(); 34 35 ......
第1行通過類名來獲取反射類ReflectionClass類的對象。
因為此反射類包含了所有父類中的屬性和方法,但源碼中只要獲取本類中的屬性和方法,所以還要獲取父類的反射類然后通過對比來剔除父類中的屬性和方法,第3行使用ReflectionClass類提供的getParentClass方法獲取父類的反射類,此方法返回父類的ReflectionClass對象。
第25行通過ReflectionClass類提供的getProperties方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個ReflectionProperty類對象。
通過ReflectionProperty類提供的getDocComment方法就可以拿到屬性的注釋。
同上第33行通過ReflectionClass類提供的getMethods方法可以拿到本類和父類中的方法,然后進行對比剔除父類的方法,保留本類的方法,此方法返回的是一個ReflectionMethod類對象。
通過ReflectionMethod對象提供的getDocComment方法就可以拿到方法的注釋。
通過第17行ReflectionClass提供的getName方法可以拿到類名。
因為反射無法獲取use類的信息,所以在2.1.3版本中的swoole_loader.so擴展中添加函數naloinwenraswwww,此函數傳入一個PHP文件的絕對路徑,返回傳入文件的相關信息的序列化數組,反序列化后數組如下
[ "swoole_namespaces" => "DrupalCoreDatetimeElement", "swoole_class_name" => "DrupalCoreDatetimeElementDateElementBase", "nestedarray" => "DrupalComponentUtilityNestedArray", "drupaldatetime" => "DrupalCoreDatetimeDrupalDateTime", "formelement"=> "DrupalCoreRenderElementFormElement" ]
其中swoole_namespaces為文件的命名空間,swoole_class_name為文件的命名空間加類名,其他為use信息,鍵為use類的類名小寫字母,如存在別名則為別名的小寫字母,值為use類的命名空間加類名,通過該函數和反射函數可以兼容StaticReflectionParser中加密后出現的無法獲取正確信息的問題
在加密后的未影響Drupal運行的潛在問題:代碼路徑:drupal/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php:39
代碼路徑:drupal/vendor/symfony/class-loader/ClassMapGenerator.php:91
代碼路徑:drupal/vendor/symfony/routing/Loader/AnnotationFileLoader.php:90
Drupal中引入了Symfony框架,此框架中部分代碼也是通過file_get_contents和token_get_all來獲取PHP文件的類名,但目前未對Druapl運行產生影響,可能并未用到其中方法解決方案:
同StaticReflectionParser類的解決方案一樣通過2.1.3版本中的swoole_loader.so擴展中添加函數naloinwenraswwww來獲取加密后文件的命名空間和類名
尚未有更好方案的問題:代碼路徑:drupal/core/includes/install.inc:220
function drupal_rewrite_settings($settings = [], $settings_file = NULL) { if (!isset($settings_file)) { $settings_file = Drupal::service("site.path") . "/settings.php"; } // Build list of setting names and insert the values into the global namespace. $variable_names = []; $settings_settings = []; foreach ($settings as $setting => $data) { if ($setting != "settings") { _drupal_rewrite_settings_global($GLOBALS[$setting], $data); } else { _drupal_rewrite_settings_global($settings_settings, $data); } $variable_names["$" . $setting] = $setting; } $contents = file_get_contents($settings_file); if ($contents !== FALSE) { // Initialize the contents for the settings.php file if it is empty. if (trim($contents) === "") { $contents = " $setting) { $buffer .= _drupal_rewrite_settings_dump($setting, "$" . $name); } // Write the new settings file. if (file_put_contents($settings_file, $buffer) === FALSE) { throw new Exception(t("Failed to modify %settings. Verify the file permissions.", ["%settings" => $settings_file])); } else { // In case any $settings variables were written, import them into the // Settings singleton. if (!empty($settings_settings)) { $old_settings = Settings::getAll(); new Settings($settings_settings + $old_settings); } // The existing settings.php file might have been included already. In // case an opcode cache is enabled, the rewritten contents of the file // will not be reflected in this process. Ensure to invalidate the file // in case an opcode cache is enabled. OpCodeCache::invalidate(DRUPAL_ROOT . "/" . $settings_file); } } else { throw new Exception(t("Failed to open %settings. Verify the file permissions.", ["%settings" => $settings_file])); } }
Drupal安裝過程中有個配置文件default.setting.php,里面存放了默認配置數組,在安裝的過程中會讓用戶在安裝界面輸入一些配置比如Mysql的信息,輸入過后此方法通過file_get_contents和token_get_all來獲取setting中的信息,然后合并用戶在頁面輸入的信息,重新存回文件,因為整個過程涉及到讀取文件,更改文件信息,在存入文件,所以Swoole Compiler在此處暫時沒有更好的解決方案,需要在加密的時候選擇不加密setting文件。
代碼路徑:drupal/vendor/symfony/class-loader/ClassCollectionLoader.php:126
此類中是Symfony讀取PHP文件然后作相應處理后緩存到文件中,存在和上面代碼同樣的問題,暫未找到更好的解決方案
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31592.html
摘要:通過類提供的方法分別獲取本類和父類中的屬性,然后進行對比剔除父類的屬性,保留本類的屬性,此方法返回的是一個類對象。 問題描述 上個星期碰到個客戶使用swoole compiler加密drupal導致drupal項目無法運行的問題,逐步排查后總結問題是drupal中有部分代碼直接通過file_get_contents獲取php源碼導致的,因為項目代碼是加密過后的,所以直接獲取php源碼解...
摘要:偏巧的是重定向的過程會給黑客提供中間人攻擊。在上例的情況下,從發送頭部到得到響應,有效性可保持年。它認為這個頭部可以預防偽造跨站請求??偨Y使用以上頭部可幫你快速容易地預防攻擊點擊挾持攻擊嗅探和中間人攻擊。請確保用戶的安全性。 它曾是世界性圖書館夢的開始,現在它是全球知識的聚集地,它是目前最流行的,人們將應用都部署之上的萬維網。 它是敏捷的代表,它不是單一的實體,它由客戶端和服務端組成...
摘要:另一方比如小明得到公鑰之后,雙方就可以通信。然而,中間人還是可能截獲公鑰,然后自己弄一對秘鑰,然后告訴小明說是小紅的公鑰。這樣,小亮在簽署小紅的身份證的時候,可以在小紅身份證后面附上自己的身份證。一般來說,自簽名的根身份證用于公司內部使用。 前言 自從 Lets Encrypt 上線之后,HTTPS 網站數量占比越來越高,相信不久的未來就可以實現全網 HTTPS,大部分主流瀏覽器也對 ...
閱讀 994·2023-04-25 15:42
閱讀 3584·2021-11-02 14:38
閱讀 2886·2021-09-30 09:48
閱讀 1419·2021-09-23 11:22
閱讀 3379·2021-09-06 15:02
閱讀 3186·2021-09-04 16:41
閱讀 607·2021-09-02 15:41
閱讀 2012·2021-08-26 14:13