原作者: Ziyahan Albeniz
在2019年3月13日,專注于靜態代碼分析軟件的RIPS科技公司發布了他們在所有版本的WordPress 5.1.1中發現的跨站點腳本(XSS)漏洞的詳細信息。該漏洞已在不同類別的各種網站上公布。有些人將其歸類為跨站點請求偽造(CSRF)漏洞,而其他人則將其正確歸類為XSS。在本文中,我們將分析此WordPress XSS漏洞(編號為CVE-2019-9887),該漏洞導致遠程執行代碼(RCE)漏洞。

WordPress的Pingback和Trackback功能
在WordPress中,nonce需要一個值來防止CSRF攻擊。這是一個隨機值,在每個請求中都會更改,并且只有服務器和用戶的瀏覽器才知道。但是,nonce自2009年以來,WordPress中的評論部分沒有使用過值。這是因為WordPress開發人員做出了兩個設計決策,限制了安全令牌的正確實現以防止CSRF攻擊。
WordPress中的pingback和trackback功能要求缺少nonce值才能正常運行:
- pingback功能通知博客他們的文章已從某人的帖子鏈接。這增加了在其搜索引擎優化中使用反向鏈接方法在任何搜索引擎上的網站評級。
- 當博主鏈接到不是使用WordPress構建的網站時,會使用引用功能。
WordPress中評論的過濾
當攻擊者設法重定向經過身份驗證的WordPress管理員用戶以訪問攻擊者控制的網站時,他們可以代表此管理員用戶提交表單,以便在用戶名稱的博客上發布評論。除了WordPress開發人員之外,任何人都認為這將是一個嚴重的漏洞。但是,如果要避免破壞pingback,則行為是絕對必要的。
為了最小化表單提交代表管理員的影響,他們實現了一般不會阻止CSRF的nonce。如果設置了正確的現時(如果管理員使用實際表單發布評論),則評論中的HTML代碼不會像表單提交是CSRF的結果那樣嚴格過濾。
因此,如果管理員帳戶發出的評論請求中沒有nonce令牌,WordPress會使用nonce值'_wp_unfiltered_html_comment_disabled'來檢查是否應該從HTML標簽中清除評論。
分析WordPress的有缺陷的過濾機制
RIPS Technologies的一名工程師在靜態代碼分析期間發現了/wp-includes/comment.php文件中檢測和清理機制的缺陷。這是與缺陷相關的代碼塊。
if ( current_user_can( 'unfiltered_html' ) ) { if (! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment' )) { $_POST['comment'] = wp_filter_post_kses($_POST['comment']); }}else { $_POST['comment'] = wp_filter_kses($_POST['comment']);}
根據代碼,如果當前用戶沒有權限unfiltered_html,則注釋文本wp_filter_kses將從其中的HTML元素定向到要清理的函數。
由于攻擊請求將通過登錄管理員帳戶的瀏覽器發送,并且管理員帳戶具有權限unfiltered_html,因此代碼的缺陷從第一個if語句開始。
在第一個條件語句中,如果未驗證nonce令牌,則注釋文本將通過一個名為的另一個函數wp_filter_post_kses來清理輸入。
職能部門之間的主要區別wp_filter_kses,并wp_filter_post_kses是wp_filter_kses刪除所有的意見,除了基本的HTML標簽,如href屬性和錨標記。該wp_filter_post_kses函數清理所有潛在風險的HTML標記,但它比wp_filter_kses函數更寬松。
使用HTML標簽繞過清理
RIPS科技公司的工程師發現,HTML元素和屬性的清理過程存在一個重大缺陷。一旦評論被清理,屬于標簽的屬性通過將它們解析為關聯數組而針對SEO目的進行優化。
例如,如果帶有標記的屬性是href="#" rel="nofollow",則字符串將被解析為一個數組,其中每個屬性名稱都是鍵:
function wp_rel_nofollow_callback( $matches ) { $text = $matches[1]; $atts = shortcode_parse_atts($matches[1]); ?
完成此轉換后,您可以使用以下方式訪問href錨標記的功能$atts["href"]。接下來,WordPress檢查注釋中的錨標記是否具有該rel屬性。
重要的是要注意,rel錨元素中的屬性只有在評論者擁有管理員帳戶時才能存在。該wp_filter_kses函數不允許此屬性; 該wp_filter_post_kses函數的作用。
if (!empty($atts['rel'])) { // the processing of the 'rel' attribute happens here ? $text = ''; foreach ($atts as $name => $value) { $text .= $name . '="' . $value . '" '; } } return '';}
使用WordPress漏洞插入XSS Payload
如上面以粗體顯示的代碼行所示,連接的字符串值不會以任何方式進行清理。如果攻擊者將以下title屬性添加到注釋中的錨標記,則可能會濫用此功能的性質。
onmouseover=alert(1) id="'
處理后代碼行將變為以下內容(注意雙引號):
希望利用此漏洞的惡意用戶必須欺騙具有管理員權限的用戶訪問將觸發和執行有效負載的頁面。
此時發送具有XSS有效負載的注釋請求。
為了進行秘密攻擊,并在提交表單時避免頂級導航,表單的響應將定向到具有display:nonetarget屬性中指定的樣式的隱藏iframe 。
最后,管理員瀏覽器將查看帶有XSS有效負載評論的博客文章,以確保攻擊完成。執行攻擊后,將通過管理面板編輯模板文件。然后,攻擊者可以執行PHP代碼注入并將此XSS攻擊轉換為遠程執行代碼(RCE)。
修復WordPress中的漏洞
如果您使用WordPress,解決此問題的最快速最簡單的方法是更新到修復漏洞的5.1.1版。
此外,Netsparker報告任何使用過時WordPress版本的掃描網站,并顯示當前版本的相關漏洞。這是一個這樣的報告的例子。
