中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何深入分析drupal8框架和漏洞動態調試

發布時間:2022-01-17 10:59:42 來源:億速云 閱讀:143 作者:柒染 欄目:安全技術

這篇文章給大家介紹如何深入分析drupal8框架和漏洞動態調試,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

前言

      在drupal框架中,比較經典又離我們最近的莫過于18年的CVE-2018-7600這個漏洞了。但是通過本人閱讀和學習過此漏洞分析文章的過程中,發現都是針對于此漏洞點的詳細分析。相對于此框架運行流程不是很熟悉的人可能在閱讀完后很難理解。

下面主要分為兩大部分:

第一部分是對drupal框架流程的簡介(這里主要針對8.x系列),讓我們知道在symfony開源框架基礎上的drupal框架是如何利用監聽者模式支撐起整個繁雜的處理流程,并讓我們對框架如何處理一個請求有基本的了解。

第二部分,結合框架對漏洞CVE-2018-7600的運行流程進行詳細解讀,在漏洞觸發的起始點首先通過動態調試正常數據包來了解drupal框架對其的處理流程,借此利用正常包中的可控變量來構造POC包。讓我們不僅能對開頭和結果得以了解,更能讓中間的過程透明化。得以觸類旁通。

一、背景介紹

Drupal是使用PHP語言編寫的開源內容管理框架(CMF),它由內容管理系統(CMS)和PHP開發框架(Framework)共同構成。連續多年榮獲全球最佳CMS大獎,是基于PHP語言最著名的WEB應用程序。

Drupal架構由三大部分組成:內核、模塊、主題。三者通過Hook機制緊密的聯系起來。其中,內核部分由世界上多位著名的WEB開發專家組成的團隊負責開發和維護。

Drupal綜合了強大并可自由配置的功能,能支持從個人博客(PersonalWeblog)到大型社區驅動(Community-Driven)的網站等各種不同應用的網站項目。Drupal最初是由DriesBuytaert所開發的一套社群討論軟件。之后,由于它的靈活的架構,方便的擴展等特性,使得世界上成千上萬個程序員加入了Drupal的開發與應用中。今天,它已經發展成為一套強大的系統,很多大型機構都采用基于Drupal的框架建站,包括The Onion,Ain't ItCool News,SpreadFirefox,Ourmedia,KernelTrap,NewsBusters等等。它特別常見于社區主導的網站。

二、準備工作

     2.1源碼下載

      首先可以直接通過官網下載頁面https://www.drupal.org/download 直接下載最新版本或者通過https://www.drupal.org/project/drupal/releases/xxx xxx代表你想下載的版本號,來下載對應版本的源碼文件。  你也可以用PHP包管理工具composer進行下載。

     2.2 drupal安裝

    安裝環境:WIN7 32位

    集成環境:PHPSTUDY

    調試環境:PHPSTORM

    安裝中可能出現的問題和解決辦法:

 1.  php版本問題:最好為PHP7.0以上

 2.    datetime問題

如何深入分析drupal8框架和漏洞動態調試

解決方法:

php.ini 中設置

如何深入分析drupal8框架和漏洞動態調試

3.安裝警告

如何深入分析drupal8框架和漏洞動態調試

      這兩個問題(warning)可以不解決。

      針對問題1解決方法:升級php版本為7.1及以上。

      針對問題2解決辦法:

      在php.ini中,找到[opcache],在這個地下添加如下內容。

如何深入分析drupal8框架和漏洞動態調試

zend_extension="C:\xxx\xxx\php\php-7.0.12-nts\ext\php_opcache.dll"

opcache.memory_consumption=128

opcache.interned_strings_buffer=8

opcache.max_accelerated_files=4000

opcache.revalidate_freq=60

opcache.fast_shutdown=1

opcache.enable_cli=1

 4.    因為drupal處理有些請求過慢,有可能會導致超時出現異常,在Php.ini中max_execution_time選項設置大點即可。

三、框架淺析

3.1目錄結構

下面是drupal 8.5.7 源碼解壓后的目錄:

如何深入分析drupal8框架和漏洞動態調試

/core drupal的內核文件夾,詳見后文說明

/modules 里存放 自定義或者下載的模塊

/profiles 里存放 下載和安裝的自定義配置文件

/sites  文件夾,在drupal 7 或者更早的版本中,主要存放站點使用的主題和模塊活其他站點文件。

/themses 里存放 自定義或者下載的主題

/vendor 里存放 代碼的依賴庫

接下來我們來看核心文件夾core下的目錄結構

如何深入分析drupal8框架和漏洞動態調試

/core/assets - drupal 所使用的各種擴展庫,如jquery,ckeditor,backbone,normalizeCSS等

/core/config  - drupal 中的核心配置文件

/core/includes – 模塊化的底層功能函數,如模塊化系統本身

/core/lib – drupal提供的原始核心類

/core/misc – 核心所需要的前端雜項文件,如JS,CSS,圖片等。

/core/modules – 核心模塊,大約80項左右

/core/profiles – 內置安裝配置文件

/core/scripts – 開發人員使用的各種命里腳本

/tests – 測試相關用的文件

/core/themes – 內核主題

3.2框架運行邏輯

    Drupal是建立在symfony開源框架之上的,在symfony的官網上可知sysmfony就是一個可復用的php組件集,可以將任何一個組件獨立的運用到自己的應用程序中來,在symfony官網里每一個組件都有獨立的文檔,這些組件有些被drupal直接使用,有些根據drupal自己的特性進行了修改。

我們首先來看一下symfony的執行流程

如何深入分析drupal8框架和漏洞動態調試

Drupal 與 symfony 在設計上也使用了相同的理念,它們都認為任何一個網站系統其實就是一個把請求轉換為響應的系統。

在drupal的路由系統中,我們可以看到各個組件之間的關系:

如何深入分析drupal8框架和漏洞動態調試

在此基礎上,drupal對symfony的處理流程進行了細化,構成了現在這個龐大的drupal處理響應流程。

圖片鏈接地址為https://www.drupal.org/docs/8/api/render-api/the-drupal-8-render-pipeline 如需要可自行下載高清版。

如何深入分析drupal8框架和漏洞動態調試

3.3從入口文件來看

如何深入分析drupal8框架和漏洞動態調試

      入口文件非常簡潔,只有6行代碼量,卻貫穿了整個drupal,由于drupal的核心系統過于龐大,分析不可能面面俱到,我們將從入口文件一行行來看,分析下它的運行流程。

      首先是$autoloader =require_once 'autoload.php'; 表面上看單單的是包含了一個autoload.php的文件,實際上drupal會利用PHP自動加載機制創建一個自動加載器,并獲取了一個自動加載的對象。

 下面從代碼方面簡略看下其流程:其根本是調用vendor/autoload.php 中的getLoader函數。

如何深入分析drupal8框架和漏洞動態調試

 接著我們進入函數看看它做了什么:

如何深入分析drupal8框架和漏洞動態調試

如何深入分析drupal8框架和漏洞動態調試

ClassLoader對象就是利用里面定義的基本對應關系去查找函數和類定義文件。

函數最后返回實例化加載器,至此第一步完成,drupal以后就不需要手動的 include一大堆文件了,省去了大量工作。

接著是 $kernel =new DrupalKernel('prod', $autoloader); drupal創建了一個新的drupal內核對象,為處理即將到來的請求對象做準備。

 如何深入分析drupal8框架和漏洞動態調試

緊接著是入口文件中的$request= Request::createFromGlobals()這一行代碼。對于一個面向對象的系統來說,我們不應該直接使用$_POST,$_GET,$_COOKIE等這些全局變量。Drupal把它們全部封裝進了$request對象。這樣不僅簡單方便,而且使用請求的對象可直接加入一些額外的功能和自定義的屬性。

如何深入分析drupal8框架和漏洞動態調試

最終,會把相應的全局變量加到request對象中,并返回封裝好的request對象。

如果說上面的操作只是預備階段,那么接下來$response = $kernel->handle($request);這行代碼將開始步入正題,由drupal內核對象kernel來處理request請求。

如何深入分析drupal8框架和漏洞動態調試

Drupal的處理核心是利用了設計模式里面的監聽者模式。其中包括一個事件源,里面包含了不同的事件以及事件等級。另一部分就是需要執行事件的程序或者函數,我們叫它監聽者。在請求處理的這個流程中,每到一個節點,會派發出相應的事件,監聽者會根據獲取的事件對象和等級來進行相應的操作。

      其中系統核心事件還是繼續沿用symfony框架中的事件,位于kernelevents.php中,其中包含八大核心:

      Const REQUEST = ‘kernel.request’ 執行框架代碼中的任何代碼之前,請求分派的開始觸發的。

      Const EXCEPTION = ‘kernel.exception’ 出現未捕獲的異常時觸發的事件。

      Const VIEW = ‘kernel.view’ 當控制器返回值不是response 實例時觸發。此時控制器返回的是渲染數組,來進一步進行渲染工作。

      Const CONTOLLER = ‘kernel.controller’ 解析request請求找到相對應的控制器時觸發,并可以對此控制器進行修改。

      Const CONTROLLER_ARGUMENTS =‘kernel.controller_arguments’ 解析控制器的參數時觸發,并可對參數進行更改。

      Const RESPONSE = ‘kernel.response’ 創建響應回復請求時觸發,并可修改或替換要回復的相應。

      Const TERMINATE = ‘kernel.terminate’ 一旦發送響應,就會觸發。這個事件會允許處理繁重的post-response任務。

      Const FINISH_REQUEST = ‘kernel.finish_request’完成Request請求時觸發,可在請求期間更改應用程序時重置應用程序的全局和環境狀態。

      除了這些核心的事件,drupal中的每個監聽者也會派發它們自己的事件。這些文件的位置位于\core\lib\Drupal\Core\目錄下相對應文件夾中。它們都是以events.php結尾,文件中定義了相應的靜態事件變量。

      我們接下來看下drupal 核心的請求流程:

開始請求request---》解析請求得到控制器并修正------》解析控制器參數----》根據控制器調用其中的方法-----》觀察控制器的返回情況:返回響應對象reponse或繼續進行渲染------》發送響應。如果整個流程中途產生異常,會直接觸發異常事件進行異常的分發。請求對象在整個流程中除了會對核心請求事件的響應,還會根據實際情況進入響應其他普通模塊事件的分支,但是不管中途的過程如何崎嶇坎坷,最終都會重新回歸主流程返回響應對象response。

接下來從源代碼中觀察下上述具體行為:

      從index.php中繼續跟進便進入了drupalkernel.php文件,我們來看看做了那些操作。

如何深入分析drupal8框架和漏洞動態調試   

接下來就是一系列的處理函數函數調用鏈,我們一直跟進handle函數即可,這樣我們直接可跟進核心函數handleraw

如何深入分析drupal8框架和漏洞動態調試

如何深入分析drupal8框架和漏洞動態調試

這里我們繼續跟進即將返回的filterResponse函數。

如何深入分析drupal8框架和漏洞動態調試

這里的響應對象將一層一層的返回(需要注意的是不是所有的響應結果都會走這個流程),但是最終都會封裝成respone響應對象,返回至index.php文件中的$response變量中。然后調用$response->send()發送封裝好的響應對象。

如何深入分析drupal8框架和漏洞動態調試

有時我們發送的請求操作的內容會過于繁瑣,所以當上面的調用結束后,我們的drupal內核在關閉前會做最后的處理。流程進入Index.php文件的最后一行,調用$kernel->terminate($request,$response),我們根據調用鏈跟進stackedhttpkernel.php文件

如何深入分析drupal8框架和漏洞動態調試

至此,整個周期已經結束。

我們發現上面整個過程中出現最多的就是派發事件這個操作了,其實所有派發進行的流程是相同的,派發的具體過程在ContainerAwareEventDispatcher.php文件中,我們拿kernel.request事件來進行舉例說明。

如何深入分析drupal8框架和漏洞動態調試

系統中監聽者總數有19個之多,每個監聽者其中又會有與之相關的服務名,我們會根據傳入的事件名稱匹配相應的監聽者,接著遍歷挨個調用其中的服務名所對應的功能函數。我們這里是kernel.request事件,調用方式為回調調用。

如何深入分析drupal8框架和漏洞動態調試

四、再看CVE-2018-7600

       通過第三部分單純的框架分析可能只對流程有一個模糊的概念,接下來我們結合漏洞實例,針對比較經典的drupal框架漏洞cve-2018-7600來仔細觀察下此漏洞在框架中的詳細運行流程。我們這里利用漏洞觸發環境的版本為8.5.0,此版本漏洞觸發更為直觀,所以我們后面分析所用代碼版本如不做說明皆為此版本。

4.1 補丁對比

      因為此漏洞在8.5.1版本中被修復,5.0 和5.1又只相差一個子版本,我們可以更清晰的在源碼中對比出其中的差異。看官方是如何修復這個漏洞的:在8.5.1版本的源碼中,新增了一個RequestSanitizer.php文件,里面是對request請求部分進行過濾,在stripDangerousValues方法中過濾了以#開頭且不再白名單里的所有鍵名的值。

如何深入分析drupal8框架和漏洞動態調試

  在prehandle方法中調用了上述文件新增的方法進行過濾,下圖右邊紅色部分為8.5.1新增的過濾代碼。

如何深入分析drupal8框架和漏洞動態調試   

此處過濾代碼的調用位置是在drupal內核處理請求之前。這樣可以一勞永逸,徹底修復了這個漏洞。

如何深入分析drupal8框架和漏洞動態調試

接著我們進入drupal官網查看官方文檔發現了drupal render api對#開頭有特殊處理,關鍵文檔鏈接在下方

https://www.drupal.org/docs/8/api/render-api/render-arrays并根據checkpoint安全團隊發布了一份關于此漏洞相關技術細節報告。鏈接如下:https://research.checkpoint.com/uncovering-drupalgeddon-2/。發現漏洞觸發的源頭是8.5.0版本中注冊用戶功能中的頭像上傳功能。

如何深入分析drupal8框架和漏洞動態調試

4.2數據包在框架中的運行流程

      我們既然知道了漏洞的觸發源頭,那么首先隨便上傳一張圖片,抓一個正常的初始包看看情況。

如何深入分析drupal8框架和漏洞動態調試

      接著在入口文件index.php中,經過createfromglobals函數的包裝,drupal把我們傳入的參數全部封裝進了request對象中。

如何深入分析drupal8框架和漏洞動態調試

4.2.1KernelEvents::REQUEST派發事件 

      由于上文中對框架流程做了介紹,下面就是drupal內核處理我們的request請求階段了,我們這里直接把斷點下在handleRaw上,并進入第一個KernelEvents::REQUEST派發事件,看看監聽者們都對此次請求做了什么。

如何深入分析drupal8框架和漏洞動態調試

      首先drupal嘗試去處理Option請求,可惜我們這里是POST請求,所以不處理,直接放行。

如何深入分析drupal8框架和漏洞動態調試     

接著會去處理URL路徑上的斜杠問題,會把多個斜杠開頭的路徑轉換成單個斜杠

如何深入分析drupal8框架和漏洞動態調試

    然后會根據請求驗證身份,我們這里沒有做登陸,是游客身份,所以這里也不做特殊處理。

如何深入分析drupal8框架和漏洞動態調試

     接下來會清理含有$ _GET['destination']和$ _REQUEST ['destination']目標參數,防止重定向攻擊。

如何深入分析drupal8框架和漏洞動態調試

      緊接著會根據POST請求中的_drupal_ajax參數來判斷此次請求是否為AJAX請求,并設置相關屬性。

如何深入分析drupal8框架和漏洞動態調試

      接下來就是根據請求中的URL部分來匹配相應的路由,這里drupal會先在路由緩存中查找相應的匹配項,如果沒有則再進行全部的路由查表操作。(由于代碼比較多,這里不做全部截取,只截取部分代碼),處理函數在onKernelRequest 中,同時,我們也可以在user.routing.yml文件中找到相關信息。

如何深入分析drupal8框架和漏洞動態調試

路由找到了,接下來就是去檢查此路由是否可用

如何深入分析drupal8框架和漏洞動態調試

緊接著就是檢查站點是否處于維護模式,如果是維護模式則退出賬戶,檢查站點是否脫機,檢查動態頁面緩存,預先處理非路由設置,根據參數看是否禁用副本服務器。這些操作的相關函數,均截圖在下方。

如何深入分析drupal8框架和漏洞動態調試

如何深入分析drupal8框架和漏洞動態調試如何深入分析drupal8框架和漏洞動態調試如何深入分析drupal8框架和漏洞動態調試

如何深入分析drupal8框架和漏洞動態調試

      至此,KernelEvents::REQUEST 的所有監聽者的行為分析完畢,我們可以看到上面這些操作主要做的是一些額外的措施,我們可以忽略不看,但是從中我們也提煉出了一些有價值的信息,通過請求對象匹配到了相關的路由信息。

4.2.2KernelEvents::CONTROLLER與KernelEvents::CONTROLLER_ARGUMENTS事件

      接下來在handleraw函數中,drupal通過剛剛匹配到的路由信息來找到真正的請求控制器和相應的參數。

如何深入分析drupal8框架和漏洞動態調試

      我們先來看看KernelEvents::CONTROLLER的監聽者們會做那些操作。

      首先,為了以后不做沖突,在相應的管理器上設置了關鍵的KEY

如何深入分析drupal8框架和漏洞動態調試

      緊接著為了確保后面處理數據時的完整性,這里利用閉包把回調處理控制器的函數存進$event對象中

如何深入分析drupal8框架和漏洞動態調試

      因為KernelEvents::CONTROLLER_ARGUMENTS并沒有屬于它自己的監聽者,所以這里派發直接放行。

4.2.3 調用控制器

      在handleRaw中處理完了請求相關的事件派發,并從request中找到了相應的控制器后,就該根據控制器找到相應的處理函數了。下方call_user_function中的控制器已經被替換為上圖中閉包回調函數了,這里的調用控制器相當于直接進入上圖中的閉包函數中。

如何深入分析drupal8框架和漏洞動態調試

      在drupal中,控制器都會被加入渲染上下文,以保證每個控制器處理過程中如果有需要渲染的地方直接進行渲染操作。

如何深入分析drupal8框架和漏洞動態調試

      根據控制器進入到了真正的調用方法,也就是getContenResult中,表單的構建正式開始。

如何深入分析drupal8框架和漏洞動態調試

 4.2.4 表單構建

      在進入buildForm 函數后,我們首先會得到POST的信息并存入form_state。    

如何深入分析drupal8框架和漏洞動態調試

      在buildForm函數的retrieveForm函數中,form表單開始初步組裝,如果其中有元素需要渲染,drupal大部分會直接利用\Drupal::service('renderer')->renderPlain();這個渲染服務對元素進行渲染操作,最終渲染函數的主要操作在doRender函數中。

如何深入分析drupal8框架和漏洞動態調試如何深入分析drupal8框架和漏洞動態調試

      根據rquest組裝的form表單在組裝完成之后,馬上就要處理表單請求了,這里processForm這個函數進行了這個操作,在這個函數中,運用遞歸的操作來處理行為,我們是一個圖片上傳操作,在這其中也會對此行為進行處理,處理完畢后會進行圖片的移動。接著對每個元素和token進行檢查校驗,最后根據結果rebuild整個Form表單。

如何深入分析drupal8框架和漏洞動態調試

      如果想在processForm中跟蹤對圖片的處理流程,可直接對下方函數進行斷點設置,并根據棧回溯來查找你關心的操作。

如何深入分析drupal8框架和漏洞動態調試     

在運行完processForm函數后這里給出rebuild后部分FORM表單截圖

如何深入分析drupal8框架和漏洞動態調試

    到這里整個表單的處理操作已經完成了。

4.2.5 異常派發。

      在上一步完成表單操作之后,不知不覺中已把request請求對象轉換成了響應response對象。眼看就要逐層返回并進行send操作了,但是在接下來的流程中drupal發現這是一個ajax請求,這里主動把操作攔截了下來,并拋出AJAX異常來對此次請求做額外的處理。

如何深入分析drupal8框架和漏洞動態調試

      捕獲到異常之后再處理異常中進行對異常的派發操作。

如何深入分析drupal8框架和漏洞動態調試

      在這里的派發其實是一個遍歷并匹配異常的過程,發生異常有很多種情況,匹配到正確的異常然后進行具體的處理。如果沒有匹配到,放行即可。我們這里匹配到了AJAX的異常,如果還比較關心其他異常的處理流程,在kernel.exception數組中尋找即可。

如何深入分析drupal8框架和漏洞動態調試     

我們進一步跟進發現onException的buildResponse函數中,有對AJAX的具體處理方法。

如何深入分析drupal8框架和漏洞動態調試

      在uploadAjaxCallback函數中,我們從數據包的URL中獲取element_parents參數的值,并以此為key從我們最終處理完成的FORM表單中獲取出結果,接著對此結果進行渲染并呈現在HTML頁面上。

如何深入分析drupal8框架和漏洞動態調試

      根據我們POST包中URL得參數,我們這里取出了FORM表單中user_picture下widget數組中的第一項。

如何深入分析drupal8框架和漏洞動態調試

      最終在doRender中要被渲染的對象就是剛剛取出來的元素。

如何深入分析drupal8框架和漏洞動態調試

      渲染過后整個處理過程已即將步入尾聲,開始構建response并逐層返回。

4.2.6 kernel.response事件

      既然到了response階段,那么肯定就要開始觸發response相應了,接下來我們來看看response 有哪些監聽者

如何深入分析drupal8框架和漏洞動態調試

      在response的派發函數中,其根本是對response對象的添磚加瓦以及做一些相應的擴展操作。如判斷動態頁面是否需要緩存,是否需要添加緩存上下文,處理占位符,在成功響應時設置額外標頭等。上述所有的操作都會在listeners下的kernel.response數組中,這里不做詳細展開介紹。

如何深入分析drupal8框架和漏洞動態調試

4.2.7 kernel.finish_request

      當 request 和response 的操作都做完了之后,接下來會告訴drupal 內核所有已經完畢,會發送finish_request事件,這個事件的監聽者只有一個:為了讓URL生成器在正確的上下文中運行,我們需要把當前請求設置為父請求。

如何深入分析drupal8框架和漏洞動態調試

4.2.8 kernel.terminate事件

      做完上述操作后,request請求從請求棧中彈出,并逐層返回至Index.php入口主頁面進行reponse的發送。最后進行掃尾工作,觸發kernel.terminate事件,判斷相關換成是否需要寫入文件。最終drupal內核關閉。整個流程結束。

4.3 整個流程總結

      通過上一個小節分解式的解析了整個流程,我們下面來簡單概括下:

發送數據包-->根據URL匹配相關路由-->根據路由找到相應的控制器-->根據控制器得到處理方法(我們這里是表單相關操作)-->進行表單的構建與渲染-->處理表單請求-->處理完表單后判斷是否為AJAX操作-->主動拋出異常利用AJAX回調來重新渲染URL中標注的FORM表單key-->完成相應構建響應對象-->發送相應-->掃尾結束。

五、漏洞POC構建

      結合上面框架的分析與理解開始對POC進行構建。在checkpoint安全團隊發布了一份關于此漏洞相關技術細節報告(上文有鏈接)中可知,漏洞觸發點是在表單構建好之后,觸發AJAX異常,從FROM表單提取出要渲染的對象,進行渲染時觸發,也就是在最終的doRender函數中。我們在doRender中發現如下可利用點:

如何深入分析drupal8框架和漏洞動態調試

       根據第四部分我們對一個正常上傳包在框架中運行的流程的分析,我們可知想讓我們自己構造的內容在doRender中成功觸發漏洞,首先需要控制流程,讓其進入AJAX回調部分。在下方這個if判斷中,我們可知需要同時滿足三個條件,$ajax_form_request ,$form_state->isProcessingInput() 和$request->request->get('form_id')== $form_id。$ajax_form_request的值從下圖可知是由ajax_form這個變量控制,form_id 是表單的id。

如何深入分析drupal8框架和漏洞動態調試

      接下來,利用url中的element_parents參數值來獲取表單數組中的值。在第四部分4.2.5小節有所講述,此處不再重復說明。 最后構造相應的變量利用doRender函數中的call_user_func_array來觸發漏洞。

      根據上述描述,我們利用mail參數構造了如下POC包

如何深入分析drupal8框架和漏洞動態調試

     除了上述mail參數可控外,在分析過程中同時發現form_build_id參數也可控,另一種POC如下。

如何深入分析drupal8框架和漏洞動態調試

關于如何深入分析drupal8框架和漏洞動態調試就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

闽清县| 定南县| 开化县| 徐州市| 敖汉旗| 甘谷县| 霍邱县| 抚远县| 楚雄市| 穆棱市| 花垣县| 泽库县| 鄂托克前旗| 东莞市| 元谋县| 凤城市| 合肥市| 随州市| 钟祥市| 旺苍县| 中山市| 县级市| 麦盖提县| 阿瓦提县| 聂拉木县| 姚安县| 达州市| 白银市| 台中市| 甘泉县| 云浮市| 平潭县| 佛坪县| 禹城市| 巴里| 卢龙县| 六枝特区| 新郑市| 彝良县| 新昌县| 平江县|